diff --git a/CMakeLists.txt b/CMakeLists.txt index 90ea519b..969779f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,306 +1,306 @@ - -cmake_minimum_required(VERSION 2.8) - -# define a macro that helps defining an option -macro(sfml_set_option var default type docstring) - if(NOT DEFINED ${var}) - set(${var} ${default}) - endif() - set(${var} ${${var}} CACHE ${type} ${docstring} FORCE) -endmacro() - -# set a default build type if none was provided -# this has to be done before the project() instruction! -sfml_set_option(CMAKE_BUILD_TYPE Release STRING "Choose the type of build (Debug or Release)") - -# project name -project(SFML) - -# include the configuration file -include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake) - -# setup version numbers -set(VERSION_MAJOR 2) -set(VERSION_MINOR 1) -set(VERSION_PATCH 0) - -# add the SFML header path -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - -# add an option for choosing the build type (shared or static) -if(NOT (SFML_OS_IOS OR SFML_OS_ANDROID)) - sfml_set_option(BUILD_SHARED_LIBS TRUE BOOL "TRUE to build SFML as shared libraries, FALSE to build it as static libraries") -else() - if(SFML_OS_IOS) - set(BUILD_SHARED_LIBS FALSE) - elseif(SFML_OS_ANDROID) - set(BUILD_SHARED_LIBS TRUE) - endif() -endif() - -# add an option for building the examples -if(NOT (SFML_OS_IOS OR SFML_OS_ANDROID)) - sfml_set_option(SFML_BUILD_EXAMPLES FALSE BOOL "TRUE to build the SFML examples, FALSE to ignore them") -else() - set(SFML_BUILD_EXAMPLES FALSE) -endif() - -# add an option for building the API documentation -sfml_set_option(SFML_BUILD_DOC FALSE BOOL "TRUE to generate the API documentation, FALSE to ignore it") - -# add an option for choosing the OpenGL implementation -sfml_set_option(SFML_OPENGL_ES ${OPENGL_ES} BOOL "TRUE to use an OpenGL ES implementation, FALSE to use a desktop OpenGL implementation") - -# Mac OS X specific options -if(SFML_OS_MACOSX) - # add an option to build frameworks instead of dylibs (release only) - sfml_set_option(SFML_BUILD_FRAMEWORKS FALSE BOOL "TRUE to build SFML as frameworks libraries (release only), FALSE to build according to BUILD_SHARED_LIBS") - - # add an option to let the user specify a custom directory for frameworks installation (SFML, sndfile, ...) - sfml_set_option(CMAKE_INSTALL_FRAMEWORK_PREFIX "/Library/Frameworks" STRING "Frameworks installation directory") - - # add an option to automatically install Xcode templates - sfml_set_option(SFML_INSTALL_XCODE_TEMPLATES FALSE BOOL "TRUE to automatically install the Xcode templates, FALSE to do nothing about it. The templates are compatible with Xcode 4 and 5.") -endif() - -# Android options -if(SFML_OS_ANDROID) - # force usage of the STL port - set(ANDROID_USE_STLPORT TRUE) - - # make sure there's the android library available - if (${ANDROID_NATIVE_API_LEVEL} LESS 9) - message(FATAL_ERROR "API level must be equal or greater than 9") - endif() - - # install everything in $NDK/sources/ because this path is appended by the NDK (convenient) - set(CMAKE_INSTALL_PREFIX ${ANDROID_NDK}/sources/sfml) - - # we install libs in a subdirectory named after the ABI (lib/mips/*.so) - set(LIB_SUFFIX "/${ANDROID_ABI}") - - # this is a workaround to compile sfml-activity without stlport_shared as dependency - # we save the original compilation command line to restore it later in Macro.cmake - set(CMAKE_CXX_CREATE_SHARED_LIBRARY_WITH_STLPORT ${CMAKE_CXX_CREATE_SHARED_LIBRARY}) - set(CMAKE_CXX_CREATE_SHARED_LIBRARY_WITHOUT_STLPORT " -o ") -endif() - -# define SFML_STATIC if the build type is not set to 'shared' -if(NOT BUILD_SHARED_LIBS) - add_definitions(-DSFML_STATIC) -endif() - -# remove SL security warnings with Visual C++ -if(SFML_COMPILER_MSVC) - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) -endif() - -# define SFML_OPENGL_ES if needed -if(SFML_OPENGL_ES) - add_definitions(-DSFML_OPENGL_ES) - add_definitions(-DGL_GLEXT_PROTOTYPES) -endif() - -# define an option for choosing between static and dynamic C runtime (Windows only) -if(SFML_OS_WINDOWS) - sfml_set_option(SFML_USE_STATIC_STD_LIBS FALSE BOOL "TRUE to statically link to the standard libraries, FALSE to use them as DLLs") - - # the following combination of flags is not valid - if (BUILD_SHARED_LIBS AND SFML_USE_STATIC_STD_LIBS) - message(FATAL_ERROR "BUILD_SHARED_LIBS and SFML_USE_STATIC_STD_LIBS cannot be used together") - endif() - - # for VC++, we can apply it globally by modifying the compiler flags - if(SFML_COMPILER_MSVC AND SFML_USE_STATIC_STD_LIBS) - foreach(flag - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - if(${flag} MATCHES "/MD") - string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}") - endif() - endforeach() - endif() -endif() - -# setup Mac OS X stuff -if(SFML_OS_MACOSX) - # SFML_BUILD_FRAMEWORKS needs two things : - # first, it's available only for release - # (because cmake currently doesn't allow specifying a custom framework name so XXX-d is not possible) - # secondly, it works only with BUILD_SHARED_LIBS enabled - if(SFML_BUILD_FRAMEWORKS) - # requirement #1 - if(NOT CMAKE_BUILD_TYPE STREQUAL "Release") - message(FATAL_ERROR "CMAKE_BUILD_TYPE should be \"Release\" when SFML_BUILD_FRAMEWORKS is TRUE") - return() - endif() - - # requirement #2 - if(NOT BUILD_SHARED_LIBS) - message(FATAL_ERROR "BUILD_SHARED_LIBS should be TRUE when SFML_BUILD_FRAMEWORKS is TRUE") - return() - endif() - endif() - - # configure Xcode templates - if(CMAKE_OSX_ARCHITECTURES) - # maybe multiple arches are present in CMAKE_OSX_ARCHITECTURES - # we simply need to replace ';' by ' ' (space) and store the result in XCODE_TEMPLATES_ARCH - string(REPLACE ";" " " XCODE_TEMPLATES_ARCH "${CMAKE_OSX_ARCHITECTURES}") - else() - # no arch was provided to cmake, so we use the default one - set(XCODE_TEMPLATES_ARCH "\$(NATIVE_ARCH_ACTUAL)") - endif() -endif() - -if(SFML_OS_LINUX OR SFML_OS_FREEBSD) - set(PKGCONFIG_DIR lib${LIB_SUFFIX}/pkgconfig) - if(SFML_OS_FREEBSD) - set(PKGCONFIG_DIR libdata/pkgconfig) - endif() - if(BUILD_SHARED_LIBS) - sfml_set_option(SFML_INSTALL_PKGCONFIG_FILES FALSE BOOL "TRUE to automatically install pkg-config files so other projects can find SFML") - if(SFML_INSTALL_PKGCONFIG_FILES) - foreach(sfml_module IN ITEMS all system window graphics audio network) - CONFIGURE_FILE( - "tools/pkg-config/sfml-${sfml_module}.pc.in" - "tools/pkg-config/sfml-${sfml_module}.pc" - @ONLY) - INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/tools/pkg-config/sfml-${sfml_module}.pc" - DESTINATION "${CMAKE_INSTALL_PREFIX}/${PKGCONFIG_DIR}") - endforeach() - endif() - else() - if(SFML_INSTALL_PKGCONFIG_FILES) - message(WARNING "No pkg-config files are provided for the static SFML libraries (SFML_INSTALL_PKGCONFIG_FILES will be ignored).") - endif() - endif() -endif() - -# enable project folders -set_property(GLOBAL PROPERTY USE_FOLDERS ON) -set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake") - -# add the subdirectories -add_subdirectory(src/SFML) -if(SFML_BUILD_EXAMPLES) - add_subdirectory(examples) -endif() -if(SFML_BUILD_DOC) - add_subdirectory(doc) -endif() - -# setup the install rules -if(NOT SFML_BUILD_FRAMEWORKS) - install(DIRECTORY include - DESTINATION . - COMPONENT devel - FILES_MATCHING PATTERN "*.hpp" PATTERN "*.inl") -else() - # find only "root" headers - file(GLOB SFML_HEADERS RELATIVE ${PROJECT_SOURCE_DIR} "include/SFML/*") - - # in fact we have to fool cmake to copy all the headers in subdirectories - # to do that we have to add the "root" headers to the PUBLIC_HEADER - # then we can run a post script to copy the remaining headers - - # we need a dummy file in order to compile the framework - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp - COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp) - - set(SFML_SOURCES ${SFML_HEADERS}) - list(APPEND SFML_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp) - - # create SFML.framework - add_library(SFML ${SFML_SOURCES}) - - # edit target properties - set_target_properties(SFML PROPERTIES - FRAMEWORK TRUE - FRAMEWORK_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} - MACOSX_FRAMEWORK_IDENTIFIER org.sfml-dev.SFML - MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} - MACOSX_FRAMEWORK_BUNDLE_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} - PUBLIC_HEADER "${SFML_HEADERS}") - - # add the remaining headers - add_custom_command(TARGET SFML - POST_BUILD - COMMAND cp -r ${PROJECT_SOURCE_DIR}/include/SFML/* $/Headers) - - # adapt install directory to allow distributing dylibs/frameworks in user’s frameworks/application bundle - # NOTE : it's not required to link agains SFML.framework - set_target_properties(SFML PROPERTIES - BUILD_WITH_INSTALL_RPATH 1 - INSTALL_NAME_DIR "@executable_path/../Frameworks") - - # install rule - install(TARGETS SFML - FRAMEWORK DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX} - COMPONENT devel) -endif() - -install(FILES license.txt DESTINATION ${INSTALL_MISC_DIR}) -install(FILES readme.txt DESTINATION ${INSTALL_MISC_DIR}) -if(NOT SFML_OS_ANDROID) - install(FILES cmake/Modules/FindSFML.cmake DESTINATION ${INSTALL_MISC_DIR}/cmake/Modules) -endif() - -# install 3rd-party libraries and tools -if(SFML_OS_WINDOWS) - - # install the binaries of SFML dependencies - if(ARCH_32BITS) - install(DIRECTORY extlibs/bin/x86/ DESTINATION bin) - if(SFML_COMPILER_MSVC) - install(DIRECTORY extlibs/libs-msvc/x86/ DESTINATION lib) - else() - install(DIRECTORY extlibs/libs-mingw/x86/ DESTINATION lib) - endif() - elseif(ARCH_64BITS) - install(DIRECTORY extlibs/bin/x64/ DESTINATION bin) - if(SFML_COMPILER_MSVC) - install(DIRECTORY extlibs/libs-msvc/x64/ DESTINATION lib) - else() - install(DIRECTORY extlibs/libs-mingw/x64/ DESTINATION lib) - endif() - endif() - -elseif(SFML_OS_MACOSX) - - # install the non-standard frameworks SFML depends on - install(DIRECTORY extlibs/libs-osx/Frameworks/sndfile.framework DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX}) - install(DIRECTORY extlibs/libs-osx/Frameworks/freetype.framework DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX}) - - # install the Xcode templates if requested - if(SFML_INSTALL_XCODE_TEMPLATES) - configure_file( - "tools/xcode/templates/SFML/SFML Compiler.xctemplate/TemplateInfo.plist.in" - "${CMAKE_CURRENT_BINARY_DIR}/tools/xcode/templates/SFML/SFML Compiler.xctemplate/TemplateInfo.plist" - @ONLY) - install(DIRECTORY "tools/xcode/templates/SFML" "${CMAKE_CURRENT_BINARY_DIR}/tools/xcode/templates/SFML" - DESTINATION /Library/Developer/Xcode/Templates - PATTERN "*.in" EXCLUDE) - endif() - -elseif(SFML_OS_IOS) - - # fix CMake install rules broken for iOS (see http://public.kitware.com/Bug/view.php?id=12506) - if(SFML_OS_IOS) - install(DIRECTORY "${CMAKE_BINARY_DIR}/lib/\$ENV{CONFIGURATION}/" DESTINATION lib${LIB_SUFFIX}) - endif() - - # since the iOS libraries are built as static, we must install the SFML dependencies - # too so that the end user can easily link them to its final application - install(FILES extlibs/libs-ios/libfreetype.a extlibs/libs-ios/libjpeg.a DESTINATION lib) - -elseif(SFML_OS_ANDROID) - - # install extlibs - install(DIRECTORY extlibs/libs-android/${ANDROID_ABI} DESTINATION extlibs/lib) - install(FILES extlibs/Android.mk DESTINATION extlibs) - - # install Android.mk so the NDK knows how to set up SFML - install(FILES src/SFML/Android.mk DESTINATION .) - -endif() + +cmake_minimum_required(VERSION 2.8) + +# define a macro that helps defining an option +macro(sfml_set_option var default type docstring) + if(NOT DEFINED ${var}) + set(${var} ${default}) + endif() + set(${var} ${${var}} CACHE ${type} ${docstring} FORCE) +endmacro() + +# set a default build type if none was provided +# this has to be done before the project() instruction! +sfml_set_option(CMAKE_BUILD_TYPE Release STRING "Choose the type of build (Debug or Release)") + +# project name +project(SFML) + +# include the configuration file +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake) + +# setup version numbers +set(VERSION_MAJOR 2) +set(VERSION_MINOR 1) +set(VERSION_PATCH 0) + +# add the SFML header path +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +# add an option for choosing the build type (shared or static) +if(NOT (SFML_OS_IOS OR SFML_OS_ANDROID)) + sfml_set_option(BUILD_SHARED_LIBS TRUE BOOL "TRUE to build SFML as shared libraries, FALSE to build it as static libraries") +else() + if(SFML_OS_IOS) + set(BUILD_SHARED_LIBS FALSE) + elseif(SFML_OS_ANDROID) + set(BUILD_SHARED_LIBS TRUE) + endif() +endif() + +# add an option for building the examples +if(NOT (SFML_OS_IOS OR SFML_OS_ANDROID)) + sfml_set_option(SFML_BUILD_EXAMPLES FALSE BOOL "TRUE to build the SFML examples, FALSE to ignore them") +else() + set(SFML_BUILD_EXAMPLES FALSE) +endif() + +# add an option for building the API documentation +sfml_set_option(SFML_BUILD_DOC FALSE BOOL "TRUE to generate the API documentation, FALSE to ignore it") + +# add an option for choosing the OpenGL implementation +sfml_set_option(SFML_OPENGL_ES ${OPENGL_ES} BOOL "TRUE to use an OpenGL ES implementation, FALSE to use a desktop OpenGL implementation") + +# Mac OS X specific options +if(SFML_OS_MACOSX) + # add an option to build frameworks instead of dylibs (release only) + sfml_set_option(SFML_BUILD_FRAMEWORKS FALSE BOOL "TRUE to build SFML as frameworks libraries (release only), FALSE to build according to BUILD_SHARED_LIBS") + + # add an option to let the user specify a custom directory for frameworks installation (SFML, sndfile, ...) + sfml_set_option(CMAKE_INSTALL_FRAMEWORK_PREFIX "/Library/Frameworks" STRING "Frameworks installation directory") + + # add an option to automatically install Xcode templates + sfml_set_option(SFML_INSTALL_XCODE_TEMPLATES FALSE BOOL "TRUE to automatically install the Xcode templates, FALSE to do nothing about it. The templates are compatible with Xcode 4 and 5.") +endif() + +# Android options +if(SFML_OS_ANDROID) + # force usage of the STL port + set(ANDROID_USE_STLPORT TRUE) + + # make sure there's the android library available + if (${ANDROID_NATIVE_API_LEVEL} LESS 9) + message(FATAL_ERROR "API level must be equal or greater than 9") + endif() + + # install everything in $NDK/sources/ because this path is appended by the NDK (convenient) + set(CMAKE_INSTALL_PREFIX ${ANDROID_NDK}/sources/sfml) + + # we install libs in a subdirectory named after the ABI (lib/mips/*.so) + set(LIB_SUFFIX "/${ANDROID_ABI}") + + # this is a workaround to compile sfml-activity without stlport_shared as dependency + # we save the original compilation command line to restore it later in Macro.cmake + set(CMAKE_CXX_CREATE_SHARED_LIBRARY_WITH_STLPORT ${CMAKE_CXX_CREATE_SHARED_LIBRARY}) + set(CMAKE_CXX_CREATE_SHARED_LIBRARY_WITHOUT_STLPORT " -o ") +endif() + +# define SFML_STATIC if the build type is not set to 'shared' +if(NOT BUILD_SHARED_LIBS) + add_definitions(-DSFML_STATIC) +endif() + +# remove SL security warnings with Visual C++ +if(SFML_COMPILER_MSVC) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) +endif() + +# define SFML_OPENGL_ES if needed +if(SFML_OPENGL_ES) + add_definitions(-DSFML_OPENGL_ES) + add_definitions(-DGL_GLEXT_PROTOTYPES) +endif() + +# define an option for choosing between static and dynamic C runtime (Windows only) +if(SFML_OS_WINDOWS) + sfml_set_option(SFML_USE_STATIC_STD_LIBS FALSE BOOL "TRUE to statically link to the standard libraries, FALSE to use them as DLLs") + + # the following combination of flags is not valid + if (BUILD_SHARED_LIBS AND SFML_USE_STATIC_STD_LIBS) + message(FATAL_ERROR "BUILD_SHARED_LIBS and SFML_USE_STATIC_STD_LIBS cannot be used together") + endif() + + # for VC++, we can apply it globally by modifying the compiler flags + if(SFML_COMPILER_MSVC AND SFML_USE_STATIC_STD_LIBS) + foreach(flag + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if(${flag} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}") + endif() + endforeach() + endif() +endif() + +# setup Mac OS X stuff +if(SFML_OS_MACOSX) + # SFML_BUILD_FRAMEWORKS needs two things: + # first, it's available only for release + # (because cmake currently doesn't allow specifying a custom framework name so XXX-d is not possible) + # secondly, it works only with BUILD_SHARED_LIBS enabled + if(SFML_BUILD_FRAMEWORKS) + # requirement #1 + if(NOT CMAKE_BUILD_TYPE STREQUAL "Release") + message(FATAL_ERROR "CMAKE_BUILD_TYPE should be \"Release\" when SFML_BUILD_FRAMEWORKS is TRUE") + return() + endif() + + # requirement #2 + if(NOT BUILD_SHARED_LIBS) + message(FATAL_ERROR "BUILD_SHARED_LIBS should be TRUE when SFML_BUILD_FRAMEWORKS is TRUE") + return() + endif() + endif() + + # configure Xcode templates + if(CMAKE_OSX_ARCHITECTURES) + # maybe multiple arches are present in CMAKE_OSX_ARCHITECTURES + # we simply need to replace ';' by ' ' (space) and store the result in XCODE_TEMPLATES_ARCH + string(REPLACE ";" " " XCODE_TEMPLATES_ARCH "${CMAKE_OSX_ARCHITECTURES}") + else() + # no arch was provided to cmake, so we use the default one + set(XCODE_TEMPLATES_ARCH "\$(NATIVE_ARCH_ACTUAL)") + endif() +endif() + +if(SFML_OS_LINUX OR SFML_OS_FREEBSD) + set(PKGCONFIG_DIR lib${LIB_SUFFIX}/pkgconfig) + if(SFML_OS_FREEBSD) + set(PKGCONFIG_DIR libdata/pkgconfig) + endif() + if(BUILD_SHARED_LIBS) + sfml_set_option(SFML_INSTALL_PKGCONFIG_FILES FALSE BOOL "TRUE to automatically install pkg-config files so other projects can find SFML") + if(SFML_INSTALL_PKGCONFIG_FILES) + foreach(sfml_module IN ITEMS all system window graphics audio network) + CONFIGURE_FILE( + "tools/pkg-config/sfml-${sfml_module}.pc.in" + "tools/pkg-config/sfml-${sfml_module}.pc" + @ONLY) + INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/tools/pkg-config/sfml-${sfml_module}.pc" + DESTINATION "${CMAKE_INSTALL_PREFIX}/${PKGCONFIG_DIR}") + endforeach() + endif() + else() + if(SFML_INSTALL_PKGCONFIG_FILES) + message(WARNING "No pkg-config files are provided for the static SFML libraries (SFML_INSTALL_PKGCONFIG_FILES will be ignored).") + endif() + endif() +endif() + +# enable project folders +set_property(GLOBAL PROPERTY USE_FOLDERS ON) +set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake") + +# add the subdirectories +add_subdirectory(src/SFML) +if(SFML_BUILD_EXAMPLES) + add_subdirectory(examples) +endif() +if(SFML_BUILD_DOC) + add_subdirectory(doc) +endif() + +# setup the install rules +if(NOT SFML_BUILD_FRAMEWORKS) + install(DIRECTORY include + DESTINATION . + COMPONENT devel + FILES_MATCHING PATTERN "*.hpp" PATTERN "*.inl") +else() + # find only "root" headers + file(GLOB SFML_HEADERS RELATIVE ${PROJECT_SOURCE_DIR} "include/SFML/*") + + # in fact we have to fool cmake to copy all the headers in subdirectories + # to do that we have to add the "root" headers to the PUBLIC_HEADER + # then we can run a post script to copy the remaining headers + + # we need a dummy file in order to compile the framework + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp + COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp) + + set(SFML_SOURCES ${SFML_HEADERS}) + list(APPEND SFML_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp) + + # create SFML.framework + add_library(SFML ${SFML_SOURCES}) + + # edit target properties + set_target_properties(SFML PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} + MACOSX_FRAMEWORK_IDENTIFIER org.sfml-dev.SFML + MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} + MACOSX_FRAMEWORK_BUNDLE_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} + PUBLIC_HEADER "${SFML_HEADERS}") + + # add the remaining headers + add_custom_command(TARGET SFML + POST_BUILD + COMMAND cp -r ${PROJECT_SOURCE_DIR}/include/SFML/* $/Headers) + + # adapt install directory to allow distributing dylibs/frameworks in user’s frameworks/application bundle + # NOTE: it's not required to link agains SFML.framework + set_target_properties(SFML PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path/../Frameworks") + + # install rule + install(TARGETS SFML + FRAMEWORK DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX} + COMPONENT devel) +endif() + +install(FILES license.txt DESTINATION ${INSTALL_MISC_DIR}) +install(FILES readme.txt DESTINATION ${INSTALL_MISC_DIR}) +if(NOT SFML_OS_ANDROID) + install(FILES cmake/Modules/FindSFML.cmake DESTINATION ${INSTALL_MISC_DIR}/cmake/Modules) +endif() + +# install 3rd-party libraries and tools +if(SFML_OS_WINDOWS) + + # install the binaries of SFML dependencies + if(ARCH_32BITS) + install(DIRECTORY extlibs/bin/x86/ DESTINATION bin) + if(SFML_COMPILER_MSVC) + install(DIRECTORY extlibs/libs-msvc/x86/ DESTINATION lib) + else() + install(DIRECTORY extlibs/libs-mingw/x86/ DESTINATION lib) + endif() + elseif(ARCH_64BITS) + install(DIRECTORY extlibs/bin/x64/ DESTINATION bin) + if(SFML_COMPILER_MSVC) + install(DIRECTORY extlibs/libs-msvc/x64/ DESTINATION lib) + else() + install(DIRECTORY extlibs/libs-mingw/x64/ DESTINATION lib) + endif() + endif() + +elseif(SFML_OS_MACOSX) + + # install the non-standard frameworks SFML depends on + install(DIRECTORY extlibs/libs-osx/Frameworks/sndfile.framework DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX}) + install(DIRECTORY extlibs/libs-osx/Frameworks/freetype.framework DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX}) + + # install the Xcode templates if requested + if(SFML_INSTALL_XCODE_TEMPLATES) + configure_file( + "tools/xcode/templates/SFML/SFML Compiler.xctemplate/TemplateInfo.plist.in" + "${CMAKE_CURRENT_BINARY_DIR}/tools/xcode/templates/SFML/SFML Compiler.xctemplate/TemplateInfo.plist" + @ONLY) + install(DIRECTORY "tools/xcode/templates/SFML" "${CMAKE_CURRENT_BINARY_DIR}/tools/xcode/templates/SFML" + DESTINATION /Library/Developer/Xcode/Templates + PATTERN "*.in" EXCLUDE) + endif() + +elseif(SFML_OS_IOS) + + # fix CMake install rules broken for iOS (see http://public.kitware.com/Bug/view.php?id=12506) + if(SFML_OS_IOS) + install(DIRECTORY "${CMAKE_BINARY_DIR}/lib/\$ENV{CONFIGURATION}/" DESTINATION lib${LIB_SUFFIX}) + endif() + + # since the iOS libraries are built as static, we must install the SFML dependencies + # too so that the end user can easily link them to its final application + install(FILES extlibs/libs-ios/libfreetype.a extlibs/libs-ios/libjpeg.a DESTINATION lib) + +elseif(SFML_OS_ANDROID) + + # install extlibs + install(DIRECTORY extlibs/libs-android/${ANDROID_ABI} DESTINATION extlibs/lib) + install(FILES extlibs/Android.mk DESTINATION extlibs) + + # install Android.mk so the NDK knows how to set up SFML + install(FILES src/SFML/Android.mk DESTINATION .) + +endif() diff --git a/cmake/Config.cmake b/cmake/Config.cmake index 625fd681..bb726ba3 100644 --- a/cmake/Config.cmake +++ b/cmake/Config.cmake @@ -1,117 +1,117 @@ -# detect the OS -if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(SFML_OS_WINDOWS 1) - - # don't use the OpenGL ES implementation on Windows - set(OPENGL_ES 0) - - # detect the architecture (note: this test won't work for cross-compilation) - include(CheckTypeSize) - check_type_size(void* SIZEOF_VOID_PTR) - if("${SIZEOF_VOID_PTR}" STREQUAL "4") - set(ARCH_32BITS 1) - elseif("${SIZEOF_VOID_PTR}" STREQUAL "8") - set(ARCH_64BITS 1) - else() - message(FATAL_ERROR "Unsupported architecture") - return() +# detect the OS +if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + set(SFML_OS_WINDOWS 1) + + # don't use the OpenGL ES implementation on Windows + set(OPENGL_ES 0) + + # detect the architecture (note: this test won't work for cross-compilation) + include(CheckTypeSize) + check_type_size(void* SIZEOF_VOID_PTR) + if("${SIZEOF_VOID_PTR}" STREQUAL "4") + set(ARCH_32BITS 1) + elseif("${SIZEOF_VOID_PTR}" STREQUAL "8") + set(ARCH_64BITS 1) + else() + message(FATAL_ERROR "Unsupported architecture") + return() endif() -elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(SFML_OS_UNIX 1) - if(ANDROID) - set(SFML_OS_ANDROID 1) - # use the OpenGL ES implementation on Android - set(OPENGL_ES 1) - else() - set(SFML_OS_LINUX 1) - # don't use the OpenGL ES implementation on Linux - set(OPENGL_ES 0) + if(ANDROID) + set(SFML_OS_ANDROID 1) + # use the OpenGL ES implementation on Android + set(OPENGL_ES 1) + else() + set(SFML_OS_LINUX 1) + # don't use the OpenGL ES implementation on Linux + set(OPENGL_ES 0) endif() -elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - set(SFML_OS_FREEBSD 1) - # don't use the OpenGL ES implementation on FreeBSD - set(OPENGL_ES 0) +elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + set(SFML_OS_FREEBSD 1) + # don't use the OpenGL ES implementation on FreeBSD + set(OPENGL_ES 0) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if(IOS) set(SFML_OS_IOS 1) - - # set the target framework and platforms - set(CMAKE_OSX_SYSROOT "iphoneos") - set(CMAKE_OSX_ARCHITECTURES "armv6;armv7;i386") - set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos;-iphonesimulator") - # help the compiler detection script below - set(CMAKE_COMPILER_IS_GNUCXX 1) - - # use the OpenGL ES implementation on iOS - set(OPENGL_ES 1) - else() - set(SFML_OS_MACOSX 1) - - # don't use the OpenGL ES implementation on Mac OS X - set(OPENGL_ES 0) - - # detect OS X version. (use '/usr/bin/sw_vers -productVersion' to extract V from '10.V.x'.) - EXEC_PROGRAM(/usr/bin/sw_vers ARGS -productVersion OUTPUT_VARIABLE MACOSX_VERSION_RAW) + # set the target framework and platforms + set(CMAKE_OSX_SYSROOT "iphoneos") + set(CMAKE_OSX_ARCHITECTURES "armv6;armv7;i386") + set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos;-iphonesimulator") + + # help the compiler detection script below + set(CMAKE_COMPILER_IS_GNUCXX 1) + + # use the OpenGL ES implementation on iOS + set(OPENGL_ES 1) + else() + set(SFML_OS_MACOSX 1) + + # don't use the OpenGL ES implementation on Mac OS X + set(OPENGL_ES 0) + + # detect OS X version. (use '/usr/bin/sw_vers -productVersion' to extract V from '10.V.x'.) + EXEC_PROGRAM(/usr/bin/sw_vers ARGS -productVersion OUTPUT_VARIABLE MACOSX_VERSION_RAW) STRING(REGEX REPLACE "10\\.([0-9]+).*" "\\1" MACOSX_VERSION "${MACOSX_VERSION_RAW}") - if(${MACOSX_VERSION} LESS 7) - message(FATAL_ERROR "Unsupported version of OS X: ${MACOSX_VERSION_RAW}") + if(${MACOSX_VERSION} LESS 7) + message(FATAL_ERROR "Unsupported version of OS X: ${MACOSX_VERSION_RAW}") return() endif() - endif() -elseif(${CMAKE_SYSTEM_NAME} MATCHES "Android") - set(SFML_OS_ANDROID 1) - - # use the OpenGL ES implementation on Android - set(OPENGL_ES 1) -else() - message(FATAL_ERROR "Unsupported operating system") - return() -endif() - -# detect the compiler and its version -# Note: on some platforms (OS X), CMAKE_COMPILER_IS_GNUCXX is true -# even when CLANG is used, therefore the Clang test is done first -if(CMAKE_CXX_COMPILER MATCHES ".*clang[+][+]" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - # CMAKE_CXX_COMPILER_ID is an internal CMake variable subject to change, - # but there is no other way to detect CLang at the moment - set(SFML_COMPILER_CLANG 1) - execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "--version" OUTPUT_VARIABLE CLANG_VERSION_OUTPUT) - string(REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" SFML_CLANG_VERSION "${CLANG_VERSION_OUTPUT}") -elseif(CMAKE_COMPILER_IS_GNUCXX) - set(SFML_COMPILER_GCC 1) - execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "-dumpversion" OUTPUT_VARIABLE GCC_VERSION_OUTPUT) - string(REGEX REPLACE "([0-9]+\\.[0-9]+).*" "\\1" SFML_GCC_VERSION "${GCC_VERSION_OUTPUT}") - execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "--version" OUTPUT_VARIABLE GCC_COMPILER_VERSION) - string(REGEX MATCHALL ".*(tdm[64]*-[1-9]).*" SFML_COMPILER_GCC_TDM "${GCC_COMPILER_VERSION}") - execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "-dumpmachine" OUTPUT_VARIABLE GCC_MACHINE) - string(STRIP "${GCC_MACHINE}" GCC_MACHINE) - if(${GCC_MACHINE} MATCHES ".*w64.*") - set(SFML_COMPILER_GCC_W64 1) - endif() -elseif(MSVC) - set(SFML_COMPILER_MSVC 1) - if(MSVC_VERSION EQUAL 1400) - set(SFML_MSVC_VERSION 8) - elseif(MSVC_VERSION EQUAL 1500) - set(SFML_MSVC_VERSION 9) - elseif(MSVC_VERSION EQUAL 1600) - set(SFML_MSVC_VERSION 10) - elseif(MSVC_VERSION EQUAL 1700) - set(SFML_MSVC_VERSION 11) - elseif(MSVC_VERSION EQUAL 1800) - set(SFML_MSVC_VERSION 12) - endif() -else() - message(FATAL_ERROR "Unsupported compiler") - return() -endif() + endif() +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Android") + set(SFML_OS_ANDROID 1) -# define the install directory for miscellaneous files + # use the OpenGL ES implementation on Android + set(OPENGL_ES 1) +else() + message(FATAL_ERROR "Unsupported operating system") + return() +endif() + +# detect the compiler and its version +# Note: on some platforms (OS X), CMAKE_COMPILER_IS_GNUCXX is true +# even when CLANG is used, therefore the Clang test is done first +if(CMAKE_CXX_COMPILER MATCHES ".*clang[+][+]" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # CMAKE_CXX_COMPILER_ID is an internal CMake variable subject to change, + # but there is no other way to detect CLang at the moment + set(SFML_COMPILER_CLANG 1) + execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "--version" OUTPUT_VARIABLE CLANG_VERSION_OUTPUT) + string(REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" SFML_CLANG_VERSION "${CLANG_VERSION_OUTPUT}") +elseif(CMAKE_COMPILER_IS_GNUCXX) + set(SFML_COMPILER_GCC 1) + execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "-dumpversion" OUTPUT_VARIABLE GCC_VERSION_OUTPUT) + string(REGEX REPLACE "([0-9]+\\.[0-9]+).*" "\\1" SFML_GCC_VERSION "${GCC_VERSION_OUTPUT}") + execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "--version" OUTPUT_VARIABLE GCC_COMPILER_VERSION) + string(REGEX MATCHALL ".*(tdm[64]*-[1-9]).*" SFML_COMPILER_GCC_TDM "${GCC_COMPILER_VERSION}") + execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "-dumpmachine" OUTPUT_VARIABLE GCC_MACHINE) + string(STRIP "${GCC_MACHINE}" GCC_MACHINE) + if(${GCC_MACHINE} MATCHES ".*w64.*") + set(SFML_COMPILER_GCC_W64 1) + endif() +elseif(MSVC) + set(SFML_COMPILER_MSVC 1) + if(MSVC_VERSION EQUAL 1400) + set(SFML_MSVC_VERSION 8) + elseif(MSVC_VERSION EQUAL 1500) + set(SFML_MSVC_VERSION 9) + elseif(MSVC_VERSION EQUAL 1600) + set(SFML_MSVC_VERSION 10) + elseif(MSVC_VERSION EQUAL 1700) + set(SFML_MSVC_VERSION 11) + elseif(MSVC_VERSION EQUAL 1800) + set(SFML_MSVC_VERSION 12) + endif() +else() + message(FATAL_ERROR "Unsupported compiler") + return() +endif() + +# define the install directory for miscellaneous files if(SFML_OS_WINDOWS OR SFML_OS_IOS) - set(INSTALL_MISC_DIR .) -elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX) - set(INSTALL_MISC_DIR share/SFML) -elseif(SFML_OS_ANDROID) - set(INSTALL_MISC_DIR ${ANDROID_NDK}/sources/sfml) -endif() + set(INSTALL_MISC_DIR .) +elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX) + set(INSTALL_MISC_DIR share/SFML) +elseif(SFML_OS_ANDROID) + set(INSTALL_MISC_DIR ${ANDROID_NDK}/sources/sfml) +endif() diff --git a/cmake/Macros.cmake b/cmake/Macros.cmake index b969930f..5e09a3cb 100644 --- a/cmake/Macros.cmake +++ b/cmake/Macros.cmake @@ -1,178 +1,178 @@ -include(CMakeParseArguments) - -# add a new target which is a SFML library -# ex: sfml_add_library(sfml-graphics -# SOURCES sprite.cpp image.cpp ... -# DEPENDS sfml-window sfml-system -# EXTERNAL_LIBS opengl freetype ...) -macro(sfml_add_library target) - - # parse the arguments - cmake_parse_arguments(THIS "" "" "SOURCES;DEPENDS;EXTERNAL_LIBS" ${ARGN}) +include(CMakeParseArguments) + +# add a new target which is a SFML library +# ex: sfml_add_library(sfml-graphics +# SOURCES sprite.cpp image.cpp ... +# DEPENDS sfml-window sfml-system +# EXTERNAL_LIBS opengl freetype ...) +macro(sfml_add_library target) + + # parse the arguments + cmake_parse_arguments(THIS "" "" "SOURCES;DEPENDS;EXTERNAL_LIBS" ${ARGN}) + + # create the target + add_library(${target} ${THIS_SOURCES}) + + # define the export symbol of the module + string(REPLACE "-" "_" NAME_UPPER "${target}") + string(TOUPPER "${NAME_UPPER}" NAME_UPPER) + set_target_properties(${target} PROPERTIES DEFINE_SYMBOL ${NAME_UPPER}_EXPORTS) + + # adjust the output file prefix/suffix to match our conventions + if(BUILD_SHARED_LIBS) + if(SFML_OS_WINDOWS) + # include the major version number in Windows shared library names (but not import library names) + set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -d) + set_target_properties(${target} PROPERTIES SUFFIX "-${VERSION_MAJOR}${CMAKE_SHARED_LIBRARY_SUFFIX}") + else() + set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -d) + endif() + if (SFML_OS_WINDOWS AND SFML_COMPILER_GCC) + # on Windows/gcc get rid of "lib" prefix for shared libraries, + # and transform the ".dll.a" suffix into ".a" for import libraries + set_target_properties(${target} PROPERTIES PREFIX "") + set_target_properties(${target} PROPERTIES IMPORT_SUFFIX ".a") + endif() + else() + set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -s-d) + set_target_properties(${target} PROPERTIES RELEASE_POSTFIX -s) + set_target_properties(${target} PROPERTIES MINSIZEREL_POSTFIX -s) + endif() + + # set the version and soversion of the target (for compatible systems -- mostly Linuxes) + # except for Android which strips soversion suffixes + if(NOT SFML_OS_ANDROID) + set_target_properties(${target} PROPERTIES SOVERSION ${VERSION_MAJOR}) + set_target_properties(${target} PROPERTIES VERSION ${VERSION_MAJOR}.${VERSION_MINOR}) + endif() + + # set the target's folder (for IDEs that support it, e.g. Visual Studio) + set_target_properties(${target} PROPERTIES FOLDER "SFML") + + # for gcc >= 4.0 on Windows, apply the SFML_USE_STATIC_STD_LIBS option if it is enabled + if(SFML_OS_WINDOWS AND SFML_COMPILER_GCC AND NOT SFML_GCC_VERSION VERSION_LESS "4") + if(SFML_USE_STATIC_STD_LIBS AND NOT SFML_COMPILER_GCC_TDM) + set_target_properties(${target} PROPERTIES LINK_FLAGS "-static-libgcc -static-libstdc++") + elseif(NOT SFML_USE_STATIC_STD_LIBS AND SFML_COMPILER_GCC_TDM) + set_target_properties(${target} PROPERTIES LINK_FLAGS "-shared-libgcc -shared-libstdc++") + endif() + endif() + + # if using gcc >= 4.0 or clang >= 3.0 on a non-Windows platform, we must hide public symbols by default + # (exported ones are explicitely marked) + if(NOT SFML_OS_WINDOWS AND ((SFML_COMPILER_GCC AND NOT SFML_GCC_VERSION VERSION_LESS "4") OR (SFML_COMPILER_CLANG AND NOT SFML_CLANG_VERSION VERSION_LESS "3"))) + set_target_properties(${target} PROPERTIES COMPILE_FLAGS -fvisibility=hidden) + endif() + + # link the target to its SFML dependencies + if(THIS_DEPENDS) + target_link_libraries(${target} ${THIS_DEPENDS}) + endif() + + # build frameworks or dylibs + if(SFML_OS_MACOSX AND BUILD_SHARED_LIBS) + if(SFML_BUILD_FRAMEWORKS) + # adapt target to build frameworks instead of dylibs + set_target_properties(${target} PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} + MACOSX_FRAMEWORK_IDENTIFIER org.sfml-dev.${target} + MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} + MACOSX_FRAMEWORK_BUNDLE_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) + endif() + + # adapt install directory to allow distributing dylibs/frameworks in user’s frameworks/application bundle + set_target_properties(${target} PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path/../Frameworks") + endif() + + # enable automatic reference counting on iOS + if (SFML_OS_IOS) + set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES) + endif() + + # sfml-activity library is our bootstrap activity and must not depend on stlport_shared + # (otherwise Android will fail to load it) + if (SFML_OS_ANDROID) + if (${target} MATCHES "sfml-activity") + set_target_properties(${target} PROPERTIES COMPILE_FLAGS -fpermissive) + set_target_properties(${target} PROPERTIES LINK_FLAGS "-landroid -llog") + set(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY_WITHOUT_STLPORT}) + else() + set(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY_WITH_STLPORT}) + endif() + endif() + + # link the target to its external dependencies + if(THIS_EXTERNAL_LIBS) + target_link_libraries(${target} ${THIS_EXTERNAL_LIBS}) + endif() + + # add the install rule + install(TARGETS ${target} + RUNTIME DESTINATION bin COMPONENT bin + LIBRARY DESTINATION lib${LIB_SUFFIX} COMPONENT bin + ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel + FRAMEWORK DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX} COMPONENT bin) +endmacro() + +# add a new target which is a SFML example +# ex: sfml_add_example(ftp +# SOURCES ftp.cpp ... +# DEPENDS sfml-network sfml-system) +macro(sfml_add_example target) + + # parse the arguments + cmake_parse_arguments(THIS "GUI_APP" "" "SOURCES;DEPENDS" ${ARGN}) + + # set a source group for the source files + source_group("" FILES ${THIS_SOURCES}) - # create the target - add_library(${target} ${THIS_SOURCES}) - - # define the export symbol of the module - string(REPLACE "-" "_" NAME_UPPER "${target}") - string(TOUPPER "${NAME_UPPER}" NAME_UPPER) - set_target_properties(${target} PROPERTIES DEFINE_SYMBOL ${NAME_UPPER}_EXPORTS) - - # adjust the output file prefix/suffix to match our conventions - if(BUILD_SHARED_LIBS) - if(SFML_OS_WINDOWS) - # include the major version number in Windows shared library names (but not import library names) - set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -d) - set_target_properties(${target} PROPERTIES SUFFIX "-${VERSION_MAJOR}${CMAKE_SHARED_LIBRARY_SUFFIX}") - else() - set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -d) - endif() - if (SFML_OS_WINDOWS AND SFML_COMPILER_GCC) - # on Windows/gcc get rid of "lib" prefix for shared libraries, - # and transform the ".dll.a" suffix into ".a" for import libraries - set_target_properties(${target} PROPERTIES PREFIX "") - set_target_properties(${target} PROPERTIES IMPORT_SUFFIX ".a") - endif() - else() - set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -s-d) - set_target_properties(${target} PROPERTIES RELEASE_POSTFIX -s) - set_target_properties(${target} PROPERTIES MINSIZEREL_POSTFIX -s) - endif() - - # set the version and soversion of the target (for compatible systems -- mostly Linuxes) - # except for Android which strips soversion suffixes - if(NOT SFML_OS_ANDROID) - set_target_properties(${target} PROPERTIES SOVERSION ${VERSION_MAJOR}) - set_target_properties(${target} PROPERTIES VERSION ${VERSION_MAJOR}.${VERSION_MINOR}) - endif() - - # set the target's folder (for IDEs that support it, e.g. Visual Studio) - set_target_properties(${target} PROPERTIES FOLDER "SFML") - - # for gcc >= 4.0 on Windows, apply the SFML_USE_STATIC_STD_LIBS option if it is enabled - if(SFML_OS_WINDOWS AND SFML_COMPILER_GCC AND NOT SFML_GCC_VERSION VERSION_LESS "4") - if(SFML_USE_STATIC_STD_LIBS AND NOT SFML_COMPILER_GCC_TDM) - set_target_properties(${target} PROPERTIES LINK_FLAGS "-static-libgcc -static-libstdc++") - elseif(NOT SFML_USE_STATIC_STD_LIBS AND SFML_COMPILER_GCC_TDM) - set_target_properties(${target} PROPERTIES LINK_FLAGS "-shared-libgcc -shared-libstdc++") - endif() - endif() - - # if using gcc >= 4.0 or clang >= 3.0 on a non-Windows platform, we must hide public symbols by default - # (exported ones are explicitely marked) - if(NOT SFML_OS_WINDOWS AND ((SFML_COMPILER_GCC AND NOT SFML_GCC_VERSION VERSION_LESS "4") OR (SFML_COMPILER_CLANG AND NOT SFML_CLANG_VERSION VERSION_LESS "3"))) - set_target_properties(${target} PROPERTIES COMPILE_FLAGS -fvisibility=hidden) - endif() - - # link the target to its SFML dependencies - if(THIS_DEPENDS) - target_link_libraries(${target} ${THIS_DEPENDS}) - endif() - - # build frameworks or dylibs - if(SFML_OS_MACOSX AND BUILD_SHARED_LIBS) - if(SFML_BUILD_FRAMEWORKS) - # adapt target to build frameworks instead of dylibs - set_target_properties(${target} PROPERTIES - FRAMEWORK TRUE - FRAMEWORK_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} - MACOSX_FRAMEWORK_IDENTIFIER org.sfml-dev.${target} - MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} - MACOSX_FRAMEWORK_BUNDLE_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) - endif() - - # adapt install directory to allow distributing dylibs/frameworks in user’s frameworks/application bundle - set_target_properties(${target} PROPERTIES - BUILD_WITH_INSTALL_RPATH 1 - INSTALL_NAME_DIR "@executable_path/../Frameworks") - endif() - - # enable automatic reference counting on iOS - if (SFML_OS_IOS) - set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES) - endif() - - # sfml-activity library is our bootstrap activity and must not depend on stlport_shared - # (otherwise Android will fail to load it) - if (SFML_OS_ANDROID) - if (${target} MATCHES "sfml-activity") - set_target_properties(${target} PROPERTIES COMPILE_FLAGS -fpermissive) - set_target_properties(${target} PROPERTIES LINK_FLAGS "-landroid -llog") - set(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY_WITHOUT_STLPORT}) - else() - set(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY_WITH_STLPORT}) - endif() - endif() - - # link the target to its external dependencies - if(THIS_EXTERNAL_LIBS) - target_link_libraries(${target} ${THIS_EXTERNAL_LIBS}) - endif() - - # add the install rule - install(TARGETS ${target} - RUNTIME DESTINATION bin COMPONENT bin - LIBRARY DESTINATION lib${LIB_SUFFIX} COMPONENT bin - ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel - FRAMEWORK DESTINATION ${CMAKE_INSTALL_FRAMEWORK_PREFIX} COMPONENT bin) -endmacro() - -# add a new target which is a SFML example -# ex: sfml_add_example(ftp -# SOURCES ftp.cpp ... -# DEPENDS sfml-network sfml-system) -macro(sfml_add_example target) - - # parse the arguments - cmake_parse_arguments(THIS "GUI_APP" "" "SOURCES;DEPENDS" ${ARGN}) - - # set a source group for the source files - source_group("" FILES ${THIS_SOURCES}) - # create the target if(THIS_GUI_APP AND SFML_OS_WINDOWS) - add_executable(${target} WIN32 ${THIS_SOURCES}) - target_link_libraries(${target} sfml-main) - else() - add_executable(${target} ${THIS_SOURCES}) - endif() - - # set the debug suffix - set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -d) - - # set the target's folder (for IDEs that support it, e.g. Visual Studio) - set_target_properties(${target} PROPERTIES FOLDER "Examples") - - # for gcc >= 4.0 on Windows, apply the SFML_USE_STATIC_STD_LIBS option if it is enabled - if(SFML_OS_WINDOWS AND SFML_COMPILER_GCC AND NOT SFML_GCC_VERSION VERSION_LESS "4") - if(SFML_USE_STATIC_STD_LIBS AND NOT SFML_COMPILER_GCC_TDM) - set_target_properties(${target} PROPERTIES LINK_FLAGS "-static-libgcc -static-libstdc++") - elseif(NOT SFML_USE_STATIC_STD_LIBS AND SFML_COMPILER_GCC_TDM) - set_target_properties(${target} PROPERTIES LINK_FLAGS "-shared-libgcc -shared-libstdc++") - endif() - endif() - - # link the target to its SFML dependencies - if(THIS_DEPENDS) - target_link_libraries(${target} ${THIS_DEPENDS}) - endif() - - # add the install rule - install(TARGETS ${target} - RUNTIME DESTINATION ${INSTALL_MISC_DIR}/examples/${target} COMPONENT examples - BUNDLE DESTINATION ${INSTALL_MISC_DIR}/examples/${target} COMPONENT examples) - - # install the example's source code - install(FILES ${THIS_SOURCES} - DESTINATION ${INSTALL_MISC_DIR}/examples/${target} - COMPONENT examples) - - # install the example's resources as well - set(EXAMPLE_RESOURCES "${CMAKE_SOURCE_DIR}/examples/${target}/resources") - if(EXISTS ${EXAMPLE_RESOURCES}) - install(DIRECTORY ${EXAMPLE_RESOURCES} - DESTINATION ${INSTALL_MISC_DIR}/examples/${target} - COMPONENT examples) - endif() - -endmacro() + add_executable(${target} WIN32 ${THIS_SOURCES}) + target_link_libraries(${target} sfml-main) + else() + add_executable(${target} ${THIS_SOURCES}) + endif() + + # set the debug suffix + set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -d) + + # set the target's folder (for IDEs that support it, e.g. Visual Studio) + set_target_properties(${target} PROPERTIES FOLDER "Examples") + + # for gcc >= 4.0 on Windows, apply the SFML_USE_STATIC_STD_LIBS option if it is enabled + if(SFML_OS_WINDOWS AND SFML_COMPILER_GCC AND NOT SFML_GCC_VERSION VERSION_LESS "4") + if(SFML_USE_STATIC_STD_LIBS AND NOT SFML_COMPILER_GCC_TDM) + set_target_properties(${target} PROPERTIES LINK_FLAGS "-static-libgcc -static-libstdc++") + elseif(NOT SFML_USE_STATIC_STD_LIBS AND SFML_COMPILER_GCC_TDM) + set_target_properties(${target} PROPERTIES LINK_FLAGS "-shared-libgcc -shared-libstdc++") + endif() + endif() + + # link the target to its SFML dependencies + if(THIS_DEPENDS) + target_link_libraries(${target} ${THIS_DEPENDS}) + endif() + + # add the install rule + install(TARGETS ${target} + RUNTIME DESTINATION ${INSTALL_MISC_DIR}/examples/${target} COMPONENT examples + BUNDLE DESTINATION ${INSTALL_MISC_DIR}/examples/${target} COMPONENT examples) + + # install the example's source code + install(FILES ${THIS_SOURCES} + DESTINATION ${INSTALL_MISC_DIR}/examples/${target} + COMPONENT examples) + + # install the example's resources as well + set(EXAMPLE_RESOURCES "${CMAKE_SOURCE_DIR}/examples/${target}/resources") + if(EXISTS ${EXAMPLE_RESOURCES}) + install(DIRECTORY ${EXAMPLE_RESOURCES} + DESTINATION ${INSTALL_MISC_DIR}/examples/${target} + COMPONENT examples) + endif() + +endmacro() diff --git a/cmake/Modules/FindEGL.cmake b/cmake/Modules/FindEGL.cmake index eb90be48..be9eda07 100644 --- a/cmake/Modules/FindEGL.cmake +++ b/cmake/Modules/FindEGL.cmake @@ -1,14 +1,14 @@ -# -# Try to find EGL library and include path. -# Once done this will define -# -# EGL_FOUND -# EGL_INCLUDE_PATH -# EGL_LIBRARY -# - -find_path(EGL_INCLUDE_DIR EGL/egl.h) -find_library(EGL_LIBRARY NAMES EGL) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(EGL DEFAULT_MSG EGL_LIBRARY EGL_INCLUDE_DIR) +# +# Try to find EGL library and include path. +# Once done this will define +# +# EGL_FOUND +# EGL_INCLUDE_PATH +# EGL_LIBRARY +# + +find_path(EGL_INCLUDE_DIR EGL/egl.h) +find_library(EGL_LIBRARY NAMES EGL) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(EGL DEFAULT_MSG EGL_LIBRARY EGL_INCLUDE_DIR) diff --git a/cmake/Modules/FindGLES.cmake b/cmake/Modules/FindGLES.cmake index 8149e2ec..948e9bf9 100644 --- a/cmake/Modules/FindGLES.cmake +++ b/cmake/Modules/FindGLES.cmake @@ -1,14 +1,14 @@ -# -# Try to find GLES library and include path. -# Once done this will define -# -# GLES_FOUND -# GLES_INCLUDE_PATH -# GLES_LIBRARY -# - -find_path(GLES_INCLUDE_DIR GLES/gl.h) -find_library(GLES_LIBRARY NAMES GLESv1_CM) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GLES DEFAULT_MSG GLES_LIBRARY GLES_INCLUDE_DIR) +# +# Try to find GLES library and include path. +# Once done this will define +# +# GLES_FOUND +# GLES_INCLUDE_PATH +# GLES_LIBRARY +# + +find_path(GLES_INCLUDE_DIR GLES/gl.h) +find_library(GLES_LIBRARY NAMES GLESv1_CM) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GLES DEFAULT_MSG GLES_LIBRARY GLES_INCLUDE_DIR) diff --git a/cmake/Modules/FindGLEW.cmake b/cmake/Modules/FindGLEW.cmake index 55464879..17c3c39c 100644 --- a/cmake/Modules/FindGLEW.cmake +++ b/cmake/Modules/FindGLEW.cmake @@ -1,65 +1,65 @@ -# -# Try to find GLEW library and include path. -# Once done this will define -# -# GLEW_FOUND -# GLEW_INCLUDE_PATH -# GLEW_LIBRARY -# - -IF (WIN32) - FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h - $ENV{PROGRAMFILES}/GLEW/include - ${GLEW_ROOT_DIR}/include - DOC "The directory where GL/glew.h resides") - - IF (NV_SYSTEM_PROCESSOR STREQUAL "AMD64") - FIND_LIBRARY( GLEW_LIBRARY - NAMES glew64 glew64s - PATHS - $ENV{PROGRAMFILES}/GLEW/lib - ${PROJECT_SOURCE_DIR}/src/nvgl/glew/bin - ${PROJECT_SOURCE_DIR}/src/nvgl/glew/lib - DOC "The GLEW library (64-bit)" - ) - ELSE(NV_SYSTEM_PROCESSOR STREQUAL "AMD64") - FIND_LIBRARY( GLEW_LIBRARY - NAMES glew GLEW glew32 glew32s - PATHS - $ENV{PROGRAMFILES}/GLEW/lib - ${PROJECT_SOURCE_DIR}/src/nvgl/glew/bin - ${PROJECT_SOURCE_DIR}/src/nvgl/glew/lib - DOC "The GLEW library" - ) - ENDIF(NV_SYSTEM_PROCESSOR STREQUAL "AMD64") -ELSE (WIN32) - FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h - /usr/include - /usr/local/include - /sw/include - /opt/local/include - ${GLEW_ROOT_DIR}/include - DOC "The directory where GL/glew.h resides") - - FIND_LIBRARY( GLEW_LIBRARY - NAMES GLEW glew - PATHS - /usr/lib64 - /usr/lib - /usr/local/lib64 - /usr/local/lib - /sw/lib - /opt/local/lib - ${GLEW_ROOT_DIR}/lib - DOC "The GLEW library") -ENDIF (WIN32) - -SET(GLEW_FOUND "NO") -IF (GLEW_INCLUDE_PATH AND GLEW_LIBRARY) - SET(GLEW_LIBRARIES ${GLEW_LIBRARY}) - SET(GLEW_FOUND "YES") -ENDIF (GLEW_INCLUDE_PATH AND GLEW_LIBRARY) - - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_LIBRARY GLEW_INCLUDE_PATH) +# +# Try to find GLEW library and include path. +# Once done this will define +# +# GLEW_FOUND +# GLEW_INCLUDE_PATH +# GLEW_LIBRARY +# + +IF (WIN32) + FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h + $ENV{PROGRAMFILES}/GLEW/include + ${GLEW_ROOT_DIR}/include + DOC "The directory where GL/glew.h resides") + + IF (NV_SYSTEM_PROCESSOR STREQUAL "AMD64") + FIND_LIBRARY( GLEW_LIBRARY + NAMES glew64 glew64s + PATHS + $ENV{PROGRAMFILES}/GLEW/lib + ${PROJECT_SOURCE_DIR}/src/nvgl/glew/bin + ${PROJECT_SOURCE_DIR}/src/nvgl/glew/lib + DOC "The GLEW library (64-bit)" + ) + ELSE(NV_SYSTEM_PROCESSOR STREQUAL "AMD64") + FIND_LIBRARY( GLEW_LIBRARY + NAMES glew GLEW glew32 glew32s + PATHS + $ENV{PROGRAMFILES}/GLEW/lib + ${PROJECT_SOURCE_DIR}/src/nvgl/glew/bin + ${PROJECT_SOURCE_DIR}/src/nvgl/glew/lib + DOC "The GLEW library" + ) + ENDIF(NV_SYSTEM_PROCESSOR STREQUAL "AMD64") +ELSE (WIN32) + FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h + /usr/include + /usr/local/include + /sw/include + /opt/local/include + ${GLEW_ROOT_DIR}/include + DOC "The directory where GL/glew.h resides") + + FIND_LIBRARY( GLEW_LIBRARY + NAMES GLEW glew + PATHS + /usr/lib64 + /usr/lib + /usr/local/lib64 + /usr/local/lib + /sw/lib + /opt/local/lib + ${GLEW_ROOT_DIR}/lib + DOC "The GLEW library") +ENDIF (WIN32) + +SET(GLEW_FOUND "NO") +IF (GLEW_INCLUDE_PATH AND GLEW_LIBRARY) + SET(GLEW_LIBRARIES ${GLEW_LIBRARY}) + SET(GLEW_FOUND "YES") +ENDIF (GLEW_INCLUDE_PATH AND GLEW_LIBRARY) + + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_LIBRARY GLEW_INCLUDE_PATH) diff --git a/cmake/Modules/FindSFML.cmake b/cmake/Modules/FindSFML.cmake index 9bed9b7e..68e18690 100644 --- a/cmake/Modules/FindSFML.cmake +++ b/cmake/Modules/FindSFML.cmake @@ -1,354 +1,354 @@ -# This script locates the SFML library -# ------------------------------------ -# -# Usage -# ----- -# -# When you try to locate the SFML libraries, you must specify which modules you want to use (system, window, graphics, network, audio, main). -# If none is given, the SFML_LIBRARIES variable will be empty and you'll end up linking to nothing. -# example: -# find_package(SFML COMPONENTS graphics window system) // find the graphics, window and system modules -# -# You can enforce a specific version, either MAJOR.MINOR or only MAJOR. -# If nothing is specified, the version won't be checked (ie. any version will be accepted). -# example: -# find_package(SFML COMPONENTS ...) // no specific version required -# find_package(SFML 2 COMPONENTS ...) // any 2.x version -# find_package(SFML 2.4 COMPONENTS ...) // version 2.4 or greater -# -# By default, the dynamic libraries of SFML will be found. To find the static ones instead, -# you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...). -# Since you have to link yourself all the SFML dependencies when you link it statically, the following -# additional variables are defined: SFML_XXX_DEPENDENCIES and SFML_DEPENDENCIES (see their detailed -# description below). -# In case of static linking, the SFML_STATIC macro will also be defined by this script. -# example: -# set(SFML_STATIC_LIBRARIES TRUE) -# find_package(SFML 2 COMPONENTS network system) -# -# On Mac OS X if SFML_STATIC_LIBRARIES is not set to TRUE then by default CMake will search for frameworks unless -# CMAKE_FIND_FRAMEWORK is set to "NEVER" for example. Please refer to CMake documentation for more details. -# Moreover, keep in mind that SFML frameworks are only available as release libraries unlike dylibs which -# are available for both release and debug modes. -# -# If SFML is not installed in a standard path, you can use the SFML_ROOT CMake (or environment) variable -# to tell CMake where SFML is. -# -# Output -# ------ -# -# This script defines the following variables: -# - For each specified module XXX (system, window, graphics, network, audio, main): -# - SFML_XXX_LIBRARY_DEBUG: the name of the debug library of the xxx module (set to SFML_XXX_LIBRARY_RELEASE is no debug version is found) -# - SFML_XXX_LIBRARY_RELEASE: the name of the release library of the xxx module (set to SFML_XXX_LIBRARY_DEBUG is no release version is found) -# - SFML_XXX_LIBRARY: the name of the library to link to for the xxx module (includes both debug and optimized names if necessary) -# - SFML_XXX_FOUND: true if either the debug or release library of the xxx module is found -# - SFML_XXX_DEPENDENCIES: the list of libraries the module depends on, in case of static linking -# - SFML_LIBRARIES: the list of all libraries corresponding to the required modules -# - SFML_FOUND: true if all the required modules are found -# - SFML_INCLUDE_DIR: the path where SFML headers are located (the directory containing the SFML/Config.hpp file) -# - SFML_DEPENDENCIES: the list of libraries SFML depends on, in case of static linking -# -# example: -# find_package(SFML 2 COMPONENTS system window graphics audio REQUIRED) -# include_directories(${SFML_INCLUDE_DIR}) -# add_executable(myapp ...) -# target_link_libraries(myapp ${SFML_LIBRARIES}) - -# define the SFML_STATIC macro if static build was chosen -if(SFML_STATIC_LIBRARIES) - add_definitions(-DSFML_STATIC) -endif() - -# define the list of search paths for headers and libraries -set(FIND_SFML_PATHS - ${SFML_ROOT} - $ENV{SFML_ROOT} - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw - /opt/local - /opt/csw - /opt) - -# find the SFML include directory -find_path(SFML_INCLUDE_DIR SFML/Config.hpp - PATH_SUFFIXES include - PATHS ${FIND_SFML_PATHS}) - -# check the version number -set(SFML_VERSION_OK TRUE) -if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR) - # extract the major and minor version numbers from SFML/Config.hpp - # we have to handle framework a little bit differently : - if("${SFML_INCLUDE_DIR}" MATCHES "SFML.framework") - set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/Headers/Config.hpp") - else() - set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp") - endif() - FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS) - STRING(REGEX MATCH ".*#define SFML_VERSION_MAJOR ([0-9]+).*#define SFML_VERSION_MINOR ([0-9]+).*" SFML_CONFIG_HPP_CONTENTS "${SFML_CONFIG_HPP_CONTENTS}") - STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}") - STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}") - math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10 + ${SFML_FIND_VERSION_MINOR}") - - # if we could extract them, compare with the requested version number - if (SFML_VERSION_MAJOR) - # transform version numbers to an integer - math(EXPR SFML_VERSION "${SFML_VERSION_MAJOR} * 10 + ${SFML_VERSION_MINOR}") - - # compare them - if(SFML_VERSION LESS SFML_REQUESTED_VERSION) - set(SFML_VERSION_OK FALSE) - endif() - else() - # SFML version is < 2.0 - if (SFML_REQUESTED_VERSION GREATER 19) - set(SFML_VERSION_OK FALSE) - set(SFML_VERSION_MAJOR 1) - set(SFML_VERSION_MINOR x) - endif() - endif() -endif() - -# find the requested modules -set(SFML_FOUND TRUE) # will be set to false if one of the required modules is not found -foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS}) - string(TOLOWER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_LOWER) - string(TOUPPER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_UPPER) - set(FIND_SFML_COMPONENT_NAME sfml-${FIND_SFML_COMPONENT_LOWER}) - - # no suffix for sfml-main, it is always a static library - if(FIND_SFML_COMPONENT_LOWER STREQUAL "main") - # release library - find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE - NAMES ${FIND_SFML_COMPONENT_NAME} - PATH_SUFFIXES lib64 lib - PATHS ${FIND_SFML_PATHS}) - - # debug library - find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG - NAMES ${FIND_SFML_COMPONENT_NAME}-d - PATH_SUFFIXES lib64 lib - PATHS ${FIND_SFML_PATHS}) - else() - # static release library - find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE - NAMES ${FIND_SFML_COMPONENT_NAME}-s - PATH_SUFFIXES lib64 lib - PATHS ${FIND_SFML_PATHS}) - - # static debug library - find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG - NAMES ${FIND_SFML_COMPONENT_NAME}-s-d - PATH_SUFFIXES lib64 lib - PATHS ${FIND_SFML_PATHS}) - - # dynamic release library - find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE - NAMES ${FIND_SFML_COMPONENT_NAME} - PATH_SUFFIXES lib64 lib - PATHS ${FIND_SFML_PATHS}) - - # dynamic debug library - find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG - NAMES ${FIND_SFML_COMPONENT_NAME}-d - PATH_SUFFIXES lib64 lib - PATHS ${FIND_SFML_PATHS}) - - # choose the entries that fit the requested link type - if(SFML_STATIC_LIBRARIES) - if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE) - set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE}) - endif() - if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG) - set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG}) - endif() - else() - if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE) - set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE}) - endif() - if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG) - set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG}) - endif() - endif() - endif() - - if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG OR SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) - # library found - set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND TRUE) - - # if both are found, set SFML_XXX_LIBRARY to contain both - if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) - set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY debug ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG} - optimized ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) - endif() - - # if only one debug/release variant is found, set the other to be equal to the found one - if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) - # debug and not release - set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}) - set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}) - endif() - if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG) - # release and not debug - set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) - set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) - endif() - else() - # library not found - set(SFML_FOUND FALSE) - set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND FALSE) - set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY "") - set(FIND_SFML_MISSING "${FIND_SFML_MISSING} SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY") - endif() - - # mark as advanced - MARK_AS_ADVANCED(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY - SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE - SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG - SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE - SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG - SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE - SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG) - - # add to the global list of libraries - set(SFML_LIBRARIES ${SFML_LIBRARIES} "${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY}") -endforeach() - -# in case of static linking, we must also define the list of all the dependencies of SFML libraries -if(SFML_STATIC_LIBRARIES) - - # detect the OS - if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(FIND_SFML_OS_WINDOWS 1) - elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(FIND_SFML_OS_LINUX 1) - elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - set(FIND_SFML_OS_FREEBSD 1) - elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(FIND_SFML_OS_MACOSX 1) - endif() - - # start with an empty list - set(SFML_DEPENDENCIES) - set(FIND_SFML_DEPENDENCIES_NOTFOUND) - - # macro that searches for a 3rd-party library - macro(find_sfml_dependency output friendlyname) - find_library(${output} NAMES ${ARGN} PATHS ${FIND_SFML_PATHS} PATH_SUFFIXES lib) - if(${${output}} STREQUAL "${output}-NOTFOUND") - unset(output) - set(FIND_SFML_DEPENDENCIES_NOTFOUND "${FIND_SFML_DEPENDENCIES_NOTFOUND} ${friendlyname}") - endif() - endmacro() - - # sfml-system - list(FIND SFML_FIND_COMPONENTS "system" FIND_SFML_SYSTEM_COMPONENT) - if(NOT ${FIND_SFML_SYSTEM_COMPONENT} EQUAL -1) - - # update the list -- these are only system libraries, no need to find them - if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD OR FIND_SFML_OS_MACOSX) - set(SFML_SYSTEM_DEPENDENCIES "pthread") - endif() - if(FIND_SFML_OS_LINUX) - set(SFML_SYSTEM_DEPENDENCIES "rt") - endif() - if(FIND_SFML_OS_WINDOWS) - set(SFML_SYSTEM_DEPENDENCIES "winmm") - endif() - set(SFML_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} ${SFML_DEPENDENCIES}) - endif() - - # sfml-network - list(FIND SFML_FIND_COMPONENTS "network" FIND_SFML_NETWORK_COMPONENT) - if(NOT ${FIND_SFML_NETWORK_COMPONENT} EQUAL -1) - - # update the list -- these are only system libraries, no need to find them - if(FIND_SFML_OS_WINDOWS) - set(SFML_NETWORK_DEPENDENCIES "ws2_32") - endif() - set(SFML_DEPENDENCIES ${SFML_NETWORK_DEPENDENCIES} ${SFML_DEPENDENCIES}) - endif() - - # sfml-window - list(FIND SFML_FIND_COMPONENTS "window" FIND_SFML_WINDOW_COMPONENT) - if(NOT ${FIND_SFML_WINDOW_COMPONENT} EQUAL -1) - - # find libraries - if(FIND_SFML_OS_LINUX) - find_sfml_dependency(X11_LIBRARY "X11" X11) - find_sfml_dependency(XRANDR_LIBRARY "Xrandr" Xrandr) - endif() - - # update the list - if(FIND_SFML_OS_WINDOWS) - set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "opengl32" "winmm" "gdi32") - elseif(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD) - set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY}) - if(FIND_SFML_OS_FREEBSD) - set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "usbhid") - endif() - elseif(FIND_SFML_OS_MACOSX) - set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "-framework OpenGL -framework Foundation -framework AppKit -framework IOKit -framework Carbon") - endif() - set(SFML_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} ${SFML_DEPENDENCIES}) - endif() - - # sfml-graphics - list(FIND SFML_FIND_COMPONENTS "graphics" FIND_SFML_GRAPHICS_COMPONENT) - if(NOT ${FIND_SFML_GRAPHICS_COMPONENT} EQUAL -1) - - # find libraries - find_sfml_dependency(FREETYPE_LIBRARY "FreeType" freetype) - find_sfml_dependency(GLEW_LIBRARY "GLEW" glew GLEW glew32 glew32s glew64 glew64s) - find_sfml_dependency(JPEG_LIBRARY "libjpeg" jpeg) - - # update the list - set(SFML_GRAPHICS_DEPENDENCIES ${FREETYPE_LIBRARY} ${GLEW_LIBRARY} ${JPEG_LIBRARY}) - set(SFML_DEPENDENCIES ${SFML_GRAPHICS_DEPENDENCIES} ${SFML_DEPENDENCIES}) - endif() - - # sfml-audio - list(FIND SFML_FIND_COMPONENTS "audio" FIND_SFML_AUDIO_COMPONENT) - if(NOT ${FIND_SFML_AUDIO_COMPONENT} EQUAL -1) - - # find libraries - find_sfml_dependency(OPENAL_LIBRARY "OpenAL" openal openal32) - find_sfml_dependency(SNDFILE_LIBRARY "libsndfile" sndfile) - - # update the list - set(SFML_AUDIO_DEPENDENCIES ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY}) - set(SFML_DEPENDENCIES ${SFML_AUDIO_DEPENDENCIES} ${SFML_DEPENDENCIES}) - endif() - -endif() - -# handle errors -if(NOT SFML_VERSION_OK) - # SFML version not ok - set(FIND_SFML_ERROR "SFML found but version too low (requested: ${SFML_FIND_VERSION}, found: ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR})") - set(SFML_FOUND FALSE) -elseif(SFML_STATIC_LIBRARIES AND FIND_SFML_DEPENDENCIES_NOTFOUND) - set(FIND_SFML_ERROR "SFML found but some of its dependencies are missing (${FIND_SFML_DEPENDENCIES_NOTFOUND})") - set(SFML_FOUND FALSE) -elseif(NOT SFML_FOUND) - # include directory or library not found - set(FIND_SFML_ERROR "Could NOT find SFML (missing: ${FIND_SFML_MISSING})") -endif() -if (NOT SFML_FOUND) - if(SFML_FIND_REQUIRED) - # fatal error - message(FATAL_ERROR ${FIND_SFML_ERROR}) - elseif(NOT SFML_FIND_QUIETLY) - # error but continue - message("${FIND_SFML_ERROR}") - endif() -endif() - -# handle success -if(SFML_FOUND) - message(STATUS "Found SFML ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR} in ${SFML_INCLUDE_DIR}") -endif() +# This script locates the SFML library +# ------------------------------------ +# +# Usage +# ----- +# +# When you try to locate the SFML libraries, you must specify which modules you want to use (system, window, graphics, network, audio, main). +# If none is given, the SFML_LIBRARIES variable will be empty and you'll end up linking to nothing. +# example: +# find_package(SFML COMPONENTS graphics window system) // find the graphics, window and system modules +# +# You can enforce a specific version, either MAJOR.MINOR or only MAJOR. +# If nothing is specified, the version won't be checked (ie. any version will be accepted). +# example: +# find_package(SFML COMPONENTS ...) // no specific version required +# find_package(SFML 2 COMPONENTS ...) // any 2.x version +# find_package(SFML 2.4 COMPONENTS ...) // version 2.4 or greater +# +# By default, the dynamic libraries of SFML will be found. To find the static ones instead, +# you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...). +# Since you have to link yourself all the SFML dependencies when you link it statically, the following +# additional variables are defined: SFML_XXX_DEPENDENCIES and SFML_DEPENDENCIES (see their detailed +# description below). +# In case of static linking, the SFML_STATIC macro will also be defined by this script. +# example: +# set(SFML_STATIC_LIBRARIES TRUE) +# find_package(SFML 2 COMPONENTS network system) +# +# On Mac OS X if SFML_STATIC_LIBRARIES is not set to TRUE then by default CMake will search for frameworks unless +# CMAKE_FIND_FRAMEWORK is set to "NEVER" for example. Please refer to CMake documentation for more details. +# Moreover, keep in mind that SFML frameworks are only available as release libraries unlike dylibs which +# are available for both release and debug modes. +# +# If SFML is not installed in a standard path, you can use the SFML_ROOT CMake (or environment) variable +# to tell CMake where SFML is. +# +# Output +# ------ +# +# This script defines the following variables: +# - For each specified module XXX (system, window, graphics, network, audio, main): +# - SFML_XXX_LIBRARY_DEBUG: the name of the debug library of the xxx module (set to SFML_XXX_LIBRARY_RELEASE is no debug version is found) +# - SFML_XXX_LIBRARY_RELEASE: the name of the release library of the xxx module (set to SFML_XXX_LIBRARY_DEBUG is no release version is found) +# - SFML_XXX_LIBRARY: the name of the library to link to for the xxx module (includes both debug and optimized names if necessary) +# - SFML_XXX_FOUND: true if either the debug or release library of the xxx module is found +# - SFML_XXX_DEPENDENCIES: the list of libraries the module depends on, in case of static linking +# - SFML_LIBRARIES: the list of all libraries corresponding to the required modules +# - SFML_FOUND: true if all the required modules are found +# - SFML_INCLUDE_DIR: the path where SFML headers are located (the directory containing the SFML/Config.hpp file) +# - SFML_DEPENDENCIES: the list of libraries SFML depends on, in case of static linking +# +# example: +# find_package(SFML 2 COMPONENTS system window graphics audio REQUIRED) +# include_directories(${SFML_INCLUDE_DIR}) +# add_executable(myapp ...) +# target_link_libraries(myapp ${SFML_LIBRARIES}) + +# define the SFML_STATIC macro if static build was chosen +if(SFML_STATIC_LIBRARIES) + add_definitions(-DSFML_STATIC) +endif() + +# define the list of search paths for headers and libraries +set(FIND_SFML_PATHS + ${SFML_ROOT} + $ENV{SFML_ROOT} + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw + /opt/local + /opt/csw + /opt) + +# find the SFML include directory +find_path(SFML_INCLUDE_DIR SFML/Config.hpp + PATH_SUFFIXES include + PATHS ${FIND_SFML_PATHS}) + +# check the version number +set(SFML_VERSION_OK TRUE) +if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR) + # extract the major and minor version numbers from SFML/Config.hpp + # we have to handle framework a little bit differently: + if("${SFML_INCLUDE_DIR}" MATCHES "SFML.framework") + set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/Headers/Config.hpp") + else() + set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp") + endif() + FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS) + STRING(REGEX MATCH ".*#define SFML_VERSION_MAJOR ([0-9]+).*#define SFML_VERSION_MINOR ([0-9]+).*" SFML_CONFIG_HPP_CONTENTS "${SFML_CONFIG_HPP_CONTENTS}") + STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}") + STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}") + math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10 + ${SFML_FIND_VERSION_MINOR}") + + # if we could extract them, compare with the requested version number + if (SFML_VERSION_MAJOR) + # transform version numbers to an integer + math(EXPR SFML_VERSION "${SFML_VERSION_MAJOR} * 10 + ${SFML_VERSION_MINOR}") + + # compare them + if(SFML_VERSION LESS SFML_REQUESTED_VERSION) + set(SFML_VERSION_OK FALSE) + endif() + else() + # SFML version is < 2.0 + if (SFML_REQUESTED_VERSION GREATER 19) + set(SFML_VERSION_OK FALSE) + set(SFML_VERSION_MAJOR 1) + set(SFML_VERSION_MINOR x) + endif() + endif() +endif() + +# find the requested modules +set(SFML_FOUND TRUE) # will be set to false if one of the required modules is not found +foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS}) + string(TOLOWER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_LOWER) + string(TOUPPER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_UPPER) + set(FIND_SFML_COMPONENT_NAME sfml-${FIND_SFML_COMPONENT_LOWER}) + + # no suffix for sfml-main, it is always a static library + if(FIND_SFML_COMPONENT_LOWER STREQUAL "main") + # release library + find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE + NAMES ${FIND_SFML_COMPONENT_NAME} + PATH_SUFFIXES lib64 lib + PATHS ${FIND_SFML_PATHS}) + + # debug library + find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG + NAMES ${FIND_SFML_COMPONENT_NAME}-d + PATH_SUFFIXES lib64 lib + PATHS ${FIND_SFML_PATHS}) + else() + # static release library + find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE + NAMES ${FIND_SFML_COMPONENT_NAME}-s + PATH_SUFFIXES lib64 lib + PATHS ${FIND_SFML_PATHS}) + + # static debug library + find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG + NAMES ${FIND_SFML_COMPONENT_NAME}-s-d + PATH_SUFFIXES lib64 lib + PATHS ${FIND_SFML_PATHS}) + + # dynamic release library + find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE + NAMES ${FIND_SFML_COMPONENT_NAME} + PATH_SUFFIXES lib64 lib + PATHS ${FIND_SFML_PATHS}) + + # dynamic debug library + find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG + NAMES ${FIND_SFML_COMPONENT_NAME}-d + PATH_SUFFIXES lib64 lib + PATHS ${FIND_SFML_PATHS}) + + # choose the entries that fit the requested link type + if(SFML_STATIC_LIBRARIES) + if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE) + set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE}) + endif() + if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG) + set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG}) + endif() + else() + if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE) + set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE}) + endif() + if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG) + set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG}) + endif() + endif() + endif() + + if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG OR SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) + # library found + set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND TRUE) + + # if both are found, set SFML_XXX_LIBRARY to contain both + if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) + set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY debug ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG} + optimized ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) + endif() + + # if only one debug/release variant is found, set the other to be equal to the found one + if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) + # debug and not release + set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}) + set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}) + endif() + if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG) + # release and not debug + set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) + set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) + endif() + else() + # library not found + set(SFML_FOUND FALSE) + set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND FALSE) + set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY "") + set(FIND_SFML_MISSING "${FIND_SFML_MISSING} SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY") + endif() + + # mark as advanced + MARK_AS_ADVANCED(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY + SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE + SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG + SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE + SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG + SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE + SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG) + + # add to the global list of libraries + set(SFML_LIBRARIES ${SFML_LIBRARIES} "${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY}") +endforeach() + +# in case of static linking, we must also define the list of all the dependencies of SFML libraries +if(SFML_STATIC_LIBRARIES) + + # detect the OS + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + set(FIND_SFML_OS_WINDOWS 1) + elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set(FIND_SFML_OS_LINUX 1) + elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + set(FIND_SFML_OS_FREEBSD 1) + elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(FIND_SFML_OS_MACOSX 1) + endif() + + # start with an empty list + set(SFML_DEPENDENCIES) + set(FIND_SFML_DEPENDENCIES_NOTFOUND) + + # macro that searches for a 3rd-party library + macro(find_sfml_dependency output friendlyname) + find_library(${output} NAMES ${ARGN} PATHS ${FIND_SFML_PATHS} PATH_SUFFIXES lib) + if(${${output}} STREQUAL "${output}-NOTFOUND") + unset(output) + set(FIND_SFML_DEPENDENCIES_NOTFOUND "${FIND_SFML_DEPENDENCIES_NOTFOUND} ${friendlyname}") + endif() + endmacro() + + # sfml-system + list(FIND SFML_FIND_COMPONENTS "system" FIND_SFML_SYSTEM_COMPONENT) + if(NOT ${FIND_SFML_SYSTEM_COMPONENT} EQUAL -1) + + # update the list -- these are only system libraries, no need to find them + if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD OR FIND_SFML_OS_MACOSX) + set(SFML_SYSTEM_DEPENDENCIES "pthread") + endif() + if(FIND_SFML_OS_LINUX) + set(SFML_SYSTEM_DEPENDENCIES "rt") + endif() + if(FIND_SFML_OS_WINDOWS) + set(SFML_SYSTEM_DEPENDENCIES "winmm") + endif() + set(SFML_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} ${SFML_DEPENDENCIES}) + endif() + + # sfml-network + list(FIND SFML_FIND_COMPONENTS "network" FIND_SFML_NETWORK_COMPONENT) + if(NOT ${FIND_SFML_NETWORK_COMPONENT} EQUAL -1) + + # update the list -- these are only system libraries, no need to find them + if(FIND_SFML_OS_WINDOWS) + set(SFML_NETWORK_DEPENDENCIES "ws2_32") + endif() + set(SFML_DEPENDENCIES ${SFML_NETWORK_DEPENDENCIES} ${SFML_DEPENDENCIES}) + endif() + + # sfml-window + list(FIND SFML_FIND_COMPONENTS "window" FIND_SFML_WINDOW_COMPONENT) + if(NOT ${FIND_SFML_WINDOW_COMPONENT} EQUAL -1) + + # find libraries + if(FIND_SFML_OS_LINUX) + find_sfml_dependency(X11_LIBRARY "X11" X11) + find_sfml_dependency(XRANDR_LIBRARY "Xrandr" Xrandr) + endif() + + # update the list + if(FIND_SFML_OS_WINDOWS) + set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "opengl32" "winmm" "gdi32") + elseif(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD) + set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY}) + if(FIND_SFML_OS_FREEBSD) + set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "usbhid") + endif() + elseif(FIND_SFML_OS_MACOSX) + set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "-framework OpenGL -framework Foundation -framework AppKit -framework IOKit -framework Carbon") + endif() + set(SFML_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} ${SFML_DEPENDENCIES}) + endif() + + # sfml-graphics + list(FIND SFML_FIND_COMPONENTS "graphics" FIND_SFML_GRAPHICS_COMPONENT) + if(NOT ${FIND_SFML_GRAPHICS_COMPONENT} EQUAL -1) + + # find libraries + find_sfml_dependency(FREETYPE_LIBRARY "FreeType" freetype) + find_sfml_dependency(GLEW_LIBRARY "GLEW" glew GLEW glew32 glew32s glew64 glew64s) + find_sfml_dependency(JPEG_LIBRARY "libjpeg" jpeg) + + # update the list + set(SFML_GRAPHICS_DEPENDENCIES ${FREETYPE_LIBRARY} ${GLEW_LIBRARY} ${JPEG_LIBRARY}) + set(SFML_DEPENDENCIES ${SFML_GRAPHICS_DEPENDENCIES} ${SFML_DEPENDENCIES}) + endif() + + # sfml-audio + list(FIND SFML_FIND_COMPONENTS "audio" FIND_SFML_AUDIO_COMPONENT) + if(NOT ${FIND_SFML_AUDIO_COMPONENT} EQUAL -1) + + # find libraries + find_sfml_dependency(OPENAL_LIBRARY "OpenAL" openal openal32) + find_sfml_dependency(SNDFILE_LIBRARY "libsndfile" sndfile) + + # update the list + set(SFML_AUDIO_DEPENDENCIES ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY}) + set(SFML_DEPENDENCIES ${SFML_AUDIO_DEPENDENCIES} ${SFML_DEPENDENCIES}) + endif() + +endif() + +# handle errors +if(NOT SFML_VERSION_OK) + # SFML version not ok + set(FIND_SFML_ERROR "SFML found but version too low (requested: ${SFML_FIND_VERSION}, found: ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR})") + set(SFML_FOUND FALSE) +elseif(SFML_STATIC_LIBRARIES AND FIND_SFML_DEPENDENCIES_NOTFOUND) + set(FIND_SFML_ERROR "SFML found but some of its dependencies are missing (${FIND_SFML_DEPENDENCIES_NOTFOUND})") + set(SFML_FOUND FALSE) +elseif(NOT SFML_FOUND) + # include directory or library not found + set(FIND_SFML_ERROR "Could NOT find SFML (missing: ${FIND_SFML_MISSING})") +endif() +if (NOT SFML_FOUND) + if(SFML_FIND_REQUIRED) + # fatal error + message(FATAL_ERROR ${FIND_SFML_ERROR}) + elseif(NOT SFML_FIND_QUIETLY) + # error but continue + message("${FIND_SFML_ERROR}") + endif() +endif() + +# handle success +if(SFML_FOUND) + message(STATUS "Found SFML ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR} in ${SFML_INCLUDE_DIR}") +endif() diff --git a/cmake/Modules/FindSndfile.cmake b/cmake/Modules/FindSndfile.cmake index 16c31dd9..ac8a6356 100644 --- a/cmake/Modules/FindSndfile.cmake +++ b/cmake/Modules/FindSndfile.cmake @@ -1,28 +1,28 @@ -# - Find sndfile -# Find the native sndfile includes and libraries -# -# SNDFILE_INCLUDE_DIR - where to find sndfile.h, etc. -# SNDFILE_LIBRARIES - List of libraries when using libsndfile. -# SNDFILE_FOUND - True if libsndfile found. - -if(SNDFILE_INCLUDE_DIR) - # Already in cache, be silent - set(SNDFILE_FIND_QUIETLY TRUE) -endif(SNDFILE_INCLUDE_DIR) - -find_path(SNDFILE_INCLUDE_DIR sndfile.h) - -find_library(SNDFILE_LIBRARY NAMES sndfile sndfile-1) - -# Handle the QUIETLY and REQUIRED arguments and set SNDFILE_FOUND to TRUE if -# all listed variables are TRUE. -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(SNDFILE DEFAULT_MSG SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR) - -if(SNDFILE_FOUND) - set(SNDFILE_LIBRARIES ${SNDFILE_LIBRARY}) -else(SNDFILE_FOUND) - set(SNDFILE_LIBRARIES) -endif(SNDFILE_FOUND) - -mark_as_advanced(SNDFILE_INCLUDE_DIR SNDFILE_LIBRARY) +# - Find sndfile +# Find the native sndfile includes and libraries +# +# SNDFILE_INCLUDE_DIR - where to find sndfile.h, etc. +# SNDFILE_LIBRARIES - List of libraries when using libsndfile. +# SNDFILE_FOUND - True if libsndfile found. + +if(SNDFILE_INCLUDE_DIR) + # Already in cache, be silent + set(SNDFILE_FIND_QUIETLY TRUE) +endif(SNDFILE_INCLUDE_DIR) + +find_path(SNDFILE_INCLUDE_DIR sndfile.h) + +find_library(SNDFILE_LIBRARY NAMES sndfile sndfile-1) + +# Handle the QUIETLY and REQUIRED arguments and set SNDFILE_FOUND to TRUE if +# all listed variables are TRUE. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SNDFILE DEFAULT_MSG SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR) + +if(SNDFILE_FOUND) + set(SNDFILE_LIBRARIES ${SNDFILE_LIBRARY}) +else(SNDFILE_FOUND) + set(SNDFILE_LIBRARIES) +endif(SNDFILE_FOUND) + +mark_as_advanced(SNDFILE_INCLUDE_DIR SNDFILE_LIBRARY) diff --git a/cmake/toolchains/android.toolchain.cmake b/cmake/toolchains/android.toolchain.cmake index 7aac9374..0b109718 100644 --- a/cmake/toolchains/android.toolchain.cmake +++ b/cmake/toolchains/android.toolchain.cmake @@ -1,1156 +1,1156 @@ -# ------------------------------------------------------------------------------ -# Android CMake toolchain file, for use with the Android NDK r9d -# Requires cmake 2.6.3 or newer (2.8.5 or newer is recommended). -# See home page: http://code.google.com/p/android-cmake/ -# -# The file was forked from the OpenCV project. This version is maintained by -# the SFML project and can be found at http://github.com/LaurentGomila/SFML -# (cmake/toolchains/android.toolchain.cmake). It brings support for the -# latest NDK versions. -# -# Usage Linux: -# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk -# $ mkdir build && cd build -# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. -# $ make -j8 -# -# Usage Linux (using standalone toolchain): -# $ export ANDROID_STANDALONE_TOOLCHAIN=/absolute/path/to/android-toolchain -# $ mkdir build && cd build -# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. -# $ make -j8 -# -# Usage Windows: -# You need native port of make to build your project. -# Android NDK r7 (or newer) already has make.exe on board. -# For older NDK you have to install it separately. -# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm -# -# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk -# $ mkdir build && cd build -# $ cmake.exe -G"MinGW Makefiles" -# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake -# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" .. -# $ "%ANDROID_NDK%\prebuilt\windows\bin\make.exe" -# -# -# Options (can be set as cmake parameters: -D=): -# ANDROID_NDK=/opt/android-ndk - path to the NDK root. -# Can be set as environment variable. Can be set only at first cmake run. -# -# ANDROID_STANDALONE_TOOLCHAIN=/opt/android-toolchain - path to the -# standalone toolchain. This option is not used if full NDK is found -# (ignored if ANDROID_NDK is set). -# Can be set as environment variable. Can be set only at first cmake run. -# -# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary -# Interface (ABI). This option nearly matches to the APP_ABI variable -# used by ndk-build tool from Android NDK. -# -# Possible targets are: -# "armeabi" - matches to the NDK ABI with the same name. -# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. -# "armeabi-v7a" - matches to the NDK ABI with the same name. -# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. -# "armeabi-v7a with NEON" - same as armeabi-v7a, but -# sets NEON as floating-point unit -# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but -# sets VFPV3 as floating-point unit (has 32 registers instead of 16). -# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP. -# "x86" - matches to the NDK ABI with the same name. -# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. -# "mips" - matches to the NDK ABI with the same name -# (not testes on real devices) -# -# ANDROID_NATIVE_API_LEVEL=android-9 - level of Android API compile for. -# Option is read-only when standalone toolchain used. -# -# ANDROID_FORCE_ARM_BUILD=OFF - set true to generate 32-bit ARM instructions -# instead of Thumb-1. Is not available for "x86" (inapplicable) and -# "armeabi-v6 with VFP" (forced) ABIs. -# -# ANDROID_NO_UNDEFINED=ON - set true to show all undefined symbols as linker -# errors even if they are not used. -# -# ANDROID_SO_UNDEFINED=OFF - set true to allow undefined symbols in shared -# libraries. Automatically turned on for NDK r5x and r6x due to GLESv2 -# problems. -# -# LIBRARY_OUTPUT_PATH_ROOT=${CMAKE_SOURCE_DIR} - where to output binary -# files. See additional details below. -# -# ANDROID_SET_OBSOLETE_VARIABLES=ON - it set, then toolchain defines some -# obsolete variables which were set by previous versions of this file for -# backward compatibility. -# -# -# What?: -# android-cmake toolchain searches for NDK/toolchain in the following order: -# ANDROID_NDK - cmake parameter -# ANDROID_NDK - environment variable -# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter -# ANDROID_STANDALONE_TOOLCHAIN - environment variable -# ANDROID_NDK - default locations -# ANDROID_STANDALONE_TOOLCHAIN - default locations -# -# Make sure to do the following in your scripts: -# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" ) -# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" ) -# The flags will be prepopulated with critical flags, so don't loose them. -# Also be aware that toolchain also sets configuration-specific compiler -# flags and linker flags. -# -# ANDROID and BUILD_ANDROID will be set to true, you may test any of these -# variables to make necessary Android-specific configuration changes. -# -# Also ARMEABI or ARMEABI_V7A or X86 will be set true, mutually exclusive. -# NEON option will be set true if VFP is set to NEON. -# -# LIBRARY_OUTPUT_PATH_ROOT should be set in cache to determine where Android -# libraries will be installed. -# Default is ${CMAKE_SOURCE_DIR}, and the android libs will always be -# under the ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME} -# (depending on the target ABI). This is convenient for Android packaging. -# -# Authors: -# Ethan Rublee ethan.ruble@gmail.com -# Andrey Kamaev andrey.kamaev@itseez.com -# -# Contributors: -# Jonathan De Wachter dewachter.jonathan@gmail.com -# -# Change Log: -# - initial version December 2010 -# - modified April 2011 -# [+] added possibility to build with NDK (without standalone toolchain) -# [+] support cross-compilation on Windows (native, no cygwin support) -# [+] added compiler option to force "char" type to be signed -# [+] added toolchain option to compile to 32-bit ARM instructions -# [+] added toolchain option to disable SWIG search -# [+] added platform "armeabi-v7a with VFPV3" -# [~] ARM_TARGETS renamed to ARM_TARGET -# [+] EXECUTABLE_OUTPUT_PATH is set by toolchain (required on Windows) -# [~] Fixed bug with ANDROID_API_LEVEL variable -# [~] turn off SWIG search if it is not found first time -# - modified May 2011 -# [~] ANDROID_LEVEL is renamed to ANDROID_API_LEVEL -# [+] ANDROID_API_LEVEL is detected by toolchain if not specified -# [~] added guard to prevent changing of output directories on the first -# cmake pass -# [~] toolchain exits with error if ARM_TARGET is not recognized -# - modified June 2011 -# [~] default NDK path is updated for version r5c -# [+] variable CMAKE_SYSTEM_PROCESSOR is set based on ARM_TARGET -# [~] toolchain install directory is added to linker paths -# [-] removed SWIG-related stuff from toolchain -# [+] added macro find_host_package, find_host_program to search -# packages/programs on the host system -# [~] fixed path to STL library -# - modified July 2011 -# [~] fixed options caching -# [~] search for all supported NDK versions -# [~] allowed spaces in NDK path -# - modified September 2011 -# [~] updated for NDK r6b -# - modified November 2011 -# [*] rewritten for NDK r7 -# [+] x86 toolchain support (experimental) -# [+] added "armeabi-v6 with VFP" ABI for ARMv6 processors. -# [~] improved compiler and linker flags management -# [+] support different build flags for Release and Debug configurations -# [~] by default compiler flags the same as used by ndk-build (but only -# where reasonable) -# [~] ANDROID_NDK_TOOLCHAIN_ROOT is splitted to ANDROID_STANDALONE_TOOLCHAIN -# and ANDROID_TOOLCHAIN_ROOT -# [~] ARM_TARGET is renamed to ANDROID_ABI -# [~] ARMEABI_NDK_NAME is renamed to ANDROID_NDK_ABI_NAME -# [~] ANDROID_API_LEVEL is renamed to ANDROID_NATIVE_API_LEVEL -# - modified January 2012 -# [+] added stlport_static support (experimental) -# [+] added special check for cygwin -# [+] filtered out hidden files (starting with .) while globbing inside NDK -# [+] automatically applied GLESv2 linkage fix for NDK revisions 5-6 -# [+] added ANDROID_GET_ABI_RAWNAME to get NDK ABI names by CMake flags -# - modified February 2012 -# [+] updated for NDK r7b -# [~] fixed cmake try_compile() command -# [~] Fix for missing install_name_tool on OS X -# - modified March 2012 -# [~] fixed incorrect C compiler flags -# [~] fixed CMAKE_SYSTEM_PROCESSOR change on ANDROID_ABI change -# [+] improved toolchain loading speed -# [+] added assembler language support (.S) -# [+] allowed preset search paths and extra search suffixes -# - modified April 2012 -# [+] updated for NDK r7c -# [~] fixed most of problems with compiler/linker flags and caching -# [+] added option ANDROID_FUNCTION_LEVEL_LINKING -# - modified May 2012 -# [+] updated for NDK r8 -# [+] added mips architecture support -# - modified August 2012 -# [+] updated for NDK r8b -# [~] all intermediate files generated by toolchain are moved into CMakeFiles -# [~] libstdc++ and libsupc are removed from explicit link libraries -# - modified September 2013 -# [+] updated for NDK r9 -# [+] support 64-bits toolchains -# - modified March 2014 -# [+] updated for NDK r9d and dropped earlier versions -# [+] replaced stlport with libc++ -# ------------------------------------------------------------------------------ - -cmake_minimum_required( VERSION 2.6.3 ) - -if( DEFINED CMAKE_CROSSCOMPILING ) - # subsequent toolchain loading is not really needed - return() -endif() - -get_property(_CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) -if( _CMAKE_IN_TRY_COMPILE ) - include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL ) -endif() - -# this one is important -set( CMAKE_SYSTEM_NAME Linux ) -# this one not so much -set( CMAKE_SYSTEM_VERSION 1 ) - -set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r9d "" ) -if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS) - if( CMAKE_HOST_WIN32 ) - file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) - set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}/android-ndk" "$ENV{SystemDrive}/NVPACK/android-ndk" ) - else() - file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS ) - set( ANDROID_NDK_SEARCH_PATHS /opt/android-ndk "${ANDROID_NDK_SEARCH_PATHS}/NVPACK/android-ndk" ) - endif() -endif() -if(NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH) - set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain ) -endif() - -set( ANDROID_SUPPORTED_ABIS_arm "armeabi;armeabi-v7a;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" ) -set( ANDROID_SUPPORTED_ABIS_x86 "x86" ) -set( ANDROID_SUPPORTED_ABIS_mipsel "mips" ) - -set( ANDROID_DEFAULT_NDK_API_LEVEL 9 ) -set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 ) -set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 ) - - -macro( __LIST_FILTER listvar regex ) - if( ${listvar} ) - foreach( __val ${${listvar}} ) - if( __val MATCHES "${regex}" ) - list( REMOVE_ITEM ${listvar} "${__val}" ) - endif() - endforeach() - endif() -endmacro() - -macro( __INIT_VARIABLE var_name ) - set( __test_path 0 ) - foreach( __var ${ARGN} ) - if( __var STREQUAL "PATH" ) - set( __test_path 1 ) - break() - endif() - endforeach() - if( __test_path AND NOT EXISTS "${${var_name}}" ) - unset( ${var_name} CACHE ) - endif() - if( "${${var_name}}" STREQUAL "" ) - set( __values 0 ) - foreach( __var ${ARGN} ) - if( __var STREQUAL "VALUES" ) - set( __values 1 ) - elseif( NOT __var STREQUAL "PATH" ) - set( __obsolete 0 ) - if( __var MATCHES "^OBSOLETE_.*$" ) - string( REPLACE "OBSOLETE_" "" __var "${__var}" ) - set( __obsolete 1 ) - endif() - if( __var MATCHES "^ENV_.*$" ) - string( REPLACE "ENV_" "" __var "${__var}" ) - set( __value "$ENV{${__var}}" ) - elseif( DEFINED ${__var} ) - set( __value "${${__var}}" ) - else() - if( __values ) - set( __value "${__var}" ) - else() - set( __value "" ) - endif() - endif() - if( NOT "${__value}" STREQUAL "" ) - if( __test_path ) - if( EXISTS "${__value}" ) - set( ${var_name} "${__value}" ) - if( __obsolete ) - message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." ) - endif() - break() - endif() - else() - set( ${var_name} "${__value}" ) - if( __obsolete ) - message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." ) - endif() - break() - endif() - endif() - endif() - endforeach() - unset( __value ) - unset( __values ) - unset( __obsolete ) - endif() - unset( __test_path ) -endmacro() - -macro( __DETECT_NATIVE_API_LEVEL _var _path ) - SET( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*$" ) - FILE( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" ) - if( NOT __apiFileContent ) - message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." ) - endif() - string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" ) - unset( __apiFileContent ) - unset( __ndkApiLevelRegex ) -endmacro() - -macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root ) - file( GLOB __gccExePath "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" ) - __LIST_FILTER( __gccExePath "bin/[.].*-gcc${TOOL_OS_SUFFIX}$" ) - list( LENGTH __gccExePath __gccExePathsCount ) - if( NOT __gccExePathsCount EQUAL 1 ) - message( WARNING "Could not uniquely determine machine name for compiler from ${_root}." ) - set( ${_var} "" ) - else() - get_filename_component( __gccExeName "${__gccExePath}" NAME_WE ) - string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" ) - endif() - unset( __gccExePath ) - unset( __gccExePathsCount ) - unset( __gccExeName ) -endmacro() - -macro( __COPY_IF_DIFFERENT _source _destination ) - execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${_source}" "${_destination}" RESULT_VARIABLE __fileCopyProcess ) - if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${_destination}") - message( SEND_ERROR "Failed copying of ${_source} to the ${_destination}" ) - endif() - unset( __fileCopyProcess ) -endmacro() - - -# stl version: by default gnustl_static will be used -set( ANDROID_USE_STLPORT TRUE CACHE BOOL "Experimental: use stlport_static instead of gnustl_static") -mark_as_advanced( ANDROID_USE_STLPORT ) - -# fight against cygwin -set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools") -mark_as_advanced( ANDROID_FORBID_SYGWIN ) -if( ANDROID_FORBID_SYGWIN ) - if( CYGWIN ) - message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." ) - endif() - - if( CMAKE_HOST_WIN32 ) - # remove cygwin from PATH - set( __new_path "$ENV{PATH}") - __LIST_FILTER( __new_path "cygwin" ) - set(ENV{PATH} "${__new_path}") - unset(__new_path) - endif() -endif() - -# see if we have path to Android NDK -__INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK ) -if( NOT ANDROID_NDK ) - # see if we have path to Android standalone toolchain - __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN OBSOLETE_ANDROID_NDK_TOOLCHAIN_ROOT OBSOLETE_ENV_ANDROID_NDK_TOOLCHAIN_ROOT ) - - if( NOT ANDROID_STANDALONE_TOOLCHAIN ) - #try to find Android NDK in one of the the default locations - set( __ndkSearchPaths ) - foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} ) - foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} ) - list( APPEND __ndkSearchPaths "${__ndkSearchPath}${suffix}" ) - endforeach() - endforeach() - __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} ) - unset( __ndkSearchPaths ) - - if( ANDROID_NDK ) - message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" ) - message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" ) - else() - #try to find Android standalone toolchain in one of the the default locations - __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) - - if( ANDROID_STANDALONE_TOOLCHAIN ) - message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" ) - message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" ) - endif( ANDROID_STANDALONE_TOOLCHAIN ) - endif( ANDROID_NDK ) - endif( NOT ANDROID_STANDALONE_TOOLCHAIN ) -endif( NOT ANDROID_NDK ) - -# remember found paths -if( ANDROID_NDK ) - get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE ) - # try to detect change - if( CMAKE_AR ) - string( LENGTH "${ANDROID_NDK}" __length ) - string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath ) - if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK ) - message( FATAL_ERROR "It is not possible to change path to the NDK on subsequent run." ) - endif() - unset( __androidNdkPreviousPath ) - unset( __length ) - endif() - set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" ) - set( BUILD_WITH_ANDROID_NDK True ) -elseif( ANDROID_STANDALONE_TOOLCHAIN ) - get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE ) - # try to detect change - if( CMAKE_AR ) - string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length ) - string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath ) - if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN ) - message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." ) - endif() - unset( __androidStandaloneToolchainPreviousPath ) - unset( __length ) - endif() - set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" ) - set( BUILD_WITH_STANDALONE_TOOLCHAIN True ) -else() - list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH) - message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolcahin. - You should either set an environment variable: - export ANDROID_NDK=~/my-android-ndk - or - export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain - or put the toolchain or NDK in the default path: - sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH} - sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" ) -endif() - -# detect current host platform -set( ANDROID_NDK_HOST_SYSTEM_ARCH "x86" ) -set( TOOL_OS_SUFFIX "" ) -if( CMAKE_HOST_APPLE ) - set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86" ) - if(NOT EXISTS "${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}") - set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" ) - set( ANDROID_NDK_HOST_SYSTEM_ARCH "x64" ) - endif() -elseif( CMAKE_HOST_WIN32 ) - set( ANDROID_NDK_HOST_SYSTEM_NAME "windows" ) - set( TOOL_OS_SUFFIX ".exe" ) - if(NOT EXISTS "${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}") - set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" ) - set( ANDROID_NDK_HOST_SYSTEM_ARCH "x64" ) - endif() -elseif( CMAKE_HOST_UNIX ) - set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86" ) - if(NOT EXISTS "${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}") - set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" ) - set( ANDROID_NDK_HOST_SYSTEM_ARCH "x64" ) - endif() -else() - message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) -endif() - -# get all the details about standalone toolchain -if( BUILD_WITH_STANDALONE_TOOLCHAIN ) - __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" ) - set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) - set( __availableToolchains "standalone" ) - __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" ) - if( NOT __availableToolchainMachines ) - message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." ) - endif() - if( __availableToolchainMachines MATCHES i686 ) - set( __availableToolchainArchs "x86" ) - elseif( __availableToolchainMachines MATCHES arm ) - set( __availableToolchainArchs "arm" ) - elseif( __availableToolchainMachines MATCHES mipsel ) - set( __availableToolchainArchs "mipsel" ) - endif() - if( ANDROID_COMPILER_VERSION ) - # do not run gcc every time because it is relatevely expencive - set( __availableToolchainCompilerVersions "${ANDROID_COMPILER_VERSION}" ) - else() - execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" --version - OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE ) - string( REGEX MATCH "[0-9]+.[0-9]+.[0-9]+" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" ) - endif() -endif() - -# get all the details about NDK -if( BUILD_WITH_ANDROID_NDK ) - file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" ) - string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" ) - file( GLOB __availableToolchains RELATIVE "${ANDROID_NDK}/toolchains" "${ANDROID_NDK}/toolchains/*" ) - __LIST_FILTER( __availableToolchains "^[.]" ) - set( __availableToolchainMachines "" ) - set( __availableToolchainArchs "" ) - set( __availableToolchainCompilerVersions "" ) - foreach( __toolchain ${__availableToolchains} ) - __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK}/toolchains/${__toolchain}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) - if( __machine ) - string( REGEX MATCH "[0-9]+[.][0-9]+[.]*[0-9]*$" __version "${__toolchain}" ) - string( REGEX MATCH "^[^-]+" __arch "${__toolchain}" ) - list( APPEND __availableToolchainMachines "${__machine}" ) - list( APPEND __availableToolchainArchs "${__arch}" ) - list( APPEND __availableToolchainCompilerVersions "${__version}" ) - else() - list( REMOVE_ITEM __availableToolchains "${__toolchain}" ) - endif() - endforeach() - if( NOT __availableToolchains ) - message( FATAL_ERROR "Could not any working toolchain in the NDK. Probably your Android NDK is broken." ) - endif() -endif() - -# build list of available ABIs -if( NOT ANDROID_SUPPORTED_ABIS ) - set( ANDROID_SUPPORTED_ABIS "" ) - set( __uniqToolchainArchNames ${__availableToolchainArchs} ) - list( REMOVE_DUPLICATES __uniqToolchainArchNames ) - list( SORT __uniqToolchainArchNames ) - foreach( __arch ${__uniqToolchainArchNames} ) - list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} ) - endforeach() - unset( __uniqToolchainArchNames ) - if( NOT ANDROID_SUPPORTED_ABIS ) - message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." ) - endif() -endif() - -# choose target ABI -__INIT_VARIABLE( ANDROID_ABI OBSOLETE_ARM_TARGET OBSOLETE_ARM_TARGETS VALUES ${ANDROID_SUPPORTED_ABIS} ) -# verify that target ABI is supported -list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) -if( __androidAbiIdx EQUAL -1 ) - string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) - message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. - Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" - " ) -endif() -unset( __androidAbiIdx ) - -# remember target ABI -set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE ) - -# set target ABI options -if( ANDROID_ABI STREQUAL "x86" ) - set( X86 true ) - set( ANDROID_NDK_ABI_NAME "x86" ) - set( ANDROID_ARCH_NAME "x86" ) - set( ANDROID_ARCH_FULLNAME "x86" ) - set( CMAKE_SYSTEM_PROCESSOR "i686" ) -elseif( ANDROID_ABI STREQUAL "mips" ) - set( MIPS true ) - set( ANDROID_NDK_ABI_NAME "mips" ) - set( ANDROID_ARCH_NAME "mips" ) - set( ANDROID_ARCH_FULLNAME "mipsel" ) - set( CMAKE_SYSTEM_PROCESSOR "mips" ) -elseif( ANDROID_ABI STREQUAL "armeabi" ) - set( ARMEABI true ) - set( ANDROID_NDK_ABI_NAME "armeabi" ) - set( ANDROID_ARCH_NAME "arm" ) - set( ANDROID_ARCH_FULLNAME "arm" ) - set( CMAKE_SYSTEM_PROCESSOR "armv5te" ) -elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" ) - set( ARMEABI_V6 true ) - set( ANDROID_NDK_ABI_NAME "armeabi" ) - set( ANDROID_ARCH_NAME "arm" ) - set( ANDROID_ARCH_FULLNAME "arm" ) - set( CMAKE_SYSTEM_PROCESSOR "armv6" ) - # need always fallback to older platform - set( ARMEABI true ) -elseif( ANDROID_ABI STREQUAL "armeabi-v7a") - set( ARMEABI_V7A true ) - set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) - set( ANDROID_ARCH_NAME "arm" ) - set( ANDROID_ARCH_FULLNAME "arm" ) - set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) -elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" ) - set( ARMEABI_V7A true ) - set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) - set( ANDROID_ARCH_NAME "arm" ) - set( ANDROID_ARCH_FULLNAME "arm" ) - set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) - set( VFPV3 true ) -elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" ) - set( ARMEABI_V7A true ) - set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) - set( ANDROID_ARCH_NAME "arm" ) - set( ANDROID_ARCH_FULLNAME "arm" ) - set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) - set( VFPV3 true ) - set( NEON true ) -else() - message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." ) -endif() - -if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" ) - # really dirty hack - # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run... - file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" ) -endif() - -set( ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME}} CACHE INTERNAL "ANDROID_ABI can be changed only to one of these ABIs. Changing to any other ABI requires to reset cmake cache." ) -if( CMAKE_VERSION VERSION_GREATER "2.8" ) - list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME} ) - set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME}} ) -endif() - -if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 ) - __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD OBSOLETE_FORCE_ARM VALUES OFF ) - set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE ) - mark_as_advanced( ANDROID_FORCE_ARM_BUILD ) -else() - unset( ANDROID_FORCE_ARM_BUILD CACHE ) -endif() - -# choose toolchain -if( ANDROID_TOOLCHAIN_NAME ) - list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx ) - if( __toolchainIdx EQUAL -1 ) - message( FATAL_ERROR "Previously selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing. You need to remove CMakeCache.txt and rerun cmake manually to change the toolchain" ) - endif() - list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch ) - if( NOT __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME ) - message( SEND_ERROR "Previously selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." ) - endif() -else() - set( __toolchainIdx -1 ) - set( __applicableToolchains "" ) - set( __toolchainMaxVersion "0.0.0" ) - list( LENGTH __availableToolchains __availableToolchainsCount ) - math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" ) - foreach( __idx RANGE ${__availableToolchainsCount} ) - list( GET __availableToolchainArchs ${__idx} __toolchainArch ) - if( __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME ) - list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion ) - if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion ) - set( __toolchainMaxVersion "${__toolchainVersion}" ) - set( __toolchainIdx ${__idx} ) - endif() - endif() - endforeach() - unset( __availableToolchainsCount ) - unset( __toolchainMaxVersion ) - unset( __toolchainVersion ) -endif() -unset( __toolchainArch ) -if( __toolchainIdx EQUAL -1 ) - message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." ) -endif() -list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME ) -list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME ) -list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION ) -set( ANDROID_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" CACHE INTERNAL "Name of toolchain used" ) -set( ANDROID_COMPILER_VERSION "${ANDROID_COMPILER_VERSION}" CACHE INTERNAL "compiler version from selected toolchain" ) -unset( __toolchainIdx ) -unset( __availableToolchains ) -unset( __availableToolchainMachines ) -unset( __availableToolchainArchs ) -unset( __availableToolchainCompilerVersions ) - -# choose native API level -__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL ) -string( REGEX MATCH "[0-9]+" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" ) -# validate -list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx ) -if( __levelIdx EQUAL -1 ) - message( SEND_ERROR "Specified Android native API level (${ANDROID_NATIVE_API_LEVEL}) is not supported by your NDK/toolchain." ) -endif() -unset( __levelIdx ) -if( BUILD_WITH_ANDROID_NDK ) - __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" ) - if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL ) - message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." ) - endif() - unset( __realApiLevel ) -endif() -set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE ) -if( CMAKE_VERSION VERSION_GREATER "2.8" ) - list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS ) - set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) -endif() - -# setup paths -if( BUILD_WITH_STANDALONE_TOOLCHAIN ) - set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) - set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" ) - set( __stlLibPath "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" ) -endif() -if( BUILD_WITH_ANDROID_NDK ) - set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) - set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" ) - if( ANDROID_USE_STLPORT ) - list( APPEND __stlIncludePath "${ANDROID_NDK}/sources/android/support/include" ) - list( APPEND __stlIncludePath "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libcxx/include" ) - set( __stlLibPath "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libs/${ANDROID_NDK_ABI_NAME}" ) - else() - if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) - set( __stlIncludePath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/include" ) - set( __stlLibPath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}" ) - else() - set( __stlIncludePath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/include" ) - set( __stlLibPath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}" ) - endif() - endif() -endif() - -# specify the cross compiler -set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "gcc" ) -set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "g++" ) -set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "Assembler" ) -if( CMAKE_VERSION VERSION_LESS 2.8.5 ) - set( CMAKE_ASM_COMPILER_ARG1 "-c" ) -endif() -# there may be a way to make cmake deduce these TODO deduce the rest of the tools -set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) -set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) -set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) -set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) -set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) -set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) -set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) -set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" ) -if( APPLE ) - find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) - if( NOT CMAKE_INSTALL_NAME_TOOL ) - message( FATAL_ERROR "Could not find install_name_tool, please check your installation." ) - endif() - mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) -endif() - -# export directories -set( ANDROID_SYSTEM_INCLUDE_DIRS "" ) -set( ANDROID_SYSTEM_LIB_DIRS "" ) - -# setup output directories -set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" ) -set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) - -if(NOT _CMAKE_IN_TRY_COMPILE) - if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) - set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) - else() - set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) - endif() - set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "path for android libs" ) -endif() - -# includes -if( __stlIncludePath ) - list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${__stlIncludePath}" ) -endif() - -# c++ bits includes -if( __stlLibPath AND EXISTS "${__stlLibPath}/include" ) - list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${__stlLibPath}/include" ) -endif() -if( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/thumb/bits" ) - list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/thumb" ) -elseif( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" ) - list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" ) -elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" ) - list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" ) -elseif( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/bits" ) - list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" ) -endif() - -# flags and definitions -if(ANDROID_SYSROOT MATCHES "[ ;\"]") - set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" ) - # quotes will break try_compile and compiler identification - message(WARNING "Your Android system root has non-alphanumeric symbols. It can break compiler features detection and the whole build.") -else() - set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) -endif() - -remove_definitions( -DANDROID ) -add_definitions( -DANDROID ) - -# Force set compilers because standard identification works badly for us -include( CMakeForceCompiler ) -CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) -set( CMAKE_C_PLATFORM_ID Linux ) -set( CMAKE_C_SIZEOF_DATA_PTR 4 ) -set( CMAKE_C_HAS_ISYSROOT 1 ) -set( CMAKE_C_COMPILER_ABI ELF ) -CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) -set( CMAKE_CXX_PLATFORM_ID Linux ) -set( CMAKE_CXX_SIZEOF_DATA_PTR 4 ) -set( CMAKE_CXX_HAS_ISYSROOT 1 ) -set( CMAKE_CXX_COMPILER_ABI ELF ) -# force ASM compiler (required for CMake < 2.8.5) -set( CMAKE_ASM_COMPILER_ID_RUN TRUE ) -set( CMAKE_ASM_COMPILER_ID GNU ) -set( CMAKE_ASM_COMPILER_WORKS TRUE ) -set( CMAKE_ASM_COMPILER_FORCED TRUE ) -set( CMAKE_COMPILER_IS_GNUASM 1) - -# NDK flags -if( ARMEABI OR ARMEABI_V7A ) - # NDK also defines -ffunction-sections -funwind-tables but they result in worse OpenCV performance - set( _CMAKE_CXX_FLAGS "-fPIC -Wno-psabi" ) - set( _CMAKE_C_FLAGS "-fPIC -Wno-psabi" ) - remove_definitions( -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ ) - add_definitions( -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ ) - # extra arm-specific flags - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) -elseif( X86 ) - set( _CMAKE_CXX_FLAGS "-funwind-tables" ) - set( _CMAKE_C_FLAGS "-funwind-tables" ) -elseif( MIPS ) - set( _CMAKE_CXX_FLAGS "-fpic -Wno-psabi -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) - set( _CMAKE_CXX_FLAGS "-fpic -Wno-psabi -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) -else() - set( _CMAKE_CXX_FLAGS "" ) - set( _CMAKE_C_FLAGS "" ) -endif() - -if( ANDROID_USE_STLPORT ) - set( _CMAKE_CXX_FLAGS "${_CMAKE_CXX_FLAGS} -frtti -fno-exceptions" ) - set( _CMAKE_C_FLAGS "${_CMAKE_C_FLAGS} -fno-exceptions" ) -else() - set( _CMAKE_CXX_FLAGS "${_CMAKE_CXX_FLAGS} -frtti -fexceptions" ) - set( _CMAKE_C_FLAGS "${_CMAKE_C_FLAGS} -fexceptions" ) -endif() - -# release and debug flags -if( ARMEABI OR ARMEABI_V7A ) - if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 ) - # It is recommended to use the -mthumb compiler flag to force the generation - # of 16-bit Thumb-1 instructions (the default being 32-bit ARM ones). - # O3 instead of O2/Os in release mode - like cmake sets for desktop gcc - set( _CMAKE_CXX_FLAGS_RELEASE "-mthumb -O3" ) - set( _CMAKE_C_FLAGS_RELEASE "-mthumb -O3" ) - set( _CMAKE_CXX_FLAGS_DEBUG "-marm -Os -finline-limit=64" ) - set( _CMAKE_C_FLAGS_DEBUG "-marm -Os -finline-limit=64" ) - else() - # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI - # O3 instead of O2/Os in release mode - like cmake sets for desktop gcc - set( _CMAKE_CXX_FLAGS_RELEASE "-marm -O3 -fstrict-aliasing" ) - set( _CMAKE_C_FLAGS_RELEASE "-marm -O3 -fstrict-aliasing" ) - set( _CMAKE_CXX_FLAGS_DEBUG "-marm -O0 -finline-limit=300" ) - set( _CMAKE_C_FLAGS_DEBUG "-marm -O0 -finline-limit=300" ) - endif() -elseif( X86 ) - set( _CMAKE_CXX_FLAGS_RELEASE "-O3 -fstrict-aliasing" ) - set( _CMAKE_C_FLAGS_RELEASE "-O3 -fstrict-aliasing" ) - set( _CMAKE_CXX_FLAGS_DEBUG "-O0 -finline-limit=300" ) - set( _CMAKE_C_FLAGS_DEBUG "-O0 -finline-limit=300" ) -elseif( MIPS ) - set( _CMAKE_CXX_FLAGS_RELEASE "-O3 -funswitch-loops -finline-limit=300" ) - set( _CMAKE_C_FLAGS_RELEASE "-O3 -funswitch-loops -finline-limit=300" ) - set( _CMAKE_CXX_FLAGS_DEBUG "-O0 -g" ) - set( _CMAKE_C_FLAGS_DEBUG "-O0 -g" ) -endif() -set( _CMAKE_CXX_FLAGS_RELEASE "${_CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -DNDEBUG" ) -set( _CMAKE_C_FLAGS_RELEASE "${_CMAKE_C_FLAGS_RELEASE} -fomit-frame-pointer -DNDEBUG" ) -set( _CMAKE_CXX_FLAGS_DEBUG "${_CMAKE_CXX_FLAGS_DEBUG} -fno-strict-aliasing -fno-omit-frame-pointer -DDEBUG -D_DEBUG" ) -set( _CMAKE_C_FLAGS_DEBUG "${_CMAKE_C_FLAGS_DEBUG} -fno-strict-aliasing -fno-omit-frame-pointer -DDEBUG -D_DEBUG" ) - -# ABI-specific flags -if( ARMEABI_V7A ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" ) - if( NEON ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) - elseif( VFPV3 ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) - else() - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) - endif() -elseif( ARMEABI_V6 ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) -elseif( ARMEABI ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) -elseif( X86 ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" )#sse? -endif() - -# linker flags -if( NOT DEFINED __ndklibspath ) - set( __ndklibspath "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/ndklibs/${ANDROID_NDK_ABI_NAME}" ) -endif() -list( APPEND ANDROID_SYSTEM_LIB_DIRS "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ) -set( ANDROID_LINKER_FLAGS "" ) - -# STL -if( ANDROID_USE_STLPORT ) - if( EXISTS "${__stlLibPath}/libc++_shared.so" ) - set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o \"${__stlLibPath}/libc++_shared.so\" -latomic") - set( CMAKE_CXX_CREATE_SHARED_MODULE " -o \"${__stlLibPath}/libc++_shared.so\" -latomic") - endif() -else( ANDROID_USE_STLPORT ) - if( EXISTS "${__stlLibPath}/libgnustl_static.a" ) - __COPY_IF_DIFFERENT( "${__stlLibPath}/libgnustl_static.a" "${__ndklibspath}/libstdc++.a" ) - elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" ) - __COPY_IF_DIFFERENT( "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" "${__ndklibspath}/libstdc++.a" ) - elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" ) - __COPY_IF_DIFFERENT( "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" "${__ndklibspath}/libstdc++.a" ) - elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${__stlLibPath}/thumb/libstdc++.a" ) - __COPY_IF_DIFFERENT( "${__stlLibPath}/thumb/libstdc++.a" "${__ndklibspath}/libstdc++.a" ) - elseif( EXISTS "${__stlLibPath}/libstdc++.a" ) - __COPY_IF_DIFFERENT( "${__stlLibPath}/libstdc++.a" "${__ndklibspath}/libstdc++.a" ) - endif() - if( EXISTS "${__stlLibPath}/libsupc++.a" ) - __COPY_IF_DIFFERENT( "${__stlLibPath}/libsupc++.a" "${__ndklibspath}/libsupc++.a" ) - elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" ) - __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" "${__ndklibspath}/libsupc++.a" ) - elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" ) - __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" "${__ndklibspath}/libsupc++.a" ) - elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" ) - __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" "${__ndklibspath}/libsupc++.a" ) - elseif( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" ) - __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" "${__ndklibspath}/libsupc++.a" ) - endif() - list( APPEND ANDROID_SYSTEM_LIB_DIRS "${__ndklibspath}" ) -endif( ANDROID_USE_STLPORT ) - -# cleanup for STL search -unset( __stlIncludePath ) -unset( __stlLibPath ) - -# other linker flags -__INIT_VARIABLE( ANDROID_NO_UNDEFINED OBSOLETE_NO_UNDEFINED VALUES ON ) -set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" FORCE ) -mark_as_advanced( ANDROID_NO_UNDEFINED ) -if( ANDROID_NO_UNDEFINED ) - set( ANDROID_LINKER_FLAGS "-Wl,--no-undefined ${ANDROID_LINKER_FLAGS}" ) -endif() - -if (ANDROID_NDK MATCHES "-r[56].?$") - # libGLESv2.so in NDK's prior to r7 refers to exteranal symbols. So this flag option is required for all projects using OpenGL from native. - __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON ) -else() - __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF ) -endif() - -set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" FORCE ) -mark_as_advanced( ANDROID_SO_UNDEFINED ) -if( ANDROID_SO_UNDEFINED ) - set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" ) -endif() - -__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON ) -set( ANDROID_FUNCTION_LEVEL_LINKING ON CACHE BOOL "Allows or disallows undefined symbols in shared libraries" FORCE ) -mark_as_advanced( ANDROID_FUNCTION_LEVEL_LINKING ) -if( ANDROID_FUNCTION_LEVEL_LINKING ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" ) - set( ANDROID_LINKER_FLAGS "-Wl,--gc-sections ${ANDROID_LINKER_FLAGS}" ) -endif() - -if( ARMEABI_V7A ) - # this is *required* to use the following linker flags that routes around - # a CPU bug in some Cortex-A8 implementations: - set( ANDROID_LINKER_FLAGS "-Wl,--fix-cortex-a8 ${ANDROID_LINKER_FLAGS}" ) -endif() - -# cache flags -set( CMAKE_CXX_FLAGS "${_CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags" ) -set( CMAKE_C_FLAGS "${_CMAKE_C_FLAGS}" CACHE STRING "c flags" ) -set( CMAKE_CXX_FLAGS_RELEASE "${_CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "c++ Release flags" ) -set( CMAKE_C_FLAGS_RELEASE "${_CMAKE_C_FLAGS_RELEASE}" CACHE STRING "c Release flags" ) -set( CMAKE_CXX_FLAGS_DEBUG "${_CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "c++ Debug flags" ) -set( CMAKE_C_FLAGS_DEBUG "${_CMAKE_C_FLAGS_DEBUG}" CACHE STRING "c Debug flags" ) -set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "linker flags" ) -set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "linker flags" ) -set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "linker flags" ) - -include_directories( SYSTEM ${ANDROID_SYSTEM_INCLUDE_DIRS} ) -link_directories( ${ANDROID_SYSTEM_LIB_DIRS} ) - -# finish flags -set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Extra Android compiler flags") -set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Extra Android linker flags") -set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) -set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) -if( MIPS AND BUILD_WITH_ANDROID_NDK ) - set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf32btsmip.xsc ${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) - set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf32btsmip.xsc ${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) - set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf32btsmip.x ${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) - # todo: should we use elf64btsmip.xsc on x64 host platforms ? - #set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf64btsmip.xsc ${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) - #set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf64btsmip.xsc ${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) - #set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf64btsmip.x ${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) -else() - set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) - set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) - set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) -endif() - -# set these global flags for cmake client scripts to change behavior -set( ANDROID True ) -set( BUILD_ANDROID True ) - -# where is the target environment -set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) - -# only search for libraries and includes in the ndk toolchain -set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) -set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) -set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) - - -# macro to find packages on the host OS -macro( find_host_package ) - set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) - set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) - set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) - if( CMAKE_HOST_WIN32 ) - SET( WIN32 1 ) - SET( UNIX ) - elseif( CMAKE_HOST_APPLE ) - SET( APPLE 1 ) - SET( UNIX ) - endif() - find_package( ${ARGN} ) - SET( WIN32 ) - SET( APPLE ) - SET( UNIX 1 ) - set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) - set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) - set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) -endmacro() - - -# macro to find programs on the host OS -macro( find_host_program ) - set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) - set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) - set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) - if( CMAKE_HOST_WIN32 ) - SET( WIN32 1 ) - SET( UNIX ) - elseif( CMAKE_HOST_APPLE ) - SET( APPLE 1 ) - SET( UNIX ) - endif() - find_program( ${ARGN} ) - SET( WIN32 ) - SET( APPLE ) - SET( UNIX 1 ) - set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) - set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) - set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) -endmacro() - - -macro( ANDROID_GET_ABI_RAWNAME TOOLCHAIN_FLAG VAR ) - if( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI" ) - set( ${VAR} "armeabi" ) - elseif( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI_V7A" ) - set( ${VAR} "armeabi-v7a" ) - elseif( "${TOOLCHAIN_FLAG}" STREQUAL "X86" ) - set( ${VAR} "x86" ) - else() - set( ${VAR} "unknown" ) - endif() -endmacro() - - -# export toolchain settings for the try_compile() command -if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" ) - set( __toolchain_config "") - foreach( __var ANDROID_ABI ANDROID_FORCE_ARM_BUILD ANDROID_NATIVE_API_LEVEL ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_SET_OBSOLETE_VARIABLES LIBRARY_OUTPUT_PATH_ROOT ANDROID_USE_STLPORT ANDROID_FORBID_SYGWIN ANDROID_NDK ANDROID_STANDALONE_TOOLCHAIN ANDROID_FUNCTION_LEVEL_LINKING __ndklibspath ) - if( DEFINED ${__var} ) - if( "${__var}" MATCHES " ") - set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" ) - else() - set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" ) - endif() - endif() - endforeach() - file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" ) - unset( __toolchain_config ) - unset( __ndklibspath ) -endif() - - -# set some obsolete variables for backward compatibility -set( ANDROID_SET_OBSOLETE_VARIABLES ON CACHE BOOL "Define obsolete Andrid-specific cmake variables" ) -mark_as_advanced( ANDROID_SET_OBSOLETE_VARIABLES ) -if( ANDROID_SET_OBSOLETE_VARIABLES ) - set( ANDROID_API_LEVEL ${ANDROID_NATIVE_API_LEVEL} ) - set( ARM_TARGET "${ANDROID_ABI}" ) - set( ARMEABI_NDK_NAME "${ANDROID_NDK_ABI_NAME}" ) -endif() - -# don't leave libs/ directories in source directory -set(LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_LIBRARY_DIR}) - -# Variables controlling behavior or set by cmake toolchain: -# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips" -# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14 (depends on NDK version) -# ANDROID_SET_OBSOLETE_VARIABLES : ON/OFF -# ANDROID_USE_STLPORT : OFF/ON - EXPERIMENTAL!!! -# ANDROID_FORBID_SYGWIN : ON/OFF -# ANDROID_NO_UNDEFINED : ON/OFF -# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version) -# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF -# Variables that takes effect only at first run: -# ANDROID_FORCE_ARM_BUILD : ON/OFF -# LIBRARY_OUTPUT_PATH_ROOT : -# Can be set only at the first run: -# ANDROID_NDK -# ANDROID_STANDALONE_TOOLCHAIN -# ANDROID_TOOLCHAIN_NAME : "arm-linux-androideabi-4.4.3" or "arm-linux-androideabi-4.6" or "mipsel-linux-android-4.4.3" or "mipsel-linux-android-4.6" or "x86-4.4.3" or "x86-4.6" -# Obsolete: -# ANDROID_API_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL -# ARM_TARGET : superseded by ANDROID_ABI -# ARM_TARGETS : superseded by ANDROID_ABI (can be set only) -# ANDROID_NDK_TOOLCHAIN_ROOT : superseded by ANDROID_STANDALONE_TOOLCHAIN (can be set only) -# ANDROID_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL (completely removed) -# -# Primary read-only variables: -# ANDROID : always TRUE -# ARMEABI : TRUE for arm v6 and older devices -# ARMEABI_V6 : TRUE for arm v6 -# ARMEABI_V7A : TRUE for arm v7a -# NEON : TRUE if NEON unit is enabled -# VFPV3 : TRUE if VFP version 3 is enabled -# X86 : TRUE if configured for x86 -# BUILD_ANDROID : always TRUE -# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used -# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used -# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform -# ANDROID_NDK_HOST_SYSTEM_ARCH : "x86", "x64" depending on host platform -# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a" or "x86" depending on ANDROID_ABI -# ANDROID_ARCH_NAME : "arm" or "x86" or "mips" depending on ANDROID_ABI -# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform -# ANDROID_SYSROOT : path to the compiler sysroot -# ANDROID_SYSTEM_INCLUDE_DIRS -# ANDROID_SYSTEM_LIB_DIRS -# Obsolete: -# ARMEABI_NDK_NAME : superseded by ANDROID_NDK_ABI_NAME -# -# Secondary (less stable) read-only variables: -# ANDROID_COMPILER_VERSION : GCC version used -# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform -# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI -# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux" -# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK) -# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK -# -# Defaults: -# ANDROID_DEFAULT_NDK_API_LEVEL -# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH} -# ANDROID_NDK_SEARCH_PATHS -# ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH -# ANDROID_SUPPORTED_ABIS_${ARCH} -# ANDROID_SUPPORTED_NDK_VERSIONS +# ------------------------------------------------------------------------------ +# Android CMake toolchain file, for use with the Android NDK r9d +# Requires cmake 2.6.3 or newer (2.8.5 or newer is recommended). +# See home page: http://code.google.com/p/android-cmake/ +# +# The file was forked from the OpenCV project. This version is maintained by +# the SFML project and can be found at http://github.com/LaurentGomila/SFML +# (cmake/toolchains/android.toolchain.cmake). It brings support for the +# latest NDK versions. +# +# Usage Linux: +# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk +# $ mkdir build && cd build +# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. +# $ make -j8 +# +# Usage Linux (using standalone toolchain): +# $ export ANDROID_STANDALONE_TOOLCHAIN=/absolute/path/to/android-toolchain +# $ mkdir build && cd build +# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. +# $ make -j8 +# +# Usage Windows: +# You need native port of make to build your project. +# Android NDK r7 (or newer) already has make.exe on board. +# For older NDK you have to install it separately. +# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm +# +# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk +# $ mkdir build && cd build +# $ cmake.exe -G"MinGW Makefiles" +# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake +# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" .. +# $ "%ANDROID_NDK%\prebuilt\windows\bin\make.exe" +# +# +# Options (can be set as cmake parameters: -D=): +# ANDROID_NDK=/opt/android-ndk - path to the NDK root. +# Can be set as environment variable. Can be set only at first cmake run. +# +# ANDROID_STANDALONE_TOOLCHAIN=/opt/android-toolchain - path to the +# standalone toolchain. This option is not used if full NDK is found +# (ignored if ANDROID_NDK is set). +# Can be set as environment variable. Can be set only at first cmake run. +# +# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary +# Interface (ABI). This option nearly matches to the APP_ABI variable +# used by ndk-build tool from Android NDK. +# +# Possible targets are: +# "armeabi" - matches to the NDK ABI with the same name. +# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. +# "armeabi-v7a" - matches to the NDK ABI with the same name. +# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. +# "armeabi-v7a with NEON" - same as armeabi-v7a, but +# sets NEON as floating-point unit +# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but +# sets VFPV3 as floating-point unit (has 32 registers instead of 16). +# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP. +# "x86" - matches to the NDK ABI with the same name. +# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. +# "mips" - matches to the NDK ABI with the same name +# (not testes on real devices) +# +# ANDROID_NATIVE_API_LEVEL=android-9 - level of Android API compile for. +# Option is read-only when standalone toolchain used. +# +# ANDROID_FORCE_ARM_BUILD=OFF - set true to generate 32-bit ARM instructions +# instead of Thumb-1. Is not available for "x86" (inapplicable) and +# "armeabi-v6 with VFP" (forced) ABIs. +# +# ANDROID_NO_UNDEFINED=ON - set true to show all undefined symbols as linker +# errors even if they are not used. +# +# ANDROID_SO_UNDEFINED=OFF - set true to allow undefined symbols in shared +# libraries. Automatically turned on for NDK r5x and r6x due to GLESv2 +# problems. +# +# LIBRARY_OUTPUT_PATH_ROOT=${CMAKE_SOURCE_DIR} - where to output binary +# files. See additional details below. +# +# ANDROID_SET_OBSOLETE_VARIABLES=ON - it set, then toolchain defines some +# obsolete variables which were set by previous versions of this file for +# backward compatibility. +# +# +# What?: +# android-cmake toolchain searches for NDK/toolchain in the following order: +# ANDROID_NDK - cmake parameter +# ANDROID_NDK - environment variable +# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter +# ANDROID_STANDALONE_TOOLCHAIN - environment variable +# ANDROID_NDK - default locations +# ANDROID_STANDALONE_TOOLCHAIN - default locations +# +# Make sure to do the following in your scripts: +# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" ) +# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" ) +# The flags will be prepopulated with critical flags, so don't loose them. +# Also be aware that toolchain also sets configuration-specific compiler +# flags and linker flags. +# +# ANDROID and BUILD_ANDROID will be set to true, you may test any of these +# variables to make necessary Android-specific configuration changes. +# +# Also ARMEABI or ARMEABI_V7A or X86 will be set true, mutually exclusive. +# NEON option will be set true if VFP is set to NEON. +# +# LIBRARY_OUTPUT_PATH_ROOT should be set in cache to determine where Android +# libraries will be installed. +# Default is ${CMAKE_SOURCE_DIR}, and the android libs will always be +# under the ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME} +# (depending on the target ABI). This is convenient for Android packaging. +# +# Authors: +# Ethan Rublee ethan.ruble@gmail.com +# Andrey Kamaev andrey.kamaev@itseez.com +# +# Contributors: +# Jonathan De Wachter dewachter.jonathan@gmail.com +# +# Change Log: +# - initial version December 2010 +# - modified April 2011 +# [+] added possibility to build with NDK (without standalone toolchain) +# [+] support cross-compilation on Windows (native, no cygwin support) +# [+] added compiler option to force "char" type to be signed +# [+] added toolchain option to compile to 32-bit ARM instructions +# [+] added toolchain option to disable SWIG search +# [+] added platform "armeabi-v7a with VFPV3" +# [~] ARM_TARGETS renamed to ARM_TARGET +# [+] EXECUTABLE_OUTPUT_PATH is set by toolchain (required on Windows) +# [~] Fixed bug with ANDROID_API_LEVEL variable +# [~] turn off SWIG search if it is not found first time +# - modified May 2011 +# [~] ANDROID_LEVEL is renamed to ANDROID_API_LEVEL +# [+] ANDROID_API_LEVEL is detected by toolchain if not specified +# [~] added guard to prevent changing of output directories on the first +# cmake pass +# [~] toolchain exits with error if ARM_TARGET is not recognized +# - modified June 2011 +# [~] default NDK path is updated for version r5c +# [+] variable CMAKE_SYSTEM_PROCESSOR is set based on ARM_TARGET +# [~] toolchain install directory is added to linker paths +# [-] removed SWIG-related stuff from toolchain +# [+] added macro find_host_package, find_host_program to search +# packages/programs on the host system +# [~] fixed path to STL library +# - modified July 2011 +# [~] fixed options caching +# [~] search for all supported NDK versions +# [~] allowed spaces in NDK path +# - modified September 2011 +# [~] updated for NDK r6b +# - modified November 2011 +# [*] rewritten for NDK r7 +# [+] x86 toolchain support (experimental) +# [+] added "armeabi-v6 with VFP" ABI for ARMv6 processors. +# [~] improved compiler and linker flags management +# [+] support different build flags for Release and Debug configurations +# [~] by default compiler flags the same as used by ndk-build (but only +# where reasonable) +# [~] ANDROID_NDK_TOOLCHAIN_ROOT is splitted to ANDROID_STANDALONE_TOOLCHAIN +# and ANDROID_TOOLCHAIN_ROOT +# [~] ARM_TARGET is renamed to ANDROID_ABI +# [~] ARMEABI_NDK_NAME is renamed to ANDROID_NDK_ABI_NAME +# [~] ANDROID_API_LEVEL is renamed to ANDROID_NATIVE_API_LEVEL +# - modified January 2012 +# [+] added stlport_static support (experimental) +# [+] added special check for cygwin +# [+] filtered out hidden files (starting with .) while globbing inside NDK +# [+] automatically applied GLESv2 linkage fix for NDK revisions 5-6 +# [+] added ANDROID_GET_ABI_RAWNAME to get NDK ABI names by CMake flags +# - modified February 2012 +# [+] updated for NDK r7b +# [~] fixed cmake try_compile() command +# [~] Fix for missing install_name_tool on OS X +# - modified March 2012 +# [~] fixed incorrect C compiler flags +# [~] fixed CMAKE_SYSTEM_PROCESSOR change on ANDROID_ABI change +# [+] improved toolchain loading speed +# [+] added assembler language support (.S) +# [+] allowed preset search paths and extra search suffixes +# - modified April 2012 +# [+] updated for NDK r7c +# [~] fixed most of problems with compiler/linker flags and caching +# [+] added option ANDROID_FUNCTION_LEVEL_LINKING +# - modified May 2012 +# [+] updated for NDK r8 +# [+] added mips architecture support +# - modified August 2012 +# [+] updated for NDK r8b +# [~] all intermediate files generated by toolchain are moved into CMakeFiles +# [~] libstdc++ and libsupc are removed from explicit link libraries +# - modified September 2013 +# [+] updated for NDK r9 +# [+] support 64-bits toolchains +# - modified March 2014 +# [+] updated for NDK r9d and dropped earlier versions +# [+] replaced stlport with libc++ +# ------------------------------------------------------------------------------ + +cmake_minimum_required( VERSION 2.6.3 ) + +if( DEFINED CMAKE_CROSSCOMPILING ) + # subsequent toolchain loading is not really needed + return() +endif() + +get_property(_CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) +if( _CMAKE_IN_TRY_COMPILE ) + include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL ) +endif() + +# this one is important +set( CMAKE_SYSTEM_NAME Linux ) +# this one not so much +set( CMAKE_SYSTEM_VERSION 1 ) + +set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r9d "" ) +if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS) + if( CMAKE_HOST_WIN32 ) + file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}/android-ndk" "$ENV{SystemDrive}/NVPACK/android-ndk" ) + else() + file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS /opt/android-ndk "${ANDROID_NDK_SEARCH_PATHS}/NVPACK/android-ndk" ) + endif() +endif() +if(NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH) + set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain ) +endif() + +set( ANDROID_SUPPORTED_ABIS_arm "armeabi;armeabi-v7a;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" ) +set( ANDROID_SUPPORTED_ABIS_x86 "x86" ) +set( ANDROID_SUPPORTED_ABIS_mipsel "mips" ) + +set( ANDROID_DEFAULT_NDK_API_LEVEL 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 ) + + +macro( __LIST_FILTER listvar regex ) + if( ${listvar} ) + foreach( __val ${${listvar}} ) + if( __val MATCHES "${regex}" ) + list( REMOVE_ITEM ${listvar} "${__val}" ) + endif() + endforeach() + endif() +endmacro() + +macro( __INIT_VARIABLE var_name ) + set( __test_path 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "PATH" ) + set( __test_path 1 ) + break() + endif() + endforeach() + if( __test_path AND NOT EXISTS "${${var_name}}" ) + unset( ${var_name} CACHE ) + endif() + if( "${${var_name}}" STREQUAL "" ) + set( __values 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "VALUES" ) + set( __values 1 ) + elseif( NOT __var STREQUAL "PATH" ) + set( __obsolete 0 ) + if( __var MATCHES "^OBSOLETE_.*$" ) + string( REPLACE "OBSOLETE_" "" __var "${__var}" ) + set( __obsolete 1 ) + endif() + if( __var MATCHES "^ENV_.*$" ) + string( REPLACE "ENV_" "" __var "${__var}" ) + set( __value "$ENV{${__var}}" ) + elseif( DEFINED ${__var} ) + set( __value "${${__var}}" ) + else() + if( __values ) + set( __value "${__var}" ) + else() + set( __value "" ) + endif() + endif() + if( NOT "${__value}" STREQUAL "" ) + if( __test_path ) + if( EXISTS "${__value}" ) + set( ${var_name} "${__value}" ) + if( __obsolete ) + message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." ) + endif() + break() + endif() + else() + set( ${var_name} "${__value}" ) + if( __obsolete ) + message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." ) + endif() + break() + endif() + endif() + endif() + endforeach() + unset( __value ) + unset( __values ) + unset( __obsolete ) + endif() + unset( __test_path ) +endmacro() + +macro( __DETECT_NATIVE_API_LEVEL _var _path ) + SET( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*$" ) + FILE( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" ) + if( NOT __apiFileContent ) + message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." ) + endif() + string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" ) + unset( __apiFileContent ) + unset( __ndkApiLevelRegex ) +endmacro() + +macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root ) + file( GLOB __gccExePath "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" ) + __LIST_FILTER( __gccExePath "bin/[.].*-gcc${TOOL_OS_SUFFIX}$" ) + list( LENGTH __gccExePath __gccExePathsCount ) + if( NOT __gccExePathsCount EQUAL 1 ) + message( WARNING "Could not uniquely determine machine name for compiler from ${_root}." ) + set( ${_var} "" ) + else() + get_filename_component( __gccExeName "${__gccExePath}" NAME_WE ) + string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" ) + endif() + unset( __gccExePath ) + unset( __gccExePathsCount ) + unset( __gccExeName ) +endmacro() + +macro( __COPY_IF_DIFFERENT _source _destination ) + execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${_source}" "${_destination}" RESULT_VARIABLE __fileCopyProcess ) + if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${_destination}") + message( SEND_ERROR "Failed copying of ${_source} to the ${_destination}" ) + endif() + unset( __fileCopyProcess ) +endmacro() + + +# stl version: by default gnustl_static will be used +set( ANDROID_USE_STLPORT TRUE CACHE BOOL "Experimental: use stlport_static instead of gnustl_static") +mark_as_advanced( ANDROID_USE_STLPORT ) + +# fight against cygwin +set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools") +mark_as_advanced( ANDROID_FORBID_SYGWIN ) +if( ANDROID_FORBID_SYGWIN ) + if( CYGWIN ) + message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." ) + endif() + + if( CMAKE_HOST_WIN32 ) + # remove cygwin from PATH + set( __new_path "$ENV{PATH}") + __LIST_FILTER( __new_path "cygwin" ) + set(ENV{PATH} "${__new_path}") + unset(__new_path) + endif() +endif() + +# see if we have path to Android NDK +__INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK ) +if( NOT ANDROID_NDK ) + # see if we have path to Android standalone toolchain + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN OBSOLETE_ANDROID_NDK_TOOLCHAIN_ROOT OBSOLETE_ENV_ANDROID_NDK_TOOLCHAIN_ROOT ) + + if( NOT ANDROID_STANDALONE_TOOLCHAIN ) + #try to find Android NDK in one of the the default locations + set( __ndkSearchPaths ) + foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} ) + foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} ) + list( APPEND __ndkSearchPaths "${__ndkSearchPath}${suffix}" ) + endforeach() + endforeach() + __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} ) + unset( __ndkSearchPaths ) + + if( ANDROID_NDK ) + message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" ) + message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" ) + else() + #try to find Android standalone toolchain in one of the the default locations + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + + if( ANDROID_STANDALONE_TOOLCHAIN ) + message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" ) + message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" ) + endif( ANDROID_STANDALONE_TOOLCHAIN ) + endif( ANDROID_NDK ) + endif( NOT ANDROID_STANDALONE_TOOLCHAIN ) +endif( NOT ANDROID_NDK ) + +# remember found paths +if( ANDROID_NDK ) + get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE ) + # try to detect change + if( CMAKE_AR ) + string( LENGTH "${ANDROID_NDK}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath ) + if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK ) + message( FATAL_ERROR "It is not possible to change path to the NDK on subsequent run." ) + endif() + unset( __androidNdkPreviousPath ) + unset( __length ) + endif() + set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" ) + set( BUILD_WITH_ANDROID_NDK True ) +elseif( ANDROID_STANDALONE_TOOLCHAIN ) + get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE ) + # try to detect change + if( CMAKE_AR ) + string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath ) + if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN ) + message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." ) + endif() + unset( __androidStandaloneToolchainPreviousPath ) + unset( __length ) + endif() + set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" ) + set( BUILD_WITH_STANDALONE_TOOLCHAIN True ) +else() + list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH) + message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolcahin. + You should either set an environment variable: + export ANDROID_NDK=~/my-android-ndk + or + export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain + or put the toolchain or NDK in the default path: + sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH} + sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" ) +endif() + +# detect current host platform +set( ANDROID_NDK_HOST_SYSTEM_ARCH "x86" ) +set( TOOL_OS_SUFFIX "" ) +if( CMAKE_HOST_APPLE ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86" ) + if(NOT EXISTS "${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}") + set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_ARCH "x64" ) + endif() +elseif( CMAKE_HOST_WIN32 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "windows" ) + set( TOOL_OS_SUFFIX ".exe" ) + if(NOT EXISTS "${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}") + set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_ARCH "x64" ) + endif() +elseif( CMAKE_HOST_UNIX ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86" ) + if(NOT EXISTS "${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}") + set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_ARCH "x64" ) + endif() +else() + message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) +endif() + +# get all the details about standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" ) + set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + set( __availableToolchains "standalone" ) + __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" ) + if( NOT __availableToolchainMachines ) + message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." ) + endif() + if( __availableToolchainMachines MATCHES i686 ) + set( __availableToolchainArchs "x86" ) + elseif( __availableToolchainMachines MATCHES arm ) + set( __availableToolchainArchs "arm" ) + elseif( __availableToolchainMachines MATCHES mipsel ) + set( __availableToolchainArchs "mipsel" ) + endif() + if( ANDROID_COMPILER_VERSION ) + # do not run gcc every time because it is relatevely expencive + set( __availableToolchainCompilerVersions "${ANDROID_COMPILER_VERSION}" ) + else() + execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" --version + OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+.[0-9]+.[0-9]+" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" ) + endif() +endif() + +# get all the details about NDK +if( BUILD_WITH_ANDROID_NDK ) + file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" ) + string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" ) + file( GLOB __availableToolchains RELATIVE "${ANDROID_NDK}/toolchains" "${ANDROID_NDK}/toolchains/*" ) + __LIST_FILTER( __availableToolchains "^[.]" ) + set( __availableToolchainMachines "" ) + set( __availableToolchainArchs "" ) + set( __availableToolchainCompilerVersions "" ) + foreach( __toolchain ${__availableToolchains} ) + __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK}/toolchains/${__toolchain}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) + if( __machine ) + string( REGEX MATCH "[0-9]+[.][0-9]+[.]*[0-9]*$" __version "${__toolchain}" ) + string( REGEX MATCH "^[^-]+" __arch "${__toolchain}" ) + list( APPEND __availableToolchainMachines "${__machine}" ) + list( APPEND __availableToolchainArchs "${__arch}" ) + list( APPEND __availableToolchainCompilerVersions "${__version}" ) + else() + list( REMOVE_ITEM __availableToolchains "${__toolchain}" ) + endif() + endforeach() + if( NOT __availableToolchains ) + message( FATAL_ERROR "Could not any working toolchain in the NDK. Probably your Android NDK is broken." ) + endif() +endif() + +# build list of available ABIs +if( NOT ANDROID_SUPPORTED_ABIS ) + set( ANDROID_SUPPORTED_ABIS "" ) + set( __uniqToolchainArchNames ${__availableToolchainArchs} ) + list( REMOVE_DUPLICATES __uniqToolchainArchNames ) + list( SORT __uniqToolchainArchNames ) + foreach( __arch ${__uniqToolchainArchNames} ) + list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} ) + endforeach() + unset( __uniqToolchainArchNames ) + if( NOT ANDROID_SUPPORTED_ABIS ) + message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." ) + endif() +endif() + +# choose target ABI +__INIT_VARIABLE( ANDROID_ABI OBSOLETE_ARM_TARGET OBSOLETE_ARM_TARGETS VALUES ${ANDROID_SUPPORTED_ABIS} ) +# verify that target ABI is supported +list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) +if( __androidAbiIdx EQUAL -1 ) + string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) + message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. + Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" + " ) +endif() +unset( __androidAbiIdx ) + +# remember target ABI +set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE ) + +# set target ABI options +if( ANDROID_ABI STREQUAL "x86" ) + set( X86 true ) + set( ANDROID_NDK_ABI_NAME "x86" ) + set( ANDROID_ARCH_NAME "x86" ) + set( ANDROID_ARCH_FULLNAME "x86" ) + set( CMAKE_SYSTEM_PROCESSOR "i686" ) +elseif( ANDROID_ABI STREQUAL "mips" ) + set( MIPS true ) + set( ANDROID_NDK_ABI_NAME "mips" ) + set( ANDROID_ARCH_NAME "mips" ) + set( ANDROID_ARCH_FULLNAME "mipsel" ) + set( CMAKE_SYSTEM_PROCESSOR "mips" ) +elseif( ANDROID_ABI STREQUAL "armeabi" ) + set( ARMEABI true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_ARCH_FULLNAME "arm" ) + set( CMAKE_SYSTEM_PROCESSOR "armv5te" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" ) + set( ARMEABI_V6 true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_ARCH_FULLNAME "arm" ) + set( CMAKE_SYSTEM_PROCESSOR "armv6" ) + # need always fallback to older platform + set( ARMEABI true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a") + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_ARCH_FULLNAME "arm" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_ARCH_FULLNAME "arm" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_ARCH_FULLNAME "arm" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) + set( NEON true ) +else() + message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." ) +endif() + +if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" ) + # really dirty hack + # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run... + file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" ) +endif() + +set( ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME}} CACHE INTERNAL "ANDROID_ABI can be changed only to one of these ABIs. Changing to any other ABI requires to reset cmake cache." ) +if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME} ) + set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME}} ) +endif() + +if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 ) + __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD OBSOLETE_FORCE_ARM VALUES OFF ) + set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE ) + mark_as_advanced( ANDROID_FORCE_ARM_BUILD ) +else() + unset( ANDROID_FORCE_ARM_BUILD CACHE ) +endif() + +# choose toolchain +if( ANDROID_TOOLCHAIN_NAME ) + list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx ) + if( __toolchainIdx EQUAL -1 ) + message( FATAL_ERROR "Previously selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing. You need to remove CMakeCache.txt and rerun cmake manually to change the toolchain" ) + endif() + list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch ) + if( NOT __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME ) + message( SEND_ERROR "Previously selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." ) + endif() +else() + set( __toolchainIdx -1 ) + set( __applicableToolchains "" ) + set( __toolchainMaxVersion "0.0.0" ) + list( LENGTH __availableToolchains __availableToolchainsCount ) + math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" ) + foreach( __idx RANGE ${__availableToolchainsCount} ) + list( GET __availableToolchainArchs ${__idx} __toolchainArch ) + if( __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME ) + list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion ) + if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion ) + set( __toolchainMaxVersion "${__toolchainVersion}" ) + set( __toolchainIdx ${__idx} ) + endif() + endif() + endforeach() + unset( __availableToolchainsCount ) + unset( __toolchainMaxVersion ) + unset( __toolchainVersion ) +endif() +unset( __toolchainArch ) +if( __toolchainIdx EQUAL -1 ) + message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." ) +endif() +list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME ) +list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME ) +list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION ) +set( ANDROID_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" CACHE INTERNAL "Name of toolchain used" ) +set( ANDROID_COMPILER_VERSION "${ANDROID_COMPILER_VERSION}" CACHE INTERNAL "compiler version from selected toolchain" ) +unset( __toolchainIdx ) +unset( __availableToolchains ) +unset( __availableToolchainMachines ) +unset( __availableToolchainArchs ) +unset( __availableToolchainCompilerVersions ) + +# choose native API level +__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL ) +string( REGEX MATCH "[0-9]+" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" ) +# validate +list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx ) +if( __levelIdx EQUAL -1 ) + message( SEND_ERROR "Specified Android native API level (${ANDROID_NATIVE_API_LEVEL}) is not supported by your NDK/toolchain." ) +endif() +unset( __levelIdx ) +if( BUILD_WITH_ANDROID_NDK ) + __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" ) + if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL ) + message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." ) + endif() + unset( __realApiLevel ) +endif() +set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE ) +if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS ) + set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) +endif() + +# setup paths +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" ) + set( __stlLibPath "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" ) +endif() +if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) + set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" ) + if( ANDROID_USE_STLPORT ) + list( APPEND __stlIncludePath "${ANDROID_NDK}/sources/android/support/include" ) + list( APPEND __stlIncludePath "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libcxx/include" ) + set( __stlLibPath "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libs/${ANDROID_NDK_ABI_NAME}" ) + else() + if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + set( __stlIncludePath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/include" ) + set( __stlLibPath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}" ) + else() + set( __stlIncludePath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/include" ) + set( __stlLibPath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}" ) + endif() + endif() +endif() + +# specify the cross compiler +set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "gcc" ) +set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "g++" ) +set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "Assembler" ) +if( CMAKE_VERSION VERSION_LESS 2.8.5 ) + set( CMAKE_ASM_COMPILER_ARG1 "-c" ) +endif() +# there may be a way to make cmake deduce these TODO deduce the rest of the tools +set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) +set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) +set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) +set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) +set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) +set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) +set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) +set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" ) +if( APPLE ) + find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) + if( NOT CMAKE_INSTALL_NAME_TOOL ) + message( FATAL_ERROR "Could not find install_name_tool, please check your installation." ) + endif() + mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) +endif() + +# export directories +set( ANDROID_SYSTEM_INCLUDE_DIRS "" ) +set( ANDROID_SYSTEM_LIB_DIRS "" ) + +# setup output directories +set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" ) +set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) + +if(NOT _CMAKE_IN_TRY_COMPILE) + if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) + else() + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) + endif() + set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "path for android libs" ) +endif() + +# includes +if( __stlIncludePath ) + list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${__stlIncludePath}" ) +endif() + +# c++ bits includes +if( __stlLibPath AND EXISTS "${__stlLibPath}/include" ) + list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${__stlLibPath}/include" ) +endif() +if( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/thumb/bits" ) + list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/thumb" ) +elseif( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" ) + list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" ) +elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" ) + list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" ) +elseif( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/bits" ) + list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" ) +endif() + +# flags and definitions +if(ANDROID_SYSROOT MATCHES "[ ;\"]") + set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" ) + # quotes will break try_compile and compiler identification + message(WARNING "Your Android system root has non-alphanumeric symbols. It can break compiler features detection and the whole build.") +else() + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) +endif() + +remove_definitions( -DANDROID ) +add_definitions( -DANDROID ) + +# Force set compilers because standard identification works badly for us +include( CMakeForceCompiler ) +CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) +set( CMAKE_C_PLATFORM_ID Linux ) +set( CMAKE_C_SIZEOF_DATA_PTR 4 ) +set( CMAKE_C_HAS_ISYSROOT 1 ) +set( CMAKE_C_COMPILER_ABI ELF ) +CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) +set( CMAKE_CXX_PLATFORM_ID Linux ) +set( CMAKE_CXX_SIZEOF_DATA_PTR 4 ) +set( CMAKE_CXX_HAS_ISYSROOT 1 ) +set( CMAKE_CXX_COMPILER_ABI ELF ) +# force ASM compiler (required for CMake < 2.8.5) +set( CMAKE_ASM_COMPILER_ID_RUN TRUE ) +set( CMAKE_ASM_COMPILER_ID GNU ) +set( CMAKE_ASM_COMPILER_WORKS TRUE ) +set( CMAKE_ASM_COMPILER_FORCED TRUE ) +set( CMAKE_COMPILER_IS_GNUASM 1) + +# NDK flags +if( ARMEABI OR ARMEABI_V7A ) + # NDK also defines -ffunction-sections -funwind-tables but they result in worse OpenCV performance + set( _CMAKE_CXX_FLAGS "-fPIC -Wno-psabi" ) + set( _CMAKE_C_FLAGS "-fPIC -Wno-psabi" ) + remove_definitions( -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ ) + add_definitions( -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ ) + # extra arm-specific flags + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) +elseif( X86 ) + set( _CMAKE_CXX_FLAGS "-funwind-tables" ) + set( _CMAKE_C_FLAGS "-funwind-tables" ) +elseif( MIPS ) + set( _CMAKE_CXX_FLAGS "-fpic -Wno-psabi -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) + set( _CMAKE_CXX_FLAGS "-fpic -Wno-psabi -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) +else() + set( _CMAKE_CXX_FLAGS "" ) + set( _CMAKE_C_FLAGS "" ) +endif() + +if( ANDROID_USE_STLPORT ) + set( _CMAKE_CXX_FLAGS "${_CMAKE_CXX_FLAGS} -frtti -fno-exceptions" ) + set( _CMAKE_C_FLAGS "${_CMAKE_C_FLAGS} -fno-exceptions" ) +else() + set( _CMAKE_CXX_FLAGS "${_CMAKE_CXX_FLAGS} -frtti -fexceptions" ) + set( _CMAKE_C_FLAGS "${_CMAKE_C_FLAGS} -fexceptions" ) +endif() + +# release and debug flags +if( ARMEABI OR ARMEABI_V7A ) + if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 ) + # It is recommended to use the -mthumb compiler flag to force the generation + # of 16-bit Thumb-1 instructions (the default being 32-bit ARM ones). + # O3 instead of O2/Os in release mode - like cmake sets for desktop gcc + set( _CMAKE_CXX_FLAGS_RELEASE "-mthumb -O3" ) + set( _CMAKE_C_FLAGS_RELEASE "-mthumb -O3" ) + set( _CMAKE_CXX_FLAGS_DEBUG "-marm -Os -finline-limit=64" ) + set( _CMAKE_C_FLAGS_DEBUG "-marm -Os -finline-limit=64" ) + else() + # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI + # O3 instead of O2/Os in release mode - like cmake sets for desktop gcc + set( _CMAKE_CXX_FLAGS_RELEASE "-marm -O3 -fstrict-aliasing" ) + set( _CMAKE_C_FLAGS_RELEASE "-marm -O3 -fstrict-aliasing" ) + set( _CMAKE_CXX_FLAGS_DEBUG "-marm -O0 -finline-limit=300" ) + set( _CMAKE_C_FLAGS_DEBUG "-marm -O0 -finline-limit=300" ) + endif() +elseif( X86 ) + set( _CMAKE_CXX_FLAGS_RELEASE "-O3 -fstrict-aliasing" ) + set( _CMAKE_C_FLAGS_RELEASE "-O3 -fstrict-aliasing" ) + set( _CMAKE_CXX_FLAGS_DEBUG "-O0 -finline-limit=300" ) + set( _CMAKE_C_FLAGS_DEBUG "-O0 -finline-limit=300" ) +elseif( MIPS ) + set( _CMAKE_CXX_FLAGS_RELEASE "-O3 -funswitch-loops -finline-limit=300" ) + set( _CMAKE_C_FLAGS_RELEASE "-O3 -funswitch-loops -finline-limit=300" ) + set( _CMAKE_CXX_FLAGS_DEBUG "-O0 -g" ) + set( _CMAKE_C_FLAGS_DEBUG "-O0 -g" ) +endif() +set( _CMAKE_CXX_FLAGS_RELEASE "${_CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -DNDEBUG" ) +set( _CMAKE_C_FLAGS_RELEASE "${_CMAKE_C_FLAGS_RELEASE} -fomit-frame-pointer -DNDEBUG" ) +set( _CMAKE_CXX_FLAGS_DEBUG "${_CMAKE_CXX_FLAGS_DEBUG} -fno-strict-aliasing -fno-omit-frame-pointer -DDEBUG -D_DEBUG" ) +set( _CMAKE_C_FLAGS_DEBUG "${_CMAKE_C_FLAGS_DEBUG} -fno-strict-aliasing -fno-omit-frame-pointer -DDEBUG -D_DEBUG" ) + +# ABI-specific flags +if( ARMEABI_V7A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" ) + if( NEON ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) + elseif( VFPV3 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) + endif() +elseif( ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) +elseif( ARMEABI ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) +elseif( X86 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" )#sse? +endif() + +# linker flags +if( NOT DEFINED __ndklibspath ) + set( __ndklibspath "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/ndklibs/${ANDROID_NDK_ABI_NAME}" ) +endif() +list( APPEND ANDROID_SYSTEM_LIB_DIRS "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ) +set( ANDROID_LINKER_FLAGS "" ) + +# STL +if( ANDROID_USE_STLPORT ) + if( EXISTS "${__stlLibPath}/libc++_shared.so" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o \"${__stlLibPath}/libc++_shared.so\" -latomic") + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o \"${__stlLibPath}/libc++_shared.so\" -latomic") + endif() +else( ANDROID_USE_STLPORT ) + if( EXISTS "${__stlLibPath}/libgnustl_static.a" ) + __COPY_IF_DIFFERENT( "${__stlLibPath}/libgnustl_static.a" "${__ndklibspath}/libstdc++.a" ) + elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" ) + __COPY_IF_DIFFERENT( "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" "${__ndklibspath}/libstdc++.a" ) + elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" ) + __COPY_IF_DIFFERENT( "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" "${__ndklibspath}/libstdc++.a" ) + elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${__stlLibPath}/thumb/libstdc++.a" ) + __COPY_IF_DIFFERENT( "${__stlLibPath}/thumb/libstdc++.a" "${__ndklibspath}/libstdc++.a" ) + elseif( EXISTS "${__stlLibPath}/libstdc++.a" ) + __COPY_IF_DIFFERENT( "${__stlLibPath}/libstdc++.a" "${__ndklibspath}/libstdc++.a" ) + endif() + if( EXISTS "${__stlLibPath}/libsupc++.a" ) + __COPY_IF_DIFFERENT( "${__stlLibPath}/libsupc++.a" "${__ndklibspath}/libsupc++.a" ) + elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" ) + __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" "${__ndklibspath}/libsupc++.a" ) + elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" ) + __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" "${__ndklibspath}/libsupc++.a" ) + elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" ) + __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" "${__ndklibspath}/libsupc++.a" ) + elseif( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" ) + __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" "${__ndklibspath}/libsupc++.a" ) + endif() + list( APPEND ANDROID_SYSTEM_LIB_DIRS "${__ndklibspath}" ) +endif( ANDROID_USE_STLPORT ) + +# cleanup for STL search +unset( __stlIncludePath ) +unset( __stlLibPath ) + +# other linker flags +__INIT_VARIABLE( ANDROID_NO_UNDEFINED OBSOLETE_NO_UNDEFINED VALUES ON ) +set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" FORCE ) +mark_as_advanced( ANDROID_NO_UNDEFINED ) +if( ANDROID_NO_UNDEFINED ) + set( ANDROID_LINKER_FLAGS "-Wl,--no-undefined ${ANDROID_LINKER_FLAGS}" ) +endif() + +if (ANDROID_NDK MATCHES "-r[56].?$") + # libGLESv2.so in NDK's prior to r7 refers to exteranal symbols. So this flag option is required for all projects using OpenGL from native. + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON ) +else() + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF ) +endif() + +set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" FORCE ) +mark_as_advanced( ANDROID_SO_UNDEFINED ) +if( ANDROID_SO_UNDEFINED ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" ) +endif() + +__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON ) +set( ANDROID_FUNCTION_LEVEL_LINKING ON CACHE BOOL "Allows or disallows undefined symbols in shared libraries" FORCE ) +mark_as_advanced( ANDROID_FUNCTION_LEVEL_LINKING ) +if( ANDROID_FUNCTION_LEVEL_LINKING ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" ) + set( ANDROID_LINKER_FLAGS "-Wl,--gc-sections ${ANDROID_LINKER_FLAGS}" ) +endif() + +if( ARMEABI_V7A ) + # this is *required* to use the following linker flags that routes around + # a CPU bug in some Cortex-A8 implementations: + set( ANDROID_LINKER_FLAGS "-Wl,--fix-cortex-a8 ${ANDROID_LINKER_FLAGS}" ) +endif() + +# cache flags +set( CMAKE_CXX_FLAGS "${_CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags" ) +set( CMAKE_C_FLAGS "${_CMAKE_C_FLAGS}" CACHE STRING "c flags" ) +set( CMAKE_CXX_FLAGS_RELEASE "${_CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "c++ Release flags" ) +set( CMAKE_C_FLAGS_RELEASE "${_CMAKE_C_FLAGS_RELEASE}" CACHE STRING "c Release flags" ) +set( CMAKE_CXX_FLAGS_DEBUG "${_CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "c++ Debug flags" ) +set( CMAKE_C_FLAGS_DEBUG "${_CMAKE_C_FLAGS_DEBUG}" CACHE STRING "c Debug flags" ) +set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "linker flags" ) +set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "linker flags" ) +set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "linker flags" ) + +include_directories( SYSTEM ${ANDROID_SYSTEM_INCLUDE_DIRS} ) +link_directories( ${ANDROID_SYSTEM_LIB_DIRS} ) + +# finish flags +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Extra Android compiler flags") +set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Extra Android linker flags") +set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) +set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) +if( MIPS AND BUILD_WITH_ANDROID_NDK ) + set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf32btsmip.xsc ${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) + set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf32btsmip.xsc ${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) + set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf32btsmip.x ${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) + # todo: should we use elf64btsmip.xsc on x64 host platforms ? + #set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf64btsmip.xsc ${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) + #set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf64btsmip.xsc ${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) + #set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/mipsel-linux-android/lib/ldscripts/elf64btsmip.x ${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) +else() + set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) + set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) + set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) +endif() + +# set these global flags for cmake client scripts to change behavior +set( ANDROID True ) +set( BUILD_ANDROID True ) + +# where is the target environment +set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) + +# only search for libraries and includes in the ndk toolchain +set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) + + +# macro to find packages on the host OS +macro( find_host_package ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_package( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# macro to find programs on the host OS +macro( find_host_program ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_program( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +macro( ANDROID_GET_ABI_RAWNAME TOOLCHAIN_FLAG VAR ) + if( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI" ) + set( ${VAR} "armeabi" ) + elseif( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI_V7A" ) + set( ${VAR} "armeabi-v7a" ) + elseif( "${TOOLCHAIN_FLAG}" STREQUAL "X86" ) + set( ${VAR} "x86" ) + else() + set( ${VAR} "unknown" ) + endif() +endmacro() + + +# export toolchain settings for the try_compile() command +if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" ) + set( __toolchain_config "") + foreach( __var ANDROID_ABI ANDROID_FORCE_ARM_BUILD ANDROID_NATIVE_API_LEVEL ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_SET_OBSOLETE_VARIABLES LIBRARY_OUTPUT_PATH_ROOT ANDROID_USE_STLPORT ANDROID_FORBID_SYGWIN ANDROID_NDK ANDROID_STANDALONE_TOOLCHAIN ANDROID_FUNCTION_LEVEL_LINKING __ndklibspath ) + if( DEFINED ${__var} ) + if( "${__var}" MATCHES " ") + set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" ) + else() + set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" ) + endif() + endif() + endforeach() + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" ) + unset( __toolchain_config ) + unset( __ndklibspath ) +endif() + + +# set some obsolete variables for backward compatibility +set( ANDROID_SET_OBSOLETE_VARIABLES ON CACHE BOOL "Define obsolete Andrid-specific cmake variables" ) +mark_as_advanced( ANDROID_SET_OBSOLETE_VARIABLES ) +if( ANDROID_SET_OBSOLETE_VARIABLES ) + set( ANDROID_API_LEVEL ${ANDROID_NATIVE_API_LEVEL} ) + set( ARM_TARGET "${ANDROID_ABI}" ) + set( ARMEABI_NDK_NAME "${ANDROID_NDK_ABI_NAME}" ) +endif() + +# don't leave libs/ directories in source directory +set(LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_LIBRARY_DIR}) + +# Variables controlling behavior or set by cmake toolchain: +# ANDROID_ABI: "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips" +# ANDROID_NATIVE_API_LEVEL: 3,4,5,8,9,14 (depends on NDK version) +# ANDROID_SET_OBSOLETE_VARIABLES: ON/OFF +# ANDROID_USE_STLPORT: OFF/ON - EXPERIMENTAL!!! +# ANDROID_FORBID_SYGWIN: ON/OFF +# ANDROID_NO_UNDEFINED: ON/OFF +# ANDROID_SO_UNDEFINED: OFF/ON (default depends on NDK version) +# ANDROID_FUNCTION_LEVEL_LINKING: ON/OFF +# Variables that takes effect only at first run: +# ANDROID_FORCE_ARM_BUILD: ON/OFF +# LIBRARY_OUTPUT_PATH_ROOT: +# Can be set only at the first run: +# ANDROID_NDK +# ANDROID_STANDALONE_TOOLCHAIN +# ANDROID_TOOLCHAIN_NAME: "arm-linux-androideabi-4.4.3" or "arm-linux-androideabi-4.6" or "mipsel-linux-android-4.4.3" or "mipsel-linux-android-4.6" or "x86-4.4.3" or "x86-4.6" +# Obsolete: +# ANDROID_API_LEVEL: superseded by ANDROID_NATIVE_API_LEVEL +# ARM_TARGET: superseded by ANDROID_ABI +# ARM_TARGETS: superseded by ANDROID_ABI (can be set only) +# ANDROID_NDK_TOOLCHAIN_ROOT: superseded by ANDROID_STANDALONE_TOOLCHAIN (can be set only) +# ANDROID_LEVEL: superseded by ANDROID_NATIVE_API_LEVEL (completely removed) +# +# Primary read-only variables: +# ANDROID: always TRUE +# ARMEABI: TRUE for arm v6 and older devices +# ARMEABI_V6: TRUE for arm v6 +# ARMEABI_V7A: TRUE for arm v7a +# NEON: TRUE if NEON unit is enabled +# VFPV3: TRUE if VFP version 3 is enabled +# X86: TRUE if configured for x86 +# BUILD_ANDROID: always TRUE +# BUILD_WITH_ANDROID_NDK: TRUE if NDK is used +# BUILD_WITH_STANDALONE_TOOLCHAIN: TRUE if standalone toolchain is used +# ANDROID_NDK_HOST_SYSTEM_NAME: "windows", "linux-x86" or "darwin-x86" depending on host platform +# ANDROID_NDK_HOST_SYSTEM_ARCH: "x86", "x64" depending on host platform +# ANDROID_NDK_ABI_NAME: "armeabi", "armeabi-v7a" or "x86" depending on ANDROID_ABI +# ANDROID_ARCH_NAME: "arm" or "x86" or "mips" depending on ANDROID_ABI +# TOOL_OS_SUFFIX: "" or ".exe" depending on host platform +# ANDROID_SYSROOT: path to the compiler sysroot +# ANDROID_SYSTEM_INCLUDE_DIRS +# ANDROID_SYSTEM_LIB_DIRS +# Obsolete: +# ARMEABI_NDK_NAME: superseded by ANDROID_NDK_ABI_NAME +# +# Secondary (less stable) read-only variables: +# ANDROID_COMPILER_VERSION: GCC version used +# ANDROID_CXX_FLAGS: C/C++ compiler flags required by Android platform +# ANDROID_SUPPORTED_ABIS: list of currently allowed values for ANDROID_ABI +# ANDROID_TOOLCHAIN_MACHINE_NAME: "arm-linux-androideabi", "arm-eabi" or "i686-android-linux" +# ANDROID_TOOLCHAIN_ROOT: path to the top level of toolchain (standalone or placed inside NDK) +# ANDROID_SUPPORTED_NATIVE_API_LEVELS: list of native API levels found inside NDK +# +# Defaults: +# ANDROID_DEFAULT_NDK_API_LEVEL +# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH} +# ANDROID_NDK_SEARCH_PATHS +# ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH +# ANDROID_SUPPORTED_ABIS_${ARCH} +# ANDROID_SUPPORTED_NDK_VERSIONS diff --git a/doc/footer.htm b/doc/footer.htm index 0e67142e..bc149dfe 100644 --- a/doc/footer.htm +++ b/doc/footer.htm @@ -1,9 +1,9 @@ - - - - + + + + diff --git a/doc/header.htm b/doc/header.htm index c1a6be4b..cb749e64 100644 --- a/doc/header.htm +++ b/doc/header.htm @@ -1,15 +1,15 @@ - - - - SFML - Simple and Fast Multimedia Library - - - - - - -
+ + + + SFML - Simple and Fast Multimedia Library + + + + + + +
diff --git a/doc/mainpage.hpp b/doc/mainpage.hpp index 9ec687c3..ed6bea81 100644 --- a/doc/mainpage.hpp +++ b/doc/mainpage.hpp @@ -1,71 +1,71 @@ -//////////////////////////////////////////////////////////// -/// \mainpage -/// -/// \section welcome Welcome -/// Welcome to the official SFML documentation. Here you will find a detailed -/// view of all the SFML classes and functions.
-/// If you are looking for tutorials, you can visit the official website -/// at www.sfml-dev.org. -/// -/// \section example Short example -/// Here is a short example, to show you how simple it is to use SFML : -/// -/// \code -/// -/// #include -/// #include -/// -/// int main() -/// { -/// // Create the main window -/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); -/// -/// // Load a sprite to display -/// sf::Texture texture; -/// if (!texture.loadFromFile("cute_image.jpg")) -/// return EXIT_FAILURE; -/// sf::Sprite sprite(texture); -/// -/// // Create a graphical text to display -/// sf::Font font; -/// if (!font.loadFromFile("arial.ttf")) -/// return EXIT_FAILURE; -/// sf::Text text("Hello SFML", font, 50); -/// -/// // Load a music to play -/// sf::Music music; -/// if (!music.openFromFile("nice_music.ogg")) -/// return EXIT_FAILURE; -/// -/// // Play the music -/// music.play(); -/// -/// // Start the game loop -/// while (window.isOpen()) -/// { -/// // Process events -/// sf::Event event; -/// while (window.pollEvent(event)) -/// { -/// // Close window : exit -/// if (event.type == sf::Event::Closed) -/// window.close(); -/// } -/// -/// // Clear screen -/// window.clear(); -/// -/// // Draw the sprite -/// window.draw(sprite); -/// -/// // Draw the string -/// window.draw(text); -/// -/// // Update the window -/// window.display(); -/// } -/// -/// return EXIT_SUCCESS; -/// } -/// \endcode -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +/// \mainpage +/// +/// \section welcome Welcome +/// Welcome to the official SFML documentation. Here you will find a detailed +/// view of all the SFML classes and functions.
+/// If you are looking for tutorials, you can visit the official website +/// at www.sfml-dev.org. +/// +/// \section example Short example +/// Here is a short example, to show you how simple it is to use SFML: +/// +/// \code +/// +/// #include +/// #include +/// +/// int main() +/// { +/// // Create the main window +/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); +/// +/// // Load a sprite to display +/// sf::Texture texture; +/// if (!texture.loadFromFile("cute_image.jpg")) +/// return EXIT_FAILURE; +/// sf::Sprite sprite(texture); +/// +/// // Create a graphical text to display +/// sf::Font font; +/// if (!font.loadFromFile("arial.ttf")) +/// return EXIT_FAILURE; +/// sf::Text text("Hello SFML", font, 50); +/// +/// // Load a music to play +/// sf::Music music; +/// if (!music.openFromFile("nice_music.ogg")) +/// return EXIT_FAILURE; +/// +/// // Play the music +/// music.play(); +/// +/// // Start the game loop +/// while (window.isOpen()) +/// { +/// // Process events +/// sf::Event event; +/// while (window.pollEvent(event)) +/// { +/// // Close window: exit +/// if (event.type == sf::Event::Closed) +/// window.close(); +/// } +/// +/// // Clear screen +/// window.clear(); +/// +/// // Draw the sprite +/// window.draw(sprite); +/// +/// // Draw the string +/// window.draw(text); +/// +/// // Update the window +/// window.display(); +/// } +/// +/// return EXIT_SUCCESS; +/// } +/// \endcode +//////////////////////////////////////////////////////////// diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 16a8711a..a55137d6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,18 +1,18 @@ - + # add the examples subdirectories -add_subdirectory(ftp) -add_subdirectory(opengl) -add_subdirectory(pong) -add_subdirectory(shader) -add_subdirectory(sockets) -add_subdirectory(sound) -add_subdirectory(sound_capture) -add_subdirectory(voip) -add_subdirectory(window) -if(SFML_OS_WINDOWS) - add_subdirectory(win32) -elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD) +add_subdirectory(ftp) +add_subdirectory(opengl) +add_subdirectory(pong) +add_subdirectory(shader) +add_subdirectory(sockets) +add_subdirectory(sound) +add_subdirectory(sound_capture) +add_subdirectory(voip) +add_subdirectory(window) +if(SFML_OS_WINDOWS) + add_subdirectory(win32) +elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD) add_subdirectory(X11) -elseif(SFML_OS_MACOSX) - add_subdirectory(cocoa) -endif() +elseif(SFML_OS_MACOSX) + add_subdirectory(cocoa) +endif() diff --git a/examples/X11/CMakeLists.txt b/examples/X11/CMakeLists.txt index d63ca9fc..75f3cc3e 100644 --- a/examples/X11/CMakeLists.txt +++ b/examples/X11/CMakeLists.txt @@ -1,16 +1,16 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/X11) - -# all source files -set(SRC ${SRCROOT}/X11.cpp) - -# find OpenGL, GLU and X11 -find_package(OpenGL REQUIRED) -include_directories(${OPENGL_INCLUDE_DIR}) -find_package(X11 REQUIRED) -include_directories(${X11_INCLUDE_DIR}) - -# define the X11 target -sfml_add_example(X11 GUI_APP - SOURCES ${SRC} - DEPENDS sfml-window sfml-system ${OPENGL_LIBRARIES} ${X11_LIBRARIES}) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/X11) + +# all source files +set(SRC ${SRCROOT}/X11.cpp) + +# find OpenGL, GLU and X11 +find_package(OpenGL REQUIRED) +include_directories(${OPENGL_INCLUDE_DIR}) +find_package(X11 REQUIRED) +include_directories(${X11_INCLUDE_DIR}) + +# define the X11 target +sfml_add_example(X11 GUI_APP + SOURCES ${SRC} + DEPENDS sfml-window sfml-system ${OPENGL_LIBRARIES} ${X11_LIBRARIES}) diff --git a/examples/X11/X11.cpp b/examples/X11/X11.cpp index 2ffa08b4..17bb4488 100644 --- a/examples/X11/X11.cpp +++ b/examples/X11/X11.cpp @@ -1,199 +1,199 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -//////////////////////////////////////////////////////////// -/// Initialize OpenGL states into the specified view -/// -/// \param Window Target window to initialize -/// -//////////////////////////////////////////////////////////// -void initialize(sf::Window& window) -{ - // Activate the window - window.setActive(); - - // Setup OpenGL states - // Set color and depth clear value - glClearDepth(1.f); - glClearColor(0.f, 0.5f, 0.5f, 0.f); - - // Enable Z-buffer read and write - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); - - // Setup a perspective projection - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(90.f, 1.f, 1.f, 500.f); -} - -//////////////////////////////////////////////////////////// -/// Draw the OpenGL scene (a rotating cube) into -/// the specified view -/// -/// \param window Target window for rendering -/// \param elapsedTime Time elapsed since the last draw -/// -//////////////////////////////////////////////////////////// -void draw(sf::Window& window, float elapsedTime) -{ - // Activate the window - window.setActive(); - - // Clear color and depth buffers - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Apply some transformations - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.f, 0.f, -200.f); - glRotatef(elapsedTime * 0.05f, 1.f, 0.f, 0.f); - glRotatef(elapsedTime * 0.03f, 0.f, 1.f, 0.f); - glRotatef(elapsedTime * 0.09f, 0.f, 0.f, 1.f); - - // Draw a cube - glBegin(GL_QUADS); - - glColor3f(1.f, 1.f, 0.f); - glVertex3f(-50.f, -50.f, -50.f); - glVertex3f(-50.f, 50.f, -50.f); - glVertex3f( 50.f, 50.f, -50.f); - glVertex3f( 50.f, -50.f, -50.f); - - glColor3f(1.f, 1.f, 0.f); - glVertex3f(-50.f, -50.f, 50.f); - glVertex3f(-50.f, 50.f, 50.f); - glVertex3f( 50.f, 50.f, 50.f); - glVertex3f( 50.f, -50.f, 50.f); - - glColor3f(0.f, 1.f, 1.f); - glVertex3f(-50.f, -50.f, -50.f); - glVertex3f(-50.f, 50.f, -50.f); - glVertex3f(-50.f, 50.f, 50.f); - glVertex3f(-50.f, -50.f, 50.f); - - glColor3f(0.f, 1.f, 1.f); - glVertex3f(50.f, -50.f, -50.f); - glVertex3f(50.f, 50.f, -50.f); - glVertex3f(50.f, 50.f, 50.f); - glVertex3f(50.f, -50.f, 50.f); - - glColor3f(1.f, 0.f, 1.f); - glVertex3f(-50.f, -50.f, 50.f); - glVertex3f(-50.f, -50.f, -50.f); - glVertex3f( 50.f, -50.f, -50.f); - glVertex3f( 50.f, -50.f, 50.f); - - glColor3f(1.f, 0.f, 1.f); - glVertex3f(-50.f, 50.f, 50.f); - glVertex3f(-50.f, 50.f, -50.f); - glVertex3f( 50.f, 50.f, -50.f); - glVertex3f( 50.f, 50.f, 50.f); - - glEnd(); -} - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \return Error code -/// -//////////////////////////////////////////////////////////// -int main() -{ - // Open a connection with the X server - Display* display = XOpenDisplay(NULL); - if (!display) - return EXIT_FAILURE; - - // Get the default screen - int screen = DefaultScreen(display); - - // Let's create the main window - XSetWindowAttributes attributes; - attributes.background_pixel = BlackPixel(display, screen); - attributes.event_mask = KeyPressMask; - Window window = XCreateWindow(display, RootWindow(display, screen), - 0, 0, 650, 330, 0, - DefaultDepth(display, screen), - InputOutput, - DefaultVisual(display, screen), - CWBackPixel | CWEventMask, &attributes); - if (!window) - return EXIT_FAILURE; - - // Set the window's name - XStoreName(display, window , "SFML Window"); - - // Let's create the windows which will serve as containers for our SFML views - Window view1 = XCreateWindow(display, window, - 10, 10, 310, 310, 0, - DefaultDepth(display, screen), - InputOutput, - DefaultVisual(display, screen), - 0, NULL); - Window view2 = XCreateWindow(display, window, - 330, 10, 310, 310, 0, - DefaultDepth(display, screen), - InputOutput, - DefaultVisual(display, screen), - 0, NULL); - - // Show our windows - XMapWindow(display, window); - XFlush(display); - - // Create our SFML views - sf::Window SFMLView1(view1); - sf::Window SFMLView2(view2); - - // Create a clock for measuring elapsed time - sf::Clock clock; - - // Initialize our views - initialize(SFMLView1); - initialize(SFMLView2); - - // Start the event loop - bool running = true; - while (running) - { - while (XPending(display)) - { - // Get the next pending event - XEvent event; - XNextEvent(display, &event); - - // Process it - switch (event.type) - { - // Any key is pressed : quit - case KeyPress : - running = false; - break; - } - } - - // Draw something into our views - draw(SFMLView1, clock.getElapsedTime().asSeconds()); - draw(SFMLView2, clock.getElapsedTime().asSeconds() * 0.3f); - - // Display the views on screen - SFMLView1.display(); - SFMLView2.display(); - } - - // Close the display - XCloseDisplay(display); - - return EXIT_SUCCESS; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +//////////////////////////////////////////////////////////// +/// Initialize OpenGL states into the specified view +/// +/// \param Window Target window to initialize +/// +//////////////////////////////////////////////////////////// +void initialize(sf::Window& window) +{ + // Activate the window + window.setActive(); + + // Setup OpenGL states + // Set color and depth clear value + glClearDepth(1.f); + glClearColor(0.f, 0.5f, 0.5f, 0.f); + + // Enable Z-buffer read and write + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); + + // Setup a perspective projection + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(90.f, 1.f, 1.f, 500.f); +} + +//////////////////////////////////////////////////////////// +/// Draw the OpenGL scene (a rotating cube) into +/// the specified view +/// +/// \param window Target window for rendering +/// \param elapsedTime Time elapsed since the last draw +/// +//////////////////////////////////////////////////////////// +void draw(sf::Window& window, float elapsedTime) +{ + // Activate the window + window.setActive(); + + // Clear color and depth buffers + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Apply some transformations + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.f, 0.f, -200.f); + glRotatef(elapsedTime * 0.05f, 1.f, 0.f, 0.f); + glRotatef(elapsedTime * 0.03f, 0.f, 1.f, 0.f); + glRotatef(elapsedTime * 0.09f, 0.f, 0.f, 1.f); + + // Draw a cube + glBegin(GL_QUADS); + + glColor3f(1.f, 1.f, 0.f); + glVertex3f(-50.f, -50.f, -50.f); + glVertex3f(-50.f, 50.f, -50.f); + glVertex3f( 50.f, 50.f, -50.f); + glVertex3f( 50.f, -50.f, -50.f); + + glColor3f(1.f, 1.f, 0.f); + glVertex3f(-50.f, -50.f, 50.f); + glVertex3f(-50.f, 50.f, 50.f); + glVertex3f( 50.f, 50.f, 50.f); + glVertex3f( 50.f, -50.f, 50.f); + + glColor3f(0.f, 1.f, 1.f); + glVertex3f(-50.f, -50.f, -50.f); + glVertex3f(-50.f, 50.f, -50.f); + glVertex3f(-50.f, 50.f, 50.f); + glVertex3f(-50.f, -50.f, 50.f); + + glColor3f(0.f, 1.f, 1.f); + glVertex3f(50.f, -50.f, -50.f); + glVertex3f(50.f, 50.f, -50.f); + glVertex3f(50.f, 50.f, 50.f); + glVertex3f(50.f, -50.f, 50.f); + + glColor3f(1.f, 0.f, 1.f); + glVertex3f(-50.f, -50.f, 50.f); + glVertex3f(-50.f, -50.f, -50.f); + glVertex3f( 50.f, -50.f, -50.f); + glVertex3f( 50.f, -50.f, 50.f); + + glColor3f(1.f, 0.f, 1.f); + glVertex3f(-50.f, 50.f, 50.f); + glVertex3f(-50.f, 50.f, -50.f); + glVertex3f( 50.f, 50.f, -50.f); + glVertex3f( 50.f, 50.f, 50.f); + + glEnd(); +} + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \return Error code +/// +//////////////////////////////////////////////////////////// +int main() +{ + // Open a connection with the X server + Display* display = XOpenDisplay(NULL); + if (!display) + return EXIT_FAILURE; + + // Get the default screen + int screen = DefaultScreen(display); + + // Let's create the main window + XSetWindowAttributes attributes; + attributes.background_pixel = BlackPixel(display, screen); + attributes.event_mask = KeyPressMask; + Window window = XCreateWindow(display, RootWindow(display, screen), + 0, 0, 650, 330, 0, + DefaultDepth(display, screen), + InputOutput, + DefaultVisual(display, screen), + CWBackPixel | CWEventMask, &attributes); + if (!window) + return EXIT_FAILURE; + + // Set the window's name + XStoreName(display, window , "SFML Window"); + + // Let's create the windows which will serve as containers for our SFML views + Window view1 = XCreateWindow(display, window, + 10, 10, 310, 310, 0, + DefaultDepth(display, screen), + InputOutput, + DefaultVisual(display, screen), + 0, NULL); + Window view2 = XCreateWindow(display, window, + 330, 10, 310, 310, 0, + DefaultDepth(display, screen), + InputOutput, + DefaultVisual(display, screen), + 0, NULL); + + // Show our windows + XMapWindow(display, window); + XFlush(display); + + // Create our SFML views + sf::Window SFMLView1(view1); + sf::Window SFMLView2(view2); + + // Create a clock for measuring elapsed time + sf::Clock clock; + + // Initialize our views + initialize(SFMLView1); + initialize(SFMLView2); + + // Start the event loop + bool running = true; + while (running) + { + while (XPending(display)) + { + // Get the next pending event + XEvent event; + XNextEvent(display, &event); + + // Process it + switch (event.type) + { + // Any key is pressed: quit + case KeyPress: + running = false; + break; + } + } + + // Draw something into our views + draw(SFMLView1, clock.getElapsedTime().asSeconds()); + draw(SFMLView2, clock.getElapsedTime().asSeconds() * 0.3f); + + // Display the views on screen + SFMLView1.display(); + SFMLView2.display(); + } + + // Close the display + XCloseDisplay(display); + + return EXIT_SUCCESS; +} diff --git a/examples/cocoa/CMakeLists.txt b/examples/cocoa/CMakeLists.txt index b8b2b4ee..6eebf8f3 100644 --- a/examples/cocoa/CMakeLists.txt +++ b/examples/cocoa/CMakeLists.txt @@ -1,8 +1,8 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/cocoa) - -# all source files -set(SRC ${SRCROOT}/CocoaAppDelegate.h + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/cocoa) + +# all source files +set(SRC ${SRCROOT}/CocoaAppDelegate.h ${SRCROOT}/CocoaAppDelegate.mm ${SRCROOT}/NSString+stdstring.h ${SRCROOT}/NSString+stdstring.mm @@ -28,9 +28,9 @@ set_target_properties(cocoa PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${SRCROOT}/resources/Cocoa-Info.plist) target_link_libraries(cocoa "-framework Cocoa -framework Foundation" sfml-system sfml-window sfml-graphics) - -# set the target's folder (for IDEs that support it, e.g. Visual Studio) -set_target_properties(cocoa PROPERTIES FOLDER "Examples") + +# set the target's folder (for IDEs that support it, e.g. Visual Studio) +set_target_properties(cocoa PROPERTIES FOLDER "Examples") # compile XIB files find_program(IBTOOL ibtool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin") @@ -48,20 +48,20 @@ foreach(XIB ${XIBS}) --compile ${XIB_OUTPUT_PATH}/${XIB}.nib ${XIB_INPUT_PATH}/${XIB}.xib COMMENT "Compiling ${XIB}.xib") - # deactivated options : --warnings --notices + # deactivated options: --warnings --notices endforeach() # add install rule -install(TARGETS cocoa +install(TARGETS cocoa BUNDLE DESTINATION ${INSTALL_MISC_DIR}/examples/cocoa - COMPONENT examples) + COMPONENT examples) -# +# # define the cocoa target # sfml_add_example is not compatible with application bundles ! -# -#sfml_add_example(cocoa -# SOURCES ${SRC} +# +#sfml_add_example(cocoa +# SOURCES ${SRC} # DEPENDS sfml-system sfml-window sfml-graphics) # - + diff --git a/examples/cocoa/CocoaAppDelegate.h b/examples/cocoa/CocoaAppDelegate.h index 3c0d1901..388b3951 100644 --- a/examples/cocoa/CocoaAppDelegate.h +++ b/examples/cocoa/CocoaAppDelegate.h @@ -27,11 +27,11 @@ #import /* - * NB : We need pointers for C++ objects fields in Obj-C interface ! - * The recommended way is to use PIMP idiom. + * NB: We need pointers for C++ objects fields in Obj-C interface ! + * The recommended way is to use PIMPL idiom. * - * It's elegant. Moreover, we do no constrain - * other file including this one to be Obj-C++. + * It's elegant. Moreover, we do no constrain + * other file including this one to be Obj-C++. */ struct SFMLmainWindow; diff --git a/examples/ftp/CMakeLists.txt b/examples/ftp/CMakeLists.txt index 7ef96842..b154e5e0 100644 --- a/examples/ftp/CMakeLists.txt +++ b/examples/ftp/CMakeLists.txt @@ -1,10 +1,10 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/ftp) - -# all source files -set(SRC ${SRCROOT}/Ftp.cpp) - -# define the ftp target -sfml_add_example(ftp - SOURCES ${SRC} - DEPENDS sfml-network sfml-system) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/ftp) + +# all source files +set(SRC ${SRCROOT}/Ftp.cpp) + +# define the ftp target +sfml_add_example(ftp + SOURCES ${SRC} + DEPENDS sfml-network sfml-system) diff --git a/examples/ftp/Ftp.cpp b/examples/ftp/Ftp.cpp index 7b978609..e4de8adc 100644 --- a/examples/ftp/Ftp.cpp +++ b/examples/ftp/Ftp.cpp @@ -1,206 +1,206 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -//////////////////////////////////////////////////////////// -/// Print a FTP response into a standard output stream -/// -//////////////////////////////////////////////////////////// -std::ostream& operator <<(std::ostream& stream, const sf::Ftp::Response& response) -{ - return stream << response.getStatus() << response.getMessage(); -} - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \return Application exit code -/// -//////////////////////////////////////////////////////////// -int main() -{ - // Choose the server address - sf::IpAddress address; - do - { - std::cout << "Enter the FTP server address : "; - std::cin >> address; - } - while (address == sf::IpAddress::None); - - // Connect to the server - sf::Ftp server; - sf::Ftp::Response connectResponse = server.connect(address); - std::cout << connectResponse << std::endl; - if (!connectResponse.isOk()) - return EXIT_FAILURE; - - // Ask for user name and password - std::string user, password; - std::cout << "User name : "; - std::cin >> user; - std::cout << "Password : "; - std::cin >> password; - - // Login to the server - sf::Ftp::Response loginResponse = server.login(user, password); - std::cout << loginResponse << std::endl; - if (!loginResponse.isOk()) - return EXIT_FAILURE; - - // Main menu - int choice = 0; - do - { - // Main FTP menu - std::cout << std::endl; - std::cout << "Choose an action:" << std::endl; - std::cout << "1. Print working directory" << std::endl; - std::cout << "2. Print contents of working directory" << std::endl; - std::cout << "3. Change directory" << std::endl; - std::cout << "4. Create directory" << std::endl; - std::cout << "5. Delete directory" << std::endl; - std::cout << "6. Rename file" << std::endl; - std::cout << "7. Remove file" << std::endl; - std::cout << "8. Download file" << std::endl; - std::cout << "9. Upload file" << std::endl; - std::cout << "0. Disconnect" << std::endl; - std::cout << std::endl; - - std::cout << "Your choice: "; - std::cin >> choice; - std::cout << std::endl; - - switch (choice) - { - default : - { - // Wrong choice - std::cout << "Invalid choice!" << std::endl; - std::cin.clear(); - std::cin.ignore(10000, '\n'); - break; - } - - case 1 : - { - // Print the current server directory - sf::Ftp::DirectoryResponse response = server.getWorkingDirectory(); - std::cout << response << std::endl; - std::cout << "Current directory is " << response.getDirectory() << std::endl; - break; - } - - case 2 : - { - // Print the contents of the current server directory - sf::Ftp::ListingResponse response = server.getDirectoryListing(); - std::cout << response << std::endl; - const std::vector& names = response.getListing(); - for (std::vector::const_iterator it = names.begin(); it != names.end(); ++it) - std::cout << *it << std::endl; - break; - } - - case 3 : - { - // Change the current directory - std::string directory; - std::cout << "Choose a directory: "; - std::cin >> directory; - std::cout << server.changeDirectory(directory) << std::endl; - break; - } - - case 4 : - { - // Create a new directory - std::string directory; - std::cout << "Name of the directory to create: "; - std::cin >> directory; - std::cout << server.createDirectory(directory) << std::endl; - break; - } - - case 5 : - { - // Remove an existing directory - std::string directory; - std::cout << "Name of the directory to remove: "; - std::cin >> directory; - std::cout << server.deleteDirectory(directory) << std::endl; - break; - } - - case 6 : - { - // Rename a file - std::string source, destination; - std::cout << "Name of the file to rename: "; - std::cin >> source; - std::cout << "New name: "; - std::cin >> destination; - std::cout << server.renameFile(source, destination) << std::endl; - break; - } - - case 7 : - { - // Remove an existing directory - std::string filename; - std::cout << "Name of the file to remove: "; - std::cin >> filename; - std::cout << server.deleteFile(filename) << std::endl; - break; - } - - case 8 : - { - // Download a file from server - std::string filename, directory; - std::cout << "Filename of the file to download (relative to current directory): "; - std::cin >> filename; - std::cout << "Directory to download the file to: "; - std::cin >> directory; - std::cout << server.download(filename, directory) << std::endl; - break; - } - - case 9 : - { - // Upload a file to server - std::string filename, directory; - std::cout << "Path of the file to upload (absolute or relative to working directory): "; - std::cin >> filename; - std::cout << "Directory to upload the file to (relative to current directory): "; - std::cin >> directory; - std::cout << server.upload(filename, directory) << std::endl; - break; - } - - case 0 : - { - // Disconnect - break; - } - } - - } while (choice != 0); - - // Disconnect from the server - std::cout << "Disconnecting from server..." << std::endl; - std::cout << server.disconnect() << std::endl; - - // Wait until the user presses 'enter' key - std::cout << "Press enter to exit..." << std::endl; - std::cin.ignore(10000, '\n'); - std::cin.ignore(10000, '\n'); - - return EXIT_SUCCESS; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +//////////////////////////////////////////////////////////// +/// Print a FTP response into a standard output stream +/// +//////////////////////////////////////////////////////////// +std::ostream& operator <<(std::ostream& stream, const sf::Ftp::Response& response) +{ + return stream << response.getStatus() << response.getMessage(); +} + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \return Application exit code +/// +//////////////////////////////////////////////////////////// +int main() +{ + // Choose the server address + sf::IpAddress address; + do + { + std::cout << "Enter the FTP server address: "; + std::cin >> address; + } + while (address == sf::IpAddress::None); + + // Connect to the server + sf::Ftp server; + sf::Ftp::Response connectResponse = server.connect(address); + std::cout << connectResponse << std::endl; + if (!connectResponse.isOk()) + return EXIT_FAILURE; + + // Ask for user name and password + std::string user, password; + std::cout << "User name: "; + std::cin >> user; + std::cout << "Password: "; + std::cin >> password; + + // Login to the server + sf::Ftp::Response loginResponse = server.login(user, password); + std::cout << loginResponse << std::endl; + if (!loginResponse.isOk()) + return EXIT_FAILURE; + + // Main menu + int choice = 0; + do + { + // Main FTP menu + std::cout << std::endl; + std::cout << "Choose an action:" << std::endl; + std::cout << "1. Print working directory" << std::endl; + std::cout << "2. Print contents of working directory" << std::endl; + std::cout << "3. Change directory" << std::endl; + std::cout << "4. Create directory" << std::endl; + std::cout << "5. Delete directory" << std::endl; + std::cout << "6. Rename file" << std::endl; + std::cout << "7. Remove file" << std::endl; + std::cout << "8. Download file" << std::endl; + std::cout << "9. Upload file" << std::endl; + std::cout << "0. Disconnect" << std::endl; + std::cout << std::endl; + + std::cout << "Your choice: "; + std::cin >> choice; + std::cout << std::endl; + + switch (choice) + { + default: + { + // Wrong choice + std::cout << "Invalid choice!" << std::endl; + std::cin.clear(); + std::cin.ignore(10000, '\n'); + break; + } + + case 1: + { + // Print the current server directory + sf::Ftp::DirectoryResponse response = server.getWorkingDirectory(); + std::cout << response << std::endl; + std::cout << "Current directory is " << response.getDirectory() << std::endl; + break; + } + + case 2: + { + // Print the contents of the current server directory + sf::Ftp::ListingResponse response = server.getDirectoryListing(); + std::cout << response << std::endl; + const std::vector& names = response.getListing(); + for (std::vector::const_iterator it = names.begin(); it != names.end(); ++it) + std::cout << *it << std::endl; + break; + } + + case 3: + { + // Change the current directory + std::string directory; + std::cout << "Choose a directory: "; + std::cin >> directory; + std::cout << server.changeDirectory(directory) << std::endl; + break; + } + + case 4: + { + // Create a new directory + std::string directory; + std::cout << "Name of the directory to create: "; + std::cin >> directory; + std::cout << server.createDirectory(directory) << std::endl; + break; + } + + case 5: + { + // Remove an existing directory + std::string directory; + std::cout << "Name of the directory to remove: "; + std::cin >> directory; + std::cout << server.deleteDirectory(directory) << std::endl; + break; + } + + case 6: + { + // Rename a file + std::string source, destination; + std::cout << "Name of the file to rename: "; + std::cin >> source; + std::cout << "New name: "; + std::cin >> destination; + std::cout << server.renameFile(source, destination) << std::endl; + break; + } + + case 7: + { + // Remove an existing directory + std::string filename; + std::cout << "Name of the file to remove: "; + std::cin >> filename; + std::cout << server.deleteFile(filename) << std::endl; + break; + } + + case 8: + { + // Download a file from server + std::string filename, directory; + std::cout << "Filename of the file to download (relative to current directory): "; + std::cin >> filename; + std::cout << "Directory to download the file to: "; + std::cin >> directory; + std::cout << server.download(filename, directory) << std::endl; + break; + } + + case 9: + { + // Upload a file to server + std::string filename, directory; + std::cout << "Path of the file to upload (absolute or relative to working directory): "; + std::cin >> filename; + std::cout << "Directory to upload the file to (relative to current directory): "; + std::cin >> directory; + std::cout << server.upload(filename, directory) << std::endl; + break; + } + + case 0: + { + // Disconnect + break; + } + } + + } while (choice != 0); + + // Disconnect from the server + std::cout << "Disconnecting from server..." << std::endl; + std::cout << server.disconnect() << std::endl; + + // Wait until the user presses 'enter' key + std::cout << "Press enter to exit..." << std::endl; + std::cin.ignore(10000, '\n'); + std::cin.ignore(10000, '\n'); + + return EXIT_SUCCESS; +} diff --git a/examples/opengl/CMakeLists.txt b/examples/opengl/CMakeLists.txt index f037488a..5e1571fc 100644 --- a/examples/opengl/CMakeLists.txt +++ b/examples/opengl/CMakeLists.txt @@ -1,15 +1,15 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/opengl) - -# all source files -set(SRC ${SRCROOT}/OpenGL.cpp) - -# find OpenGL and GLU -find_package(OpenGL REQUIRED) -include_directories(${OPENGL_INCLUDE_DIR}) -set(ADDITIONAL_LIBRARIES ${OPENGL_LIBRARIES}) - -# define the opengl target -sfml_add_example(opengl GUI_APP - SOURCES ${SRC} - DEPENDS sfml-graphics sfml-window sfml-system ${ADDITIONAL_LIBRARIES}) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/opengl) + +# all source files +set(SRC ${SRCROOT}/OpenGL.cpp) + +# find OpenGL and GLU +find_package(OpenGL REQUIRED) +include_directories(${OPENGL_INCLUDE_DIR}) +set(ADDITIONAL_LIBRARIES ${OPENGL_LIBRARIES}) + +# define the opengl target +sfml_add_example(opengl GUI_APP + SOURCES ${SRC} + DEPENDS sfml-graphics sfml-window sfml-system ${ADDITIONAL_LIBRARIES}) diff --git a/examples/opengl/OpenGL.cpp b/examples/opengl/OpenGL.cpp index ccb1d34d..c9008014 100644 --- a/examples/opengl/OpenGL.cpp +++ b/examples/opengl/OpenGL.cpp @@ -1,198 +1,198 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \return Application exit code -/// -//////////////////////////////////////////////////////////// -int main() -{ - // Request a 32-bits depth buffer when creating the window - sf::ContextSettings contextSettings; - contextSettings.depthBits = 32; - - // Create the main window - sf::RenderWindow window(sf::VideoMode(800, 600), "SFML graphics with OpenGL", sf::Style::Default, contextSettings); - window.setVerticalSyncEnabled(true); - - // Create a sprite for the background - sf::Texture backgroundTexture; - if (!backgroundTexture.loadFromFile("resources/background.jpg")) - return EXIT_FAILURE; - sf::Sprite background(backgroundTexture); - - // Create some text to draw on top of our OpenGL object - sf::Font font; - if (!font.loadFromFile("resources/sansation.ttf")) - return EXIT_FAILURE; - sf::Text text("SFML / OpenGL demo", font); - text.setColor(sf::Color(255, 255, 255, 170)); - text.setPosition(250.f, 450.f); - - // Make the window the active target for OpenGL calls - // Note: If using sf::Texture or sf::Shader with OpenGL, - // be sure to call sf::Texture::getMaximumSize() and/or - // sf::Shader::isAvailable() at least once before calling - // setActive(), as those functions will cause a context switch - window.setActive(); - - // Load an OpenGL texture. - // We could directly use a sf::Texture as an OpenGL texture (with its Bind() member function), - // but here we want more control on it (generate mipmaps, ...) so we create a new one from an image - GLuint texture = 0; - { - sf::Image image; - if (!image.loadFromFile("resources/texture.jpg")) - return EXIT_FAILURE; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.getSize().x, image.getSize().y, GL_RGBA, GL_UNSIGNED_BYTE, image.getPixelsPtr()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - - // Enable Z-buffer read and write - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); - glClearDepth(1.f); - - // Disable lighting - glDisable(GL_LIGHTING); - - // Configure the viewport (the same size as the window) - glViewport(0, 0, window.getSize().x, window.getSize().y); - - // Setup a perspective projection - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - GLfloat ratio = static_cast(window.getSize().x) / window.getSize().y; - glFrustum(-ratio, ratio, -1.f, 1.f, 1.f, 500.f); - - // Bind the texture - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, texture); - - // Define a 3D cube (6 faces made of 2 triangles composed by 3 vertices) - GLfloat cube[] = - { - // positions // texture coordinates - -20, -20, -20, 0, 0, - -20, 20, -20, 1, 0, - -20, -20, 20, 0, 1, - -20, -20, 20, 0, 1, - -20, 20, -20, 1, 0, - -20, 20, 20, 1, 1, - - 20, -20, -20, 0, 0, - 20, 20, -20, 1, 0, - 20, -20, 20, 0, 1, - 20, -20, 20, 0, 1, - 20, 20, -20, 1, 0, - 20, 20, 20, 1, 1, - - -20, -20, -20, 0, 0, - 20, -20, -20, 1, 0, - -20, -20, 20, 0, 1, - -20, -20, 20, 0, 1, - 20, -20, -20, 1, 0, - 20, -20, 20, 1, 1, - - -20, 20, -20, 0, 0, - 20, 20, -20, 1, 0, - -20, 20, 20, 0, 1, - -20, 20, 20, 0, 1, - 20, 20, -20, 1, 0, - 20, 20, 20, 1, 1, - - -20, -20, -20, 0, 0, - 20, -20, -20, 1, 0, - -20, 20, -20, 0, 1, - -20, 20, -20, 0, 1, - 20, -20, -20, 1, 0, - 20, 20, -20, 1, 1, - - -20, -20, 20, 0, 0, - 20, -20, 20, 1, 0, - -20, 20, 20, 0, 1, - -20, 20, 20, 0, 1, - 20, -20, 20, 1, 0, - 20, 20, 20, 1, 1 - }; - - // Enable position and texture coordinates vertex components - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(3, GL_FLOAT, 5 * sizeof(GLfloat), cube); - glTexCoordPointer(2, GL_FLOAT, 5 * sizeof(GLfloat), cube + 3); - - // Disable normal and color vertex components - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - - // Create a clock for measuring the time elapsed - sf::Clock clock; - - // Start game loop - while (window.isOpen()) - { - // Process events - sf::Event event; - while (window.pollEvent(event)) - { - // Close window : exit - if (event.type == sf::Event::Closed) - window.close(); - - // Escape key : exit - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) - window.close(); - - // Adjust the viewport when the window is resized - if (event.type == sf::Event::Resized) - glViewport(0, 0, event.size.width, event.size.height); - } - - // Draw the background - window.pushGLStates(); - window.draw(background); - window.popGLStates(); - - // Clear the depth buffer - glClear(GL_DEPTH_BUFFER_BIT); - - // We get the position of the mouse cursor, so that we can move the box accordingly - float x = sf::Mouse::getPosition(window).x * 200.f / window.getSize().x - 100.f; - float y = -sf::Mouse::getPosition(window).y * 200.f / window.getSize().y + 100.f; - - // Apply some transformations - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(x, y, -100.f); - glRotatef(clock.getElapsedTime().asSeconds() * 50.f, 1.f, 0.f, 0.f); - glRotatef(clock.getElapsedTime().asSeconds() * 30.f, 0.f, 1.f, 0.f); - glRotatef(clock.getElapsedTime().asSeconds() * 90.f, 0.f, 0.f, 1.f); - - // Draw the cube - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Draw some text on top of our OpenGL object - window.pushGLStates(); - window.draw(text); - window.popGLStates(); - - // Finally, display the rendered frame on screen - window.display(); - } - - // Don't forget to destroy our texture - glDeleteTextures(1, &texture); - - return EXIT_SUCCESS; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \return Application exit code +/// +//////////////////////////////////////////////////////////// +int main() +{ + // Request a 32-bits depth buffer when creating the window + sf::ContextSettings contextSettings; + contextSettings.depthBits = 32; + + // Create the main window + sf::RenderWindow window(sf::VideoMode(800, 600), "SFML graphics with OpenGL", sf::Style::Default, contextSettings); + window.setVerticalSyncEnabled(true); + + // Create a sprite for the background + sf::Texture backgroundTexture; + if (!backgroundTexture.loadFromFile("resources/background.jpg")) + return EXIT_FAILURE; + sf::Sprite background(backgroundTexture); + + // Create some text to draw on top of our OpenGL object + sf::Font font; + if (!font.loadFromFile("resources/sansation.ttf")) + return EXIT_FAILURE; + sf::Text text("SFML / OpenGL demo", font); + text.setColor(sf::Color(255, 255, 255, 170)); + text.setPosition(250.f, 450.f); + + // Make the window the active target for OpenGL calls + // Note: If using sf::Texture or sf::Shader with OpenGL, + // be sure to call sf::Texture::getMaximumSize() and/or + // sf::Shader::isAvailable() at least once before calling + // setActive(), as those functions will cause a context switch + window.setActive(); + + // Load an OpenGL texture. + // We could directly use a sf::Texture as an OpenGL texture (with its Bind() member function), + // but here we want more control on it (generate mipmaps, ...) so we create a new one from an image + GLuint texture = 0; + { + sf::Image image; + if (!image.loadFromFile("resources/texture.jpg")) + return EXIT_FAILURE; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.getSize().x, image.getSize().y, GL_RGBA, GL_UNSIGNED_BYTE, image.getPixelsPtr()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + + // Enable Z-buffer read and write + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); + glClearDepth(1.f); + + // Disable lighting + glDisable(GL_LIGHTING); + + // Configure the viewport (the same size as the window) + glViewport(0, 0, window.getSize().x, window.getSize().y); + + // Setup a perspective projection + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + GLfloat ratio = static_cast(window.getSize().x) / window.getSize().y; + glFrustum(-ratio, ratio, -1.f, 1.f, 1.f, 500.f); + + // Bind the texture + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, texture); + + // Define a 3D cube (6 faces made of 2 triangles composed by 3 vertices) + GLfloat cube[] = + { + // positions // texture coordinates + -20, -20, -20, 0, 0, + -20, 20, -20, 1, 0, + -20, -20, 20, 0, 1, + -20, -20, 20, 0, 1, + -20, 20, -20, 1, 0, + -20, 20, 20, 1, 1, + + 20, -20, -20, 0, 0, + 20, 20, -20, 1, 0, + 20, -20, 20, 0, 1, + 20, -20, 20, 0, 1, + 20, 20, -20, 1, 0, + 20, 20, 20, 1, 1, + + -20, -20, -20, 0, 0, + 20, -20, -20, 1, 0, + -20, -20, 20, 0, 1, + -20, -20, 20, 0, 1, + 20, -20, -20, 1, 0, + 20, -20, 20, 1, 1, + + -20, 20, -20, 0, 0, + 20, 20, -20, 1, 0, + -20, 20, 20, 0, 1, + -20, 20, 20, 0, 1, + 20, 20, -20, 1, 0, + 20, 20, 20, 1, 1, + + -20, -20, -20, 0, 0, + 20, -20, -20, 1, 0, + -20, 20, -20, 0, 1, + -20, 20, -20, 0, 1, + 20, -20, -20, 1, 0, + 20, 20, -20, 1, 1, + + -20, -20, 20, 0, 0, + 20, -20, 20, 1, 0, + -20, 20, 20, 0, 1, + -20, 20, 20, 0, 1, + 20, -20, 20, 1, 0, + 20, 20, 20, 1, 1 + }; + + // Enable position and texture coordinates vertex components + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(3, GL_FLOAT, 5 * sizeof(GLfloat), cube); + glTexCoordPointer(2, GL_FLOAT, 5 * sizeof(GLfloat), cube + 3); + + // Disable normal and color vertex components + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + // Create a clock for measuring the time elapsed + sf::Clock clock; + + // Start game loop + while (window.isOpen()) + { + // Process events + sf::Event event; + while (window.pollEvent(event)) + { + // Close window: exit + if (event.type == sf::Event::Closed) + window.close(); + + // Escape key: exit + if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) + window.close(); + + // Adjust the viewport when the window is resized + if (event.type == sf::Event::Resized) + glViewport(0, 0, event.size.width, event.size.height); + } + + // Draw the background + window.pushGLStates(); + window.draw(background); + window.popGLStates(); + + // Clear the depth buffer + glClear(GL_DEPTH_BUFFER_BIT); + + // We get the position of the mouse cursor, so that we can move the box accordingly + float x = sf::Mouse::getPosition(window).x * 200.f / window.getSize().x - 100.f; + float y = -sf::Mouse::getPosition(window).y * 200.f / window.getSize().y + 100.f; + + // Apply some transformations + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(x, y, -100.f); + glRotatef(clock.getElapsedTime().asSeconds() * 50.f, 1.f, 0.f, 0.f); + glRotatef(clock.getElapsedTime().asSeconds() * 30.f, 0.f, 1.f, 0.f); + glRotatef(clock.getElapsedTime().asSeconds() * 90.f, 0.f, 0.f, 1.f); + + // Draw the cube + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Draw some text on top of our OpenGL object + window.pushGLStates(); + window.draw(text); + window.popGLStates(); + + // Finally, display the rendered frame on screen + window.display(); + } + + // Don't forget to destroy our texture + glDeleteTextures(1, &texture); + + return EXIT_SUCCESS; +} diff --git a/examples/pong/CMakeLists.txt b/examples/pong/CMakeLists.txt index 2a76ecc1..8b1c4bcb 100644 --- a/examples/pong/CMakeLists.txt +++ b/examples/pong/CMakeLists.txt @@ -1,10 +1,10 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/pong) - -# all source files -set(SRC ${SRCROOT}/Pong.cpp) - -# define the pong target -sfml_add_example(pong GUI_APP - SOURCES ${SRC} - DEPENDS sfml-audio sfml-graphics sfml-window sfml-system) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/pong) + +# all source files +set(SRC ${SRCROOT}/Pong.cpp) + +# define the pong target +sfml_add_example(pong GUI_APP + SOURCES ${SRC} + DEPENDS sfml-audio sfml-graphics sfml-window sfml-system) diff --git a/examples/pong/Pong.cpp b/examples/pong/Pong.cpp index 2b6ec1f1..bef98c09 100644 --- a/examples/pong/Pong.cpp +++ b/examples/pong/Pong.cpp @@ -1,241 +1,241 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \return Application exit code -/// -//////////////////////////////////////////////////////////// -int main() -{ - std::srand(static_cast(std::time(NULL))); - - // Define some constants - const float pi = 3.14159f; - const int gameWidth = 800; - const int gameHeight = 600; - sf::Vector2f paddleSize(25, 100); - float ballRadius = 10.f; - - // Create the window of the application - sf::RenderWindow window(sf::VideoMode(gameWidth, gameHeight, 32), "SFML Pong"); - window.setVerticalSyncEnabled(true); - - // Load the sounds used in the game - sf::SoundBuffer ballSoundBuffer; - if (!ballSoundBuffer.loadFromFile("resources/ball.wav")) - return EXIT_FAILURE; - sf::Sound ballSound(ballSoundBuffer); - - // Create the left paddle - sf::RectangleShape leftPaddle; - leftPaddle.setSize(paddleSize - sf::Vector2f(3, 3)); - leftPaddle.setOutlineThickness(3); - leftPaddle.setOutlineColor(sf::Color::Black); - leftPaddle.setFillColor(sf::Color(100, 100, 200)); - leftPaddle.setOrigin(paddleSize / 2.f); - - // Create the right paddle - sf::RectangleShape rightPaddle; - rightPaddle.setSize(paddleSize - sf::Vector2f(3, 3)); - rightPaddle.setOutlineThickness(3); - rightPaddle.setOutlineColor(sf::Color::Black); - rightPaddle.setFillColor(sf::Color(200, 100, 100)); - rightPaddle.setOrigin(paddleSize / 2.f); - - // Create the ball - sf::CircleShape ball; - ball.setRadius(ballRadius - 3); - ball.setOutlineThickness(3); - ball.setOutlineColor(sf::Color::Black); - ball.setFillColor(sf::Color::White); - ball.setOrigin(ballRadius / 2, ballRadius / 2); - - // Load the text font - sf::Font font; - if (!font.loadFromFile("resources/sansation.ttf")) - return EXIT_FAILURE; - - // Initialize the pause message - sf::Text pauseMessage; - pauseMessage.setFont(font); - pauseMessage.setCharacterSize(40); - pauseMessage.setPosition(170.f, 150.f); - pauseMessage.setColor(sf::Color::White); - pauseMessage.setString("Welcome to SFML pong!\nPress space to start the game"); - - // Define the paddles properties - sf::Clock AITimer; - const sf::Time AITime = sf::seconds(0.1f); - const float paddleSpeed = 400.f; - float rightPaddleSpeed = 0.f; - const float ballSpeed = 400.f; - float ballAngle = 0.f; // to be changed later - - sf::Clock clock; - bool isPlaying = false; - while (window.isOpen()) - { - // Handle events - sf::Event event; - while (window.pollEvent(event)) - { - // Window closed or escape key pressed: exit - if ((event.type == sf::Event::Closed) || - ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))) - { - window.close(); - break; - } - - // Space key pressed: play - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space)) - { - if (!isPlaying) - { - // (re)start the game - isPlaying = true; - clock.restart(); - - // Reset the position of the paddles and ball - leftPaddle.setPosition(10 + paddleSize.x / 2, gameHeight / 2); - rightPaddle.setPosition(gameWidth - 10 - paddleSize.x / 2, gameHeight / 2); - ball.setPosition(gameWidth / 2, gameHeight / 2); - - // Reset the ball angle - do - { - // Make sure the ball initial angle is not too much vertical - ballAngle = (std::rand() % 360) * 2 * pi / 360; - } - while (std::abs(std::cos(ballAngle)) < 0.7f); - } - } - } - - if (isPlaying) - { - float deltaTime = clock.restart().asSeconds(); - - // Move the player's paddle - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && - (leftPaddle.getPosition().y - paddleSize.y / 2 > 5.f)) - { - leftPaddle.move(0.f, -paddleSpeed * deltaTime); - } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) && - (leftPaddle.getPosition().y + paddleSize.y / 2 < gameHeight - 5.f)) - { - leftPaddle.move(0.f, paddleSpeed * deltaTime); - } - - // Move the computer's paddle - if (((rightPaddleSpeed < 0.f) && (rightPaddle.getPosition().y - paddleSize.y / 2 > 5.f)) || - ((rightPaddleSpeed > 0.f) && (rightPaddle.getPosition().y + paddleSize.y / 2 < gameHeight - 5.f))) - { - rightPaddle.move(0.f, rightPaddleSpeed * deltaTime); - } - - // Update the computer's paddle direction according to the ball position - if (AITimer.getElapsedTime() > AITime) - { - AITimer.restart(); - if (ball.getPosition().y + ballRadius > rightPaddle.getPosition().y + paddleSize.y / 2) - rightPaddleSpeed = paddleSpeed; - else if (ball.getPosition().y - ballRadius < rightPaddle.getPosition().y - paddleSize.y / 2) - rightPaddleSpeed = -paddleSpeed; - else - rightPaddleSpeed = 0.f; - } - - // Move the ball - float factor = ballSpeed * deltaTime; - ball.move(std::cos(ballAngle) * factor, std::sin(ballAngle) * factor); - - // Check collisions between the ball and the screen - if (ball.getPosition().x - ballRadius < 0.f) - { - isPlaying = false; - pauseMessage.setString("You lost!\nPress space to restart or\nescape to exit"); - } - if (ball.getPosition().x + ballRadius > gameWidth) - { - isPlaying = false; - pauseMessage.setString("You won!\nPress space to restart or\nescape to exit"); - } - if (ball.getPosition().y - ballRadius < 0.f) - { - ballSound.play(); - ballAngle = -ballAngle; - ball.setPosition(ball.getPosition().x, ballRadius + 0.1f); - } - if (ball.getPosition().y + ballRadius > gameHeight) - { - ballSound.play(); - ballAngle = -ballAngle; - ball.setPosition(ball.getPosition().x, gameHeight - ballRadius - 0.1f); - } - - // Check the collisions between the ball and the paddles - // Left Paddle - if (ball.getPosition().x - ballRadius < leftPaddle.getPosition().x + paddleSize.x / 2 && - ball.getPosition().x - ballRadius > leftPaddle.getPosition().x && - ball.getPosition().y + ballRadius >= leftPaddle.getPosition().y - paddleSize.y / 2 && - ball.getPosition().y - ballRadius <= leftPaddle.getPosition().y + paddleSize.y / 2) - { - if (ball.getPosition().y > leftPaddle.getPosition().y) - ballAngle = pi - ballAngle + (std::rand() % 20) * pi / 180; - else - ballAngle = pi - ballAngle - (std::rand() % 20) * pi / 180; - - ballSound.play(); - ball.setPosition(leftPaddle.getPosition().x + ballRadius + paddleSize.x / 2 + 0.1f, ball.getPosition().y); - } - - // Right Paddle - if (ball.getPosition().x + ballRadius > rightPaddle.getPosition().x - paddleSize.x / 2 && - ball.getPosition().x + ballRadius < rightPaddle.getPosition().x && - ball.getPosition().y + ballRadius >= rightPaddle.getPosition().y - paddleSize.y / 2 && - ball.getPosition().y - ballRadius <= rightPaddle.getPosition().y + paddleSize.y / 2) - { - if (ball.getPosition().y > rightPaddle.getPosition().y) - ballAngle = pi - ballAngle + (std::rand() % 20) * pi / 180; - else - ballAngle = pi - ballAngle - (std::rand() % 20) * pi / 180; - - ballSound.play(); - ball.setPosition(rightPaddle.getPosition().x - ballRadius - paddleSize.x / 2 - 0.1f, ball.getPosition().y); - } - } - - // Clear the window - window.clear(sf::Color(50, 200, 50)); - - if (isPlaying) - { - // Draw the paddles and the ball - window.draw(leftPaddle); - window.draw(rightPaddle); - window.draw(ball); - } - else - { - // Draw the pause message - window.draw(pauseMessage); - } - - // Display things on screen - window.display(); - } - - return EXIT_SUCCESS; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \return Application exit code +/// +//////////////////////////////////////////////////////////// +int main() +{ + std::srand(static_cast(std::time(NULL))); + + // Define some constants + const float pi = 3.14159f; + const int gameWidth = 800; + const int gameHeight = 600; + sf::Vector2f paddleSize(25, 100); + float ballRadius = 10.f; + + // Create the window of the application + sf::RenderWindow window(sf::VideoMode(gameWidth, gameHeight, 32), "SFML Pong"); + window.setVerticalSyncEnabled(true); + + // Load the sounds used in the game + sf::SoundBuffer ballSoundBuffer; + if (!ballSoundBuffer.loadFromFile("resources/ball.wav")) + return EXIT_FAILURE; + sf::Sound ballSound(ballSoundBuffer); + + // Create the left paddle + sf::RectangleShape leftPaddle; + leftPaddle.setSize(paddleSize - sf::Vector2f(3, 3)); + leftPaddle.setOutlineThickness(3); + leftPaddle.setOutlineColor(sf::Color::Black); + leftPaddle.setFillColor(sf::Color(100, 100, 200)); + leftPaddle.setOrigin(paddleSize / 2.f); + + // Create the right paddle + sf::RectangleShape rightPaddle; + rightPaddle.setSize(paddleSize - sf::Vector2f(3, 3)); + rightPaddle.setOutlineThickness(3); + rightPaddle.setOutlineColor(sf::Color::Black); + rightPaddle.setFillColor(sf::Color(200, 100, 100)); + rightPaddle.setOrigin(paddleSize / 2.f); + + // Create the ball + sf::CircleShape ball; + ball.setRadius(ballRadius - 3); + ball.setOutlineThickness(3); + ball.setOutlineColor(sf::Color::Black); + ball.setFillColor(sf::Color::White); + ball.setOrigin(ballRadius / 2, ballRadius / 2); + + // Load the text font + sf::Font font; + if (!font.loadFromFile("resources/sansation.ttf")) + return EXIT_FAILURE; + + // Initialize the pause message + sf::Text pauseMessage; + pauseMessage.setFont(font); + pauseMessage.setCharacterSize(40); + pauseMessage.setPosition(170.f, 150.f); + pauseMessage.setColor(sf::Color::White); + pauseMessage.setString("Welcome to SFML pong!\nPress space to start the game"); + + // Define the paddles properties + sf::Clock AITimer; + const sf::Time AITime = sf::seconds(0.1f); + const float paddleSpeed = 400.f; + float rightPaddleSpeed = 0.f; + const float ballSpeed = 400.f; + float ballAngle = 0.f; // to be changed later + + sf::Clock clock; + bool isPlaying = false; + while (window.isOpen()) + { + // Handle events + sf::Event event; + while (window.pollEvent(event)) + { + // Window closed or escape key pressed: exit + if ((event.type == sf::Event::Closed) || + ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))) + { + window.close(); + break; + } + + // Space key pressed: play + if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space)) + { + if (!isPlaying) + { + // (re)start the game + isPlaying = true; + clock.restart(); + + // Reset the position of the paddles and ball + leftPaddle.setPosition(10 + paddleSize.x / 2, gameHeight / 2); + rightPaddle.setPosition(gameWidth - 10 - paddleSize.x / 2, gameHeight / 2); + ball.setPosition(gameWidth / 2, gameHeight / 2); + + // Reset the ball angle + do + { + // Make sure the ball initial angle is not too much vertical + ballAngle = (std::rand() % 360) * 2 * pi / 360; + } + while (std::abs(std::cos(ballAngle)) < 0.7f); + } + } + } + + if (isPlaying) + { + float deltaTime = clock.restart().asSeconds(); + + // Move the player's paddle + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && + (leftPaddle.getPosition().y - paddleSize.y / 2 > 5.f)) + { + leftPaddle.move(0.f, -paddleSpeed * deltaTime); + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) && + (leftPaddle.getPosition().y + paddleSize.y / 2 < gameHeight - 5.f)) + { + leftPaddle.move(0.f, paddleSpeed * deltaTime); + } + + // Move the computer's paddle + if (((rightPaddleSpeed < 0.f) && (rightPaddle.getPosition().y - paddleSize.y / 2 > 5.f)) || + ((rightPaddleSpeed > 0.f) && (rightPaddle.getPosition().y + paddleSize.y / 2 < gameHeight - 5.f))) + { + rightPaddle.move(0.f, rightPaddleSpeed * deltaTime); + } + + // Update the computer's paddle direction according to the ball position + if (AITimer.getElapsedTime() > AITime) + { + AITimer.restart(); + if (ball.getPosition().y + ballRadius > rightPaddle.getPosition().y + paddleSize.y / 2) + rightPaddleSpeed = paddleSpeed; + else if (ball.getPosition().y - ballRadius < rightPaddle.getPosition().y - paddleSize.y / 2) + rightPaddleSpeed = -paddleSpeed; + else + rightPaddleSpeed = 0.f; + } + + // Move the ball + float factor = ballSpeed * deltaTime; + ball.move(std::cos(ballAngle) * factor, std::sin(ballAngle) * factor); + + // Check collisions between the ball and the screen + if (ball.getPosition().x - ballRadius < 0.f) + { + isPlaying = false; + pauseMessage.setString("You lost!\nPress space to restart or\nescape to exit"); + } + if (ball.getPosition().x + ballRadius > gameWidth) + { + isPlaying = false; + pauseMessage.setString("You won!\nPress space to restart or\nescape to exit"); + } + if (ball.getPosition().y - ballRadius < 0.f) + { + ballSound.play(); + ballAngle = -ballAngle; + ball.setPosition(ball.getPosition().x, ballRadius + 0.1f); + } + if (ball.getPosition().y + ballRadius > gameHeight) + { + ballSound.play(); + ballAngle = -ballAngle; + ball.setPosition(ball.getPosition().x, gameHeight - ballRadius - 0.1f); + } + + // Check the collisions between the ball and the paddles + // Left Paddle + if (ball.getPosition().x - ballRadius < leftPaddle.getPosition().x + paddleSize.x / 2 && + ball.getPosition().x - ballRadius > leftPaddle.getPosition().x && + ball.getPosition().y + ballRadius >= leftPaddle.getPosition().y - paddleSize.y / 2 && + ball.getPosition().y - ballRadius <= leftPaddle.getPosition().y + paddleSize.y / 2) + { + if (ball.getPosition().y > leftPaddle.getPosition().y) + ballAngle = pi - ballAngle + (std::rand() % 20) * pi / 180; + else + ballAngle = pi - ballAngle - (std::rand() % 20) * pi / 180; + + ballSound.play(); + ball.setPosition(leftPaddle.getPosition().x + ballRadius + paddleSize.x / 2 + 0.1f, ball.getPosition().y); + } + + // Right Paddle + if (ball.getPosition().x + ballRadius > rightPaddle.getPosition().x - paddleSize.x / 2 && + ball.getPosition().x + ballRadius < rightPaddle.getPosition().x && + ball.getPosition().y + ballRadius >= rightPaddle.getPosition().y - paddleSize.y / 2 && + ball.getPosition().y - ballRadius <= rightPaddle.getPosition().y + paddleSize.y / 2) + { + if (ball.getPosition().y > rightPaddle.getPosition().y) + ballAngle = pi - ballAngle + (std::rand() % 20) * pi / 180; + else + ballAngle = pi - ballAngle - (std::rand() % 20) * pi / 180; + + ballSound.play(); + ball.setPosition(rightPaddle.getPosition().x - ballRadius - paddleSize.x / 2 - 0.1f, ball.getPosition().y); + } + } + + // Clear the window + window.clear(sf::Color(50, 200, 50)); + + if (isPlaying) + { + // Draw the paddles and the ball + window.draw(leftPaddle); + window.draw(rightPaddle); + window.draw(ball); + } + else + { + // Draw the pause message + window.draw(pauseMessage); + } + + // Display things on screen + window.display(); + } + + return EXIT_SUCCESS; +} diff --git a/examples/shader/CMakeLists.txt b/examples/shader/CMakeLists.txt index acb1bac8..eb908b25 100644 --- a/examples/shader/CMakeLists.txt +++ b/examples/shader/CMakeLists.txt @@ -1,12 +1,12 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/shader) - -# all source files -set(SRC - ${SRCROOT}/Effect.hpp - ${SRCROOT}/Shader.cpp) - -# define the shader target -sfml_add_example(shader GUI_APP - SOURCES ${SRC} - DEPENDS sfml-graphics sfml-window sfml-system) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/shader) + +# all source files +set(SRC + ${SRCROOT}/Effect.hpp + ${SRCROOT}/Shader.cpp) + +# define the shader target +sfml_add_example(shader GUI_APP + SOURCES ${SRC} + DEPENDS sfml-graphics sfml-window sfml-system) diff --git a/examples/shader/Effect.hpp b/examples/shader/Effect.hpp index ce29c47b..0ff65b43 100644 --- a/examples/shader/Effect.hpp +++ b/examples/shader/Effect.hpp @@ -14,7 +14,7 @@ //////////////////////////////////////////////////////////// class Effect : public sf::Drawable { -public : +public: virtual ~Effect() { @@ -56,7 +56,7 @@ public : } } -protected : +protected: Effect(const std::string& name) : m_name(name), @@ -70,14 +70,14 @@ protected : return *s_font; } -private : +private: // Virtual functions to be implemented in derived effects virtual bool onLoad() = 0; virtual void onUpdate(float time, float x, float y) = 0; virtual void onDraw(sf::RenderTarget& target, sf::RenderStates states) const = 0; -private : +private: std::string m_name; bool m_isLoaded; diff --git a/examples/shader/Shader.cpp b/examples/shader/Shader.cpp index 95959206..5ec4cdb6 100644 --- a/examples/shader/Shader.cpp +++ b/examples/shader/Shader.cpp @@ -1,379 +1,379 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include "Effect.hpp" -#include -#include - - -const sf::Font* Effect::s_font = NULL; - -//////////////////////////////////////////////////////////// -// "Pixelate" fragment shader -//////////////////////////////////////////////////////////// -class Pixelate : public Effect -{ -public : - - Pixelate() : - Effect("pixelate") - { - } - - bool onLoad() - { - // Load the texture and initialize the sprite - if (!m_texture.loadFromFile("resources/background.jpg")) - return false; - m_sprite.setTexture(m_texture); - - // Load the shader - if (!m_shader.loadFromFile("resources/pixelate.frag", sf::Shader::Fragment)) - return false; - m_shader.setParameter("texture", sf::Shader::CurrentTexture); - - return true; - } - - void onUpdate(float, float x, float y) - { - m_shader.setParameter("pixel_threshold", (x + y) / 30); - } - - void onDraw(sf::RenderTarget& target, sf::RenderStates states) const - { - states.shader = &m_shader; - target.draw(m_sprite, states); - } - -private: - - sf::Texture m_texture; - sf::Sprite m_sprite; - sf::Shader m_shader; -}; - - -//////////////////////////////////////////////////////////// -// "Wave" vertex shader + "blur" fragment shader -//////////////////////////////////////////////////////////// -class WaveBlur : public Effect -{ -public : - - WaveBlur() : - Effect("wave + blur") - { - } - - bool onLoad() - { - // Create the text - m_text.setString("Praesent suscipit augue in velit pulvinar hendrerit varius purus aliquam.\n" - "Mauris mi odio, bibendum quis fringilla a, laoreet vel orci. Proin vitae vulputate tortor.\n" - "Praesent cursus ultrices justo, ut feugiat ante vehicula quis.\n" - "Donec fringilla scelerisque mauris et viverra.\n" - "Maecenas adipiscing ornare scelerisque. Nullam at libero elit.\n" - "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.\n" - "Nullam leo urna, tincidunt id semper eget, ultricies sed mi.\n" - "Morbi mauris massa, commodo id dignissim vel, lobortis et elit.\n" - "Fusce vel libero sed neque scelerisque venenatis.\n" - "Integer mattis tincidunt quam vitae iaculis.\n" - "Vivamus fringilla sem non velit venenatis fermentum.\n" - "Vivamus varius tincidunt nisi id vehicula.\n" - "Integer ullamcorper, enim vitae euismod rutrum, massa nisl semper ipsum,\n" - "vestibulum sodales sem ante in massa.\n" - "Vestibulum in augue non felis convallis viverra.\n" - "Mauris ultricies dolor sed massa convallis sed aliquet augue fringilla.\n" - "Duis erat eros, porta in accumsan in, blandit quis sem.\n" - "In hac habitasse platea dictumst. Etiam fringilla est id odio dapibus sit amet semper dui laoreet.\n"); - m_text.setFont(getFont()); - m_text.setCharacterSize(22); - m_text.setPosition(30, 20); - - // Load the shader - if (!m_shader.loadFromFile("resources/wave.vert", "resources/blur.frag")) - return false; - - return true; - } - - void onUpdate(float time, float x, float y) - { - m_shader.setParameter("wave_phase", time); - m_shader.setParameter("wave_amplitude", x * 40, y * 40); - m_shader.setParameter("blur_radius", (x + y) * 0.008f); - } - - void onDraw(sf::RenderTarget& target, sf::RenderStates states) const - { - states.shader = &m_shader; - target.draw(m_text, states); - } - -private: - - sf::Text m_text; - sf::Shader m_shader; -}; - - -//////////////////////////////////////////////////////////// -// "Storm" vertex shader + "blink" fragment shader -//////////////////////////////////////////////////////////// -class StormBlink : public Effect -{ -public : - - StormBlink() : - Effect("storm + blink") - { - } - - bool onLoad() - { - // Create the points - m_points.setPrimitiveType(sf::Points); - for (int i = 0; i < 40000; ++i) - { - float x = static_cast(std::rand() % 800); - float y = static_cast(std::rand() % 600); - sf::Uint8 r = std::rand() % 255; - sf::Uint8 g = std::rand() % 255; - sf::Uint8 b = std::rand() % 255; - m_points.append(sf::Vertex(sf::Vector2f(x, y), sf::Color(r, g, b))); - } - - // Load the shader - if (!m_shader.loadFromFile("resources/storm.vert", "resources/blink.frag")) - return false; - - return true; - } - - void onUpdate(float time, float x, float y) - { - float radius = 200 + std::cos(time) * 150; - m_shader.setParameter("storm_position", x * 800, y * 600); - m_shader.setParameter("storm_inner_radius", radius / 3); - m_shader.setParameter("storm_total_radius", radius); - m_shader.setParameter("blink_alpha", 0.5f + std::cos(time * 3) * 0.25f); - } - - void onDraw(sf::RenderTarget& target, sf::RenderStates states) const - { - states.shader = &m_shader; - target.draw(m_points, states); - } - -private: - - sf::VertexArray m_points; - sf::Shader m_shader; -}; - - -//////////////////////////////////////////////////////////// -// "Edge" post-effect fragment shader -//////////////////////////////////////////////////////////// -class Edge : public Effect -{ -public : - - Edge() : - Effect("edge post-effect") - { - } - - bool onLoad() - { - // Create the off-screen surface - if (!m_surface.create(800, 600)) - return false; - m_surface.setSmooth(true); - - // Load the textures - if (!m_backgroundTexture.loadFromFile("resources/sfml.png")) - return false; - m_backgroundTexture.setSmooth(true); - if (!m_entityTexture.loadFromFile("resources/devices.png")) - return false; - m_entityTexture.setSmooth(true); - - // Initialize the background sprite - m_backgroundSprite.setTexture(m_backgroundTexture); - m_backgroundSprite.setPosition(135, 100); - - // Load the moving entities - for (int i = 0; i < 6; ++i) - { - sf::Sprite entity(m_entityTexture, sf::IntRect(96 * i, 0, 96, 96)); - m_entities.push_back(entity); - } - - // Load the shader - if (!m_shader.loadFromFile("resources/edge.frag", sf::Shader::Fragment)) - return false; - m_shader.setParameter("texture", sf::Shader::CurrentTexture); - - return true; - } - - void onUpdate(float time, float x, float y) - { - m_shader.setParameter("edge_threshold", 1 - (x + y) / 2); - - // Update the position of the moving entities - for (std::size_t i = 0; i < m_entities.size(); ++i) - { - sf::Vector2f position; - position.x = std::cos(0.25f * (time * i + (m_entities.size() - i))) * 300 + 350; - position.y = std::sin(0.25f * (time * (m_entities.size() - i) + i)) * 200 + 250; - m_entities[i].setPosition(position); - } - - // Render the updated scene to the off-screen surface - m_surface.clear(sf::Color::White); - m_surface.draw(m_backgroundSprite); - for (std::size_t i = 0; i < m_entities.size(); ++i) - m_surface.draw(m_entities[i]); - m_surface.display(); - } - - void onDraw(sf::RenderTarget& target, sf::RenderStates states) const - { - states.shader = &m_shader; - target.draw(sf::Sprite(m_surface.getTexture()), states); - } - -private: - - sf::RenderTexture m_surface; - sf::Texture m_backgroundTexture; - sf::Texture m_entityTexture; - sf::Sprite m_backgroundSprite; - std::vector m_entities; - sf::Shader m_shader; -}; - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \return Application exit code -/// -//////////////////////////////////////////////////////////// -int main() -{ - // Create the main window - sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Shader"); - window.setVerticalSyncEnabled(true); - - // Load the application font and pass it to the Effect class - sf::Font font; - if (!font.loadFromFile("resources/sansation.ttf")) - return EXIT_FAILURE; - Effect::setFont(font); - - // Create the effects - std::vector effects; - effects.push_back(new Pixelate); - effects.push_back(new WaveBlur); - effects.push_back(new StormBlink); - effects.push_back(new Edge); - std::size_t current = 0; - - // Initialize them - for (std::size_t i = 0; i < effects.size(); ++i) - effects[i]->load(); - - // Create the messages background - sf::Texture textBackgroundTexture; - if (!textBackgroundTexture.loadFromFile("resources/text-background.png")) - return EXIT_FAILURE; - sf::Sprite textBackground(textBackgroundTexture); - textBackground.setPosition(0, 520); - textBackground.setColor(sf::Color(255, 255, 255, 200)); - - // Create the description text - sf::Text description("Current effect: " + effects[current]->getName(), font, 20); - description.setPosition(10, 530); - description.setColor(sf::Color(80, 80, 80)); - - // Create the instructions text - sf::Text instructions("Press left and right arrows to change the current shader", font, 20); - instructions.setPosition(280, 555); - instructions.setColor(sf::Color(80, 80, 80)); - - // Start the game loop - sf::Clock clock; - while (window.isOpen()) - { - // Process events - sf::Event event; - while (window.pollEvent(event)) - { - // Close window: exit - if (event.type == sf::Event::Closed) - window.close(); - - if (event.type == sf::Event::KeyPressed) - { - switch (event.key.code) - { - // Escape key: exit - case sf::Keyboard::Escape: - window.close(); - break; - - // Left arrow key: previous shader - case sf::Keyboard::Left: - if (current == 0) - current = effects.size() - 1; - else - current--; - description.setString("Current effect: " + effects[current]->getName()); - break; - - // Right arrow key: next shader - case sf::Keyboard::Right: - if (current == effects.size() - 1) - current = 0; - else - current++; - description.setString("Current effect: " + effects[current]->getName()); - break; - - default: - break; - } - } - } - - // Update the current example - float x = static_cast(sf::Mouse::getPosition(window).x) / window.getSize().x; - float y = static_cast(sf::Mouse::getPosition(window).y) / window.getSize().y; - effects[current]->update(clock.getElapsedTime().asSeconds(), x, y); - - // Clear the window - window.clear(sf::Color(255, 128, 0)); - - // Draw the current example - window.draw(*effects[current]); - - // Draw the text - window.draw(textBackground); - window.draw(instructions); - window.draw(description); - - // Finally, display the rendered frame on screen - window.display(); - } - - // delete the effects - for (std::size_t i = 0; i < effects.size(); ++i) - delete effects[i]; - - return EXIT_SUCCESS; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include "Effect.hpp" +#include +#include + + +const sf::Font* Effect::s_font = NULL; + +//////////////////////////////////////////////////////////// +// "Pixelate" fragment shader +//////////////////////////////////////////////////////////// +class Pixelate : public Effect +{ +public: + + Pixelate() : + Effect("pixelate") + { + } + + bool onLoad() + { + // Load the texture and initialize the sprite + if (!m_texture.loadFromFile("resources/background.jpg")) + return false; + m_sprite.setTexture(m_texture); + + // Load the shader + if (!m_shader.loadFromFile("resources/pixelate.frag", sf::Shader::Fragment)) + return false; + m_shader.setParameter("texture", sf::Shader::CurrentTexture); + + return true; + } + + void onUpdate(float, float x, float y) + { + m_shader.setParameter("pixel_threshold", (x + y) / 30); + } + + void onDraw(sf::RenderTarget& target, sf::RenderStates states) const + { + states.shader = &m_shader; + target.draw(m_sprite, states); + } + +private: + + sf::Texture m_texture; + sf::Sprite m_sprite; + sf::Shader m_shader; +}; + + +//////////////////////////////////////////////////////////// +// "Wave" vertex shader + "blur" fragment shader +//////////////////////////////////////////////////////////// +class WaveBlur : public Effect +{ +public: + + WaveBlur() : + Effect("wave + blur") + { + } + + bool onLoad() + { + // Create the text + m_text.setString("Praesent suscipit augue in velit pulvinar hendrerit varius purus aliquam.\n" + "Mauris mi odio, bibendum quis fringilla a, laoreet vel orci. Proin vitae vulputate tortor.\n" + "Praesent cursus ultrices justo, ut feugiat ante vehicula quis.\n" + "Donec fringilla scelerisque mauris et viverra.\n" + "Maecenas adipiscing ornare scelerisque. Nullam at libero elit.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.\n" + "Nullam leo urna, tincidunt id semper eget, ultricies sed mi.\n" + "Morbi mauris massa, commodo id dignissim vel, lobortis et elit.\n" + "Fusce vel libero sed neque scelerisque venenatis.\n" + "Integer mattis tincidunt quam vitae iaculis.\n" + "Vivamus fringilla sem non velit venenatis fermentum.\n" + "Vivamus varius tincidunt nisi id vehicula.\n" + "Integer ullamcorper, enim vitae euismod rutrum, massa nisl semper ipsum,\n" + "vestibulum sodales sem ante in massa.\n" + "Vestibulum in augue non felis convallis viverra.\n" + "Mauris ultricies dolor sed massa convallis sed aliquet augue fringilla.\n" + "Duis erat eros, porta in accumsan in, blandit quis sem.\n" + "In hac habitasse platea dictumst. Etiam fringilla est id odio dapibus sit amet semper dui laoreet.\n"); + m_text.setFont(getFont()); + m_text.setCharacterSize(22); + m_text.setPosition(30, 20); + + // Load the shader + if (!m_shader.loadFromFile("resources/wave.vert", "resources/blur.frag")) + return false; + + return true; + } + + void onUpdate(float time, float x, float y) + { + m_shader.setParameter("wave_phase", time); + m_shader.setParameter("wave_amplitude", x * 40, y * 40); + m_shader.setParameter("blur_radius", (x + y) * 0.008f); + } + + void onDraw(sf::RenderTarget& target, sf::RenderStates states) const + { + states.shader = &m_shader; + target.draw(m_text, states); + } + +private: + + sf::Text m_text; + sf::Shader m_shader; +}; + + +//////////////////////////////////////////////////////////// +// "Storm" vertex shader + "blink" fragment shader +//////////////////////////////////////////////////////////// +class StormBlink : public Effect +{ +public: + + StormBlink() : + Effect("storm + blink") + { + } + + bool onLoad() + { + // Create the points + m_points.setPrimitiveType(sf::Points); + for (int i = 0; i < 40000; ++i) + { + float x = static_cast(std::rand() % 800); + float y = static_cast(std::rand() % 600); + sf::Uint8 r = std::rand() % 255; + sf::Uint8 g = std::rand() % 255; + sf::Uint8 b = std::rand() % 255; + m_points.append(sf::Vertex(sf::Vector2f(x, y), sf::Color(r, g, b))); + } + + // Load the shader + if (!m_shader.loadFromFile("resources/storm.vert", "resources/blink.frag")) + return false; + + return true; + } + + void onUpdate(float time, float x, float y) + { + float radius = 200 + std::cos(time) * 150; + m_shader.setParameter("storm_position", x * 800, y * 600); + m_shader.setParameter("storm_inner_radius", radius / 3); + m_shader.setParameter("storm_total_radius", radius); + m_shader.setParameter("blink_alpha", 0.5f + std::cos(time * 3) * 0.25f); + } + + void onDraw(sf::RenderTarget& target, sf::RenderStates states) const + { + states.shader = &m_shader; + target.draw(m_points, states); + } + +private: + + sf::VertexArray m_points; + sf::Shader m_shader; +}; + + +//////////////////////////////////////////////////////////// +// "Edge" post-effect fragment shader +//////////////////////////////////////////////////////////// +class Edge : public Effect +{ +public: + + Edge() : + Effect("edge post-effect") + { + } + + bool onLoad() + { + // Create the off-screen surface + if (!m_surface.create(800, 600)) + return false; + m_surface.setSmooth(true); + + // Load the textures + if (!m_backgroundTexture.loadFromFile("resources/sfml.png")) + return false; + m_backgroundTexture.setSmooth(true); + if (!m_entityTexture.loadFromFile("resources/devices.png")) + return false; + m_entityTexture.setSmooth(true); + + // Initialize the background sprite + m_backgroundSprite.setTexture(m_backgroundTexture); + m_backgroundSprite.setPosition(135, 100); + + // Load the moving entities + for (int i = 0; i < 6; ++i) + { + sf::Sprite entity(m_entityTexture, sf::IntRect(96 * i, 0, 96, 96)); + m_entities.push_back(entity); + } + + // Load the shader + if (!m_shader.loadFromFile("resources/edge.frag", sf::Shader::Fragment)) + return false; + m_shader.setParameter("texture", sf::Shader::CurrentTexture); + + return true; + } + + void onUpdate(float time, float x, float y) + { + m_shader.setParameter("edge_threshold", 1 - (x + y) / 2); + + // Update the position of the moving entities + for (std::size_t i = 0; i < m_entities.size(); ++i) + { + sf::Vector2f position; + position.x = std::cos(0.25f * (time * i + (m_entities.size() - i))) * 300 + 350; + position.y = std::sin(0.25f * (time * (m_entities.size() - i) + i)) * 200 + 250; + m_entities[i].setPosition(position); + } + + // Render the updated scene to the off-screen surface + m_surface.clear(sf::Color::White); + m_surface.draw(m_backgroundSprite); + for (std::size_t i = 0; i < m_entities.size(); ++i) + m_surface.draw(m_entities[i]); + m_surface.display(); + } + + void onDraw(sf::RenderTarget& target, sf::RenderStates states) const + { + states.shader = &m_shader; + target.draw(sf::Sprite(m_surface.getTexture()), states); + } + +private: + + sf::RenderTexture m_surface; + sf::Texture m_backgroundTexture; + sf::Texture m_entityTexture; + sf::Sprite m_backgroundSprite; + std::vector m_entities; + sf::Shader m_shader; +}; + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \return Application exit code +/// +//////////////////////////////////////////////////////////// +int main() +{ + // Create the main window + sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Shader"); + window.setVerticalSyncEnabled(true); + + // Load the application font and pass it to the Effect class + sf::Font font; + if (!font.loadFromFile("resources/sansation.ttf")) + return EXIT_FAILURE; + Effect::setFont(font); + + // Create the effects + std::vector effects; + effects.push_back(new Pixelate); + effects.push_back(new WaveBlur); + effects.push_back(new StormBlink); + effects.push_back(new Edge); + std::size_t current = 0; + + // Initialize them + for (std::size_t i = 0; i < effects.size(); ++i) + effects[i]->load(); + + // Create the messages background + sf::Texture textBackgroundTexture; + if (!textBackgroundTexture.loadFromFile("resources/text-background.png")) + return EXIT_FAILURE; + sf::Sprite textBackground(textBackgroundTexture); + textBackground.setPosition(0, 520); + textBackground.setColor(sf::Color(255, 255, 255, 200)); + + // Create the description text + sf::Text description("Current effect: " + effects[current]->getName(), font, 20); + description.setPosition(10, 530); + description.setColor(sf::Color(80, 80, 80)); + + // Create the instructions text + sf::Text instructions("Press left and right arrows to change the current shader", font, 20); + instructions.setPosition(280, 555); + instructions.setColor(sf::Color(80, 80, 80)); + + // Start the game loop + sf::Clock clock; + while (window.isOpen()) + { + // Process events + sf::Event event; + while (window.pollEvent(event)) + { + // Close window: exit + if (event.type == sf::Event::Closed) + window.close(); + + if (event.type == sf::Event::KeyPressed) + { + switch (event.key.code) + { + // Escape key: exit + case sf::Keyboard::Escape: + window.close(); + break; + + // Left arrow key: previous shader + case sf::Keyboard::Left: + if (current == 0) + current = effects.size() - 1; + else + current--; + description.setString("Current effect: " + effects[current]->getName()); + break; + + // Right arrow key: next shader + case sf::Keyboard::Right: + if (current == effects.size() - 1) + current = 0; + else + current++; + description.setString("Current effect: " + effects[current]->getName()); + break; + + default: + break; + } + } + } + + // Update the current example + float x = static_cast(sf::Mouse::getPosition(window).x) / window.getSize().x; + float y = static_cast(sf::Mouse::getPosition(window).y) / window.getSize().y; + effects[current]->update(clock.getElapsedTime().asSeconds(), x, y); + + // Clear the window + window.clear(sf::Color(255, 128, 0)); + + // Draw the current example + window.draw(*effects[current]); + + // Draw the text + window.draw(textBackground); + window.draw(instructions); + window.draw(description); + + // Finally, display the rendered frame on screen + window.display(); + } + + // delete the effects + for (std::size_t i = 0; i < effects.size(); ++i) + delete effects[i]; + + return EXIT_SUCCESS; +} diff --git a/examples/shader/resources/blur.frag b/examples/shader/resources/blur.frag index c40e5b3f..8d4261ab 100644 --- a/examples/shader/resources/blur.frag +++ b/examples/shader/resources/blur.frag @@ -1,20 +1,20 @@ -uniform sampler2D texture; -uniform float blur_radius; - -void main() -{ - vec2 offx = vec2(blur_radius, 0.0); - vec2 offy = vec2(0.0, blur_radius); - - vec4 pixel = texture2D(texture, gl_TexCoord[0].xy) * 4.0 + - texture2D(texture, gl_TexCoord[0].xy - offx) * 2.0 + - texture2D(texture, gl_TexCoord[0].xy + offx) * 2.0 + - texture2D(texture, gl_TexCoord[0].xy - offy) * 2.0 + - texture2D(texture, gl_TexCoord[0].xy + offy) * 2.0 + - texture2D(texture, gl_TexCoord[0].xy - offx - offy) * 1.0 + - texture2D(texture, gl_TexCoord[0].xy - offx + offy) * 1.0 + - texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1.0 + - texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1.0; - - gl_FragColor = gl_Color * (pixel / 16.0); -} +uniform sampler2D texture; +uniform float blur_radius; + +void main() +{ + vec2 offx = vec2(blur_radius, 0.0); + vec2 offy = vec2(0.0, blur_radius); + + vec4 pixel = texture2D(texture, gl_TexCoord[0].xy) * 4.0 + + texture2D(texture, gl_TexCoord[0].xy - offx) * 2.0 + + texture2D(texture, gl_TexCoord[0].xy + offx) * 2.0 + + texture2D(texture, gl_TexCoord[0].xy - offy) * 2.0 + + texture2D(texture, gl_TexCoord[0].xy + offy) * 2.0 + + texture2D(texture, gl_TexCoord[0].xy - offx - offy) * 1.0 + + texture2D(texture, gl_TexCoord[0].xy - offx + offy) * 1.0 + + texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1.0 + + texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1.0; + + gl_FragColor = gl_Color * (pixel / 16.0); +} diff --git a/examples/shader/resources/edge.frag b/examples/shader/resources/edge.frag index 14551f98..ad2cd8db 100644 --- a/examples/shader/resources/edge.frag +++ b/examples/shader/resources/edge.frag @@ -1,32 +1,32 @@ -uniform sampler2D texture; -uniform float edge_threshold; - -void main() -{ - const float offset = 1.0 / 512.0; - vec2 offx = vec2(offset, 0.0); - vec2 offy = vec2(0.0, offset); - - vec4 hEdge = texture2D(texture, gl_TexCoord[0].xy - offy) * -2.0 + - texture2D(texture, gl_TexCoord[0].xy + offy) * 2.0 + - texture2D(texture, gl_TexCoord[0].xy - offx - offy) * -1.0 + - texture2D(texture, gl_TexCoord[0].xy - offx + offy) * 1.0 + - texture2D(texture, gl_TexCoord[0].xy + offx - offy) * -1.0 + - texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1.0; - - vec4 vEdge = texture2D(texture, gl_TexCoord[0].xy - offx) * 2.0 + - texture2D(texture, gl_TexCoord[0].xy + offx) * -2.0 + - texture2D(texture, gl_TexCoord[0].xy - offx - offy) * 1.0 + - texture2D(texture, gl_TexCoord[0].xy - offx + offy) * -1.0 + - texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1.0 + - texture2D(texture, gl_TexCoord[0].xy + offx + offy) * -1.0; - - vec3 result = sqrt(hEdge.rgb * hEdge.rgb + vEdge.rgb * vEdge.rgb); - float edge = length(result); - vec4 pixel = gl_Color * texture2D(texture, gl_TexCoord[0].xy); - if (edge > (edge_threshold * 8.0)) - pixel.rgb = vec3(0.0, 0.0, 0.0); - else - pixel.a = edge_threshold; - gl_FragColor = pixel; -} +uniform sampler2D texture; +uniform float edge_threshold; + +void main() +{ + const float offset = 1.0 / 512.0; + vec2 offx = vec2(offset, 0.0); + vec2 offy = vec2(0.0, offset); + + vec4 hEdge = texture2D(texture, gl_TexCoord[0].xy - offy) * -2.0 + + texture2D(texture, gl_TexCoord[0].xy + offy) * 2.0 + + texture2D(texture, gl_TexCoord[0].xy - offx - offy) * -1.0 + + texture2D(texture, gl_TexCoord[0].xy - offx + offy) * 1.0 + + texture2D(texture, gl_TexCoord[0].xy + offx - offy) * -1.0 + + texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1.0; + + vec4 vEdge = texture2D(texture, gl_TexCoord[0].xy - offx) * 2.0 + + texture2D(texture, gl_TexCoord[0].xy + offx) * -2.0 + + texture2D(texture, gl_TexCoord[0].xy - offx - offy) * 1.0 + + texture2D(texture, gl_TexCoord[0].xy - offx + offy) * -1.0 + + texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1.0 + + texture2D(texture, gl_TexCoord[0].xy + offx + offy) * -1.0; + + vec3 result = sqrt(hEdge.rgb * hEdge.rgb + vEdge.rgb * vEdge.rgb); + float edge = length(result); + vec4 pixel = gl_Color * texture2D(texture, gl_TexCoord[0].xy); + if (edge > (edge_threshold * 8.0)) + pixel.rgb = vec3(0.0, 0.0, 0.0); + else + pixel.a = edge_threshold; + gl_FragColor = pixel; +} diff --git a/examples/shader/resources/pixelate.frag b/examples/shader/resources/pixelate.frag index 3c8eb0e0..d8d01d01 100644 --- a/examples/shader/resources/pixelate.frag +++ b/examples/shader/resources/pixelate.frag @@ -1,9 +1,9 @@ -uniform sampler2D texture; -uniform float pixel_threshold; - -void main() -{ - float factor = 1.0 / (pixel_threshold + 0.001); - vec2 pos = floor(gl_TexCoord[0].xy * factor + 0.5) / factor; - gl_FragColor = texture2D(texture, pos) * gl_Color; -} +uniform sampler2D texture; +uniform float pixel_threshold; + +void main() +{ + float factor = 1.0 / (pixel_threshold + 0.001); + vec2 pos = floor(gl_TexCoord[0].xy * factor + 0.5) / factor; + gl_FragColor = texture2D(texture, pos) * gl_Color; +} diff --git a/examples/sockets/CMakeLists.txt b/examples/sockets/CMakeLists.txt index 04b3583e..b9f4b648 100644 --- a/examples/sockets/CMakeLists.txt +++ b/examples/sockets/CMakeLists.txt @@ -1,12 +1,12 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/sockets) - -# all source files -set(SRC ${SRCROOT}/Sockets.cpp - ${SRCROOT}/TCP.cpp - ${SRCROOT}/UDP.cpp) - -# define the sockets target -sfml_add_example(sockets - SOURCES ${SRC} - DEPENDS sfml-network sfml-system) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/sockets) + +# all source files +set(SRC ${SRCROOT}/Sockets.cpp + ${SRCROOT}/TCP.cpp + ${SRCROOT}/UDP.cpp) + +# define the sockets target +sfml_add_example(sockets + SOURCES ${SRC} + DEPENDS sfml-network sfml-system) diff --git a/examples/sockets/Sockets.cpp b/examples/sockets/Sockets.cpp index a73609c2..8201afb2 100644 --- a/examples/sockets/Sockets.cpp +++ b/examples/sockets/Sockets.cpp @@ -1,59 +1,59 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -void runTcpServer(unsigned short port); -void runTcpClient(unsigned short port); -void runUdpServer(unsigned short port); -void runUdpClient(unsigned short port); - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \return Application exit code -/// -//////////////////////////////////////////////////////////// -int main() -{ - // Choose an arbitrary port for opening sockets - const unsigned short port = 50001; - - // TCP, UDP or connected UDP ? - char protocol; - std::cout << "Do you want to use TCP (t) or UDP (u) ? "; - std::cin >> protocol; - - // Client or server ? - char who; - std::cout << "Do you want to be a server (s) or a client (c) ? "; - std::cin >> who; - - if (protocol == 't') - { - // Test the TCP protocol - if (who == 's') - runTcpServer(port); - else - runTcpClient(port); - } - else - { - // Test the unconnected UDP protocol - if (who == 's') - runUdpServer(port); - else - runUdpClient(port); - } - - // Wait until the user presses 'enter' key - std::cout << "Press enter to exit..." << std::endl; - std::cin.ignore(10000, '\n'); - std::cin.ignore(10000, '\n'); - - return EXIT_SUCCESS; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +void runTcpServer(unsigned short port); +void runTcpClient(unsigned short port); +void runUdpServer(unsigned short port); +void runUdpClient(unsigned short port); + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \return Application exit code +/// +//////////////////////////////////////////////////////////// +int main() +{ + // Choose an arbitrary port for opening sockets + const unsigned short port = 50001; + + // TCP, UDP or connected UDP ? + char protocol; + std::cout << "Do you want to use TCP (t) or UDP (u) ? "; + std::cin >> protocol; + + // Client or server ? + char who; + std::cout << "Do you want to be a server (s) or a client (c) ? "; + std::cin >> who; + + if (protocol == 't') + { + // Test the TCP protocol + if (who == 's') + runTcpServer(port); + else + runTcpClient(port); + } + else + { + // Test the unconnected UDP protocol + if (who == 's') + runUdpServer(port); + else + runUdpClient(port); + } + + // Wait until the user presses 'enter' key + std::cout << "Press enter to exit..." << std::endl; + std::cin.ignore(10000, '\n'); + std::cin.ignore(10000, '\n'); + + return EXIT_SUCCESS; +} diff --git a/examples/sockets/TCP.cpp b/examples/sockets/TCP.cpp index ff1e1f67..64fb7f91 100644 --- a/examples/sockets/TCP.cpp +++ b/examples/sockets/TCP.cpp @@ -1,81 +1,81 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -//////////////////////////////////////////////////////////// -/// Launch a server, wait for an incoming connection, -/// send a message and wait for the answer. -/// -//////////////////////////////////////////////////////////// -void runTcpServer(unsigned short port) -{ - // Create a server socket to accept new connections - sf::TcpListener listener; - - // Listen to the given port for incoming connections - if (listener.listen(port) != sf::Socket::Done) - return; - std::cout << "Server is listening to port " << port << ", waiting for connections... " << std::endl; - - // Wait for a connection - sf::TcpSocket socket; - if (listener.accept(socket) != sf::Socket::Done) - return; - std::cout << "Client connected: " << socket.getRemoteAddress() << std::endl; - - // Send a message to the connected client - const char out[] = "Hi, I'm the server"; - if (socket.send(out, sizeof(out)) != sf::Socket::Done) - return; - std::cout << "Message sent to the client: \"" << out << "\"" << std::endl; - - // Receive a message back from the client - char in[128]; - std::size_t received; - if (socket.receive(in, sizeof(in), received) != sf::Socket::Done) - return; - std::cout << "Answer received from the client: \"" << in << "\"" << std::endl; -} - - -//////////////////////////////////////////////////////////// -/// Create a client, connect it to a server, display the -/// welcome message and send an answer. -/// -//////////////////////////////////////////////////////////// -void runTcpClient(unsigned short port) -{ - // Ask for the server address - sf::IpAddress server; - do - { - std::cout << "Type the address or name of the server to connect to: "; - std::cin >> server; - } - while (server == sf::IpAddress::None); - - // Create a socket for communicating with the server - sf::TcpSocket socket; - - // Connect to the server - if (socket.connect(server, port) != sf::Socket::Done) - return; - std::cout << "Connected to server " << server << std::endl; - - // Receive a message from the server - char in[128]; - std::size_t received; - if (socket.receive(in, sizeof(in), received) != sf::Socket::Done) - return; - std::cout << "Message received from the server: \"" << in << "\"" << std::endl; - - // Send an answer to the server - const char out[] = "Hi, I'm a client"; - if (socket.send(out, sizeof(out)) != sf::Socket::Done) - return; - std::cout << "Message sent to the server: \"" << out << "\"" << std::endl; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +//////////////////////////////////////////////////////////// +/// Launch a server, wait for an incoming connection, +/// send a message and wait for the answer. +/// +//////////////////////////////////////////////////////////// +void runTcpServer(unsigned short port) +{ + // Create a server socket to accept new connections + sf::TcpListener listener; + + // Listen to the given port for incoming connections + if (listener.listen(port) != sf::Socket::Done) + return; + std::cout << "Server is listening to port " << port << ", waiting for connections... " << std::endl; + + // Wait for a connection + sf::TcpSocket socket; + if (listener.accept(socket) != sf::Socket::Done) + return; + std::cout << "Client connected: " << socket.getRemoteAddress() << std::endl; + + // Send a message to the connected client + const char out[] = "Hi, I'm the server"; + if (socket.send(out, sizeof(out)) != sf::Socket::Done) + return; + std::cout << "Message sent to the client: \"" << out << "\"" << std::endl; + + // Receive a message back from the client + char in[128]; + std::size_t received; + if (socket.receive(in, sizeof(in), received) != sf::Socket::Done) + return; + std::cout << "Answer received from the client: \"" << in << "\"" << std::endl; +} + + +//////////////////////////////////////////////////////////// +/// Create a client, connect it to a server, display the +/// welcome message and send an answer. +/// +//////////////////////////////////////////////////////////// +void runTcpClient(unsigned short port) +{ + // Ask for the server address + sf::IpAddress server; + do + { + std::cout << "Type the address or name of the server to connect to: "; + std::cin >> server; + } + while (server == sf::IpAddress::None); + + // Create a socket for communicating with the server + sf::TcpSocket socket; + + // Connect to the server + if (socket.connect(server, port) != sf::Socket::Done) + return; + std::cout << "Connected to server " << server << std::endl; + + // Receive a message from the server + char in[128]; + std::size_t received; + if (socket.receive(in, sizeof(in), received) != sf::Socket::Done) + return; + std::cout << "Message received from the server: \"" << in << "\"" << std::endl; + + // Send an answer to the server + const char out[] = "Hi, I'm a client"; + if (socket.send(out, sizeof(out)) != sf::Socket::Done) + return; + std::cout << "Message sent to the server: \"" << out << "\"" << std::endl; +} diff --git a/examples/sockets/UDP.cpp b/examples/sockets/UDP.cpp index abc7b4bc..37a07c53 100644 --- a/examples/sockets/UDP.cpp +++ b/examples/sockets/UDP.cpp @@ -1,72 +1,72 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -//////////////////////////////////////////////////////////// -/// Launch a server, wait for a message, send an answer. -/// -//////////////////////////////////////////////////////////// -void runUdpServer(unsigned short port) -{ - // Create a socket to receive a message from anyone - sf::UdpSocket socket; - - // Listen to messages on the specified port - if (socket.bind(port) != sf::Socket::Done) - return; - std::cout << "Server is listening to port " << port << ", waiting for a message... " << std::endl; - - // Wait for a message - char in[128]; - std::size_t received; - sf::IpAddress sender; - unsigned short senderPort; - if (socket.receive(in, sizeof(in), received, sender, senderPort) != sf::Socket::Done) - return; - std::cout << "Message received from client " << sender << ": \"" << in << "\"" << std::endl; - - // Send an answer to the client - const char out[] = "Hi, I'm the server"; - if (socket.send(out, sizeof(out), sender, senderPort) != sf::Socket::Done) - return; - std::cout << "Message sent to the client: \"" << out << "\"" << std::endl; -} - - -//////////////////////////////////////////////////////////// -/// Send a message to the server, wait for the answer -/// -//////////////////////////////////////////////////////////// -void runUdpClient(unsigned short port) -{ - // Ask for the server address - sf::IpAddress server; - do - { - std::cout << "Type the address or name of the server to connect to: "; - std::cin >> server; - } - while (server == sf::IpAddress::None); - - // Create a socket for communicating with the server - sf::UdpSocket socket; - - // Send a message to the server - const char out[] = "Hi, I'm a client"; - if (socket.send(out, sizeof(out), server, port) != sf::Socket::Done) - return; - std::cout << "Message sent to the server: \"" << out << "\"" << std::endl; - - // Receive an answer from anyone (but most likely from the server) - char in[128]; - std::size_t received; - sf::IpAddress sender; - unsigned short senderPort; - if (socket.receive(in, sizeof(in), received, sender, senderPort) != sf::Socket::Done) - return; - std::cout << "Message received from " << sender << ": \"" << in << "\"" << std::endl; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +//////////////////////////////////////////////////////////// +/// Launch a server, wait for a message, send an answer. +/// +//////////////////////////////////////////////////////////// +void runUdpServer(unsigned short port) +{ + // Create a socket to receive a message from anyone + sf::UdpSocket socket; + + // Listen to messages on the specified port + if (socket.bind(port) != sf::Socket::Done) + return; + std::cout << "Server is listening to port " << port << ", waiting for a message... " << std::endl; + + // Wait for a message + char in[128]; + std::size_t received; + sf::IpAddress sender; + unsigned short senderPort; + if (socket.receive(in, sizeof(in), received, sender, senderPort) != sf::Socket::Done) + return; + std::cout << "Message received from client " << sender << ": \"" << in << "\"" << std::endl; + + // Send an answer to the client + const char out[] = "Hi, I'm the server"; + if (socket.send(out, sizeof(out), sender, senderPort) != sf::Socket::Done) + return; + std::cout << "Message sent to the client: \"" << out << "\"" << std::endl; +} + + +//////////////////////////////////////////////////////////// +/// Send a message to the server, wait for the answer +/// +//////////////////////////////////////////////////////////// +void runUdpClient(unsigned short port) +{ + // Ask for the server address + sf::IpAddress server; + do + { + std::cout << "Type the address or name of the server to connect to: "; + std::cin >> server; + } + while (server == sf::IpAddress::None); + + // Create a socket for communicating with the server + sf::UdpSocket socket; + + // Send a message to the server + const char out[] = "Hi, I'm a client"; + if (socket.send(out, sizeof(out), server, port) != sf::Socket::Done) + return; + std::cout << "Message sent to the server: \"" << out << "\"" << std::endl; + + // Receive an answer from anyone (but most likely from the server) + char in[128]; + std::size_t received; + sf::IpAddress sender; + unsigned short senderPort; + if (socket.receive(in, sizeof(in), received, sender, senderPort) != sf::Socket::Done) + return; + std::cout << "Message received from " << sender << ": \"" << in << "\"" << std::endl; +} diff --git a/examples/sound/CMakeLists.txt b/examples/sound/CMakeLists.txt index 12f12e14..01085771 100644 --- a/examples/sound/CMakeLists.txt +++ b/examples/sound/CMakeLists.txt @@ -1,10 +1,10 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/sound) - -# all source files -set(SRC ${SRCROOT}/Sound.cpp) - -# define the sound target -sfml_add_example(sound - SOURCES ${SRC} - DEPENDS sfml-audio sfml-system) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/sound) + +# all source files +set(SRC ${SRCROOT}/Sound.cpp) + +# define the sound target +sfml_add_example(sound + SOURCES ${SRC} + DEPENDS sfml-audio sfml-system) diff --git a/examples/sound/Sound.cpp b/examples/sound/Sound.cpp index 5c75ab87..7005f648 100644 --- a/examples/sound/Sound.cpp +++ b/examples/sound/Sound.cpp @@ -1,98 +1,98 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -//////////////////////////////////////////////////////////// -/// Play a sound -/// -//////////////////////////////////////////////////////////// -void playSound() -{ - // Load a sound buffer from a wav file - sf::SoundBuffer buffer; - if (!buffer.loadFromFile("resources/canary.wav")) - return; - - // Display sound informations - std::cout << "canary.wav :" << std::endl; - std::cout << " " << buffer.getDuration().asSeconds() << " seconds" << std::endl; - std::cout << " " << buffer.getSampleRate() << " samples / sec" << std::endl; - std::cout << " " << buffer.getChannelCount() << " channels" << std::endl; - - // Create a sound instance and play it - sf::Sound sound(buffer); - sound.play(); - - // Loop while the sound is playing - while (sound.getStatus() == sf::Sound::Playing) - { - // Leave some CPU time for other processes - sf::sleep(sf::milliseconds(100)); - - // Display the playing position - std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << sound.getPlayingOffset().asSeconds() << " sec "; - std::cout << std::flush; - } - std::cout << std::endl << std::endl; -} - - -//////////////////////////////////////////////////////////// -/// Play a music -/// -//////////////////////////////////////////////////////////// -void playMusic() -{ - // Load an ogg music file - sf::Music music; - if (!music.openFromFile("resources/orchestral.ogg")) - return; - - // Display music informations - std::cout << "orchestral.ogg :" << std::endl; - std::cout << " " << music.getDuration().asSeconds() << " seconds" << std::endl; - std::cout << " " << music.getSampleRate() << " samples / sec" << std::endl; - std::cout << " " << music.getChannelCount() << " channels" << std::endl; - - // Play it - music.play(); - - // Loop while the music is playing - while (music.getStatus() == sf::Music::Playing) - { - // Leave some CPU time for other processes - sf::sleep(sf::milliseconds(100)); - - // Display the playing position - std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << music.getPlayingOffset().asSeconds() << " sec "; - std::cout << std::flush; - } - std::cout << std::endl; -} - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \return Application exit code -/// -//////////////////////////////////////////////////////////// -int main() -{ - // Play a sound - playSound(); - - // Play a music - playMusic(); - - // Wait until the user presses 'enter' key - std::cout << "Press enter to exit..." << std::endl; - std::cin.ignore(10000, '\n'); - - return EXIT_SUCCESS; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +//////////////////////////////////////////////////////////// +/// Play a sound +/// +//////////////////////////////////////////////////////////// +void playSound() +{ + // Load a sound buffer from a wav file + sf::SoundBuffer buffer; + if (!buffer.loadFromFile("resources/canary.wav")) + return; + + // Display sound informations + std::cout << "canary.wav:" << std::endl; + std::cout << " " << buffer.getDuration().asSeconds() << " seconds" << std::endl; + std::cout << " " << buffer.getSampleRate() << " samples / sec" << std::endl; + std::cout << " " << buffer.getChannelCount() << " channels" << std::endl; + + // Create a sound instance and play it + sf::Sound sound(buffer); + sound.play(); + + // Loop while the sound is playing + while (sound.getStatus() == sf::Sound::Playing) + { + // Leave some CPU time for other processes + sf::sleep(sf::milliseconds(100)); + + // Display the playing position + std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << sound.getPlayingOffset().asSeconds() << " sec "; + std::cout << std::flush; + } + std::cout << std::endl << std::endl; +} + + +//////////////////////////////////////////////////////////// +/// Play a music +/// +//////////////////////////////////////////////////////////// +void playMusic() +{ + // Load an ogg music file + sf::Music music; + if (!music.openFromFile("resources/orchestral.ogg")) + return; + + // Display music informations + std::cout << "orchestral.ogg:" << std::endl; + std::cout << " " << music.getDuration().asSeconds() << " seconds" << std::endl; + std::cout << " " << music.getSampleRate() << " samples / sec" << std::endl; + std::cout << " " << music.getChannelCount() << " channels" << std::endl; + + // Play it + music.play(); + + // Loop while the music is playing + while (music.getStatus() == sf::Music::Playing) + { + // Leave some CPU time for other processes + sf::sleep(sf::milliseconds(100)); + + // Display the playing position + std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << music.getPlayingOffset().asSeconds() << " sec "; + std::cout << std::flush; + } + std::cout << std::endl; +} + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \return Application exit code +/// +//////////////////////////////////////////////////////////// +int main() +{ + // Play a sound + playSound(); + + // Play a music + playMusic(); + + // Wait until the user presses 'enter' key + std::cout << "Press enter to exit..." << std::endl; + std::cin.ignore(10000, '\n'); + + return EXIT_SUCCESS; +} diff --git a/examples/sound_capture/CMakeLists.txt b/examples/sound_capture/CMakeLists.txt index ac75c3cd..e62b3b3b 100644 --- a/examples/sound_capture/CMakeLists.txt +++ b/examples/sound_capture/CMakeLists.txt @@ -1,10 +1,10 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/sound_capture) - -# all source files -set(SRC ${SRCROOT}/SoundCapture.cpp) - -# define the sound-capture target -sfml_add_example(sound-capture - SOURCES ${SRC} - DEPENDS sfml-audio sfml-system) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/sound_capture) + +# all source files +set(SRC ${SRCROOT}/SoundCapture.cpp) + +# define the sound-capture target +sfml_add_example(sound-capture + SOURCES ${SRC} + DEPENDS sfml-audio sfml-system) diff --git a/examples/sound_capture/SoundCapture.cpp b/examples/sound_capture/SoundCapture.cpp index d3543441..b5814aa9 100644 --- a/examples/sound_capture/SoundCapture.cpp +++ b/examples/sound_capture/SoundCapture.cpp @@ -1,95 +1,95 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \return Application exit code -/// -//////////////////////////////////////////////////////////// -int main() -{ - // Check that the device can capture audio - if (sf::SoundRecorder::isAvailable() == false) - { - std::cout << "Sorry, audio capture is not supported by your system" << std::endl; - return EXIT_SUCCESS; - } - - // Choose the sample rate - unsigned int sampleRate; - std::cout << "Please choose the sample rate for sound capture (44100 is CD quality) : "; - std::cin >> sampleRate; - std::cin.ignore(10000, '\n'); - - // Wait for user input... - std::cout << "Press enter to start recording audio"; - std::cin.ignore(10000, '\n'); - - // Here we'll use an integrated custom recorder, which saves the captured data into a SoundBuffer - sf::SoundBufferRecorder recorder; - - // Audio capture is done in a separate thread, so we can block the main thread while it is capturing - recorder.start(sampleRate); - std::cout << "Recording... press enter to stop"; - std::cin.ignore(10000, '\n'); - recorder.stop(); - - // Get the buffer containing the captured data - const sf::SoundBuffer& buffer = recorder.getBuffer(); - - // Display captured sound informations - std::cout << "Sound information :" << std::endl; - std::cout << " " << buffer.getDuration().asSeconds() << " seconds" << std::endl; - std::cout << " " << buffer.getSampleRate() << " samples / seconds" << std::endl; - std::cout << " " << buffer.getChannelCount() << " channels" << std::endl; - - // Choose what to do with the recorded sound data - char choice; - std::cout << "What do you want to do with captured sound (p = play, s = save) ? "; - std::cin >> choice; - std::cin.ignore(10000, '\n'); - - if (choice == 's') - { - // Choose the filename - std::string filename; - std::cout << "Choose the file to create : "; - std::getline(std::cin, filename); - - // Save the buffer - buffer.saveToFile(filename); - } - else - { - // Create a sound instance and play it - sf::Sound sound(buffer); - sound.play(); - - // Wait until finished - while (sound.getStatus() == sf::Sound::Playing) - { - // Display the playing position - std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << sound.getPlayingOffset().asSeconds() << " sec"; - std::cout << std::flush; - - // Leave some CPU time for other threads - sf::sleep(sf::milliseconds(100)); - } - } - - // Finished! - std::cout << std::endl << "Done!" << std::endl; - - // Wait until the user presses 'enter' key - std::cout << "Press enter to exit..." << std::endl; - std::cin.ignore(10000, '\n'); - - return EXIT_SUCCESS; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \return Application exit code +/// +//////////////////////////////////////////////////////////// +int main() +{ + // Check that the device can capture audio + if (sf::SoundRecorder::isAvailable() == false) + { + std::cout << "Sorry, audio capture is not supported by your system" << std::endl; + return EXIT_SUCCESS; + } + + // Choose the sample rate + unsigned int sampleRate; + std::cout << "Please choose the sample rate for sound capture (44100 is CD quality) : "; + std::cin >> sampleRate; + std::cin.ignore(10000, '\n'); + + // Wait for user input... + std::cout << "Press enter to start recording audio"; + std::cin.ignore(10000, '\n'); + + // Here we'll use an integrated custom recorder, which saves the captured data into a SoundBuffer + sf::SoundBufferRecorder recorder; + + // Audio capture is done in a separate thread, so we can block the main thread while it is capturing + recorder.start(sampleRate); + std::cout << "Recording... press enter to stop"; + std::cin.ignore(10000, '\n'); + recorder.stop(); + + // Get the buffer containing the captured data + const sf::SoundBuffer& buffer = recorder.getBuffer(); + + // Display captured sound informations + std::cout << "Sound information:" << std::endl; + std::cout << " " << buffer.getDuration().asSeconds() << " seconds" << std::endl; + std::cout << " " << buffer.getSampleRate() << " samples / seconds" << std::endl; + std::cout << " " << buffer.getChannelCount() << " channels" << std::endl; + + // Choose what to do with the recorded sound data + char choice; + std::cout << "What do you want to do with captured sound (p = play, s = save) ? "; + std::cin >> choice; + std::cin.ignore(10000, '\n'); + + if (choice == 's') + { + // Choose the filename + std::string filename; + std::cout << "Choose the file to create: "; + std::getline(std::cin, filename); + + // Save the buffer + buffer.saveToFile(filename); + } + else + { + // Create a sound instance and play it + sf::Sound sound(buffer); + sound.play(); + + // Wait until finished + while (sound.getStatus() == sf::Sound::Playing) + { + // Display the playing position + std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << sound.getPlayingOffset().asSeconds() << " sec"; + std::cout << std::flush; + + // Leave some CPU time for other threads + sf::sleep(sf::milliseconds(100)); + } + } + + // Finished! + std::cout << std::endl << "Done!" << std::endl; + + // Wait until the user presses 'enter' key + std::cout << "Press enter to exit..." << std::endl; + std::cin.ignore(10000, '\n'); + + return EXIT_SUCCESS; +} diff --git a/examples/voip/CMakeLists.txt b/examples/voip/CMakeLists.txt index c2e0738e..0e4e710c 100644 --- a/examples/voip/CMakeLists.txt +++ b/examples/voip/CMakeLists.txt @@ -1,12 +1,12 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/voip) - -# all source files -set(SRC ${SRCROOT}/VoIP.cpp - ${SRCROOT}/Client.cpp - ${SRCROOT}/Server.cpp) - -# define the voip target -sfml_add_example(voip - SOURCES ${SRC} - DEPENDS sfml-audio sfml-network sfml-system) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/voip) + +# all source files +set(SRC ${SRCROOT}/VoIP.cpp + ${SRCROOT}/Client.cpp + ${SRCROOT}/Server.cpp) + +# define the voip target +sfml_add_example(voip + SOURCES ${SRC} + DEPENDS sfml-audio sfml-network sfml-system) diff --git a/examples/voip/Client.cpp b/examples/voip/Client.cpp index ceb2da60..595d6247 100644 --- a/examples/voip/Client.cpp +++ b/examples/voip/Client.cpp @@ -1,129 +1,129 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -const sf::Uint8 audioData = 1; -const sf::Uint8 endOfStream = 2; - - -//////////////////////////////////////////////////////////// -/// Specialization of audio recorder for sending recorded audio -/// data through the network -//////////////////////////////////////////////////////////// -class NetworkRecorder : public sf::SoundRecorder -{ -public : - - //////////////////////////////////////////////////////////// - /// Constructor - /// - /// \param host Remote host to which send the recording data - /// \param port Port of the remote host - /// - //////////////////////////////////////////////////////////// - NetworkRecorder(const sf::IpAddress& host, unsigned short port) : - m_host(host), - m_port(port) - { - } - -private : - - //////////////////////////////////////////////////////////// - /// /see SoundRecorder::OnStart - /// - //////////////////////////////////////////////////////////// - virtual bool onStart() - { - if (m_socket.connect(m_host, m_port) == sf::Socket::Done) - { - std::cout << "Connected to server " << m_host << std::endl; - return true; - } - else - { - return false; - } - } - - //////////////////////////////////////////////////////////// - /// /see SoundRecorder::ProcessSamples - /// - //////////////////////////////////////////////////////////// - virtual bool onProcessSamples(const sf::Int16* samples, std::size_t sampleCount) - { - // Pack the audio samples into a network packet - sf::Packet packet; - packet << audioData; - packet.append(samples, sampleCount * sizeof(sf::Int16)); - - // Send the audio packet to the server - return m_socket.send(packet) == sf::Socket::Done; - } - - //////////////////////////////////////////////////////////// - /// /see SoundRecorder::OnStop - /// - //////////////////////////////////////////////////////////// - virtual void onStop() - { - // Send a "end-of-stream" packet - sf::Packet packet; - packet << endOfStream; - m_socket.send(packet); - - // Close the socket - m_socket.disconnect(); - } - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - sf::IpAddress m_host; ///< Address of the remote host - unsigned short m_port; ///< Remote port - sf::TcpSocket m_socket; ///< Socket used to communicate with the server -}; - - -//////////////////////////////////////////////////////////// -/// Create a client, connect it to a running server and -/// start sending him audio data -/// -//////////////////////////////////////////////////////////// -void doClient(unsigned short port) -{ - // Check that the device can capture audio - if (sf::SoundRecorder::isAvailable() == false) - { - std::cout << "Sorry, audio capture is not supported by your system" << std::endl; - return; - } - - // Ask for server address - sf::IpAddress server; - do - { - std::cout << "Type address or name of the server to connect to : "; - std::cin >> server; - } - while (server == sf::IpAddress::None); - - // Create an instance of our custom recorder - NetworkRecorder recorder(server, port); - - // Wait for user input... - std::cin.ignore(10000, '\n'); - std::cout << "Press enter to start recording audio"; - std::cin.ignore(10000, '\n'); - - // Start capturing audio data - recorder.start(44100); - std::cout << "Recording... press enter to stop"; - std::cin.ignore(10000, '\n'); - recorder.stop(); -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +const sf::Uint8 audioData = 1; +const sf::Uint8 endOfStream = 2; + + +//////////////////////////////////////////////////////////// +/// Specialization of audio recorder for sending recorded audio +/// data through the network +//////////////////////////////////////////////////////////// +class NetworkRecorder : public sf::SoundRecorder +{ +public: + + //////////////////////////////////////////////////////////// + /// Constructor + /// + /// \param host Remote host to which send the recording data + /// \param port Port of the remote host + /// + //////////////////////////////////////////////////////////// + NetworkRecorder(const sf::IpAddress& host, unsigned short port) : + m_host(host), + m_port(port) + { + } + +private: + + //////////////////////////////////////////////////////////// + /// /see SoundRecorder::OnStart + /// + //////////////////////////////////////////////////////////// + virtual bool onStart() + { + if (m_socket.connect(m_host, m_port) == sf::Socket::Done) + { + std::cout << "Connected to server " << m_host << std::endl; + return true; + } + else + { + return false; + } + } + + //////////////////////////////////////////////////////////// + /// /see SoundRecorder::ProcessSamples + /// + //////////////////////////////////////////////////////////// + virtual bool onProcessSamples(const sf::Int16* samples, std::size_t sampleCount) + { + // Pack the audio samples into a network packet + sf::Packet packet; + packet << audioData; + packet.append(samples, sampleCount * sizeof(sf::Int16)); + + // Send the audio packet to the server + return m_socket.send(packet) == sf::Socket::Done; + } + + //////////////////////////////////////////////////////////// + /// /see SoundRecorder::OnStop + /// + //////////////////////////////////////////////////////////// + virtual void onStop() + { + // Send a "end-of-stream" packet + sf::Packet packet; + packet << endOfStream; + m_socket.send(packet); + + // Close the socket + m_socket.disconnect(); + } + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + sf::IpAddress m_host; ///< Address of the remote host + unsigned short m_port; ///< Remote port + sf::TcpSocket m_socket; ///< Socket used to communicate with the server +}; + + +//////////////////////////////////////////////////////////// +/// Create a client, connect it to a running server and +/// start sending him audio data +/// +//////////////////////////////////////////////////////////// +void doClient(unsigned short port) +{ + // Check that the device can capture audio + if (sf::SoundRecorder::isAvailable() == false) + { + std::cout << "Sorry, audio capture is not supported by your system" << std::endl; + return; + } + + // Ask for server address + sf::IpAddress server; + do + { + std::cout << "Type address or name of the server to connect to: "; + std::cin >> server; + } + while (server == sf::IpAddress::None); + + // Create an instance of our custom recorder + NetworkRecorder recorder(server, port); + + // Wait for user input... + std::cin.ignore(10000, '\n'); + std::cout << "Press enter to start recording audio"; + std::cin.ignore(10000, '\n'); + + // Start capturing audio data + recorder.start(44100); + std::cout << "Recording... press enter to stop"; + std::cin.ignore(10000, '\n'); + recorder.stop(); +} diff --git a/examples/voip/Server.cpp b/examples/voip/Server.cpp index 29227fab..0875bf95 100644 --- a/examples/voip/Server.cpp +++ b/examples/voip/Server.cpp @@ -1,200 +1,200 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -const sf::Uint8 audioData = 1; -const sf::Uint8 endOfStream = 2; - - -//////////////////////////////////////////////////////////// -/// Customized sound stream for acquiring audio data -/// from the network -//////////////////////////////////////////////////////////// -class NetworkAudioStream : public sf::SoundStream -{ -public : - - //////////////////////////////////////////////////////////// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - NetworkAudioStream() : - m_offset (0), - m_hasFinished(false) - { - // Set the sound parameters - initialize(1, 44100); - } - - //////////////////////////////////////////////////////////// - /// Run the server, stream audio data from the client - /// - //////////////////////////////////////////////////////////// - void start(unsigned short port) - { - if (!m_hasFinished) - { - // Listen to the given port for incoming connections - if (m_listener.listen(port) != sf::Socket::Done) - return; - std::cout << "Server is listening to port " << port << ", waiting for connections... " << std::endl; - - // Wait for a connection - if (m_listener.accept(m_client) != sf::Socket::Done) - return; - std::cout << "Client connected: " << m_client.getRemoteAddress() << std::endl; - - // Start playback - play(); - - // Start receiving audio data - receiveLoop(); - } - else - { - // Start playback - play(); - } - } - -private : - - //////////////////////////////////////////////////////////// - /// /see SoundStream::OnGetData - /// - //////////////////////////////////////////////////////////// - virtual bool onGetData(sf::SoundStream::Chunk& data) - { - // We have reached the end of the buffer and all audio data have been played : we can stop playback - if ((m_offset >= m_samples.size()) && m_hasFinished) - return false; - - // No new data has arrived since last update : wait until we get some - while ((m_offset >= m_samples.size()) && !m_hasFinished) - sf::sleep(sf::milliseconds(10)); - - // Copy samples into a local buffer to avoid synchronization problems - // (don't forget that we run in two separate threads) - { - sf::Lock lock(m_mutex); - m_tempBuffer.assign(m_samples.begin() + m_offset, m_samples.end()); - } - - // Fill audio data to pass to the stream - data.samples = &m_tempBuffer[0]; - data.sampleCount = m_tempBuffer.size(); - - // Update the playing offset - m_offset += m_tempBuffer.size(); - - return true; - } - - //////////////////////////////////////////////////////////// - /// /see SoundStream::OnSeek - /// - //////////////////////////////////////////////////////////// - virtual void onSeek(sf::Time timeOffset) - { - m_offset = timeOffset.asMilliseconds() * getSampleRate() * getChannelCount() / 1000; - } - - //////////////////////////////////////////////////////////// - /// Get audio data from the client until playback is stopped - /// - //////////////////////////////////////////////////////////// - void receiveLoop() - { - while (!m_hasFinished) - { - // Get waiting audio data from the network - sf::Packet packet; - if (m_client.receive(packet) != sf::Socket::Done) - break; - - // Extract the message ID - sf::Uint8 id; - packet >> id; - - if (id == audioData) - { - // Extract audio samples from the packet, and append it to our samples buffer - const sf::Int16* samples = reinterpret_cast(static_cast(packet.getData()) + 1); - std::size_t sampleCount = (packet.getDataSize() - 1) / sizeof(sf::Int16); - - // Don't forget that the other thread can access the sample array at any time - // (so we protect any operation on it with the mutex) - { - sf::Lock lock(m_mutex); - std::copy(samples, samples + sampleCount, std::back_inserter(m_samples)); - } - } - else if (id == endOfStream) - { - // End of stream reached : we stop receiving audio data - std::cout << "Audio data has been 100% received!" << std::endl; - m_hasFinished = true; - } - else - { - // Something's wrong... - std::cout << "Invalid packet received..." << std::endl; - m_hasFinished = true; - } - } - } - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - sf::TcpListener m_listener; - sf::TcpSocket m_client; - sf::Mutex m_mutex; - std::vector m_samples; - std::vector m_tempBuffer; - std::size_t m_offset; - bool m_hasFinished; -}; - - -//////////////////////////////////////////////////////////// -/// Launch a server and wait for incoming audio data from -/// a connected client -/// -//////////////////////////////////////////////////////////// -void doServer(unsigned short port) -{ - // Build an audio stream to play sound data as it is received through the network - NetworkAudioStream audioStream; - audioStream.start(port); - - // Loop until the sound playback is finished - while (audioStream.getStatus() != sf::SoundStream::Stopped) - { - // Leave some CPU time for other threads - sf::sleep(sf::milliseconds(100)); - } - - std::cin.ignore(10000, '\n'); - - // Wait until the user presses 'enter' key - std::cout << "Press enter to replay the sound..." << std::endl; - std::cin.ignore(10000, '\n'); - - // Replay the sound (just to make sure replaying the received data is OK) - audioStream.play(); - - // Loop until the sound playback is finished - while (audioStream.getStatus() != sf::SoundStream::Stopped) - { - // Leave some CPU time for other threads - sf::sleep(sf::milliseconds(100)); - } -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +const sf::Uint8 audioData = 1; +const sf::Uint8 endOfStream = 2; + + +//////////////////////////////////////////////////////////// +/// Customized sound stream for acquiring audio data +/// from the network +//////////////////////////////////////////////////////////// +class NetworkAudioStream : public sf::SoundStream +{ +public: + + //////////////////////////////////////////////////////////// + /// Default constructor + /// + //////////////////////////////////////////////////////////// + NetworkAudioStream() : + m_offset (0), + m_hasFinished(false) + { + // Set the sound parameters + initialize(1, 44100); + } + + //////////////////////////////////////////////////////////// + /// Run the server, stream audio data from the client + /// + //////////////////////////////////////////////////////////// + void start(unsigned short port) + { + if (!m_hasFinished) + { + // Listen to the given port for incoming connections + if (m_listener.listen(port) != sf::Socket::Done) + return; + std::cout << "Server is listening to port " << port << ", waiting for connections... " << std::endl; + + // Wait for a connection + if (m_listener.accept(m_client) != sf::Socket::Done) + return; + std::cout << "Client connected: " << m_client.getRemoteAddress() << std::endl; + + // Start playback + play(); + + // Start receiving audio data + receiveLoop(); + } + else + { + // Start playback + play(); + } + } + +private: + + //////////////////////////////////////////////////////////// + /// /see SoundStream::OnGetData + /// + //////////////////////////////////////////////////////////// + virtual bool onGetData(sf::SoundStream::Chunk& data) + { + // We have reached the end of the buffer and all audio data have been played: we can stop playback + if ((m_offset >= m_samples.size()) && m_hasFinished) + return false; + + // No new data has arrived since last update: wait until we get some + while ((m_offset >= m_samples.size()) && !m_hasFinished) + sf::sleep(sf::milliseconds(10)); + + // Copy samples into a local buffer to avoid synchronization problems + // (don't forget that we run in two separate threads) + { + sf::Lock lock(m_mutex); + m_tempBuffer.assign(m_samples.begin() + m_offset, m_samples.end()); + } + + // Fill audio data to pass to the stream + data.samples = &m_tempBuffer[0]; + data.sampleCount = m_tempBuffer.size(); + + // Update the playing offset + m_offset += m_tempBuffer.size(); + + return true; + } + + //////////////////////////////////////////////////////////// + /// /see SoundStream::OnSeek + /// + //////////////////////////////////////////////////////////// + virtual void onSeek(sf::Time timeOffset) + { + m_offset = timeOffset.asMilliseconds() * getSampleRate() * getChannelCount() / 1000; + } + + //////////////////////////////////////////////////////////// + /// Get audio data from the client until playback is stopped + /// + //////////////////////////////////////////////////////////// + void receiveLoop() + { + while (!m_hasFinished) + { + // Get waiting audio data from the network + sf::Packet packet; + if (m_client.receive(packet) != sf::Socket::Done) + break; + + // Extract the message ID + sf::Uint8 id; + packet >> id; + + if (id == audioData) + { + // Extract audio samples from the packet, and append it to our samples buffer + const sf::Int16* samples = reinterpret_cast(static_cast(packet.getData()) + 1); + std::size_t sampleCount = (packet.getDataSize() - 1) / sizeof(sf::Int16); + + // Don't forget that the other thread can access the sample array at any time + // (so we protect any operation on it with the mutex) + { + sf::Lock lock(m_mutex); + std::copy(samples, samples + sampleCount, std::back_inserter(m_samples)); + } + } + else if (id == endOfStream) + { + // End of stream reached: we stop receiving audio data + std::cout << "Audio data has been 100% received!" << std::endl; + m_hasFinished = true; + } + else + { + // Something's wrong... + std::cout << "Invalid packet received..." << std::endl; + m_hasFinished = true; + } + } + } + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + sf::TcpListener m_listener; + sf::TcpSocket m_client; + sf::Mutex m_mutex; + std::vector m_samples; + std::vector m_tempBuffer; + std::size_t m_offset; + bool m_hasFinished; +}; + + +//////////////////////////////////////////////////////////// +/// Launch a server and wait for incoming audio data from +/// a connected client +/// +//////////////////////////////////////////////////////////// +void doServer(unsigned short port) +{ + // Build an audio stream to play sound data as it is received through the network + NetworkAudioStream audioStream; + audioStream.start(port); + + // Loop until the sound playback is finished + while (audioStream.getStatus() != sf::SoundStream::Stopped) + { + // Leave some CPU time for other threads + sf::sleep(sf::milliseconds(100)); + } + + std::cin.ignore(10000, '\n'); + + // Wait until the user presses 'enter' key + std::cout << "Press enter to replay the sound..." << std::endl; + std::cin.ignore(10000, '\n'); + + // Replay the sound (just to make sure replaying the received data is OK) + audioStream.play(); + + // Loop until the sound playback is finished + while (audioStream.getStatus() != sf::SoundStream::Stopped) + { + // Leave some CPU time for other threads + sf::sleep(sf::milliseconds(100)); + } +} diff --git a/examples/voip/VoIP.cpp b/examples/voip/VoIP.cpp index 93f95129..d3e05306 100644 --- a/examples/voip/VoIP.cpp +++ b/examples/voip/VoIP.cpp @@ -1,50 +1,50 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -//////////////////////////////////////////////////////////// -// Function prototypes -// (I'm too lazy to put them into separate headers...) -//////////////////////////////////////////////////////////// -void doClient(unsigned short port); -void doServer(unsigned short port); - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \return Application exit code -/// -//////////////////////////////////////////////////////////// -int main() -{ - // Choose a random port for opening sockets (ports < 1024 are reserved) - const unsigned short port = 2435; - - // Client or server ? - char who; - std::cout << "Do you want to be a server ('s') or a client ('c') ? "; - std::cin >> who; - - if (who == 's') - { - // Run as a server - doServer(port); - } - else - { - // Run as a client - doClient(port); - } - - // Wait until the user presses 'enter' key - std::cout << "Press enter to exit..." << std::endl; - std::cin.ignore(10000, '\n'); - - return EXIT_SUCCESS; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +//////////////////////////////////////////////////////////// +// Function prototypes +// (I'm too lazy to put them into separate headers...) +//////////////////////////////////////////////////////////// +void doClient(unsigned short port); +void doServer(unsigned short port); + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \return Application exit code +/// +//////////////////////////////////////////////////////////// +int main() +{ + // Choose a random port for opening sockets (ports < 1024 are reserved) + const unsigned short port = 2435; + + // Client or server ? + char who; + std::cout << "Do you want to be a server ('s') or a client ('c') ? "; + std::cin >> who; + + if (who == 's') + { + // Run as a server + doServer(port); + } + else + { + // Run as a client + doClient(port); + } + + // Wait until the user presses 'enter' key + std::cout << "Press enter to exit..." << std::endl; + std::cin.ignore(10000, '\n'); + + return EXIT_SUCCESS; +} diff --git a/examples/win32/CMakeLists.txt b/examples/win32/CMakeLists.txt index edd82371..c0bea6e2 100644 --- a/examples/win32/CMakeLists.txt +++ b/examples/win32/CMakeLists.txt @@ -1,10 +1,10 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/win32) - -# all source files -set(SRC ${SRCROOT}/Win32.cpp) - -# define the win32 target -sfml_add_example(win32 GUI_APP - SOURCES ${SRC} - DEPENDS sfml-graphics sfml-window sfml-system) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/win32) + +# all source files +set(SRC ${SRCROOT}/Win32.cpp) + +# define the win32 target +sfml_add_example(win32 GUI_APP + SOURCES ${SRC} + DEPENDS sfml-graphics sfml-window sfml-system) diff --git a/examples/win32/Win32.cpp b/examples/win32/Win32.cpp index 4d70931d..5df33a84 100644 --- a/examples/win32/Win32.cpp +++ b/examples/win32/Win32.cpp @@ -1,130 +1,130 @@ - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - -HWND button; - - -//////////////////////////////////////////////////////////// -/// Function called whenever one of our windows receives a message -/// -//////////////////////////////////////////////////////////// -LRESULT CALLBACK onEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - // Quit when we close the main window - case WM_CLOSE : - { - PostQuitMessage(0); - return 0; - } - - // Quit when we click the "quit" button - case WM_COMMAND : - { - if (reinterpret_cast(lParam) == button) - { - PostQuitMessage(0); - return 0; - } - } - } - - return DefWindowProc(handle, message, wParam, lParam); -} - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \param Instance : Instance of the application -/// -/// \return Error code -/// -//////////////////////////////////////////////////////////// -INT WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, INT) -{ - // Define a class for our main window - WNDCLASS windowClass; - windowClass.style = 0; - windowClass.lpfnWndProc = &onEvent; - windowClass.cbClsExtra = 0; - windowClass.cbWndExtra = 0; - windowClass.hInstance = instance; - windowClass.hIcon = NULL; - windowClass.hCursor = 0; - windowClass.hbrBackground = reinterpret_cast(COLOR_BACKGROUND); - windowClass.lpszMenuName = NULL; - windowClass.lpszClassName = TEXT("SFML App"); - RegisterClass(&windowClass); - - // Let's create the main window - HWND window = CreateWindow(TEXT("SFML App"), TEXT("SFML Win32"), WS_SYSMENU | WS_VISIBLE, 200, 200, 660, 520, NULL, NULL, instance, NULL); - - // Add a button for exiting - button = CreateWindow(TEXT("BUTTON"), TEXT("Quit"), WS_CHILD | WS_VISIBLE, 560, 440, 80, 40, window, NULL, instance, NULL); - - // Let's create two SFML views - HWND view1 = CreateWindow(TEXT("STATIC"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, 20, 20, 300, 400, window, NULL, instance, NULL); - HWND view2 = CreateWindow(TEXT("STATIC"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, 340, 20, 300, 400, window, NULL, instance, NULL); - sf::RenderWindow SFMLView1(view1); - sf::RenderWindow SFMLView2(view2); - - // Load some textures to display - sf::Texture texture1, texture2; - if (!texture1.loadFromFile("resources/image1.jpg") || !texture2.loadFromFile("resources/image2.jpg")) - return EXIT_FAILURE; - sf::Sprite sprite1(texture1); - sf::Sprite sprite2(texture2); - sprite1.setOrigin(sf::Vector2f(texture1.getSize()) / 2.f); - sprite1.setPosition(sprite1.getOrigin()); - - // Create a clock for measuring elapsed time - sf::Clock clock; - - // Loop until a WM_QUIT message is received - MSG message; - message.message = static_cast(~WM_QUIT); - while (message.message != WM_QUIT) - { - if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) - { - // If a message was waiting in the message queue, process it - TranslateMessage(&message); - DispatchMessage(&message); - } - else - { - float time = clock.getElapsedTime().asSeconds(); - - // Clear views - SFMLView1.clear(); - SFMLView2.clear(); - - // Draw sprite 1 on view 1 - sprite1.setRotation(time * 100); - SFMLView1.draw(sprite1); - - // Draw sprite 2 on view 2 - sprite2.setPosition(std::cos(time) * 100.f, 0.f); - SFMLView2.draw(sprite2); - - // Display each view on screen - SFMLView1.display(); - SFMLView2.display(); - } - } - - // Destroy the main window (all its child controls will be destroyed) - DestroyWindow(window); - - // Don't forget to unregister the window class - UnregisterClass(TEXT("SFML App"), instance); - - return EXIT_SUCCESS; -} + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + +HWND button; + + +//////////////////////////////////////////////////////////// +/// Function called whenever one of our windows receives a message +/// +//////////////////////////////////////////////////////////// +LRESULT CALLBACK onEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + // Quit when we close the main window + case WM_CLOSE: + { + PostQuitMessage(0); + return 0; + } + + // Quit when we click the "quit" button + case WM_COMMAND: + { + if (reinterpret_cast(lParam) == button) + { + PostQuitMessage(0); + return 0; + } + } + } + + return DefWindowProc(handle, message, wParam, lParam); +} + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \param Instance: Instance of the application +/// +/// \return Error code +/// +//////////////////////////////////////////////////////////// +INT WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, INT) +{ + // Define a class for our main window + WNDCLASS windowClass; + windowClass.style = 0; + windowClass.lpfnWndProc = &onEvent; + windowClass.cbClsExtra = 0; + windowClass.cbWndExtra = 0; + windowClass.hInstance = instance; + windowClass.hIcon = NULL; + windowClass.hCursor = 0; + windowClass.hbrBackground = reinterpret_cast(COLOR_BACKGROUND); + windowClass.lpszMenuName = NULL; + windowClass.lpszClassName = TEXT("SFML App"); + RegisterClass(&windowClass); + + // Let's create the main window + HWND window = CreateWindow(TEXT("SFML App"), TEXT("SFML Win32"), WS_SYSMENU | WS_VISIBLE, 200, 200, 660, 520, NULL, NULL, instance, NULL); + + // Add a button for exiting + button = CreateWindow(TEXT("BUTTON"), TEXT("Quit"), WS_CHILD | WS_VISIBLE, 560, 440, 80, 40, window, NULL, instance, NULL); + + // Let's create two SFML views + HWND view1 = CreateWindow(TEXT("STATIC"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, 20, 20, 300, 400, window, NULL, instance, NULL); + HWND view2 = CreateWindow(TEXT("STATIC"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, 340, 20, 300, 400, window, NULL, instance, NULL); + sf::RenderWindow SFMLView1(view1); + sf::RenderWindow SFMLView2(view2); + + // Load some textures to display + sf::Texture texture1, texture2; + if (!texture1.loadFromFile("resources/image1.jpg") || !texture2.loadFromFile("resources/image2.jpg")) + return EXIT_FAILURE; + sf::Sprite sprite1(texture1); + sf::Sprite sprite2(texture2); + sprite1.setOrigin(sf::Vector2f(texture1.getSize()) / 2.f); + sprite1.setPosition(sprite1.getOrigin()); + + // Create a clock for measuring elapsed time + sf::Clock clock; + + // Loop until a WM_QUIT message is received + MSG message; + message.message = static_cast(~WM_QUIT); + while (message.message != WM_QUIT) + { + if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) + { + // If a message was waiting in the message queue, process it + TranslateMessage(&message); + DispatchMessage(&message); + } + else + { + float time = clock.getElapsedTime().asSeconds(); + + // Clear views + SFMLView1.clear(); + SFMLView2.clear(); + + // Draw sprite 1 on view 1 + sprite1.setRotation(time * 100); + SFMLView1.draw(sprite1); + + // Draw sprite 2 on view 2 + sprite2.setPosition(std::cos(time) * 100.f, 0.f); + SFMLView2.draw(sprite2); + + // Display each view on screen + SFMLView1.display(); + SFMLView2.display(); + } + } + + // Destroy the main window (all its child controls will be destroyed) + DestroyWindow(window); + + // Don't forget to unregister the window class + UnregisterClass(TEXT("SFML App"), instance); + + return EXIT_SUCCESS; +} diff --git a/examples/window/CMakeLists.txt b/examples/window/CMakeLists.txt index 7ec6b127..e49340cc 100644 --- a/examples/window/CMakeLists.txt +++ b/examples/window/CMakeLists.txt @@ -1,15 +1,15 @@ - -set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/window) - -# all source files -set(SRC ${SRCROOT}/Window.cpp) - -# find OpenGL and GLU -find_package(OpenGL REQUIRED) -include_directories(${OPENGL_INCLUDE_DIR}) -set(ADDITIONAL_LIBRARIES ${OPENGL_LIBRARIES}) - -# define the window target -sfml_add_example(window GUI_APP - SOURCES ${SRC} - DEPENDS sfml-window sfml-system ${ADDITIONAL_LIBRARIES}) + +set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/window) + +# all source files +set(SRC ${SRCROOT}/Window.cpp) + +# find OpenGL and GLU +find_package(OpenGL REQUIRED) +include_directories(${OPENGL_INCLUDE_DIR}) +set(ADDITIONAL_LIBRARIES ${OPENGL_LIBRARIES}) + +# define the window target +sfml_add_example(window GUI_APP + SOURCES ${SRC} + DEPENDS sfml-window sfml-system ${ADDITIONAL_LIBRARIES}) diff --git a/examples/window/Window.cpp b/examples/window/Window.cpp index 360703b4..46adf0d3 100644 --- a/examples/window/Window.cpp +++ b/examples/window/Window.cpp @@ -1,146 +1,146 @@ -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -//////////////////////////////////////////////////////////// -/// Entry point of application -/// -/// \return Application exit code -/// -//////////////////////////////////////////////////////////// -int main() -{ - // Request a 32-bits depth buffer when creating the window - sf::ContextSettings contextSettings; - contextSettings.depthBits = 32; - - // Create the main window - sf::Window window(sf::VideoMode(640, 480), "SFML window with OpenGL", sf::Style::Default, contextSettings); - - // Make it the active window for OpenGL calls - window.setActive(); - - // Set the color and depth clear values - glClearDepth(1.f); - glClearColor(0.f, 0.f, 0.f, 1.f); - - // Enable Z-buffer read and write - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); - - // Disable lighting and texturing - glDisable(GL_LIGHTING); - glDisable(GL_TEXTURE_2D); - - // Configure the viewport (the same size as the window) - glViewport(0, 0, window.getSize().x, window.getSize().y); - - // Setup a perspective projection - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - GLfloat ratio = static_cast(window.getSize().x) / window.getSize().y; - glFrustum(-ratio, ratio, -1.f, 1.f, 1.f, 500.f); - - // Define a 3D cube (6 faces made of 2 triangles composed by 3 vertices) - GLfloat cube[] = - { - // positions // colors (r, g, b, a) - -50, -50, -50, 0, 0, 1, 1, - -50, 50, -50, 0, 0, 1, 1, - -50, -50, 50, 0, 0, 1, 1, - -50, -50, 50, 0, 0, 1, 1, - -50, 50, -50, 0, 0, 1, 1, - -50, 50, 50, 0, 0, 1, 1, - - 50, -50, -50, 0, 1, 0, 1, - 50, 50, -50, 0, 1, 0, 1, - 50, -50, 50, 0, 1, 0, 1, - 50, -50, 50, 0, 1, 0, 1, - 50, 50, -50, 0, 1, 0, 1, - 50, 50, 50, 0, 1, 0, 1, - - -50, -50, -50, 1, 0, 0, 1, - 50, -50, -50, 1, 0, 0, 1, - -50, -50, 50, 1, 0, 0, 1, - -50, -50, 50, 1, 0, 0, 1, - 50, -50, -50, 1, 0, 0, 1, - 50, -50, 50, 1, 0, 0, 1, - - -50, 50, -50, 0, 1, 1, 1, - 50, 50, -50, 0, 1, 1, 1, - -50, 50, 50, 0, 1, 1, 1, - -50, 50, 50, 0, 1, 1, 1, - 50, 50, -50, 0, 1, 1, 1, - 50, 50, 50, 0, 1, 1, 1, - - -50, -50, -50, 1, 0, 1, 1, - 50, -50, -50, 1, 0, 1, 1, - -50, 50, -50, 1, 0, 1, 1, - -50, 50, -50, 1, 0, 1, 1, - 50, -50, -50, 1, 0, 1, 1, - 50, 50, -50, 1, 0, 1, 1, - - -50, -50, 50, 1, 1, 0, 1, - 50, -50, 50, 1, 1, 0, 1, - -50, 50, 50, 1, 1, 0, 1, - -50, 50, 50, 1, 1, 0, 1, - 50, -50, 50, 1, 1, 0, 1, - 50, 50, 50, 1, 1, 0, 1, - }; - - // Enable position and color vertex components - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(3, GL_FLOAT, 7 * sizeof(GLfloat), cube); - glColorPointer(4, GL_FLOAT, 7 * sizeof(GLfloat), cube + 3); - - // Disable normal and texture coordinates vertex components - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - // Create a clock for measuring the time elapsed - sf::Clock clock; - - // Start the game loop - while (window.isOpen()) - { - // Process events - sf::Event event; - while (window.pollEvent(event)) - { - // Close window: exit - if (event.type == sf::Event::Closed) - window.close(); - - // Escape key: exit - if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) - window.close(); - - // Resize event: adjust the viewport - if (event.type == sf::Event::Resized) - glViewport(0, 0, event.size.width, event.size.height); - } - - // Clear the color and depth buffers - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Apply some transformations to rotate the cube - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.f, 0.f, -200.f); - glRotatef(clock.getElapsedTime().asSeconds() * 50, 1.f, 0.f, 0.f); - glRotatef(clock.getElapsedTime().asSeconds() * 30, 0.f, 1.f, 0.f); - glRotatef(clock.getElapsedTime().asSeconds() * 90, 0.f, 0.f, 1.f); - - // Draw the cube - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Finally, display the rendered frame on screen - window.display(); - } - - return EXIT_SUCCESS; -} +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +//////////////////////////////////////////////////////////// +/// Entry point of application +/// +/// \return Application exit code +/// +//////////////////////////////////////////////////////////// +int main() +{ + // Request a 32-bits depth buffer when creating the window + sf::ContextSettings contextSettings; + contextSettings.depthBits = 32; + + // Create the main window + sf::Window window(sf::VideoMode(640, 480), "SFML window with OpenGL", sf::Style::Default, contextSettings); + + // Make it the active window for OpenGL calls + window.setActive(); + + // Set the color and depth clear values + glClearDepth(1.f); + glClearColor(0.f, 0.f, 0.f, 1.f); + + // Enable Z-buffer read and write + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); + + // Disable lighting and texturing + glDisable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + + // Configure the viewport (the same size as the window) + glViewport(0, 0, window.getSize().x, window.getSize().y); + + // Setup a perspective projection + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + GLfloat ratio = static_cast(window.getSize().x) / window.getSize().y; + glFrustum(-ratio, ratio, -1.f, 1.f, 1.f, 500.f); + + // Define a 3D cube (6 faces made of 2 triangles composed by 3 vertices) + GLfloat cube[] = + { + // positions // colors (r, g, b, a) + -50, -50, -50, 0, 0, 1, 1, + -50, 50, -50, 0, 0, 1, 1, + -50, -50, 50, 0, 0, 1, 1, + -50, -50, 50, 0, 0, 1, 1, + -50, 50, -50, 0, 0, 1, 1, + -50, 50, 50, 0, 0, 1, 1, + + 50, -50, -50, 0, 1, 0, 1, + 50, 50, -50, 0, 1, 0, 1, + 50, -50, 50, 0, 1, 0, 1, + 50, -50, 50, 0, 1, 0, 1, + 50, 50, -50, 0, 1, 0, 1, + 50, 50, 50, 0, 1, 0, 1, + + -50, -50, -50, 1, 0, 0, 1, + 50, -50, -50, 1, 0, 0, 1, + -50, -50, 50, 1, 0, 0, 1, + -50, -50, 50, 1, 0, 0, 1, + 50, -50, -50, 1, 0, 0, 1, + 50, -50, 50, 1, 0, 0, 1, + + -50, 50, -50, 0, 1, 1, 1, + 50, 50, -50, 0, 1, 1, 1, + -50, 50, 50, 0, 1, 1, 1, + -50, 50, 50, 0, 1, 1, 1, + 50, 50, -50, 0, 1, 1, 1, + 50, 50, 50, 0, 1, 1, 1, + + -50, -50, -50, 1, 0, 1, 1, + 50, -50, -50, 1, 0, 1, 1, + -50, 50, -50, 1, 0, 1, 1, + -50, 50, -50, 1, 0, 1, 1, + 50, -50, -50, 1, 0, 1, 1, + 50, 50, -50, 1, 0, 1, 1, + + -50, -50, 50, 1, 1, 0, 1, + 50, -50, 50, 1, 1, 0, 1, + -50, 50, 50, 1, 1, 0, 1, + -50, 50, 50, 1, 1, 0, 1, + 50, -50, 50, 1, 1, 0, 1, + 50, 50, 50, 1, 1, 0, 1, + }; + + // Enable position and color vertex components + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(3, GL_FLOAT, 7 * sizeof(GLfloat), cube); + glColorPointer(4, GL_FLOAT, 7 * sizeof(GLfloat), cube + 3); + + // Disable normal and texture coordinates vertex components + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + // Create a clock for measuring the time elapsed + sf::Clock clock; + + // Start the game loop + while (window.isOpen()) + { + // Process events + sf::Event event; + while (window.pollEvent(event)) + { + // Close window: exit + if (event.type == sf::Event::Closed) + window.close(); + + // Escape key: exit + if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) + window.close(); + + // Resize event: adjust the viewport + if (event.type == sf::Event::Resized) + glViewport(0, 0, event.size.width, event.size.height); + } + + // Clear the color and depth buffers + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Apply some transformations to rotate the cube + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.f, 0.f, -200.f); + glRotatef(clock.getElapsedTime().asSeconds() * 50, 1.f, 0.f, 0.f); + glRotatef(clock.getElapsedTime().asSeconds() * 30, 0.f, 1.f, 0.f); + glRotatef(clock.getElapsedTime().asSeconds() * 90, 0.f, 0.f, 1.f); + + // Draw the cube + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Finally, display the rendered frame on screen + window.display(); + } + + return EXIT_SUCCESS; +} diff --git a/include/SFML/Audio.hpp b/include/SFML/Audio.hpp index ee2360c5..15a079f6 100644 --- a/include/SFML/Audio.hpp +++ b/include/SFML/Audio.hpp @@ -1,50 +1,50 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_AUDIO_HPP -#define SFML_AUDIO_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include - - -#endif // SFML_AUDIO_HPP - -//////////////////////////////////////////////////////////// -/// \defgroup audio Audio module -/// -/// Sounds, streaming (musics or custom sources), recording, -/// spatialization. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_AUDIO_HPP +#define SFML_AUDIO_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif // SFML_AUDIO_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup audio Audio module +/// +/// Sounds, streaming (musics or custom sources), recording, +/// spatialization. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Audio/Listener.hpp b/include/SFML/Audio/Listener.hpp index 35cf8217..2ab203ef 100644 --- a/include/SFML/Audio/Listener.hpp +++ b/include/SFML/Audio/Listener.hpp @@ -1,234 +1,234 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_LISTENER_HPP -#define SFML_LISTENER_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief The audio listener is the point in the scene -/// from where all the sounds are heard -/// -//////////////////////////////////////////////////////////// -class SFML_AUDIO_API Listener -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Change the global volume of all the sounds and musics - /// - /// The volume is a number between 0 and 100; it is combined with - /// the individual volume of each sound / music. - /// The default value for the volume is 100 (maximum). - /// - /// \param volume New global volume, in the range [0, 100] - /// - /// \see getGlobalVolume - /// - //////////////////////////////////////////////////////////// - static void setGlobalVolume(float volume); - - //////////////////////////////////////////////////////////// - /// \brief Get the current value of the global volume - /// - /// \return Current global volume, in the range [0, 100] - /// - /// \see setGlobalVolume - /// - //////////////////////////////////////////////////////////// - static float getGlobalVolume(); - - //////////////////////////////////////////////////////////// - /// \brief Set the position of the listener in the scene - /// - /// The default listener's position is (0, 0, 0). - /// - /// \param x X coordinate of the listener's position - /// \param y Y coordinate of the listener's position - /// \param z Z coordinate of the listener's position - /// - /// \see getPosition, setDirection - /// - //////////////////////////////////////////////////////////// - static void setPosition(float x, float y, float z); - - //////////////////////////////////////////////////////////// - /// \brief Set the position of the listener in the scene - /// - /// The default listener's position is (0, 0, 0). - /// - /// \param position New listener's position - /// - /// \see getPosition, setDirection - /// - //////////////////////////////////////////////////////////// - static void setPosition(const Vector3f& position); - - //////////////////////////////////////////////////////////// - /// \brief Get the current position of the listener in the scene - /// - /// \return Listener's position - /// - /// \see setPosition - /// - //////////////////////////////////////////////////////////// - static Vector3f getPosition(); - - //////////////////////////////////////////////////////////// - /// \brief Set the forward vector of the listener in the scene - /// - /// The direction (also called "at vector") is the vector - /// pointing forward from the listener's perspective. Together - /// with the up vector, it defines the 3D orientation of the - /// listener in the scene. The direction vector doesn't - /// have to be normalized. - /// The default listener's direction is (0, 0, -1). - /// - /// \param x X coordinate of the listener's direction - /// \param y Y coordinate of the listener's direction - /// \param z Z coordinate of the listener's direction - /// - /// \see getDirection, setUpVector, setPosition - /// - //////////////////////////////////////////////////////////// - static void setDirection(float x, float y, float z); - - //////////////////////////////////////////////////////////// - /// \brief Set the forward vector of the listener in the scene - /// - /// The direction (also called "at vector") is the vector - /// pointing forward from the listener's perspective. Together - /// with the up vector, it defines the 3D orientation of the - /// listener in the scene. The direction vector doesn't - /// have to be normalized. - /// The default listener's direction is (0, 0, -1). - /// - /// \param direction New listener's direction - /// - /// \see getDirection, setUpVector, setPosition - /// - //////////////////////////////////////////////////////////// - static void setDirection(const Vector3f& direction); - - //////////////////////////////////////////////////////////// - /// \brief Get the current forward vector of the listener in the scene - /// - /// \return Listener's forward vector (not normalized) - /// - /// \see setDirection - /// - //////////////////////////////////////////////////////////// - static Vector3f getDirection(); - - //////////////////////////////////////////////////////////// - /// \brief Set the upward vector of the listener in the scene - /// - /// The up vector is the vector that points upward from the - /// listener's perspective. Together with the direction, it - /// defines the 3D orientation of the listener in the scene. - /// The up vector doesn't have to be normalized. - /// The default listener's up vector is (0, 1, 0). It is usually - /// not necessary to change it, especially in 2D scenarios. - /// - /// \param x X coordinate of the listener's up vector - /// \param y Y coordinate of the listener's up vector - /// \param z Z coordinate of the listener's up vector - /// - /// \see getUpVector, setDirection, setPosition - /// - //////////////////////////////////////////////////////////// - static void setUpVector(float x, float y, float z); - - //////////////////////////////////////////////////////////// - /// \brief Set the upward vector of the listener in the scene - /// - /// The up vector is the vector that points upward from the - /// listener's perspective. Together with the direction, it - /// defines the 3D orientation of the listener in the scene. - /// The up vector doesn't have to be normalized. - /// The default listener's up vector is (0, 1, 0). It is usually - /// not necessary to change it, especially in 2D scenarios. - /// - /// \param upVector New listener's up vector - /// - /// \see getUpVector, setDirection, setPosition - /// - //////////////////////////////////////////////////////////// - static void setUpVector(const Vector3f& upVector); - - //////////////////////////////////////////////////////////// - /// \brief Get the current upward vector of the listener in the scene - /// - /// \return Listener's upward vector (not normalized) - /// - /// \see setUpVector - /// - //////////////////////////////////////////////////////////// - static Vector3f getUpVector(); -}; - -} // namespace sf - - -#endif // SFML_LISTENER_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Listener -/// \ingroup audio -/// -/// The audio listener defines the global properties of the -/// audio environment, it defines where and how sounds and musics -/// are heard. If sf::View is the eyes of the user, then sf::Listener -/// is his ears (by the way, they are often linked together -- -/// same position, orientation, etc.). -/// -/// sf::Listener is a simple interface, which allows to setup the -/// listener in the 3D audio environment (position, direction and -/// up vector), and to adjust the global volume. -/// -/// Because the listener is unique in the scene, sf::Listener only -/// contains static functions and doesn't have to be instantiated. -/// -/// Usage example: -/// \code -/// // Move the listener to the position (1, 0, -5) -/// sf::Listener::setPosition(1, 0, -5); -/// -/// // Make it face the right axis (1, 0, 0) -/// sf::Listener::setDirection(1, 0, 0); -/// -/// // Reduce the global volume -/// sf::Listener::setGlobalVolume(50); -/// \endcode -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_LISTENER_HPP +#define SFML_LISTENER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief The audio listener is the point in the scene +/// from where all the sounds are heard +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API Listener +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Change the global volume of all the sounds and musics + /// + /// The volume is a number between 0 and 100; it is combined with + /// the individual volume of each sound / music. + /// The default value for the volume is 100 (maximum). + /// + /// \param volume New global volume, in the range [0, 100] + /// + /// \see getGlobalVolume + /// + //////////////////////////////////////////////////////////// + static void setGlobalVolume(float volume); + + //////////////////////////////////////////////////////////// + /// \brief Get the current value of the global volume + /// + /// \return Current global volume, in the range [0, 100] + /// + /// \see setGlobalVolume + /// + //////////////////////////////////////////////////////////// + static float getGlobalVolume(); + + //////////////////////////////////////////////////////////// + /// \brief Set the position of the listener in the scene + /// + /// The default listener's position is (0, 0, 0). + /// + /// \param x X coordinate of the listener's position + /// \param y Y coordinate of the listener's position + /// \param z Z coordinate of the listener's position + /// + /// \see getPosition, setDirection + /// + //////////////////////////////////////////////////////////// + static void setPosition(float x, float y, float z); + + //////////////////////////////////////////////////////////// + /// \brief Set the position of the listener in the scene + /// + /// The default listener's position is (0, 0, 0). + /// + /// \param position New listener's position + /// + /// \see getPosition, setDirection + /// + //////////////////////////////////////////////////////////// + static void setPosition(const Vector3f& position); + + //////////////////////////////////////////////////////////// + /// \brief Get the current position of the listener in the scene + /// + /// \return Listener's position + /// + /// \see setPosition + /// + //////////////////////////////////////////////////////////// + static Vector3f getPosition(); + + //////////////////////////////////////////////////////////// + /// \brief Set the forward vector of the listener in the scene + /// + /// The direction (also called "at vector") is the vector + /// pointing forward from the listener's perspective. Together + /// with the up vector, it defines the 3D orientation of the + /// listener in the scene. The direction vector doesn't + /// have to be normalized. + /// The default listener's direction is (0, 0, -1). + /// + /// \param x X coordinate of the listener's direction + /// \param y Y coordinate of the listener's direction + /// \param z Z coordinate of the listener's direction + /// + /// \see getDirection, setUpVector, setPosition + /// + //////////////////////////////////////////////////////////// + static void setDirection(float x, float y, float z); + + //////////////////////////////////////////////////////////// + /// \brief Set the forward vector of the listener in the scene + /// + /// The direction (also called "at vector") is the vector + /// pointing forward from the listener's perspective. Together + /// with the up vector, it defines the 3D orientation of the + /// listener in the scene. The direction vector doesn't + /// have to be normalized. + /// The default listener's direction is (0, 0, -1). + /// + /// \param direction New listener's direction + /// + /// \see getDirection, setUpVector, setPosition + /// + //////////////////////////////////////////////////////////// + static void setDirection(const Vector3f& direction); + + //////////////////////////////////////////////////////////// + /// \brief Get the current forward vector of the listener in the scene + /// + /// \return Listener's forward vector (not normalized) + /// + /// \see setDirection + /// + //////////////////////////////////////////////////////////// + static Vector3f getDirection(); + + //////////////////////////////////////////////////////////// + /// \brief Set the upward vector of the listener in the scene + /// + /// The up vector is the vector that points upward from the + /// listener's perspective. Together with the direction, it + /// defines the 3D orientation of the listener in the scene. + /// The up vector doesn't have to be normalized. + /// The default listener's up vector is (0, 1, 0). It is usually + /// not necessary to change it, especially in 2D scenarios. + /// + /// \param x X coordinate of the listener's up vector + /// \param y Y coordinate of the listener's up vector + /// \param z Z coordinate of the listener's up vector + /// + /// \see getUpVector, setDirection, setPosition + /// + //////////////////////////////////////////////////////////// + static void setUpVector(float x, float y, float z); + + //////////////////////////////////////////////////////////// + /// \brief Set the upward vector of the listener in the scene + /// + /// The up vector is the vector that points upward from the + /// listener's perspective. Together with the direction, it + /// defines the 3D orientation of the listener in the scene. + /// The up vector doesn't have to be normalized. + /// The default listener's up vector is (0, 1, 0). It is usually + /// not necessary to change it, especially in 2D scenarios. + /// + /// \param upVector New listener's up vector + /// + /// \see getUpVector, setDirection, setPosition + /// + //////////////////////////////////////////////////////////// + static void setUpVector(const Vector3f& upVector); + + //////////////////////////////////////////////////////////// + /// \brief Get the current upward vector of the listener in the scene + /// + /// \return Listener's upward vector (not normalized) + /// + /// \see setUpVector + /// + //////////////////////////////////////////////////////////// + static Vector3f getUpVector(); +}; + +} // namespace sf + + +#endif // SFML_LISTENER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Listener +/// \ingroup audio +/// +/// The audio listener defines the global properties of the +/// audio environment, it defines where and how sounds and musics +/// are heard. If sf::View is the eyes of the user, then sf::Listener +/// is his ears (by the way, they are often linked together -- +/// same position, orientation, etc.). +/// +/// sf::Listener is a simple interface, which allows to setup the +/// listener in the 3D audio environment (position, direction and +/// up vector), and to adjust the global volume. +/// +/// Because the listener is unique in the scene, sf::Listener only +/// contains static functions and doesn't have to be instantiated. +/// +/// Usage example: +/// \code +/// // Move the listener to the position (1, 0, -5) +/// sf::Listener::setPosition(1, 0, -5); +/// +/// // Make it face the right axis (1, 0, 0) +/// sf::Listener::setDirection(1, 0, 0); +/// +/// // Reduce the global volume +/// sf::Listener::setGlobalVolume(50); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Audio/Music.hpp b/include/SFML/Audio/Music.hpp index 2274cb32..2100ba97 100644 --- a/include/SFML/Audio/Music.hpp +++ b/include/SFML/Audio/Music.hpp @@ -1,228 +1,228 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_MUSIC_HPP -#define SFML_MUSIC_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ - class SoundFile; -} - -class InputStream; - -//////////////////////////////////////////////////////////// -/// \brief Streamed music played from an audio file -/// -//////////////////////////////////////////////////////////// -class SFML_AUDIO_API Music : public SoundStream -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - Music(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~Music(); - - //////////////////////////////////////////////////////////// - /// \brief Open a music from an audio file - /// - /// This function doesn't start playing the music (call play() - /// to do so). - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// \param filename Path of the music file to open - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see openFromMemory, openFromStream - /// - //////////////////////////////////////////////////////////// - bool openFromFile(const std::string& filename); - - //////////////////////////////////////////////////////////// - /// \brief Open a music from an audio file in memory - /// - /// This function doesn't start playing the music (call play() - /// to do so). - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// Since the music is not loaded completely but rather streamed - /// continuously, the \a data must remain available as long as the - /// music is playing (ie. you can't deallocate it right after calling - /// this function). - /// - /// \param data Pointer to the file data in memory - /// \param sizeInBytes Size of the data to load, in bytes - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see openFromFile, openFromStream - /// - //////////////////////////////////////////////////////////// - bool openFromMemory(const void* data, std::size_t sizeInBytes); - - //////////////////////////////////////////////////////////// - /// \brief Open a music from an audio file in a custom stream - /// - /// This function doesn't start playing the music (call play() - /// to do so). - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// Since the music is not loaded completely but rather streamed - /// continuously, the \a stream must remain alive as long as the - /// music is playing (ie. you can't destroy it right after calling - /// this function). - /// - /// \param stream Source stream to read from - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see openFromFile, openFromMemory - /// - //////////////////////////////////////////////////////////// - bool openFromStream(InputStream& stream); - - //////////////////////////////////////////////////////////// - /// \brief Get the total duration of the music - /// - /// \return Music duration - /// - //////////////////////////////////////////////////////////// - Time getDuration() const; - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Request a new chunk of audio samples from the stream source - /// - /// This function fills the chunk from the next samples - /// to read from the audio file. - /// - /// \param data Chunk of data to fill - /// - /// \return True to continue playback, false to stop - /// - //////////////////////////////////////////////////////////// - virtual bool onGetData(Chunk& data); - - //////////////////////////////////////////////////////////// - /// \brief Change the current playing position in the stream source - /// - /// \param timeOffset New playing position, from the beginning of the music - /// - //////////////////////////////////////////////////////////// - virtual void onSeek(Time timeOffset); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Initialize the internal state after loading a new music - /// - //////////////////////////////////////////////////////////// - void initialize(); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - priv::SoundFile* m_file; ///< Sound file - Time m_duration; ///< Music duration - std::vector m_samples; ///< Temporary buffer of samples - Mutex m_mutex; ///< Mutex protecting the data -}; - -} // namespace sf - - -#endif // SFML_MUSIC_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Music -/// \ingroup audio -/// -/// Musics are sounds that are streamed rather than completely -/// loaded in memory. This is especially useful for compressed -/// musics that usually take hundreds of MB when they are -/// uncompressed: by streaming it instead of loading it entirely, -/// you avoid saturating the memory and have almost no loading delay. -/// -/// Apart from that, a sf::Music has almost the same features as -/// the sf::SoundBuffer / sf::Sound pair: you can play/pause/stop -/// it, request its parameters (channels, sample rate), change -/// the way it is played (pitch, volume, 3D position, ...), etc. -/// -/// As a sound stream, a music is played in its own thread in order -/// not to block the rest of the program. This means that you can -/// leave the music alone after calling play(), it will manage itself -/// very well. -/// -/// Usage example: -/// \code -/// // Declare a new music -/// sf::Music music; -/// -/// // Open it from an audio file -/// if (!music.openFromFile("music.ogg")) -/// { -/// // error... -/// } -/// -/// // Change some parameters -/// music.setPosition(0, 1, 10); // change its 3D position -/// music.setPitch(2); // increase the pitch -/// music.setVolume(50); // reduce the volume -/// music.setLoop(true); // make it loop -/// -/// // Play it -/// music.play(); -/// \endcode -/// -/// \see sf::Sound, sf::SoundStream -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_MUSIC_HPP +#define SFML_MUSIC_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class SoundFile; +} + +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Streamed music played from an audio file +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API Music : public SoundStream +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Music(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Music(); + + //////////////////////////////////////////////////////////// + /// \brief Open a music from an audio file + /// + /// This function doesn't start playing the music (call play() + /// to do so). + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// \param filename Path of the music file to open + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see openFromMemory, openFromStream + /// + //////////////////////////////////////////////////////////// + bool openFromFile(const std::string& filename); + + //////////////////////////////////////////////////////////// + /// \brief Open a music from an audio file in memory + /// + /// This function doesn't start playing the music (call play() + /// to do so). + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// Since the music is not loaded completely but rather streamed + /// continuously, the \a data must remain available as long as the + /// music is playing (ie. you can't deallocate it right after calling + /// this function). + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see openFromFile, openFromStream + /// + //////////////////////////////////////////////////////////// + bool openFromMemory(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Open a music from an audio file in a custom stream + /// + /// This function doesn't start playing the music (call play() + /// to do so). + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// Since the music is not loaded completely but rather streamed + /// continuously, the \a stream must remain alive as long as the + /// music is playing (ie. you can't destroy it right after calling + /// this function). + /// + /// \param stream Source stream to read from + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see openFromFile, openFromMemory + /// + //////////////////////////////////////////////////////////// + bool openFromStream(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Get the total duration of the music + /// + /// \return Music duration + /// + //////////////////////////////////////////////////////////// + Time getDuration() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Request a new chunk of audio samples from the stream source + /// + /// This function fills the chunk from the next samples + /// to read from the audio file. + /// + /// \param data Chunk of data to fill + /// + /// \return True to continue playback, false to stop + /// + //////////////////////////////////////////////////////////// + virtual bool onGetData(Chunk& data); + + //////////////////////////////////////////////////////////// + /// \brief Change the current playing position in the stream source + /// + /// \param timeOffset New playing position, from the beginning of the music + /// + //////////////////////////////////////////////////////////// + virtual void onSeek(Time timeOffset); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Initialize the internal state after loading a new music + /// + //////////////////////////////////////////////////////////// + void initialize(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::SoundFile* m_file; ///< Sound file + Time m_duration; ///< Music duration + std::vector m_samples; ///< Temporary buffer of samples + Mutex m_mutex; ///< Mutex protecting the data +}; + +} // namespace sf + + +#endif // SFML_MUSIC_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Music +/// \ingroup audio +/// +/// Musics are sounds that are streamed rather than completely +/// loaded in memory. This is especially useful for compressed +/// musics that usually take hundreds of MB when they are +/// uncompressed: by streaming it instead of loading it entirely, +/// you avoid saturating the memory and have almost no loading delay. +/// +/// Apart from that, a sf::Music has almost the same features as +/// the sf::SoundBuffer / sf::Sound pair: you can play/pause/stop +/// it, request its parameters (channels, sample rate), change +/// the way it is played (pitch, volume, 3D position, ...), etc. +/// +/// As a sound stream, a music is played in its own thread in order +/// not to block the rest of the program. This means that you can +/// leave the music alone after calling play(), it will manage itself +/// very well. +/// +/// Usage example: +/// \code +/// // Declare a new music +/// sf::Music music; +/// +/// // Open it from an audio file +/// if (!music.openFromFile("music.ogg")) +/// { +/// // error... +/// } +/// +/// // Change some parameters +/// music.setPosition(0, 1, 10); // change its 3D position +/// music.setPitch(2); // increase the pitch +/// music.setVolume(50); // reduce the volume +/// music.setLoop(true); // make it loop +/// +/// // Play it +/// music.play(); +/// \endcode +/// +/// \see sf::Sound, sf::SoundStream +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Audio/Sound.hpp b/include/SFML/Audio/Sound.hpp index 6c346ba0..5e36ddd2 100644 --- a/include/SFML/Audio/Sound.hpp +++ b/include/SFML/Audio/Sound.hpp @@ -1,264 +1,264 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOUND_HPP -#define SFML_SOUND_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -class SoundBuffer; - -//////////////////////////////////////////////////////////// -/// \brief Regular sound that can be played in the audio environment -/// -//////////////////////////////////////////////////////////// -class SFML_AUDIO_API Sound : public SoundSource -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - Sound(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the sound with a buffer - /// - /// \param buffer Sound buffer containing the audio data to play with the sound - /// - //////////////////////////////////////////////////////////// - explicit Sound(const SoundBuffer& buffer); - - //////////////////////////////////////////////////////////// - /// \brief Copy constructor - /// - /// \param copy Instance to copy - /// - //////////////////////////////////////////////////////////// - Sound(const Sound& copy); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~Sound(); - - //////////////////////////////////////////////////////////// - /// \brief Start or resume playing the sound - /// - /// This function starts the stream if it was stopped, resumes - /// it if it was paused, and restarts it from beginning if it - /// was it already playing. - /// This function uses its own thread so that it doesn't block - /// the rest of the program while the sound is played. - /// - /// \see pause, stop - /// - //////////////////////////////////////////////////////////// - void play(); - - //////////////////////////////////////////////////////////// - /// \brief Pause the sound - /// - /// This function pauses the sound if it was playing, - /// otherwise (sound already paused or stopped) it has no effect. - /// - /// \see play, stop - /// - //////////////////////////////////////////////////////////// - void pause(); - - //////////////////////////////////////////////////////////// - /// \brief stop playing the sound - /// - /// This function stops the sound if it was playing or paused, - /// and does nothing if it was already stopped. - /// It also resets the playing position (unlike pause()). - /// - /// \see play, pause - /// - //////////////////////////////////////////////////////////// - void stop(); - - //////////////////////////////////////////////////////////// - /// \brief Set the source buffer containing the audio data to play - /// - /// It is important to note that the sound buffer is not copied, - /// thus the sf::SoundBuffer instance must remain alive as long - /// as it is attached to the sound. - /// - /// \param buffer Sound buffer to attach to the sound - /// - /// \see getBuffer - /// - //////////////////////////////////////////////////////////// - void setBuffer(const SoundBuffer& buffer); - - //////////////////////////////////////////////////////////// - /// \brief Set whether or not the sound should loop after reaching the end - /// - /// If set, the sound will restart from beginning after - /// reaching the end and so on, until it is stopped or - /// setLoop(false) is called. - /// The default looping state for sound is false. - /// - /// \param loop True to play in loop, false to play once - /// - /// \see getLoop - /// - //////////////////////////////////////////////////////////// - void setLoop(bool loop); - - //////////////////////////////////////////////////////////// - /// \brief Change the current playing position of the sound - /// - /// The playing position can be changed when the sound is - /// either paused or playing. Changing the playing position - /// when the sound is stopped has no effect, since playing - /// the sound would reset its position. - /// - /// \param timeOffset New playing position, from the beginning of the sound - /// - /// \see getPlayingOffset - /// - //////////////////////////////////////////////////////////// - void setPlayingOffset(Time timeOffset); - - //////////////////////////////////////////////////////////// - /// \brief Get the audio buffer attached to the sound - /// - /// \return Sound buffer attached to the sound (can be NULL) - /// - //////////////////////////////////////////////////////////// - const SoundBuffer* getBuffer() const; - - //////////////////////////////////////////////////////////// - /// \brief Tell whether or not the sound is in loop mode - /// - /// \return True if the sound is looping, false otherwise - /// - /// \see setLoop - /// - //////////////////////////////////////////////////////////// - bool getLoop() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the current playing position of the sound - /// - /// \return Current playing position, from the beginning of the sound - /// - /// \see setPlayingOffset - /// - //////////////////////////////////////////////////////////// - Time getPlayingOffset() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the current status of the sound (stopped, paused, playing) - /// - /// \return Current status of the sound - /// - //////////////////////////////////////////////////////////// - Status getStatus() const; - - //////////////////////////////////////////////////////////// - /// \brief Overload of assignment operator - /// - /// \param right Instance to assign - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - Sound& operator =(const Sound& right); - - //////////////////////////////////////////////////////////// - /// \brief Reset the internal buffer of the sound - /// - /// This function is for internal use only, you don't have - /// to use it. It is called by the sf::SoundBuffer that - /// this sound uses, when it is destroyed in order to prevent - /// the sound from using a dead buffer. - /// - //////////////////////////////////////////////////////////// - void resetBuffer(); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - const SoundBuffer* m_buffer; ///< Sound buffer bound to the source -}; - -} // namespace sf - - -#endif // SFML_SOUND_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Sound -/// \ingroup audio -/// -/// sf::Sound is the class to use to play sounds. -/// It provides: -/// \li Control (play, pause, stop) -/// \li Ability to modify output parameters in real-time (pitch, volume, ...) -/// \li 3D spatial features (position, attenuation, ...). -/// -/// sf::Sound is perfect for playing short sounds that can -/// fit in memory and require no latency, like foot steps or -/// gun shots. For longer sounds, like background musics -/// or long speeches, rather see sf::Music (which is based -/// on streaming). -/// -/// In order to work, a sound must be given a buffer of audio -/// data to play. Audio data (samples) is stored in sf::SoundBuffer, -/// and attached to a sound with the setBuffer() function. -/// The buffer object attached to a sound must remain alive -/// as long as the sound uses it. Note that multiple sounds -/// can use the same sound buffer at the same time. -/// -/// Usage example: -/// \code -/// sf::SoundBuffer buffer; -/// buffer.loadFromFile("sound.wav"); -/// -/// sf::Sound sound; -/// sound.setBuffer(buffer); -/// sound.play(); -/// \endcode -/// -/// \see sf::SoundBuffer, sf::Music -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUND_HPP +#define SFML_SOUND_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +class SoundBuffer; + +//////////////////////////////////////////////////////////// +/// \brief Regular sound that can be played in the audio environment +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API Sound : public SoundSource +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Sound(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the sound with a buffer + /// + /// \param buffer Sound buffer containing the audio data to play with the sound + /// + //////////////////////////////////////////////////////////// + explicit Sound(const SoundBuffer& buffer); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + Sound(const Sound& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Sound(); + + //////////////////////////////////////////////////////////// + /// \brief Start or resume playing the sound + /// + /// This function starts the stream if it was stopped, resumes + /// it if it was paused, and restarts it from beginning if it + /// was it already playing. + /// This function uses its own thread so that it doesn't block + /// the rest of the program while the sound is played. + /// + /// \see pause, stop + /// + //////////////////////////////////////////////////////////// + void play(); + + //////////////////////////////////////////////////////////// + /// \brief Pause the sound + /// + /// This function pauses the sound if it was playing, + /// otherwise (sound already paused or stopped) it has no effect. + /// + /// \see play, stop + /// + //////////////////////////////////////////////////////////// + void pause(); + + //////////////////////////////////////////////////////////// + /// \brief stop playing the sound + /// + /// This function stops the sound if it was playing or paused, + /// and does nothing if it was already stopped. + /// It also resets the playing position (unlike pause()). + /// + /// \see play, pause + /// + //////////////////////////////////////////////////////////// + void stop(); + + //////////////////////////////////////////////////////////// + /// \brief Set the source buffer containing the audio data to play + /// + /// It is important to note that the sound buffer is not copied, + /// thus the sf::SoundBuffer instance must remain alive as long + /// as it is attached to the sound. + /// + /// \param buffer Sound buffer to attach to the sound + /// + /// \see getBuffer + /// + //////////////////////////////////////////////////////////// + void setBuffer(const SoundBuffer& buffer); + + //////////////////////////////////////////////////////////// + /// \brief Set whether or not the sound should loop after reaching the end + /// + /// If set, the sound will restart from beginning after + /// reaching the end and so on, until it is stopped or + /// setLoop(false) is called. + /// The default looping state for sound is false. + /// + /// \param loop True to play in loop, false to play once + /// + /// \see getLoop + /// + //////////////////////////////////////////////////////////// + void setLoop(bool loop); + + //////////////////////////////////////////////////////////// + /// \brief Change the current playing position of the sound + /// + /// The playing position can be changed when the sound is + /// either paused or playing. Changing the playing position + /// when the sound is stopped has no effect, since playing + /// the sound would reset its position. + /// + /// \param timeOffset New playing position, from the beginning of the sound + /// + /// \see getPlayingOffset + /// + //////////////////////////////////////////////////////////// + void setPlayingOffset(Time timeOffset); + + //////////////////////////////////////////////////////////// + /// \brief Get the audio buffer attached to the sound + /// + /// \return Sound buffer attached to the sound (can be NULL) + /// + //////////////////////////////////////////////////////////// + const SoundBuffer* getBuffer() const; + + //////////////////////////////////////////////////////////// + /// \brief Tell whether or not the sound is in loop mode + /// + /// \return True if the sound is looping, false otherwise + /// + /// \see setLoop + /// + //////////////////////////////////////////////////////////// + bool getLoop() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the current playing position of the sound + /// + /// \return Current playing position, from the beginning of the sound + /// + /// \see setPlayingOffset + /// + //////////////////////////////////////////////////////////// + Time getPlayingOffset() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the current status of the sound (stopped, paused, playing) + /// + /// \return Current status of the sound + /// + //////////////////////////////////////////////////////////// + Status getStatus() const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + Sound& operator =(const Sound& right); + + //////////////////////////////////////////////////////////// + /// \brief Reset the internal buffer of the sound + /// + /// This function is for internal use only, you don't have + /// to use it. It is called by the sf::SoundBuffer that + /// this sound uses, when it is destroyed in order to prevent + /// the sound from using a dead buffer. + /// + //////////////////////////////////////////////////////////// + void resetBuffer(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + const SoundBuffer* m_buffer; ///< Sound buffer bound to the source +}; + +} // namespace sf + + +#endif // SFML_SOUND_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Sound +/// \ingroup audio +/// +/// sf::Sound is the class to use to play sounds. +/// It provides: +/// \li Control (play, pause, stop) +/// \li Ability to modify output parameters in real-time (pitch, volume, ...) +/// \li 3D spatial features (position, attenuation, ...). +/// +/// sf::Sound is perfect for playing short sounds that can +/// fit in memory and require no latency, like foot steps or +/// gun shots. For longer sounds, like background musics +/// or long speeches, rather see sf::Music (which is based +/// on streaming). +/// +/// In order to work, a sound must be given a buffer of audio +/// data to play. Audio data (samples) is stored in sf::SoundBuffer, +/// and attached to a sound with the setBuffer() function. +/// The buffer object attached to a sound must remain alive +/// as long as the sound uses it. Note that multiple sounds +/// can use the same sound buffer at the same time. +/// +/// Usage example: +/// \code +/// sf::SoundBuffer buffer; +/// buffer.loadFromFile("sound.wav"); +/// +/// sf::Sound sound; +/// sound.setBuffer(buffer); +/// sound.play(); +/// \endcode +/// +/// \see sf::SoundBuffer, sf::Music +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Audio/SoundBuffer.hpp b/include/SFML/Audio/SoundBuffer.hpp index 4bdf2f6a..392b4617 100644 --- a/include/SFML/Audio/SoundBuffer.hpp +++ b/include/SFML/Audio/SoundBuffer.hpp @@ -1,359 +1,359 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOUNDBUFFER_HPP -#define SFML_SOUNDBUFFER_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ - class SoundFile; -} - -class Sound; -class InputStream; - -//////////////////////////////////////////////////////////// -/// \brief Storage for audio samples defining a sound -/// -//////////////////////////////////////////////////////////// -class SFML_AUDIO_API SoundBuffer -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - SoundBuffer(); - - //////////////////////////////////////////////////////////// - /// \brief Copy constructor - /// - /// \param copy Instance to copy - /// - //////////////////////////////////////////////////////////// - SoundBuffer(const SoundBuffer& copy); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~SoundBuffer(); - - //////////////////////////////////////////////////////////// - /// \brief Load the sound buffer from a file - /// - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// \param filename Path of the sound file to load - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromMemory, loadFromStream, loadFromSamples, saveToFile - /// - //////////////////////////////////////////////////////////// - bool loadFromFile(const std::string& filename); - - //////////////////////////////////////////////////////////// - /// \brief Load the sound buffer from a file in memory - /// - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// \param data Pointer to the file data in memory - /// \param sizeInBytes Size of the data to load, in bytes - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromFile, loadFromStream, loadFromSamples - /// - //////////////////////////////////////////////////////////// - bool loadFromMemory(const void* data, std::size_t sizeInBytes); - - //////////////////////////////////////////////////////////// - /// \brief Load the sound buffer from a custom stream - /// - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// \param stream Source stream to read from - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromFile, loadFromMemory, loadFromSamples - /// - //////////////////////////////////////////////////////////// - bool loadFromStream(InputStream& stream); - - //////////////////////////////////////////////////////////// - /// \brief Load the sound buffer from an array of audio samples - /// - /// The assumed format of the audio samples is 16 bits signed integer - /// (sf::Int16). - /// - /// \param samples Pointer to the array of samples in memory - /// \param sampleCount Number of samples in the array - /// \param channelCount Number of channels (1 = mono, 2 = stereo, ...) - /// \param sampleRate Sample rate (number of samples to play per second) - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromFile, loadFromMemory, saveToFile - /// - //////////////////////////////////////////////////////////// - bool loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate); - - //////////////////////////////////////////////////////////// - /// \brief Save the sound buffer to an audio file - /// - /// Here is a complete list of all the supported audio formats: - /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, - /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. - /// - /// \param filename Path of the sound file to write - /// - /// \return True if saving succeeded, false if it failed - /// - /// \see loadFromFile, loadFromMemory, loadFromSamples - /// - //////////////////////////////////////////////////////////// - bool saveToFile(const std::string& filename) const; - - //////////////////////////////////////////////////////////// - /// \brief Get the array of audio samples stored in the buffer - /// - /// The format of the returned samples is 16 bits signed integer - /// (sf::Int16). The total number of samples in this array - /// is given by the getSampleCount() function. - /// - /// \return Read-only pointer to the array of sound samples - /// - /// \see getSampleCount - /// - //////////////////////////////////////////////////////////// - const Int16* getSamples() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the number of samples stored in the buffer - /// - /// The array of samples can be accessed with the getSamples() - /// function. - /// - /// \return Number of samples - /// - /// \see getSamples - /// - //////////////////////////////////////////////////////////// - std::size_t getSampleCount() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the sample rate of the sound - /// - /// The sample rate is the number of samples played per second. - /// The higher, the better the quality (for example, 44100 - /// samples/s is CD quality). - /// - /// \return Sample rate (number of samples per second) - /// - /// \see getChannelCount, getDuration - /// - //////////////////////////////////////////////////////////// - unsigned int getSampleRate() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the number of channels used by the sound - /// - /// If the sound is mono then the number of channels will - /// be 1, 2 for stereo, etc. - /// - /// \return Number of channels - /// - /// \see getSampleRate, getDuration - /// - //////////////////////////////////////////////////////////// - unsigned int getChannelCount() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the total duration of the sound - /// - /// \return Sound duration - /// - /// \see getSampleRate, getChannelCount - /// - //////////////////////////////////////////////////////////// - Time getDuration() const; - - //////////////////////////////////////////////////////////// - /// \brief Overload of assignment operator - /// - /// \param right Instance to assign - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - SoundBuffer& operator =(const SoundBuffer& right); - -private : - - friend class Sound; - - //////////////////////////////////////////////////////////// - /// \brief Initialize the internal state after loading a new sound - /// - /// \param file Sound file providing access to the new loaded sound - /// - /// \return True on succesful initialization, false on failure - /// - //////////////////////////////////////////////////////////// - bool initialize(priv::SoundFile& file); - - //////////////////////////////////////////////////////////// - /// \brief Update the internal buffer with the cached audio samples - /// - /// \param channelCount Number of channels - /// \param sampleRate Sample rate (number of samples per second) - /// - /// \return True on success, false if any error happened - /// - //////////////////////////////////////////////////////////// - bool update(unsigned int channelCount, unsigned int sampleRate); - - //////////////////////////////////////////////////////////// - /// \brief Add a sound to the list of sounds that use this buffer - /// - /// \param sound Sound instance to attach - /// - //////////////////////////////////////////////////////////// - void attachSound(Sound* sound) const; - - //////////////////////////////////////////////////////////// - /// \brief Remove a sound from the list of sounds that use this buffer - /// - /// \param sound Sound instance to detach - /// - //////////////////////////////////////////////////////////// - void detachSound(Sound* sound) const; - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef std::set SoundList; ///< Set of unique sound instances - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - unsigned int m_buffer; ///< OpenAL buffer identifier - std::vector m_samples; ///< Samples buffer - Time m_duration; ///< Sound duration - mutable SoundList m_sounds; ///< List of sounds that are using this buffer -}; - -} // namespace sf - - -#endif // SFML_SOUNDBUFFER_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::SoundBuffer -/// \ingroup audio -/// -/// A sound buffer holds the data of a sound, which is -/// an array of audio samples. A sample is a 16 bits signed integer -/// that defines the amplitude of the sound at a given time. -/// The sound is then restituted by playing these samples at -/// a high rate (for example, 44100 samples per second is the -/// standard rate used for playing CDs). In short, audio samples -/// are like texture pixels, and a sf::SoundBuffer is similar to -/// a sf::Texture. -/// -/// A sound buffer can be loaded from a file (see loadFromFile() -/// for the complete list of supported formats), from memory, from -/// a custom stream (see sf::InputStream) or directly from an array -/// of samples. It can also be saved back to a file. -/// -/// Sound buffers alone are not very useful: they hold the audio data -/// but cannot be played. To do so, you need to use the sf::Sound class, -/// which provides functions to play/pause/stop the sound as well as -/// changing the way it is outputted (volume, pitch, 3D position, ...). -/// This separation allows more flexibility and better performances: -/// indeed a sf::SoundBuffer is a heavy resource, and any operation on it -/// is slow (often too slow for real-time applications). On the other -/// side, a sf::Sound is a lightweight object, which can use the audio data -/// of a sound buffer and change the way it is played without actually -/// modifying that data. Note that it is also possible to bind -/// several sf::Sound instances to the same sf::SoundBuffer. -/// -/// It is important to note that the sf::Sound instance doesn't -/// copy the buffer that it uses, it only keeps a reference to it. -/// Thus, a sf::SoundBuffer must not be destructed while it is -/// used by a sf::Sound (i.e. never write a function that -/// uses a local sf::SoundBuffer instance for loading a sound). -/// -/// Usage example: -/// \code -/// // Declare a new sound buffer -/// sf::SoundBuffer buffer; -/// -/// // Load it from a file -/// if (!buffer.loadFromFile("sound.wav")) -/// { -/// // error... -/// } -/// -/// // Create a sound source and bind it to the buffer -/// sf::Sound sound1; -/// sound1.setBuffer(buffer); -/// -/// // Play the sound -/// sound1.play(); -/// -/// // Create another sound source bound to the same buffer -/// sf::Sound sound2; -/// sound2.setBuffer(buffer); -/// -/// // Play it with a higher pitch -- the first sound remains unchanged -/// sound2.setPitch(2); -/// sound2.play(); -/// \endcode -/// -/// \see sf::Sound, sf::SoundBufferRecorder -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDBUFFER_HPP +#define SFML_SOUNDBUFFER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class SoundFile; +} + +class Sound; +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Storage for audio samples defining a sound +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API SoundBuffer +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + SoundBuffer(); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + SoundBuffer(const SoundBuffer& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~SoundBuffer(); + + //////////////////////////////////////////////////////////// + /// \brief Load the sound buffer from a file + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// \param filename Path of the sound file to load + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromMemory, loadFromStream, loadFromSamples, saveToFile + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& filename); + + //////////////////////////////////////////////////////////// + /// \brief Load the sound buffer from a file in memory + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromStream, loadFromSamples + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Load the sound buffer from a custom stream + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// \param stream Source stream to read from + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory, loadFromSamples + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Load the sound buffer from an array of audio samples + /// + /// The assumed format of the audio samples is 16 bits signed integer + /// (sf::Int16). + /// + /// \param samples Pointer to the array of samples in memory + /// \param sampleCount Number of samples in the array + /// \param channelCount Number of channels (1 = mono, 2 = stereo, ...) + /// \param sampleRate Sample rate (number of samples to play per second) + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory, saveToFile + /// + //////////////////////////////////////////////////////////// + bool loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate); + + //////////////////////////////////////////////////////////// + /// \brief Save the sound buffer to an audio file + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// \param filename Path of the sound file to write + /// + /// \return True if saving succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory, loadFromSamples + /// + //////////////////////////////////////////////////////////// + bool saveToFile(const std::string& filename) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the array of audio samples stored in the buffer + /// + /// The format of the returned samples is 16 bits signed integer + /// (sf::Int16). The total number of samples in this array + /// is given by the getSampleCount() function. + /// + /// \return Read-only pointer to the array of sound samples + /// + /// \see getSampleCount + /// + //////////////////////////////////////////////////////////// + const Int16* getSamples() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the number of samples stored in the buffer + /// + /// The array of samples can be accessed with the getSamples() + /// function. + /// + /// \return Number of samples + /// + /// \see getSamples + /// + //////////////////////////////////////////////////////////// + std::size_t getSampleCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the sample rate of the sound + /// + /// The sample rate is the number of samples played per second. + /// The higher, the better the quality (for example, 44100 + /// samples/s is CD quality). + /// + /// \return Sample rate (number of samples per second) + /// + /// \see getChannelCount, getDuration + /// + //////////////////////////////////////////////////////////// + unsigned int getSampleRate() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the number of channels used by the sound + /// + /// If the sound is mono then the number of channels will + /// be 1, 2 for stereo, etc. + /// + /// \return Number of channels + /// + /// \see getSampleRate, getDuration + /// + //////////////////////////////////////////////////////////// + unsigned int getChannelCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the total duration of the sound + /// + /// \return Sound duration + /// + /// \see getSampleRate, getChannelCount + /// + //////////////////////////////////////////////////////////// + Time getDuration() const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + SoundBuffer& operator =(const SoundBuffer& right); + +private: + + friend class Sound; + + //////////////////////////////////////////////////////////// + /// \brief Initialize the internal state after loading a new sound + /// + /// \param file Sound file providing access to the new loaded sound + /// + /// \return True on succesful initialization, false on failure + /// + //////////////////////////////////////////////////////////// + bool initialize(priv::SoundFile& file); + + //////////////////////////////////////////////////////////// + /// \brief Update the internal buffer with the cached audio samples + /// + /// \param channelCount Number of channels + /// \param sampleRate Sample rate (number of samples per second) + /// + /// \return True on success, false if any error happened + /// + //////////////////////////////////////////////////////////// + bool update(unsigned int channelCount, unsigned int sampleRate); + + //////////////////////////////////////////////////////////// + /// \brief Add a sound to the list of sounds that use this buffer + /// + /// \param sound Sound instance to attach + /// + //////////////////////////////////////////////////////////// + void attachSound(Sound* sound) const; + + //////////////////////////////////////////////////////////// + /// \brief Remove a sound from the list of sounds that use this buffer + /// + /// \param sound Sound instance to detach + /// + //////////////////////////////////////////////////////////// + void detachSound(Sound* sound) const; + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::set SoundList; ///< Set of unique sound instances + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int m_buffer; ///< OpenAL buffer identifier + std::vector m_samples; ///< Samples buffer + Time m_duration; ///< Sound duration + mutable SoundList m_sounds; ///< List of sounds that are using this buffer +}; + +} // namespace sf + + +#endif // SFML_SOUNDBUFFER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SoundBuffer +/// \ingroup audio +/// +/// A sound buffer holds the data of a sound, which is +/// an array of audio samples. A sample is a 16 bits signed integer +/// that defines the amplitude of the sound at a given time. +/// The sound is then restituted by playing these samples at +/// a high rate (for example, 44100 samples per second is the +/// standard rate used for playing CDs). In short, audio samples +/// are like texture pixels, and a sf::SoundBuffer is similar to +/// a sf::Texture. +/// +/// A sound buffer can be loaded from a file (see loadFromFile() +/// for the complete list of supported formats), from memory, from +/// a custom stream (see sf::InputStream) or directly from an array +/// of samples. It can also be saved back to a file. +/// +/// Sound buffers alone are not very useful: they hold the audio data +/// but cannot be played. To do so, you need to use the sf::Sound class, +/// which provides functions to play/pause/stop the sound as well as +/// changing the way it is outputted (volume, pitch, 3D position, ...). +/// This separation allows more flexibility and better performances: +/// indeed a sf::SoundBuffer is a heavy resource, and any operation on it +/// is slow (often too slow for real-time applications). On the other +/// side, a sf::Sound is a lightweight object, which can use the audio data +/// of a sound buffer and change the way it is played without actually +/// modifying that data. Note that it is also possible to bind +/// several sf::Sound instances to the same sf::SoundBuffer. +/// +/// It is important to note that the sf::Sound instance doesn't +/// copy the buffer that it uses, it only keeps a reference to it. +/// Thus, a sf::SoundBuffer must not be destructed while it is +/// used by a sf::Sound (i.e. never write a function that +/// uses a local sf::SoundBuffer instance for loading a sound). +/// +/// Usage example: +/// \code +/// // Declare a new sound buffer +/// sf::SoundBuffer buffer; +/// +/// // Load it from a file +/// if (!buffer.loadFromFile("sound.wav")) +/// { +/// // error... +/// } +/// +/// // Create a sound source and bind it to the buffer +/// sf::Sound sound1; +/// sound1.setBuffer(buffer); +/// +/// // Play the sound +/// sound1.play(); +/// +/// // Create another sound source bound to the same buffer +/// sf::Sound sound2; +/// sound2.setBuffer(buffer); +/// +/// // Play it with a higher pitch -- the first sound remains unchanged +/// sound2.setPitch(2); +/// sound2.play(); +/// \endcode +/// +/// \see sf::Sound, sf::SoundBufferRecorder +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Audio/SoundBufferRecorder.hpp b/include/SFML/Audio/SoundBufferRecorder.hpp index 1672f0c9..cb174b01 100644 --- a/include/SFML/Audio/SoundBufferRecorder.hpp +++ b/include/SFML/Audio/SoundBufferRecorder.hpp @@ -1,138 +1,138 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOUNDBUFFERRECORDER_HPP -#define SFML_SOUNDBUFFERRECORDER_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Specialized SoundRecorder which stores the captured -/// audio data into a sound buffer -/// -//////////////////////////////////////////////////////////// -class SFML_AUDIO_API SoundBufferRecorder : public SoundRecorder -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Get the sound buffer containing the captured audio data - /// - /// The sound buffer is valid only after the capture has ended. - /// This function provides a read-only access to the internal - /// sound buffer, but it can be copied if you need to - /// make any modification to it. - /// - /// \return Read-only access to the sound buffer - /// - //////////////////////////////////////////////////////////// - const SoundBuffer& getBuffer() const; - -protected: - - //////////////////////////////////////////////////////////// - /// \brief Start capturing audio data - /// - /// \return True to start the capture, or false to abort it - /// - //////////////////////////////////////////////////////////// - virtual bool onStart(); - - //////////////////////////////////////////////////////////// - /// \brief Process a new chunk of recorded samples - /// - /// \param samples Pointer to the new chunk of recorded samples - /// \param sampleCount Number of samples pointed by \a samples - /// - /// \return True to continue the capture, or false to stop it - /// - //////////////////////////////////////////////////////////// - virtual bool onProcessSamples(const Int16* samples, std::size_t sampleCount); - - //////////////////////////////////////////////////////////// - /// \brief Stop capturing audio data - /// - //////////////////////////////////////////////////////////// - virtual void onStop(); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - std::vector m_samples; ///< Temporary sample buffer to hold the recorded data - SoundBuffer m_buffer; ///< Sound buffer that will contain the recorded data -}; - -} // namespace sf - -#endif // SFML_SOUNDBUFFERRECORDER_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::SoundBufferRecorder -/// \ingroup audio -/// -/// sf::SoundBufferRecorder allows to access a recorded sound -/// through a sf::SoundBuffer, so that it can be played, saved -/// to a file, etc. -/// -/// It has the same simple interface as its base class (start(), stop()) -/// and adds a function to retrieve the recorded sound buffer -/// (getBuffer()). -/// -/// As usual, don't forget to call the isAvailable() function -/// before using this class (see sf::SoundRecorder for more details -/// about this). -/// -/// Usage example: -/// \code -/// if (sf::SoundBufferRecorder::isAvailable()) -/// { -/// // Record some audio data -/// sf::SoundBufferRecorder recorder; -/// recorder.start(); -/// ... -/// recorder.stop(); -/// -/// // Get the buffer containing the captured audio data -/// const sf::SoundBuffer& buffer = recorder.getBuffer(); -/// -/// // Save it to a file (for example...) -/// buffer.saveToFile("my_record.ogg"); -/// } -/// \endcode -/// -/// \see sf::SoundRecorder -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDBUFFERRECORDER_HPP +#define SFML_SOUNDBUFFERRECORDER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Specialized SoundRecorder which stores the captured +/// audio data into a sound buffer +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API SoundBufferRecorder : public SoundRecorder +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Get the sound buffer containing the captured audio data + /// + /// The sound buffer is valid only after the capture has ended. + /// This function provides a read-only access to the internal + /// sound buffer, but it can be copied if you need to + /// make any modification to it. + /// + /// \return Read-only access to the sound buffer + /// + //////////////////////////////////////////////////////////// + const SoundBuffer& getBuffer() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Start capturing audio data + /// + /// \return True to start the capture, or false to abort it + /// + //////////////////////////////////////////////////////////// + virtual bool onStart(); + + //////////////////////////////////////////////////////////// + /// \brief Process a new chunk of recorded samples + /// + /// \param samples Pointer to the new chunk of recorded samples + /// \param sampleCount Number of samples pointed by \a samples + /// + /// \return True to continue the capture, or false to stop it + /// + //////////////////////////////////////////////////////////// + virtual bool onProcessSamples(const Int16* samples, std::size_t sampleCount); + + //////////////////////////////////////////////////////////// + /// \brief Stop capturing audio data + /// + //////////////////////////////////////////////////////////// + virtual void onStop(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector m_samples; ///< Temporary sample buffer to hold the recorded data + SoundBuffer m_buffer; ///< Sound buffer that will contain the recorded data +}; + +} // namespace sf + +#endif // SFML_SOUNDBUFFERRECORDER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SoundBufferRecorder +/// \ingroup audio +/// +/// sf::SoundBufferRecorder allows to access a recorded sound +/// through a sf::SoundBuffer, so that it can be played, saved +/// to a file, etc. +/// +/// It has the same simple interface as its base class (start(), stop()) +/// and adds a function to retrieve the recorded sound buffer +/// (getBuffer()). +/// +/// As usual, don't forget to call the isAvailable() function +/// before using this class (see sf::SoundRecorder for more details +/// about this). +/// +/// Usage example: +/// \code +/// if (sf::SoundBufferRecorder::isAvailable()) +/// { +/// // Record some audio data +/// sf::SoundBufferRecorder recorder; +/// recorder.start(); +/// ... +/// recorder.stop(); +/// +/// // Get the buffer containing the captured audio data +/// const sf::SoundBuffer& buffer = recorder.getBuffer(); +/// +/// // Save it to a file (for example...) +/// buffer.saveToFile("my_record.ogg"); +/// } +/// \endcode +/// +/// \see sf::SoundRecorder +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Audio/SoundRecorder.hpp b/include/SFML/Audio/SoundRecorder.hpp index 2ad250c1..59a3030a 100644 --- a/include/SFML/Audio/SoundRecorder.hpp +++ b/include/SFML/Audio/SoundRecorder.hpp @@ -1,363 +1,363 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOUNDRECORDER_HPP -#define SFML_SOUNDRECORDER_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Abstract base class for capturing sound data -/// -//////////////////////////////////////////////////////////// -class SFML_AUDIO_API SoundRecorder -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief destructor - /// - //////////////////////////////////////////////////////////// - virtual ~SoundRecorder(); - - //////////////////////////////////////////////////////////// - /// \brief Start the capture - /// - /// The \a sampleRate parameter defines the number of audio samples - /// captured per second. The higher, the better the quality - /// (for example, 44100 samples/sec is CD quality). - /// This function uses its own thread so that it doesn't block - /// the rest of the program while the capture runs. - /// Please note that only one capture can happen at the same time. - /// You can select which capture device will be used, by passing - /// the name to the setDevice() method. If none was selected - /// before, the default capture device will be used. You can get a - /// list of the names of all available capture devices by calling - /// getAvailableDevices(). - /// - /// \param sampleRate Desired capture rate, in number of samples per second - /// - /// \return True, if start of capture was successful - /// - /// \see stop, getAvailableDevices - /// - //////////////////////////////////////////////////////////// - bool start(unsigned int sampleRate = 44100); - - //////////////////////////////////////////////////////////// - /// \brief Stop the capture - /// - /// \see start - /// - //////////////////////////////////////////////////////////// - void stop(); - - //////////////////////////////////////////////////////////// - /// \brief Get the sample rate - /// - /// The sample rate defines the number of audio samples - /// captured per second. The higher, the better the quality - /// (for example, 44100 samples/sec is CD quality). - /// - /// \return Sample rate, in samples per second - /// - //////////////////////////////////////////////////////////// - unsigned int getSampleRate() const; - - //////////////////////////////////////////////////////////// - /// \brief Get a list of the names of all availabe audio capture devices - /// - /// This function returns a vector of strings, containing - /// the names of all availabe audio capture devices. - /// - /// \return A vector of strings containing the names - /// - //////////////////////////////////////////////////////////// - static std::vector getAvailableDevices(); - - //////////////////////////////////////////////////////////// - /// \brief Get the name of the default audio capture device - /// - /// This function returns the name of the default audio - /// capture device. If none is available, an empty string - /// is returned. - /// - /// \return The name of the default audio capture device - /// - //////////////////////////////////////////////////////////// - static std::string getDefaultDevice(); - - //////////////////////////////////////////////////////////// - /// \brief Set the audio capture device - /// - /// This function sets the audio capture device to the device - /// with the given \a name. It can be called on the fly (i.e: - /// while recording). If you do so while recording and - /// opening the device fails, it stops the recording. - /// - /// \param name The name of the audio capture device - /// - /// \return True, if it was able to set the requested device - /// - /// \see getAvailableDevices, getDefaultDevice - /// - //////////////////////////////////////////////////////////// - bool setDevice(const std::string& name); - - //////////////////////////////////////////////////////////// - /// \brief Get the name of the current audio capture device - /// - /// \return The name of the current audio capture device - /// - //////////////////////////////////////////////////////////// - const std::string& getDevice() const; - - //////////////////////////////////////////////////////////// - /// \brief Check if the system supports audio capture - /// - /// This function should always be called before using - /// the audio capture features. If it returns false, then - /// any attempt to use sf::SoundRecorder or one of its derived - /// classes will fail. - /// - /// \return True if audio capture is supported, false otherwise - /// - //////////////////////////////////////////////////////////// - static bool isAvailable(); - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor is only meant to be called by derived classes. - /// - //////////////////////////////////////////////////////////// - SoundRecorder(); - - //////////////////////////////////////////////////////////// - /// \brief Set the processing interval - /// - /// The processing interval controls the period - /// between calls to the onProcessSamples function. You may - /// want to use a small interval if you want to process the - /// recorded data in real time, for example. - /// - /// Note: this is only a hint, the actual period may vary. - /// So don't rely on this parameter to implement precise timing. - /// - /// The default processing interval is 100 ms. - /// - /// \param interval Processing interval - /// - //////////////////////////////////////////////////////////// - void setProcessingInterval(sf::Time interval); - - //////////////////////////////////////////////////////////// - /// \brief Start capturing audio data - /// - /// This virtual function may be overriden by a derived class - /// if something has to be done every time a new capture - /// starts. If not, this function can be ignored; the default - /// implementation does nothing. - /// - /// \return True to start the capture, or false to abort it - /// - //////////////////////////////////////////////////////////// - virtual bool onStart(); - - //////////////////////////////////////////////////////////// - /// \brief Process a new chunk of recorded samples - /// - /// This virtual function is called every time a new chunk of - /// recorded data is available. The derived class can then do - /// whatever it wants with it (storing it, playing it, sending - /// it over the network, etc.). - /// - /// \param samples Pointer to the new chunk of recorded samples - /// \param sampleCount Number of samples pointed by \a samples - /// - /// \return True to continue the capture, or false to stop it - /// - //////////////////////////////////////////////////////////// - virtual bool onProcessSamples(const Int16* samples, std::size_t sampleCount) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Stop capturing audio data - /// - /// This virtual function may be overriden by a derived class - /// if something has to be done every time the capture - /// ends. If not, this function can be ignored; the default - /// implementation does nothing. - /// - //////////////////////////////////////////////////////////// - virtual void onStop(); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Function called as the entry point of the thread - /// - /// This function starts the recording loop, and returns - /// only when the capture is stopped. - /// - //////////////////////////////////////////////////////////// - void record(); - - //////////////////////////////////////////////////////////// - /// \brief Get the new available audio samples and process them - /// - /// This function is called continuously during the - /// capture loop. It retrieves the captured samples and - /// forwards them to the derived class. - /// - //////////////////////////////////////////////////////////// - void processCapturedSamples(); - - //////////////////////////////////////////////////////////// - /// \brief Clean up the recorder's internal resources - /// - /// This function is called when the capture stops. - /// - //////////////////////////////////////////////////////////// - void cleanup(); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Thread m_thread; ///< Thread running the background recording task - std::vector m_samples; ///< Buffer to store captured samples - unsigned int m_sampleRate; ///< Sample rate - sf::Time m_processingInterval; ///< Time period between calls to onProcessSamples - bool m_isCapturing; ///< Capturing state - std::string m_deviceName; ///< Name of the audio capture device -}; - -} // namespace sf - - -#endif // SFML_SOUNDRECORDER_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::SoundRecorder -/// \ingroup audio -/// -/// sf::SoundBuffer provides a simple interface to access -/// the audio recording capabilities of the computer -/// (the microphone). As an abstract base class, it only cares -/// about capturing sound samples, the task of making something -/// useful with them is left to the derived class. Note that -/// SFML provides a built-in specialization for saving the -/// captured data to a sound buffer (see sf::SoundBufferRecorder). -/// -/// A derived class has only one virtual function to override: -/// \li onProcessSamples provides the new chunks of audio samples while the capture happens -/// -/// Moreover, two additionnal virtual functions can be overriden -/// as well if necessary: -/// \li onStart is called before the capture happens, to perform custom initializations -/// \li onStop is called after the capture ends, to perform custom cleanup -/// -/// A derived class can also control the frequency of the onProcessSamples -/// calls, with the setProcessingInterval protected function. The default -/// interval is chosen so that recording thread doesn't consume too much -/// CPU, but it can be changed to a smaller value if you need to process -/// the recorded data in real time, for example. -/// -/// The audio capture feature may not be supported or activated -/// on every platform, thus it is recommended to check its -/// availability with the isAvailable() function. If it returns -/// false, then any attempt to use an audio recorder will fail. -/// -/// If you have multiple sound input devices connected to your -/// computer (for example: microphone, external soundcard, webcam mic, ...) -/// you can get a list of all available devices throught the -/// getAvailableDevices() function. You can then select a device -/// by calling setDevice() with the appropiate device. Otherwise -/// the default capturing device will be used. -/// -/// It is important to note that the audio capture happens in a -/// separate thread, so that it doesn't block the rest of the -/// program. In particular, the onProcessSamples virtual function -/// (but not onStart and not onStop) will be called -/// from this separate thread. It is important to keep this in -/// mind, because you may have to take care of synchronization -/// issues if you share data between threads. -/// -/// Usage example: -/// \code -/// class CustomRecorder : public sf::SoundRecorder -/// { -/// virtual bool onStart() // optional -/// { -/// // Initialize whatever has to be done before the capture starts -/// ... -/// -/// // Return true to start playing -/// return true; -/// } -/// -/// virtual bool onProcessSamples(const Int16* samples, std::size_t sampleCount) -/// { -/// // Do something with the new chunk of samples (store them, send them, ...) -/// ... -/// -/// // Return true to continue playing -/// return true; -/// } -/// -/// virtual void onStop() // optional -/// { -/// // Clean up whatever has to be done after the capture ends -/// ... -/// } -/// } -/// -/// // Usage -/// if (CustomRecorder::isAvailable()) -/// { -/// CustomRecorder recorder; -/// -/// if (!recorder.start()) -/// return -1; -/// -/// ... -/// recorder.stop(); -/// } -/// \endcode -/// -/// \see sf::SoundBufferRecorder -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDRECORDER_HPP +#define SFML_SOUNDRECORDER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Abstract base class for capturing sound data +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API SoundRecorder +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief destructor + /// + //////////////////////////////////////////////////////////// + virtual ~SoundRecorder(); + + //////////////////////////////////////////////////////////// + /// \brief Start the capture + /// + /// The \a sampleRate parameter defines the number of audio samples + /// captured per second. The higher, the better the quality + /// (for example, 44100 samples/sec is CD quality). + /// This function uses its own thread so that it doesn't block + /// the rest of the program while the capture runs. + /// Please note that only one capture can happen at the same time. + /// You can select which capture device will be used, by passing + /// the name to the setDevice() method. If none was selected + /// before, the default capture device will be used. You can get a + /// list of the names of all available capture devices by calling + /// getAvailableDevices(). + /// + /// \param sampleRate Desired capture rate, in number of samples per second + /// + /// \return True, if start of capture was successful + /// + /// \see stop, getAvailableDevices + /// + //////////////////////////////////////////////////////////// + bool start(unsigned int sampleRate = 44100); + + //////////////////////////////////////////////////////////// + /// \brief Stop the capture + /// + /// \see start + /// + //////////////////////////////////////////////////////////// + void stop(); + + //////////////////////////////////////////////////////////// + /// \brief Get the sample rate + /// + /// The sample rate defines the number of audio samples + /// captured per second. The higher, the better the quality + /// (for example, 44100 samples/sec is CD quality). + /// + /// \return Sample rate, in samples per second + /// + //////////////////////////////////////////////////////////// + unsigned int getSampleRate() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a list of the names of all availabe audio capture devices + /// + /// This function returns a vector of strings, containing + /// the names of all availabe audio capture devices. + /// + /// \return A vector of strings containing the names + /// + //////////////////////////////////////////////////////////// + static std::vector getAvailableDevices(); + + //////////////////////////////////////////////////////////// + /// \brief Get the name of the default audio capture device + /// + /// This function returns the name of the default audio + /// capture device. If none is available, an empty string + /// is returned. + /// + /// \return The name of the default audio capture device + /// + //////////////////////////////////////////////////////////// + static std::string getDefaultDevice(); + + //////////////////////////////////////////////////////////// + /// \brief Set the audio capture device + /// + /// This function sets the audio capture device to the device + /// with the given \a name. It can be called on the fly (i.e: + /// while recording). If you do so while recording and + /// opening the device fails, it stops the recording. + /// + /// \param name The name of the audio capture device + /// + /// \return True, if it was able to set the requested device + /// + /// \see getAvailableDevices, getDefaultDevice + /// + //////////////////////////////////////////////////////////// + bool setDevice(const std::string& name); + + //////////////////////////////////////////////////////////// + /// \brief Get the name of the current audio capture device + /// + /// \return The name of the current audio capture device + /// + //////////////////////////////////////////////////////////// + const std::string& getDevice() const; + + //////////////////////////////////////////////////////////// + /// \brief Check if the system supports audio capture + /// + /// This function should always be called before using + /// the audio capture features. If it returns false, then + /// any attempt to use sf::SoundRecorder or one of its derived + /// classes will fail. + /// + /// \return True if audio capture is supported, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isAvailable(); + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor is only meant to be called by derived classes. + /// + //////////////////////////////////////////////////////////// + SoundRecorder(); + + //////////////////////////////////////////////////////////// + /// \brief Set the processing interval + /// + /// The processing interval controls the period + /// between calls to the onProcessSamples function. You may + /// want to use a small interval if you want to process the + /// recorded data in real time, for example. + /// + /// Note: this is only a hint, the actual period may vary. + /// So don't rely on this parameter to implement precise timing. + /// + /// The default processing interval is 100 ms. + /// + /// \param interval Processing interval + /// + //////////////////////////////////////////////////////////// + void setProcessingInterval(sf::Time interval); + + //////////////////////////////////////////////////////////// + /// \brief Start capturing audio data + /// + /// This virtual function may be overriden by a derived class + /// if something has to be done every time a new capture + /// starts. If not, this function can be ignored; the default + /// implementation does nothing. + /// + /// \return True to start the capture, or false to abort it + /// + //////////////////////////////////////////////////////////// + virtual bool onStart(); + + //////////////////////////////////////////////////////////// + /// \brief Process a new chunk of recorded samples + /// + /// This virtual function is called every time a new chunk of + /// recorded data is available. The derived class can then do + /// whatever it wants with it (storing it, playing it, sending + /// it over the network, etc.). + /// + /// \param samples Pointer to the new chunk of recorded samples + /// \param sampleCount Number of samples pointed by \a samples + /// + /// \return True to continue the capture, or false to stop it + /// + //////////////////////////////////////////////////////////// + virtual bool onProcessSamples(const Int16* samples, std::size_t sampleCount) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Stop capturing audio data + /// + /// This virtual function may be overriden by a derived class + /// if something has to be done every time the capture + /// ends. If not, this function can be ignored; the default + /// implementation does nothing. + /// + //////////////////////////////////////////////////////////// + virtual void onStop(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Function called as the entry point of the thread + /// + /// This function starts the recording loop, and returns + /// only when the capture is stopped. + /// + //////////////////////////////////////////////////////////// + void record(); + + //////////////////////////////////////////////////////////// + /// \brief Get the new available audio samples and process them + /// + /// This function is called continuously during the + /// capture loop. It retrieves the captured samples and + /// forwards them to the derived class. + /// + //////////////////////////////////////////////////////////// + void processCapturedSamples(); + + //////////////////////////////////////////////////////////// + /// \brief Clean up the recorder's internal resources + /// + /// This function is called when the capture stops. + /// + //////////////////////////////////////////////////////////// + void cleanup(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Thread m_thread; ///< Thread running the background recording task + std::vector m_samples; ///< Buffer to store captured samples + unsigned int m_sampleRate; ///< Sample rate + sf::Time m_processingInterval; ///< Time period between calls to onProcessSamples + bool m_isCapturing; ///< Capturing state + std::string m_deviceName; ///< Name of the audio capture device +}; + +} // namespace sf + + +#endif // SFML_SOUNDRECORDER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SoundRecorder +/// \ingroup audio +/// +/// sf::SoundBuffer provides a simple interface to access +/// the audio recording capabilities of the computer +/// (the microphone). As an abstract base class, it only cares +/// about capturing sound samples, the task of making something +/// useful with them is left to the derived class. Note that +/// SFML provides a built-in specialization for saving the +/// captured data to a sound buffer (see sf::SoundBufferRecorder). +/// +/// A derived class has only one virtual function to override: +/// \li onProcessSamples provides the new chunks of audio samples while the capture happens +/// +/// Moreover, two additionnal virtual functions can be overriden +/// as well if necessary: +/// \li onStart is called before the capture happens, to perform custom initializations +/// \li onStop is called after the capture ends, to perform custom cleanup +/// +/// A derived class can also control the frequency of the onProcessSamples +/// calls, with the setProcessingInterval protected function. The default +/// interval is chosen so that recording thread doesn't consume too much +/// CPU, but it can be changed to a smaller value if you need to process +/// the recorded data in real time, for example. +/// +/// The audio capture feature may not be supported or activated +/// on every platform, thus it is recommended to check its +/// availability with the isAvailable() function. If it returns +/// false, then any attempt to use an audio recorder will fail. +/// +/// If you have multiple sound input devices connected to your +/// computer (for example: microphone, external soundcard, webcam mic, ...) +/// you can get a list of all available devices throught the +/// getAvailableDevices() function. You can then select a device +/// by calling setDevice() with the appropiate device. Otherwise +/// the default capturing device will be used. +/// +/// It is important to note that the audio capture happens in a +/// separate thread, so that it doesn't block the rest of the +/// program. In particular, the onProcessSamples virtual function +/// (but not onStart and not onStop) will be called +/// from this separate thread. It is important to keep this in +/// mind, because you may have to take care of synchronization +/// issues if you share data between threads. +/// +/// Usage example: +/// \code +/// class CustomRecorder : public sf::SoundRecorder +/// { +/// virtual bool onStart() // optional +/// { +/// // Initialize whatever has to be done before the capture starts +/// ... +/// +/// // Return true to start playing +/// return true; +/// } +/// +/// virtual bool onProcessSamples(const Int16* samples, std::size_t sampleCount) +/// { +/// // Do something with the new chunk of samples (store them, send them, ...) +/// ... +/// +/// // Return true to continue playing +/// return true; +/// } +/// +/// virtual void onStop() // optional +/// { +/// // Clean up whatever has to be done after the capture ends +/// ... +/// } +/// } +/// +/// // Usage +/// if (CustomRecorder::isAvailable()) +/// { +/// CustomRecorder recorder; +/// +/// if (!recorder.start()) +/// return -1; +/// +/// ... +/// recorder.stop(); +/// } +/// \endcode +/// +/// \see sf::SoundBufferRecorder +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Audio/SoundSource.hpp b/include/SFML/Audio/SoundSource.hpp index 2ed42cc1..8660dd26 100644 --- a/include/SFML/Audio/SoundSource.hpp +++ b/include/SFML/Audio/SoundSource.hpp @@ -1,286 +1,286 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOUNDSOURCE_HPP -#define SFML_SOUNDSOURCE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Base class defining a sound's properties -/// -//////////////////////////////////////////////////////////// -class SFML_AUDIO_API SoundSource -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Enumeration of the sound source states - /// - //////////////////////////////////////////////////////////// - enum Status - { - Stopped, ///< Sound is not playing - Paused, ///< Sound is paused - Playing ///< Sound is playing - }; - - //////////////////////////////////////////////////////////// - /// \brief Copy constructor - /// - /// \param copy Instance to copy - /// - //////////////////////////////////////////////////////////// - SoundSource(const SoundSource& copy); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - virtual ~SoundSource(); - - //////////////////////////////////////////////////////////// - /// \brief Set the pitch of the sound - /// - /// The pitch represents the perceived fundamental frequency - /// of a sound; thus you can make a sound more acute or grave - /// by changing its pitch. A side effect of changing the pitch - /// is to modify the playing speed of the sound as well. - /// The default value for the pitch is 1. - /// - /// \param pitch New pitch to apply to the sound - /// - /// \see getPitch - /// - //////////////////////////////////////////////////////////// - void setPitch(float pitch); - - //////////////////////////////////////////////////////////// - /// \brief Set the volume of the sound - /// - /// The volume is a value between 0 (mute) and 100 (full volume). - /// The default value for the volume is 100. - /// - /// \param volume Volume of the sound - /// - /// \see getVolume - /// - //////////////////////////////////////////////////////////// - void setVolume(float volume); - - //////////////////////////////////////////////////////////// - /// \brief Set the 3D position of the sound in the audio scene - /// - /// Only sounds with one channel (mono sounds) can be - /// spatialized. - /// The default position of a sound is (0, 0, 0). - /// - /// \param x X coordinate of the position of the sound in the scene - /// \param y Y coordinate of the position of the sound in the scene - /// \param z Z coordinate of the position of the sound in the scene - /// - /// \see getPosition - /// - //////////////////////////////////////////////////////////// - void setPosition(float x, float y, float z); - - //////////////////////////////////////////////////////////// - /// \brief Set the 3D position of the sound in the audio scene - /// - /// Only sounds with one channel (mono sounds) can be - /// spatialized. - /// The default position of a sound is (0, 0, 0). - /// - /// \param position Position of the sound in the scene - /// - /// \see getPosition - /// - //////////////////////////////////////////////////////////// - void setPosition(const Vector3f& position); - - //////////////////////////////////////////////////////////// - /// \brief Make the sound's position relative to the listener or absolute - /// - /// Making a sound relative to the listener will ensure that it will always - /// be played the same way regardless the position of the listener. - /// This can be useful for non-spatialized sounds, sounds that are - /// produced by the listener, or sounds attached to it. - /// The default value is false (position is absolute). - /// - /// \param relative True to set the position relative, false to set it absolute - /// - /// \see isRelativeToListener - /// - //////////////////////////////////////////////////////////// - void setRelativeToListener(bool relative); - - //////////////////////////////////////////////////////////// - /// \brief Set the minimum distance of the sound - /// - /// The "minimum distance" of a sound is the maximum - /// distance at which it is heard at its maximum volume. Further - /// than the minimum distance, it will start to fade out according - /// to its attenuation factor. A value of 0 ("inside the head - /// of the listener") is an invalid value and is forbidden. - /// The default value of the minimum distance is 1. - /// - /// \param distance New minimum distance of the sound - /// - /// \see getMinDistance, setAttenuation - /// - //////////////////////////////////////////////////////////// - void setMinDistance(float distance); - - //////////////////////////////////////////////////////////// - /// \brief Set the attenuation factor of the sound - /// - /// The attenuation is a multiplicative factor which makes - /// the sound more or less loud according to its distance - /// from the listener. An attenuation of 0 will produce a - /// non-attenuated sound, i.e. its volume will always be the same - /// whether it is heard from near or from far. On the other hand, - /// an attenuation value such as 100 will make the sound fade out - /// very quickly as it gets further from the listener. - /// The default value of the attenuation is 1. - /// - /// \param attenuation New attenuation factor of the sound - /// - /// \see getAttenuation, setMinDistance - /// - //////////////////////////////////////////////////////////// - void setAttenuation(float attenuation); - - //////////////////////////////////////////////////////////// - /// \brief Get the pitch of the sound - /// - /// \return Pitch of the sound - /// - /// \see setPitch - /// - //////////////////////////////////////////////////////////// - float getPitch() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the volume of the sound - /// - /// \return Volume of the sound, in the range [0, 100] - /// - /// \see setVolume - /// - //////////////////////////////////////////////////////////// - float getVolume() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the 3D position of the sound in the audio scene - /// - /// \return Position of the sound - /// - /// \see setPosition - /// - //////////////////////////////////////////////////////////// - Vector3f getPosition() const; - - //////////////////////////////////////////////////////////// - /// \brief Tell whether the sound's position is relative to the - /// listener or is absolute - /// - /// \return True if the position is relative, false if it's absolute - /// - /// \see setRelativeToListener - /// - //////////////////////////////////////////////////////////// - bool isRelativeToListener() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the minimum distance of the sound - /// - /// \return Minimum distance of the sound - /// - /// \see setMinDistance, getAttenuation - /// - //////////////////////////////////////////////////////////// - float getMinDistance() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the attenuation factor of the sound - /// - /// \return Attenuation factor of the sound - /// - /// \see setAttenuation, getMinDistance - /// - //////////////////////////////////////////////////////////// - float getAttenuation() const; - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor is meant ot be called by derived classes only. - /// - //////////////////////////////////////////////////////////// - SoundSource(); - - //////////////////////////////////////////////////////////// - /// \brief Get the current status of the sound (stopped, paused, playing) - /// - /// \return Current status of the sound - /// - //////////////////////////////////////////////////////////// - Status getStatus() const; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - unsigned int m_source; ///< OpenAL source identifier -}; - -} // namespace sf - - -#endif // SFML_SOUNDSOURCE_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::SoundSource -/// \ingroup audio -/// -/// sf::SoundSource is not meant to be used directly, it -/// only serves as a common base for all audio objects -/// that can live in the audio environment. -/// -/// It defines several properties for the sound: pitch, -/// volume, position, attenuation, etc. All of them can be -/// changed at any time with no impact on performances. -/// -/// \see sf::Sound, sf::SoundStream -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDSOURCE_HPP +#define SFML_SOUNDSOURCE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Base class defining a sound's properties +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API SoundSource +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Enumeration of the sound source states + /// + //////////////////////////////////////////////////////////// + enum Status + { + Stopped, ///< Sound is not playing + Paused, ///< Sound is paused + Playing ///< Sound is playing + }; + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + SoundSource(const SoundSource& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~SoundSource(); + + //////////////////////////////////////////////////////////// + /// \brief Set the pitch of the sound + /// + /// The pitch represents the perceived fundamental frequency + /// of a sound; thus you can make a sound more acute or grave + /// by changing its pitch. A side effect of changing the pitch + /// is to modify the playing speed of the sound as well. + /// The default value for the pitch is 1. + /// + /// \param pitch New pitch to apply to the sound + /// + /// \see getPitch + /// + //////////////////////////////////////////////////////////// + void setPitch(float pitch); + + //////////////////////////////////////////////////////////// + /// \brief Set the volume of the sound + /// + /// The volume is a value between 0 (mute) and 100 (full volume). + /// The default value for the volume is 100. + /// + /// \param volume Volume of the sound + /// + /// \see getVolume + /// + //////////////////////////////////////////////////////////// + void setVolume(float volume); + + //////////////////////////////////////////////////////////// + /// \brief Set the 3D position of the sound in the audio scene + /// + /// Only sounds with one channel (mono sounds) can be + /// spatialized. + /// The default position of a sound is (0, 0, 0). + /// + /// \param x X coordinate of the position of the sound in the scene + /// \param y Y coordinate of the position of the sound in the scene + /// \param z Z coordinate of the position of the sound in the scene + /// + /// \see getPosition + /// + //////////////////////////////////////////////////////////// + void setPosition(float x, float y, float z); + + //////////////////////////////////////////////////////////// + /// \brief Set the 3D position of the sound in the audio scene + /// + /// Only sounds with one channel (mono sounds) can be + /// spatialized. + /// The default position of a sound is (0, 0, 0). + /// + /// \param position Position of the sound in the scene + /// + /// \see getPosition + /// + //////////////////////////////////////////////////////////// + void setPosition(const Vector3f& position); + + //////////////////////////////////////////////////////////// + /// \brief Make the sound's position relative to the listener or absolute + /// + /// Making a sound relative to the listener will ensure that it will always + /// be played the same way regardless the position of the listener. + /// This can be useful for non-spatialized sounds, sounds that are + /// produced by the listener, or sounds attached to it. + /// The default value is false (position is absolute). + /// + /// \param relative True to set the position relative, false to set it absolute + /// + /// \see isRelativeToListener + /// + //////////////////////////////////////////////////////////// + void setRelativeToListener(bool relative); + + //////////////////////////////////////////////////////////// + /// \brief Set the minimum distance of the sound + /// + /// The "minimum distance" of a sound is the maximum + /// distance at which it is heard at its maximum volume. Further + /// than the minimum distance, it will start to fade out according + /// to its attenuation factor. A value of 0 ("inside the head + /// of the listener") is an invalid value and is forbidden. + /// The default value of the minimum distance is 1. + /// + /// \param distance New minimum distance of the sound + /// + /// \see getMinDistance, setAttenuation + /// + //////////////////////////////////////////////////////////// + void setMinDistance(float distance); + + //////////////////////////////////////////////////////////// + /// \brief Set the attenuation factor of the sound + /// + /// The attenuation is a multiplicative factor which makes + /// the sound more or less loud according to its distance + /// from the listener. An attenuation of 0 will produce a + /// non-attenuated sound, i.e. its volume will always be the same + /// whether it is heard from near or from far. On the other hand, + /// an attenuation value such as 100 will make the sound fade out + /// very quickly as it gets further from the listener. + /// The default value of the attenuation is 1. + /// + /// \param attenuation New attenuation factor of the sound + /// + /// \see getAttenuation, setMinDistance + /// + //////////////////////////////////////////////////////////// + void setAttenuation(float attenuation); + + //////////////////////////////////////////////////////////// + /// \brief Get the pitch of the sound + /// + /// \return Pitch of the sound + /// + /// \see setPitch + /// + //////////////////////////////////////////////////////////// + float getPitch() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the volume of the sound + /// + /// \return Volume of the sound, in the range [0, 100] + /// + /// \see setVolume + /// + //////////////////////////////////////////////////////////// + float getVolume() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the 3D position of the sound in the audio scene + /// + /// \return Position of the sound + /// + /// \see setPosition + /// + //////////////////////////////////////////////////////////// + Vector3f getPosition() const; + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the sound's position is relative to the + /// listener or is absolute + /// + /// \return True if the position is relative, false if it's absolute + /// + /// \see setRelativeToListener + /// + //////////////////////////////////////////////////////////// + bool isRelativeToListener() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the minimum distance of the sound + /// + /// \return Minimum distance of the sound + /// + /// \see setMinDistance, getAttenuation + /// + //////////////////////////////////////////////////////////// + float getMinDistance() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the attenuation factor of the sound + /// + /// \return Attenuation factor of the sound + /// + /// \see setAttenuation, getMinDistance + /// + //////////////////////////////////////////////////////////// + float getAttenuation() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor is meant ot be called by derived classes only. + /// + //////////////////////////////////////////////////////////// + SoundSource(); + + //////////////////////////////////////////////////////////// + /// \brief Get the current status of the sound (stopped, paused, playing) + /// + /// \return Current status of the sound + /// + //////////////////////////////////////////////////////////// + Status getStatus() const; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int m_source; ///< OpenAL source identifier +}; + +} // namespace sf + + +#endif // SFML_SOUNDSOURCE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SoundSource +/// \ingroup audio +/// +/// sf::SoundSource is not meant to be used directly, it +/// only serves as a common base for all audio objects +/// that can live in the audio environment. +/// +/// It defines several properties for the sound: pitch, +/// volume, position, attenuation, etc. All of them can be +/// changed at any time with no impact on performances. +/// +/// \see sf::Sound, sf::SoundStream +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Audio/SoundStream.hpp b/include/SFML/Audio/SoundStream.hpp index 348f562a..24120f2d 100644 --- a/include/SFML/Audio/SoundStream.hpp +++ b/include/SFML/Audio/SoundStream.hpp @@ -1,386 +1,386 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOUNDSTREAM_HPP -#define SFML_SOUNDSTREAM_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Abstract base class for streamed audio sources -/// -//////////////////////////////////////////////////////////// -class SFML_AUDIO_API SoundStream : public SoundSource -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Structure defining a chunk of audio data to stream - /// - //////////////////////////////////////////////////////////// - struct Chunk - { - const Int16* samples; ///< Pointer to the audio samples - std::size_t sampleCount; ///< Number of samples pointed by Samples - }; - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - virtual ~SoundStream(); - - //////////////////////////////////////////////////////////// - /// \brief Start or resume playing the audio stream - /// - /// This function starts the stream if it was stopped, resumes - /// it if it was paused, and restarts it from the beginning if - /// it was already playing. - /// This function uses its own thread so that it doesn't block - /// the rest of the program while the stream is played. - /// - /// \see pause, stop - /// - //////////////////////////////////////////////////////////// - void play(); - - //////////////////////////////////////////////////////////// - /// \brief Pause the audio stream - /// - /// This function pauses the stream if it was playing, - /// otherwise (stream already paused or stopped) it has no effect. - /// - /// \see play, stop - /// - //////////////////////////////////////////////////////////// - void pause(); - - //////////////////////////////////////////////////////////// - /// \brief Stop playing the audio stream - /// - /// This function stops the stream if it was playing or paused, - /// and does nothing if it was already stopped. - /// It also resets the playing position (unlike pause()). - /// - /// \see play, pause - /// - //////////////////////////////////////////////////////////// - void stop(); - - //////////////////////////////////////////////////////////// - /// \brief Return the number of channels of the stream - /// - /// 1 channel means a mono sound, 2 means stereo, etc. - /// - /// \return Number of channels - /// - //////////////////////////////////////////////////////////// - unsigned int getChannelCount() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the stream sample rate of the stream - /// - /// The sample rate is the number of audio samples played per - /// second. The higher, the better the quality. - /// - /// \return Sample rate, in number of samples per second - /// - //////////////////////////////////////////////////////////// - unsigned int getSampleRate() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the current status of the stream (stopped, paused, playing) - /// - /// \return Current status - /// - //////////////////////////////////////////////////////////// - Status getStatus() const; - - //////////////////////////////////////////////////////////// - /// \brief Change the current playing position of the stream - /// - /// The playing position can be changed when the stream is - /// either paused or playing. Changing the playing position - /// when the stream is stopped has no effect, since playing - /// the stream would reset its position. - /// - /// \param timeOffset New playing position, from the beginning of the stream - /// - /// \see getPlayingOffset - /// - //////////////////////////////////////////////////////////// - void setPlayingOffset(Time timeOffset); - - //////////////////////////////////////////////////////////// - /// \brief Get the current playing position of the stream - /// - /// \return Current playing position, from the beginning of the stream - /// - /// \see setPlayingOffset - /// - //////////////////////////////////////////////////////////// - Time getPlayingOffset() const; - - //////////////////////////////////////////////////////////// - /// \brief Set whether or not the stream should loop after reaching the end - /// - /// If set, the stream will restart from beginning after - /// reaching the end and so on, until it is stopped or - /// setLoop(false) is called. - /// The default looping state for streams is false. - /// - /// \param loop True to play in loop, false to play once - /// - /// \see getLoop - /// - //////////////////////////////////////////////////////////// - void setLoop(bool loop); - - //////////////////////////////////////////////////////////// - /// \brief Tell whether or not the stream is in loop mode - /// - /// \return True if the stream is looping, false otherwise - /// - /// \see setLoop - /// - //////////////////////////////////////////////////////////// - bool getLoop() const; - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor is only meant to be called by derived classes. - /// - //////////////////////////////////////////////////////////// - SoundStream(); - - //////////////////////////////////////////////////////////// - /// \brief Define the audio stream parameters - /// - /// This function must be called by derived classes as soon - /// as they know the audio settings of the stream to play. - /// Any attempt to manipulate the stream (play(), ...) before - /// calling this function will fail. - /// It can be called multiple times if the settings of the - /// audio stream change, but only when the stream is stopped. - /// - /// \param channelCount Number of channels of the stream - /// \param sampleRate Sample rate, in samples per second - /// - //////////////////////////////////////////////////////////// - void initialize(unsigned int channelCount, unsigned int sampleRate); - - //////////////////////////////////////////////////////////// - /// \brief Request a new chunk of audio samples from the stream source - /// - /// This function must be overriden by derived classes to provide - /// the audio samples to play. It is called continuously by the - /// streaming loop, in a separate thread. - /// The source can choose to stop the streaming loop at any time, by - /// returning false to the caller. - /// If you return true (i.e. continue streaming) it is important that - /// the returned array of samples is not empty; this would stop the stream - /// due to an internal limitation. - /// - /// \param data Chunk of data to fill - /// - /// \return True to continue playback, false to stop - /// - //////////////////////////////////////////////////////////// - virtual bool onGetData(Chunk& data) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Change the current playing position in the stream source - /// - /// This function must be overriden by derived classes to - /// allow random seeking into the stream source. - /// - /// \param timeOffset New playing position, relative to the beginning of the stream - /// - //////////////////////////////////////////////////////////// - virtual void onSeek(Time timeOffset) = 0; - -private : - - //////////////////////////////////////////////////////////// - /// \brief Function called as the entry point of the thread - /// - /// This function starts the streaming loop, and returns - /// only when the sound is stopped. - /// - //////////////////////////////////////////////////////////// - void streamData(); - - //////////////////////////////////////////////////////////// - /// \brief Fill a new buffer with audio samples, and append - /// it to the playing queue - /// - /// This function is called as soon as a buffer has been fully - /// consumed; it fills it again and inserts it back into the - /// playing queue. - /// - /// \param bufferNum Number of the buffer to fill (in [0, BufferCount]) - /// - /// \return True if the stream source has requested to stop, false otherwise - /// - //////////////////////////////////////////////////////////// - bool fillAndPushBuffer(unsigned int bufferNum); - - //////////////////////////////////////////////////////////// - /// \brief Fill the audio buffers and put them all into the playing queue - /// - /// This function is called when playing starts and the - /// playing queue is empty. - /// - /// \return True if the derived class has requested to stop, false otherwise - /// - //////////////////////////////////////////////////////////// - bool fillQueue(); - - //////////////////////////////////////////////////////////// - /// \brief Clear all the audio buffers and empty the playing queue - /// - /// This function is called when the stream is stopped. - /// - //////////////////////////////////////////////////////////// - void clearQueue(); - - enum - { - BufferCount = 3 ///< Number of audio buffers used by the streaming loop - }; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Thread m_thread; ///< Thread running the background tasks - mutable Mutex m_threadMutex; ///< Thread mutex - Status m_threadStartState; ///< State the thread starts in (Playing, Paused, Stopped) - bool m_isStreaming; ///< Streaming state (true = playing, false = stopped) - unsigned int m_buffers[BufferCount]; ///< Sound buffers used to store temporary audio data - unsigned int m_channelCount; ///< Number of channels (1 = mono, 2 = stereo, ...) - unsigned int m_sampleRate; ///< Frequency (samples / second) - Uint32 m_format; ///< Format of the internal sound buffers - bool m_loop; ///< Loop flag (true to loop, false to play once) - Uint64 m_samplesProcessed; ///< Number of buffers processed since beginning of the stream - bool m_endBuffers[BufferCount]; ///< Each buffer is marked as "end buffer" or not, for proper duration calculation -}; - -} // namespace sf - - -#endif // SFML_SOUNDSTREAM_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::SoundStream -/// \ingroup audio -/// -/// Unlike audio buffers (see sf::SoundBuffer), audio streams -/// are never completely loaded in memory. Instead, the audio -/// data is acquired continuously while the stream is playing. -/// This behaviour allows to play a sound with no loading delay, -/// and keeps the memory consumption very low. -/// -/// Sound sources that need to be streamed are usually big files -/// (compressed audio musics that would eat hundreds of MB in memory) -/// or files that would take a lot of time to be received -/// (sounds played over the network). -/// -/// sf::SoundStream is a base class that doesn't care about the -/// stream source, which is left to the derived class. SFML provides -/// a built-in specialization for big files (see sf::Music). -/// No network stream source is provided, but you can write your own -/// by combining this class with the network module. -/// -/// A derived class has to override two virtual functions: -/// \li onGetData fills a new chunk of audio data to be played -/// \li onSeek changes the current playing position in the source -/// -/// It is important to note that each SoundStream is played in its -/// own separate thread, so that the streaming loop doesn't block the -/// rest of the program. In particular, the OnGetData and OnSeek -/// virtual functions may sometimes be called from this separate thread. -/// It is important to keep this in mind, because you may have to take -/// care of synchronization issues if you share data between threads. -/// -/// Usage example: -/// \code -/// class CustomStream : public sf::SoundStream -/// { -/// public : -/// -/// bool open(const std::string& location) -/// { -/// // Open the source and get audio settings -/// ... -/// unsigned int channelCount = ...; -/// unsigned int sampleRate = ...; -/// -/// // Initialize the stream -- important! -/// initialize(channelCount, sampleRate); -/// } -/// -/// private : -/// -/// virtual bool onGetData(Chunk& data) -/// { -/// // Fill the chunk with audio data from the stream source -/// // (note: must not be empty if you want to continue playing) -/// data.samples = ...; -/// data.sampleCount = ...; -/// -/// // Return true to continue playing -/// return true; -/// } -/// -/// virtual void onSeek(Uint32 timeOffset) -/// { -/// // Change the current position in the stream source -/// ... -/// } -/// } -/// -/// // Usage -/// CustomStream stream; -/// stream.open("path/to/stream"); -/// stream.play(); -/// \endcode -/// -/// \see sf::Music -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDSTREAM_HPP +#define SFML_SOUNDSTREAM_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Abstract base class for streamed audio sources +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API SoundStream : public SoundSource +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Structure defining a chunk of audio data to stream + /// + //////////////////////////////////////////////////////////// + struct Chunk + { + const Int16* samples; ///< Pointer to the audio samples + std::size_t sampleCount; ///< Number of samples pointed by Samples + }; + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~SoundStream(); + + //////////////////////////////////////////////////////////// + /// \brief Start or resume playing the audio stream + /// + /// This function starts the stream if it was stopped, resumes + /// it if it was paused, and restarts it from the beginning if + /// it was already playing. + /// This function uses its own thread so that it doesn't block + /// the rest of the program while the stream is played. + /// + /// \see pause, stop + /// + //////////////////////////////////////////////////////////// + void play(); + + //////////////////////////////////////////////////////////// + /// \brief Pause the audio stream + /// + /// This function pauses the stream if it was playing, + /// otherwise (stream already paused or stopped) it has no effect. + /// + /// \see play, stop + /// + //////////////////////////////////////////////////////////// + void pause(); + + //////////////////////////////////////////////////////////// + /// \brief Stop playing the audio stream + /// + /// This function stops the stream if it was playing or paused, + /// and does nothing if it was already stopped. + /// It also resets the playing position (unlike pause()). + /// + /// \see play, pause + /// + //////////////////////////////////////////////////////////// + void stop(); + + //////////////////////////////////////////////////////////// + /// \brief Return the number of channels of the stream + /// + /// 1 channel means a mono sound, 2 means stereo, etc. + /// + /// \return Number of channels + /// + //////////////////////////////////////////////////////////// + unsigned int getChannelCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the stream sample rate of the stream + /// + /// The sample rate is the number of audio samples played per + /// second. The higher, the better the quality. + /// + /// \return Sample rate, in number of samples per second + /// + //////////////////////////////////////////////////////////// + unsigned int getSampleRate() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the current status of the stream (stopped, paused, playing) + /// + /// \return Current status + /// + //////////////////////////////////////////////////////////// + Status getStatus() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the current playing position of the stream + /// + /// The playing position can be changed when the stream is + /// either paused or playing. Changing the playing position + /// when the stream is stopped has no effect, since playing + /// the stream would reset its position. + /// + /// \param timeOffset New playing position, from the beginning of the stream + /// + /// \see getPlayingOffset + /// + //////////////////////////////////////////////////////////// + void setPlayingOffset(Time timeOffset); + + //////////////////////////////////////////////////////////// + /// \brief Get the current playing position of the stream + /// + /// \return Current playing position, from the beginning of the stream + /// + /// \see setPlayingOffset + /// + //////////////////////////////////////////////////////////// + Time getPlayingOffset() const; + + //////////////////////////////////////////////////////////// + /// \brief Set whether or not the stream should loop after reaching the end + /// + /// If set, the stream will restart from beginning after + /// reaching the end and so on, until it is stopped or + /// setLoop(false) is called. + /// The default looping state for streams is false. + /// + /// \param loop True to play in loop, false to play once + /// + /// \see getLoop + /// + //////////////////////////////////////////////////////////// + void setLoop(bool loop); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether or not the stream is in loop mode + /// + /// \return True if the stream is looping, false otherwise + /// + /// \see setLoop + /// + //////////////////////////////////////////////////////////// + bool getLoop() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor is only meant to be called by derived classes. + /// + //////////////////////////////////////////////////////////// + SoundStream(); + + //////////////////////////////////////////////////////////// + /// \brief Define the audio stream parameters + /// + /// This function must be called by derived classes as soon + /// as they know the audio settings of the stream to play. + /// Any attempt to manipulate the stream (play(), ...) before + /// calling this function will fail. + /// It can be called multiple times if the settings of the + /// audio stream change, but only when the stream is stopped. + /// + /// \param channelCount Number of channels of the stream + /// \param sampleRate Sample rate, in samples per second + /// + //////////////////////////////////////////////////////////// + void initialize(unsigned int channelCount, unsigned int sampleRate); + + //////////////////////////////////////////////////////////// + /// \brief Request a new chunk of audio samples from the stream source + /// + /// This function must be overriden by derived classes to provide + /// the audio samples to play. It is called continuously by the + /// streaming loop, in a separate thread. + /// The source can choose to stop the streaming loop at any time, by + /// returning false to the caller. + /// If you return true (i.e. continue streaming) it is important that + /// the returned array of samples is not empty; this would stop the stream + /// due to an internal limitation. + /// + /// \param data Chunk of data to fill + /// + /// \return True to continue playback, false to stop + /// + //////////////////////////////////////////////////////////// + virtual bool onGetData(Chunk& data) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Change the current playing position in the stream source + /// + /// This function must be overriden by derived classes to + /// allow random seeking into the stream source. + /// + /// \param timeOffset New playing position, relative to the beginning of the stream + /// + //////////////////////////////////////////////////////////// + virtual void onSeek(Time timeOffset) = 0; + +private: + + //////////////////////////////////////////////////////////// + /// \brief Function called as the entry point of the thread + /// + /// This function starts the streaming loop, and returns + /// only when the sound is stopped. + /// + //////////////////////////////////////////////////////////// + void streamData(); + + //////////////////////////////////////////////////////////// + /// \brief Fill a new buffer with audio samples, and append + /// it to the playing queue + /// + /// This function is called as soon as a buffer has been fully + /// consumed; it fills it again and inserts it back into the + /// playing queue. + /// + /// \param bufferNum Number of the buffer to fill (in [0, BufferCount]) + /// + /// \return True if the stream source has requested to stop, false otherwise + /// + //////////////////////////////////////////////////////////// + bool fillAndPushBuffer(unsigned int bufferNum); + + //////////////////////////////////////////////////////////// + /// \brief Fill the audio buffers and put them all into the playing queue + /// + /// This function is called when playing starts and the + /// playing queue is empty. + /// + /// \return True if the derived class has requested to stop, false otherwise + /// + //////////////////////////////////////////////////////////// + bool fillQueue(); + + //////////////////////////////////////////////////////////// + /// \brief Clear all the audio buffers and empty the playing queue + /// + /// This function is called when the stream is stopped. + /// + //////////////////////////////////////////////////////////// + void clearQueue(); + + enum + { + BufferCount = 3 ///< Number of audio buffers used by the streaming loop + }; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Thread m_thread; ///< Thread running the background tasks + mutable Mutex m_threadMutex; ///< Thread mutex + Status m_threadStartState; ///< State the thread starts in (Playing, Paused, Stopped) + bool m_isStreaming; ///< Streaming state (true = playing, false = stopped) + unsigned int m_buffers[BufferCount]; ///< Sound buffers used to store temporary audio data + unsigned int m_channelCount; ///< Number of channels (1 = mono, 2 = stereo, ...) + unsigned int m_sampleRate; ///< Frequency (samples / second) + Uint32 m_format; ///< Format of the internal sound buffers + bool m_loop; ///< Loop flag (true to loop, false to play once) + Uint64 m_samplesProcessed; ///< Number of buffers processed since beginning of the stream + bool m_endBuffers[BufferCount]; ///< Each buffer is marked as "end buffer" or not, for proper duration calculation +}; + +} // namespace sf + + +#endif // SFML_SOUNDSTREAM_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SoundStream +/// \ingroup audio +/// +/// Unlike audio buffers (see sf::SoundBuffer), audio streams +/// are never completely loaded in memory. Instead, the audio +/// data is acquired continuously while the stream is playing. +/// This behaviour allows to play a sound with no loading delay, +/// and keeps the memory consumption very low. +/// +/// Sound sources that need to be streamed are usually big files +/// (compressed audio musics that would eat hundreds of MB in memory) +/// or files that would take a lot of time to be received +/// (sounds played over the network). +/// +/// sf::SoundStream is a base class that doesn't care about the +/// stream source, which is left to the derived class. SFML provides +/// a built-in specialization for big files (see sf::Music). +/// No network stream source is provided, but you can write your own +/// by combining this class with the network module. +/// +/// A derived class has to override two virtual functions: +/// \li onGetData fills a new chunk of audio data to be played +/// \li onSeek changes the current playing position in the source +/// +/// It is important to note that each SoundStream is played in its +/// own separate thread, so that the streaming loop doesn't block the +/// rest of the program. In particular, the OnGetData and OnSeek +/// virtual functions may sometimes be called from this separate thread. +/// It is important to keep this in mind, because you may have to take +/// care of synchronization issues if you share data between threads. +/// +/// Usage example: +/// \code +/// class CustomStream : public sf::SoundStream +/// { +/// public: +/// +/// bool open(const std::string& location) +/// { +/// // Open the source and get audio settings +/// ... +/// unsigned int channelCount = ...; +/// unsigned int sampleRate = ...; +/// +/// // Initialize the stream -- important! +/// initialize(channelCount, sampleRate); +/// } +/// +/// private: +/// +/// virtual bool onGetData(Chunk& data) +/// { +/// // Fill the chunk with audio data from the stream source +/// // (note: must not be empty if you want to continue playing) +/// data.samples = ...; +/// data.sampleCount = ...; +/// +/// // Return true to continue playing +/// return true; +/// } +/// +/// virtual void onSeek(Uint32 timeOffset) +/// { +/// // Change the current position in the stream source +/// ... +/// } +/// } +/// +/// // Usage +/// CustomStream stream; +/// stream.open("path/to/stream"); +/// stream.play(); +/// \endcode +/// +/// \see sf::Music +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Config.hpp b/include/SFML/Config.hpp index fd4e89d2..2366f187 100644 --- a/include/SFML/Config.hpp +++ b/include/SFML/Config.hpp @@ -1,192 +1,192 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_CONFIG_HPP -#define SFML_CONFIG_HPP - - -//////////////////////////////////////////////////////////// -// Define the SFML version -//////////////////////////////////////////////////////////// -#define SFML_VERSION_MAJOR 2 -#define SFML_VERSION_MINOR 1 - - -//////////////////////////////////////////////////////////// -// Identify the operating system -// see http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system -//////////////////////////////////////////////////////////// -#if defined(_WIN32) - - // Windows - #define SFML_SYSTEM_WINDOWS - #ifndef NOMINMAX - #define NOMINMAX - #endif - -#elif defined(__APPLE__) && defined(__MACH__) - - // Apple platform, see which one it is - #include "TargetConditionals.h" - - #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR - - // iOS - #define SFML_SYSTEM_IOS - - #elif TARGET_OS_MAC - - // MacOS - #define SFML_SYSTEM_MACOS - - #else - - // Unsupported Apple system - #error This Apple operating system is not supported by SFML library - - #endif - -#elif defined(__unix__) - - // UNIX system, see which one it is - #if defined(__ANDROID__) - - // Android - #define SFML_SYSTEM_ANDROID - - #elif defined(__linux__) - - // Linux - #define SFML_SYSTEM_LINUX - - #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - - // FreeBSD - #define SFML_SYSTEM_FREEBSD - - #else - - // Unsupported UNIX system - #error This UNIX operating system is not supported by SFML library - - #endif - -#else - - // Unsupported system - #error This operating system is not supported by SFML library - -#endif - - -//////////////////////////////////////////////////////////// -// Define a portable debug macro -//////////////////////////////////////////////////////////// -#if !defined(NDEBUG) - - #define SFML_DEBUG - -#endif - - -//////////////////////////////////////////////////////////// -// Define helpers to create portable import / export macros for each module -//////////////////////////////////////////////////////////// -#if !defined(SFML_STATIC) - - #if defined(SFML_SYSTEM_WINDOWS) - - // Windows compilers need specific (and different) keywords for export and import - #define SFML_API_EXPORT __declspec(dllexport) - #define SFML_API_IMPORT __declspec(dllimport) - - // For Visual C++ compilers, we also need to turn off this annoying C4251 warning - #ifdef _MSC_VER - - #pragma warning(disable : 4251) - - #endif - - #else // Linux, FreeBSD, Mac OS X - - #if __GNUC__ >= 4 - - // GCC 4 has special keywords for showing/hidding symbols, - // the same keyword is used for both importing and exporting - #define SFML_API_EXPORT __attribute__ ((__visibility__ ("default"))) - #define SFML_API_IMPORT __attribute__ ((__visibility__ ("default"))) - - #else - - // GCC < 4 has no mechanism to explicitely hide symbols, everything's exported - #define SFML_API_EXPORT - #define SFML_API_IMPORT - - #endif - - #endif - -#else - - // Static build doesn't need import/export macros - #define SFML_API_EXPORT - #define SFML_API_IMPORT - -#endif - - -//////////////////////////////////////////////////////////// -// Define portable fixed-size types -//////////////////////////////////////////////////////////// -namespace sf -{ - // All "common" platforms use the same size for char, short and int - // (basically there are 3 types for 3 sizes, so no other match is possible), - // we can use them without doing any kind of check - - // 8 bits integer types - typedef signed char Int8; - typedef unsigned char Uint8; - - // 16 bits integer types - typedef signed short Int16; - typedef unsigned short Uint16; - - // 32 bits integer types - typedef signed int Int32; - typedef unsigned int Uint32; - - // 64 bits integer types - #if defined(_MSC_VER) - typedef signed __int64 Int64; - typedef unsigned __int64 Uint64; - #else - typedef signed long long Int64; - typedef unsigned long long Uint64; - #endif - -} // namespace sf - - -#endif // SFML_CONFIG_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CONFIG_HPP +#define SFML_CONFIG_HPP + + +//////////////////////////////////////////////////////////// +// Define the SFML version +//////////////////////////////////////////////////////////// +#define SFML_VERSION_MAJOR 2 +#define SFML_VERSION_MINOR 1 + + +//////////////////////////////////////////////////////////// +// Identify the operating system +// see http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system +//////////////////////////////////////////////////////////// +#if defined(_WIN32) + + // Windows + #define SFML_SYSTEM_WINDOWS + #ifndef NOMINMAX + #define NOMINMAX + #endif + +#elif defined(__APPLE__) && defined(__MACH__) + + // Apple platform, see which one it is + #include "TargetConditionals.h" + + #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR + + // iOS + #define SFML_SYSTEM_IOS + + #elif TARGET_OS_MAC + + // MacOS + #define SFML_SYSTEM_MACOS + + #else + + // Unsupported Apple system + #error This Apple operating system is not supported by SFML library + + #endif + +#elif defined(__unix__) + + // UNIX system, see which one it is + #if defined(__ANDROID__) + + // Android + #define SFML_SYSTEM_ANDROID + + #elif defined(__linux__) + + // Linux + #define SFML_SYSTEM_LINUX + + #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + + // FreeBSD + #define SFML_SYSTEM_FREEBSD + + #else + + // Unsupported UNIX system + #error This UNIX operating system is not supported by SFML library + + #endif + +#else + + // Unsupported system + #error This operating system is not supported by SFML library + +#endif + + +//////////////////////////////////////////////////////////// +// Define a portable debug macro +//////////////////////////////////////////////////////////// +#if !defined(NDEBUG) + + #define SFML_DEBUG + +#endif + + +//////////////////////////////////////////////////////////// +// Define helpers to create portable import / export macros for each module +//////////////////////////////////////////////////////////// +#if !defined(SFML_STATIC) + + #if defined(SFML_SYSTEM_WINDOWS) + + // Windows compilers need specific (and different) keywords for export and import + #define SFML_API_EXPORT __declspec(dllexport) + #define SFML_API_IMPORT __declspec(dllimport) + + // For Visual C++ compilers, we also need to turn off this annoying C4251 warning + #ifdef _MSC_VER + + #pragma warning(disable: 4251) + + #endif + + #else // Linux, FreeBSD, Mac OS X + + #if __GNUC__ >= 4 + + // GCC 4 has special keywords for showing/hidding symbols, + // the same keyword is used for both importing and exporting + #define SFML_API_EXPORT __attribute__ ((__visibility__ ("default"))) + #define SFML_API_IMPORT __attribute__ ((__visibility__ ("default"))) + + #else + + // GCC < 4 has no mechanism to explicitely hide symbols, everything's exported + #define SFML_API_EXPORT + #define SFML_API_IMPORT + + #endif + + #endif + +#else + + // Static build doesn't need import/export macros + #define SFML_API_EXPORT + #define SFML_API_IMPORT + +#endif + + +//////////////////////////////////////////////////////////// +// Define portable fixed-size types +//////////////////////////////////////////////////////////// +namespace sf +{ + // All "common" platforms use the same size for char, short and int + // (basically there are 3 types for 3 sizes, so no other match is possible), + // we can use them without doing any kind of check + + // 8 bits integer types + typedef signed char Int8; + typedef unsigned char Uint8; + + // 16 bits integer types + typedef signed short Int16; + typedef unsigned short Uint16; + + // 32 bits integer types + typedef signed int Int32; + typedef unsigned int Uint32; + + // 64 bits integer types + #if defined(_MSC_VER) + typedef signed __int64 Int64; + typedef unsigned __int64 Uint64; + #else + typedef signed long long Int64; + typedef unsigned long long Uint64; + #endif + +} // namespace sf + + +#endif // SFML_CONFIG_HPP diff --git a/include/SFML/Graphics.hpp b/include/SFML/Graphics.hpp index 8a37a6be..ac5231c6 100644 --- a/include/SFML/Graphics.hpp +++ b/include/SFML/Graphics.hpp @@ -1,62 +1,62 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_GRAPHICS_HPP -#define SFML_GRAPHICS_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#endif // SFML_GRAPHICS_HPP - -//////////////////////////////////////////////////////////// -/// \defgroup graphics Graphics module -/// -/// 2D graphics module: sprites, text, shapes, ... -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GRAPHICS_HPP +#define SFML_GRAPHICS_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif // SFML_GRAPHICS_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup graphics Graphics module +/// +/// 2D graphics module: sprites, text, shapes, ... +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/CircleShape.hpp b/include/SFML/Graphics/CircleShape.hpp index 7dd6b7e9..07e35ca1 100644 --- a/include/SFML/Graphics/CircleShape.hpp +++ b/include/SFML/Graphics/CircleShape.hpp @@ -40,7 +40,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_GRAPHICS_API CircleShape : public Shape { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -106,7 +106,7 @@ public : //////////////////////////////////////////////////////////// virtual Vector2f getPoint(unsigned int index) const; -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/include/SFML/Graphics/Color.hpp b/include/SFML/Graphics/Color.hpp index 6ac5bccb..fd3b9c5a 100644 --- a/include/SFML/Graphics/Color.hpp +++ b/include/SFML/Graphics/Color.hpp @@ -1,259 +1,259 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_COLOR_HPP -#define SFML_COLOR_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Utility class for manpulating RGBA colors -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API Color -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Constructs an opaque black color. It is equivalent to - /// sf::Color(0, 0, 0, 255). - /// - //////////////////////////////////////////////////////////// - Color(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the color from its 4 RGBA components - /// - /// \param red Red component (in the range [0, 255]) - /// \param green Green component (in the range [0, 255]) - /// \param blue Blue component (in the range [0, 255]) - /// \param alpha Alpha (opacity) component (in the range [0, 255]) - /// - //////////////////////////////////////////////////////////// - Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha = 255); - - //////////////////////////////////////////////////////////// - // Static member data - //////////////////////////////////////////////////////////// - static const Color Black; ///< Black predefined color - static const Color White; ///< White predefined color - static const Color Red; ///< Red predefined color - static const Color Green; ///< Green predefined color - static const Color Blue; ///< Blue predefined color - static const Color Yellow; ///< Yellow predefined color - static const Color Magenta; ///< Magenta predefined color - static const Color Cyan; ///< Cyan predefined color - static const Color Transparent; ///< Transparent (black) predefined color - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Uint8 r; ///< Red component - Uint8 g; ///< Green component - Uint8 b; ///< Blue component - Uint8 a; ///< Alpha (opacity) component -}; - -//////////////////////////////////////////////////////////// -/// \relates Color -/// \brief Overload of the == operator -/// -/// This operator compares two colors and check if they are equal. -/// -/// \param left Left operand -/// \param right Right operand -/// -/// \return True if colors are equal, false if they are different -/// -//////////////////////////////////////////////////////////// -SFML_GRAPHICS_API bool operator ==(const Color& left, const Color& right); - -//////////////////////////////////////////////////////////// -/// \relates Color -/// \brief Overload of the != operator -/// -/// This operator compares two colors and check if they are different. -/// -/// \param left Left operand -/// \param right Right operand -/// -/// \return True if colors are different, false if they are equal -/// -//////////////////////////////////////////////////////////// -SFML_GRAPHICS_API bool operator !=(const Color& left, const Color& right); - -//////////////////////////////////////////////////////////// -/// \relates Color -/// \brief Overload of the binary + operator -/// -/// This operator returns the component-wise sum of two colors. -/// Components that exceed 255 are clamped to 255. -/// -/// \param left Left operand -/// \param right Right operand -/// -/// \return Result of \a left + \a right -/// -//////////////////////////////////////////////////////////// -SFML_GRAPHICS_API Color operator +(const Color& left, const Color& right); - -//////////////////////////////////////////////////////////// -/// \relates Color -/// \brief Overload of the binary - operator -/// -/// This operator returns the component-wise subtraction of two colors. -/// Components below 0 are clamped to 0. -/// -/// \param left Left operand -/// \param right Right operand -/// -/// \return Result of \a left - \a right -/// -//////////////////////////////////////////////////////////// -SFML_GRAPHICS_API Color operator -(const Color& left, const Color& right); - -//////////////////////////////////////////////////////////// -/// \relates Color -/// \brief Overload of the binary * operator -/// -/// This operator returns the component-wise multiplication -/// (also called "modulation") of two colors. -/// Components are then divided by 255 so that the result is -/// still in the range [0, 255]. -/// -/// \param left Left operand -/// \param right Right operand -/// -/// \return Result of \a left * \a right -/// -//////////////////////////////////////////////////////////// -SFML_GRAPHICS_API Color operator *(const Color& left, const Color& right); - -//////////////////////////////////////////////////////////// -/// \relates Color -/// \brief Overload of the binary += operator -/// -/// This operator computes the component-wise sum of two colors, -/// and assigns the result to the left operand. -/// Components that exceed 255 are clamped to 255. -/// -/// \param left Left operand -/// \param right Right operand -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -SFML_GRAPHICS_API Color& operator +=(Color& left, const Color& right); - -//////////////////////////////////////////////////////////// -/// \relates Color -/// \brief Overload of the binary -= operator -/// -/// This operator computes the component-wise subtraction of two colors, -/// and assigns the result to the left operand. -/// Components below 0 are clamped to 0. -/// -/// \param left Left operand -/// \param right Right operand -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -SFML_GRAPHICS_API Color& operator -=(Color& left, const Color& right); - -//////////////////////////////////////////////////////////// -/// \relates Color -/// \brief Overload of the binary *= operator -/// -/// This operator returns the component-wise multiplication -/// (also called "modulation") of two colors, and assigns -/// the result to the left operand. -/// Components are then divided by 255 so that the result is -/// still in the range [0, 255]. -/// -/// \param left Left operand -/// \param right Right operand -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -SFML_GRAPHICS_API Color& operator *=(Color& left, const Color& right); - -} // namespace sf - - -#endif // SFML_COLOR_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Color -/// \ingroup graphics -/// -/// sf::Color is a simple color class composed of 4 components: -/// \li Red -/// \li Green -/// \li Blue -/// \li Alpha (opacity) -/// -/// Each component is a public member, an unsigned integer in -/// the range [0, 255]. Thus, colors can be constructed and -/// manipulated very easily: -/// -/// \code -/// sf::Color color(255, 0, 0); // red -/// color.r = 0; // make it black -/// color.b = 128; // make it dark blue -/// \endcode -/// -/// The fourth component of colors, named "alpha", represents -/// the opacity of the color. A color with an alpha value of -/// 255 will be fully opaque, while an alpha value of 0 will -/// make a color fully transparent, whatever the value of the -/// other components is. -/// -/// The most common colors are already defined as static variables: -/// \code -/// sf::Color black = sf::Color::Black; -/// sf::Color white = sf::Color::White; -/// sf::Color red = sf::Color::Red; -/// sf::Color green = sf::Color::Green; -/// sf::Color blue = sf::Color::Blue; -/// sf::Color yellow = sf::Color::Yellow; -/// sf::Color magenta = sf::Color::Magenta; -/// sf::Color cyan = sf::Color::Cyan; -/// sf::Color transparent = sf::Color::Transparent; -/// \endcode -/// -/// Colors can also be added and modulated (multiplied) using the -/// overloaded operators + and *. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_COLOR_HPP +#define SFML_COLOR_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility class for manpulating RGBA colors +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Color +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Constructs an opaque black color. It is equivalent to + /// sf::Color(0, 0, 0, 255). + /// + //////////////////////////////////////////////////////////// + Color(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the color from its 4 RGBA components + /// + /// \param red Red component (in the range [0, 255]) + /// \param green Green component (in the range [0, 255]) + /// \param blue Blue component (in the range [0, 255]) + /// \param alpha Alpha (opacity) component (in the range [0, 255]) + /// + //////////////////////////////////////////////////////////// + Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha = 255); + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const Color Black; ///< Black predefined color + static const Color White; ///< White predefined color + static const Color Red; ///< Red predefined color + static const Color Green; ///< Green predefined color + static const Color Blue; ///< Blue predefined color + static const Color Yellow; ///< Yellow predefined color + static const Color Magenta; ///< Magenta predefined color + static const Color Cyan; ///< Cyan predefined color + static const Color Transparent; ///< Transparent (black) predefined color + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Uint8 r; ///< Red component + Uint8 g; ///< Green component + Uint8 b; ///< Blue component + Uint8 a; ///< Alpha (opacity) component +}; + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the == operator +/// +/// This operator compares two colors and check if they are equal. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return True if colors are equal, false if they are different +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API bool operator ==(const Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the != operator +/// +/// This operator compares two colors and check if they are different. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return True if colors are different, false if they are equal +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API bool operator !=(const Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the binary + operator +/// +/// This operator returns the component-wise sum of two colors. +/// Components that exceed 255 are clamped to 255. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return Result of \a left + \a right +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Color operator +(const Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the binary - operator +/// +/// This operator returns the component-wise subtraction of two colors. +/// Components below 0 are clamped to 0. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return Result of \a left - \a right +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Color operator -(const Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the binary * operator +/// +/// This operator returns the component-wise multiplication +/// (also called "modulation") of two colors. +/// Components are then divided by 255 so that the result is +/// still in the range [0, 255]. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return Result of \a left * \a right +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Color operator *(const Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the binary += operator +/// +/// This operator computes the component-wise sum of two colors, +/// and assigns the result to the left operand. +/// Components that exceed 255 are clamped to 255. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Color& operator +=(Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the binary -= operator +/// +/// This operator computes the component-wise subtraction of two colors, +/// and assigns the result to the left operand. +/// Components below 0 are clamped to 0. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Color& operator -=(Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the binary *= operator +/// +/// This operator returns the component-wise multiplication +/// (also called "modulation") of two colors, and assigns +/// the result to the left operand. +/// Components are then divided by 255 so that the result is +/// still in the range [0, 255]. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Color& operator *=(Color& left, const Color& right); + +} // namespace sf + + +#endif // SFML_COLOR_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Color +/// \ingroup graphics +/// +/// sf::Color is a simple color class composed of 4 components: +/// \li Red +/// \li Green +/// \li Blue +/// \li Alpha (opacity) +/// +/// Each component is a public member, an unsigned integer in +/// the range [0, 255]. Thus, colors can be constructed and +/// manipulated very easily: +/// +/// \code +/// sf::Color color(255, 0, 0); // red +/// color.r = 0; // make it black +/// color.b = 128; // make it dark blue +/// \endcode +/// +/// The fourth component of colors, named "alpha", represents +/// the opacity of the color. A color with an alpha value of +/// 255 will be fully opaque, while an alpha value of 0 will +/// make a color fully transparent, whatever the value of the +/// other components is. +/// +/// The most common colors are already defined as static variables: +/// \code +/// sf::Color black = sf::Color::Black; +/// sf::Color white = sf::Color::White; +/// sf::Color red = sf::Color::Red; +/// sf::Color green = sf::Color::Green; +/// sf::Color blue = sf::Color::Blue; +/// sf::Color yellow = sf::Color::Yellow; +/// sf::Color magenta = sf::Color::Magenta; +/// sf::Color cyan = sf::Color::Cyan; +/// sf::Color transparent = sf::Color::Transparent; +/// \endcode +/// +/// Colors can also be added and modulated (multiplied) using the +/// overloaded operators + and *. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/ConvexShape.hpp b/include/SFML/Graphics/ConvexShape.hpp index 6ae756f6..080ca04d 100644 --- a/include/SFML/Graphics/ConvexShape.hpp +++ b/include/SFML/Graphics/ConvexShape.hpp @@ -41,7 +41,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_GRAPHICS_API ConvexShape : public Shape { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -107,7 +107,7 @@ public : //////////////////////////////////////////////////////////// virtual Vector2f getPoint(unsigned int index) const; -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/include/SFML/Graphics/Drawable.hpp b/include/SFML/Graphics/Drawable.hpp index 01758b63..8e30a6d6 100644 --- a/include/SFML/Graphics/Drawable.hpp +++ b/include/SFML/Graphics/Drawable.hpp @@ -1,126 +1,126 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_DRAWABLE_HPP -#define SFML_DRAWABLE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -class RenderTarget; - -//////////////////////////////////////////////////////////// -/// \brief Abstract base class for objects that can be drawn -/// to a render target -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API Drawable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Virtual destructor - /// - //////////////////////////////////////////////////////////// - virtual ~Drawable() {} - -protected : - - friend class RenderTarget; - - //////////////////////////////////////////////////////////// - /// \brief Draw the object to a render target - /// - /// This is a pure virtual function that has to be implemented - /// by the derived class to define how the drawable should be - /// drawn. - /// - /// \param target Render target to draw to - /// \param states Current render states - /// - //////////////////////////////////////////////////////////// - virtual void draw(RenderTarget& target, RenderStates states) const = 0; -}; - -} // namespace sf - - -#endif // SFML_DRAWABLE_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Drawable -/// \ingroup graphics -/// -/// sf::Drawable is a very simple base class that allows objects -/// of derived classes to be drawn to a sf::RenderTarget. -/// -/// All you have to do in your derived class is to override the -/// draw virtual function. -/// -/// Note that inheriting from sf::Drawable is not mandatory, -/// but it allows this nice syntax "window.draw(object)" rather -/// than "object.draw(window)", which is more consistent with other -/// SFML classes. -/// -/// Example: -/// \code -/// class MyDrawable : public sf::Drawable -/// { -/// public : -/// -/// ... -/// -/// private : -/// -/// virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const -/// { -/// // You can draw other high-level objects -/// target.draw(m_sprite, states); -/// -/// // ... or use the low-level API -/// states.texture = &m_texture; -/// target.draw(m_vertices, states); -/// -/// // ... or draw with OpenGL directly -/// glBegin(GL_QUADS); -/// ... -/// glEnd(); -/// } -/// -/// sf::Sprite m_sprite; -/// sf::Texture m_texture; -/// sf::VertexArray m_vertices; -/// }; -/// \endcode -/// -/// \see sf::RenderTarget -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_DRAWABLE_HPP +#define SFML_DRAWABLE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +class RenderTarget; + +//////////////////////////////////////////////////////////// +/// \brief Abstract base class for objects that can be drawn +/// to a render target +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Drawable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Drawable() {} + +protected: + + friend class RenderTarget; + + //////////////////////////////////////////////////////////// + /// \brief Draw the object to a render target + /// + /// This is a pure virtual function that has to be implemented + /// by the derived class to define how the drawable should be + /// drawn. + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void draw(RenderTarget& target, RenderStates states) const = 0; +}; + +} // namespace sf + + +#endif // SFML_DRAWABLE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Drawable +/// \ingroup graphics +/// +/// sf::Drawable is a very simple base class that allows objects +/// of derived classes to be drawn to a sf::RenderTarget. +/// +/// All you have to do in your derived class is to override the +/// draw virtual function. +/// +/// Note that inheriting from sf::Drawable is not mandatory, +/// but it allows this nice syntax "window.draw(object)" rather +/// than "object.draw(window)", which is more consistent with other +/// SFML classes. +/// +/// Example: +/// \code +/// class MyDrawable : public sf::Drawable +/// { +/// public: +/// +/// ... +/// +/// private: +/// +/// virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const +/// { +/// // You can draw other high-level objects +/// target.draw(m_sprite, states); +/// +/// // ... or use the low-level API +/// states.texture = &m_texture; +/// target.draw(m_vertices, states); +/// +/// // ... or draw with OpenGL directly +/// glBegin(GL_QUADS); +/// ... +/// glEnd(); +/// } +/// +/// sf::Sprite m_sprite; +/// sf::Texture m_texture; +/// sf::VertexArray m_vertices; +/// }; +/// \endcode +/// +/// \see sf::RenderTarget +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Font.hpp b/include/SFML/Graphics/Font.hpp index 64efaa55..8b360c92 100644 --- a/include/SFML/Graphics/Font.hpp +++ b/include/SFML/Graphics/Font.hpp @@ -1,423 +1,423 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_FONT_HPP -#define SFML_FONT_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -class InputStream; - -//////////////////////////////////////////////////////////// -/// \brief Class for loading and manipulating character fonts -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API Font -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Holds various information about a font - /// - //////////////////////////////////////////////////////////// - struct Info - { - std::string family; ///< The font family - }; - -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor defines an empty font - /// - //////////////////////////////////////////////////////////// - Font(); - - //////////////////////////////////////////////////////////// - /// \brief Copy constructor - /// - /// \param copy Instance to copy - /// - //////////////////////////////////////////////////////////// - Font(const Font& copy); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - /// Cleans up all the internal resources used by the font - /// - //////////////////////////////////////////////////////////// - ~Font(); - - //////////////////////////////////////////////////////////// - /// \brief Load the font from a file - /// - /// The supported font formats are: TrueType, Type 1, CFF, - /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. - /// Note that this function know nothing about the standard - /// fonts installed on the user's system, thus you can't - /// load them directly. - /// - /// \param filename Path of the font file to load - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromMemory, loadFromStream - /// - //////////////////////////////////////////////////////////// - bool loadFromFile(const std::string& filename); - - //////////////////////////////////////////////////////////// - /// \brief Load the font from a file in memory - /// - /// The supported font formats are: TrueType, Type 1, CFF, - /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. - /// Warning: SFML cannot preload all the font data in this - /// function, so the buffer pointed by \a data has to remain - /// valid as long as the font is used. - /// - /// \param data Pointer to the file data in memory - /// \param sizeInBytes Size of the data to load, in bytes - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromFile, loadFromStream - /// - //////////////////////////////////////////////////////////// - bool loadFromMemory(const void* data, std::size_t sizeInBytes); - - //////////////////////////////////////////////////////////// - /// \brief Load the font from a custom stream - /// - /// The supported font formats are: TrueType, Type 1, CFF, - /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. - /// Warning: SFML cannot preload all the font data in this - /// function, so the contents of \a stream have to remain - /// valid as long as the font is used. - /// - /// \param stream Source stream to read from - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromFile, loadFromMemory - /// - //////////////////////////////////////////////////////////// - bool loadFromStream(InputStream& stream); - - //////////////////////////////////////////////////////////// - /// \brief Get the font information - /// - /// \return A structure that holds the font information - /// - //////////////////////////////////////////////////////////// - const Info& getInfo() const; - - //////////////////////////////////////////////////////////// - /// \brief Retrieve a glyph of the font - /// - /// If the font is a bitmap font, not all character sizes - /// might be available. If the glyph is not available at the - /// requested size, an empty glyph is returned. - /// - /// \param codePoint Unicode code point of the character to get - /// \param characterSize Reference character size - /// \param bold Retrieve the bold version or the regular one? - /// - /// \return The glyph corresponding to \a codePoint and \a characterSize - /// - //////////////////////////////////////////////////////////// - const Glyph& getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const; - - //////////////////////////////////////////////////////////// - /// \brief Get the kerning offset of two glyphs - /// - /// The kerning is an extra offset (negative) to apply between two - /// glyphs when rendering them, to make the pair look more "natural". - /// For example, the pair "AV" have a special kerning to make them - /// closer than other characters. Most of the glyphs pairs have a - /// kerning offset of zero, though. - /// - /// \param first Unicode code point of the first character - /// \param second Unicode code point of the second character - /// \param characterSize Reference character size - /// - /// \return Kerning value for \a first and \a second, in pixels - /// - //////////////////////////////////////////////////////////// - float getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const; - - //////////////////////////////////////////////////////////// - /// \brief Get the line spacing - /// - /// Line spacing is the vertical offset to apply between two - /// consecutive lines of text. - /// - /// \param characterSize Reference character size - /// - /// \return Line spacing, in pixels - /// - //////////////////////////////////////////////////////////// - float getLineSpacing(unsigned int characterSize) const; - - //////////////////////////////////////////////////////////// - /// \brief Get the position of the underline - /// - /// Underline position is the vertical offset to apply between the - /// baseline and the underline. - /// - /// \param characterSize Reference character size - /// - /// \return Underline position, in pixels - /// - /// \see getUnderlineThickness - /// - //////////////////////////////////////////////////////////// - float getUnderlinePosition(unsigned int characterSize) const; - - //////////////////////////////////////////////////////////// - /// \brief Get the thickness of the underline - /// - /// Underline thickness is the vertical size of the underline. - /// - /// \param characterSize Reference character size - /// - /// \return Underline thickness, in pixels - /// - /// \see getUnderlinePosition - /// - //////////////////////////////////////////////////////////// - float getUnderlineThickness(unsigned int characterSize) const; - - //////////////////////////////////////////////////////////// - /// \brief Retrieve the texture containing the loaded glyphs of a certain size - /// - /// The contents of the returned texture changes as more glyphs - /// are requested, thus it is not very relevant. It is mainly - /// used internally by sf::Text. - /// - /// \param characterSize Reference character size - /// - /// \return Texture containing the glyphs of the requested size - /// - //////////////////////////////////////////////////////////// - const Texture& getTexture(unsigned int characterSize) const; - - //////////////////////////////////////////////////////////// - /// \brief Overload of assignment operator - /// - /// \param right Instance to assign - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - Font& operator =(const Font& right); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Structure defining a row of glyphs - /// - //////////////////////////////////////////////////////////// - struct Row - { - Row(unsigned int rowTop, unsigned int rowHeight) : width(0), top(rowTop), height(rowHeight) {} - - unsigned int width; ///< Current width of the row - unsigned int top; ///< Y position of the row into the texture - unsigned int height; ///< Height of the row - }; - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef std::map GlyphTable; ///< Table mapping a codepoint to its glyph - - //////////////////////////////////////////////////////////// - /// \brief Structure defining a page of glyphs - /// - //////////////////////////////////////////////////////////// - struct Page - { - Page(); - - GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph - sf::Texture texture; ///< Texture containing the pixels of the glyphs - unsigned int nextRow; ///< Y position of the next new row in the texture - std::vector rows; ///< List containing the position of all the existing rows - }; - - //////////////////////////////////////////////////////////// - /// \brief Free all the internal resources - /// - //////////////////////////////////////////////////////////// - void cleanup(); - - //////////////////////////////////////////////////////////// - /// \brief Load a new glyph and store it in the cache - /// - /// \param codePoint Unicode code point of the character to load - /// \param characterSize Reference character size - /// \param bold Retrieve the bold version or the regular one? - /// - /// \return The glyph corresponding to \a codePoint and \a characterSize - /// - //////////////////////////////////////////////////////////// - Glyph loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const; - - //////////////////////////////////////////////////////////// - /// \brief Find a suitable rectangle within the texture for a glyph - /// - /// \param page Page of glyphs to search in - /// \param width Width of the rectangle - /// \param height Height of the rectangle - /// - /// \return Found rectangle within the texture - /// - //////////////////////////////////////////////////////////// - IntRect findGlyphRect(Page& page, unsigned int width, unsigned int height) const; - - //////////////////////////////////////////////////////////// - /// \brief Make sure that the given size is the current one - /// - /// \param characterSize Reference character size - /// - /// \return True on success, false if any error happened - /// - //////////////////////////////////////////////////////////// - bool setCurrentSize(unsigned int characterSize) const; - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef std::map PageTable; ///< Table mapping a character size to its page (texture) - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - void* m_library; ///< Pointer to the internal library interface (it is typeless to avoid exposing implementation details) - void* m_face; ///< Pointer to the internal font face (it is typeless to avoid exposing implementation details) - void* m_streamRec; ///< Pointer to the stream rec instance (it is typeless to avoid exposing implementation details) - int* m_refCount; ///< Reference counter used by implicit sharing - Info m_info; ///< Information about the font - mutable PageTable m_pages; ///< Table containing the glyphs pages by character size - mutable std::vector m_pixelBuffer; ///< Pixel buffer holding a glyph's pixels before being written to the texture - #ifdef SFML_SYSTEM_ANDROID - void* m_stream; ///< Asset file streamer (if loaded from file) - #endif -}; - -} // namespace sf - - -#endif // SFML_FONT_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Font -/// \ingroup graphics -/// -/// Fonts can be loaded from a file, from memory or from a custom -/// stream, and supports the most common types of fonts. See -/// the loadFromFile function for the complete list of supported formats. -/// -/// Once it is loaded, a sf::Font instance provides three -/// types of information about the font: -/// \li Global metrics, such as the line spacing -/// \li Per-glyph metrics, such as bounding box or kerning -/// \li Pixel representation of glyphs -/// -/// Fonts alone are not very useful: they hold the font data -/// but cannot make anything useful of it. To do so you need to -/// use the sf::Text class, which is able to properly output text -/// with several options such as character size, style, color, -/// position, rotation, etc. -/// This separation allows more flexibility and better performances: -/// indeed a sf::Font is a heavy resource, and any operation on it -/// is slow (often too slow for real-time applications). On the other -/// side, a sf::Text is a lightweight object which can combine the -/// glyphs data and metrics of a sf::Font to display any text on a -/// render target. -/// Note that it is also possible to bind several sf::Text instances -/// to the same sf::Font. -/// -/// It is important to note that the sf::Text instance doesn't -/// copy the font that it uses, it only keeps a reference to it. -/// Thus, a sf::Font must not be destructed while it is -/// used by a sf::Text (i.e. never write a function that -/// uses a local sf::Font instance for creating a text). -/// -/// Usage example: -/// \code -/// // Declare a new font -/// sf::Font font; -/// -/// // Load it from a file -/// if (!font.loadFromFile("arial.ttf")) -/// { -/// // error... -/// } -/// -/// // Create a text which uses our font -/// sf::Text text1; -/// text1.setFont(font); -/// text1.setCharacterSize(30); -/// text1.setStyle(sf::Text::Regular); -/// -/// // Create another text using the same font, but with different parameters -/// sf::Text text2; -/// text2.setFont(font); -/// text2.setCharacterSize(50); -/// text1.setStyle(sf::Text::Italic); -/// \endcode -/// -/// Apart from loading font files, and passing them to instances -/// of sf::Text, you should normally not have to deal directly -/// with this class. However, it may be useful to access the -/// font metrics or rasterized glyphs for advanced usage. -/// -/// Note that if the font is a bitmap font, it is not scalable, -/// thus not all requested sizes will be available to use. This -/// needs to be taken into consideration when using sf::Text. -/// If you need to display text of a certain size, make sure the -/// corresponding bitmap font that supports that size is used. -/// -/// \see sf::Text -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_FONT_HPP +#define SFML_FONT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Class for loading and manipulating character fonts +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Font +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Holds various information about a font + /// + //////////////////////////////////////////////////////////// + struct Info + { + std::string family; ///< The font family + }; + +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor defines an empty font + /// + //////////////////////////////////////////////////////////// + Font(); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + Font(const Font& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// Cleans up all the internal resources used by the font + /// + //////////////////////////////////////////////////////////// + ~Font(); + + //////////////////////////////////////////////////////////// + /// \brief Load the font from a file + /// + /// The supported font formats are: TrueType, Type 1, CFF, + /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. + /// Note that this function know nothing about the standard + /// fonts installed on the user's system, thus you can't + /// load them directly. + /// + /// \param filename Path of the font file to load + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& filename); + + //////////////////////////////////////////////////////////// + /// \brief Load the font from a file in memory + /// + /// The supported font formats are: TrueType, Type 1, CFF, + /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. + /// Warning: SFML cannot preload all the font data in this + /// function, so the buffer pointed by \a data has to remain + /// valid as long as the font is used. + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Load the font from a custom stream + /// + /// The supported font formats are: TrueType, Type 1, CFF, + /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. + /// Warning: SFML cannot preload all the font data in this + /// function, so the contents of \a stream have to remain + /// valid as long as the font is used. + /// + /// \param stream Source stream to read from + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Get the font information + /// + /// \return A structure that holds the font information + /// + //////////////////////////////////////////////////////////// + const Info& getInfo() const; + + //////////////////////////////////////////////////////////// + /// \brief Retrieve a glyph of the font + /// + /// If the font is a bitmap font, not all character sizes + /// might be available. If the glyph is not available at the + /// requested size, an empty glyph is returned. + /// + /// \param codePoint Unicode code point of the character to get + /// \param characterSize Reference character size + /// \param bold Retrieve the bold version or the regular one? + /// + /// \return The glyph corresponding to \a codePoint and \a characterSize + /// + //////////////////////////////////////////////////////////// + const Glyph& getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the kerning offset of two glyphs + /// + /// The kerning is an extra offset (negative) to apply between two + /// glyphs when rendering them, to make the pair look more "natural". + /// For example, the pair "AV" have a special kerning to make them + /// closer than other characters. Most of the glyphs pairs have a + /// kerning offset of zero, though. + /// + /// \param first Unicode code point of the first character + /// \param second Unicode code point of the second character + /// \param characterSize Reference character size + /// + /// \return Kerning value for \a first and \a second, in pixels + /// + //////////////////////////////////////////////////////////// + float getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the line spacing + /// + /// Line spacing is the vertical offset to apply between two + /// consecutive lines of text. + /// + /// \param characterSize Reference character size + /// + /// \return Line spacing, in pixels + /// + //////////////////////////////////////////////////////////// + float getLineSpacing(unsigned int characterSize) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the position of the underline + /// + /// Underline position is the vertical offset to apply between the + /// baseline and the underline. + /// + /// \param characterSize Reference character size + /// + /// \return Underline position, in pixels + /// + /// \see getUnderlineThickness + /// + //////////////////////////////////////////////////////////// + float getUnderlinePosition(unsigned int characterSize) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the thickness of the underline + /// + /// Underline thickness is the vertical size of the underline. + /// + /// \param characterSize Reference character size + /// + /// \return Underline thickness, in pixels + /// + /// \see getUnderlinePosition + /// + //////////////////////////////////////////////////////////// + float getUnderlineThickness(unsigned int characterSize) const; + + //////////////////////////////////////////////////////////// + /// \brief Retrieve the texture containing the loaded glyphs of a certain size + /// + /// The contents of the returned texture changes as more glyphs + /// are requested, thus it is not very relevant. It is mainly + /// used internally by sf::Text. + /// + /// \param characterSize Reference character size + /// + /// \return Texture containing the glyphs of the requested size + /// + //////////////////////////////////////////////////////////// + const Texture& getTexture(unsigned int characterSize) const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + Font& operator =(const Font& right); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Structure defining a row of glyphs + /// + //////////////////////////////////////////////////////////// + struct Row + { + Row(unsigned int rowTop, unsigned int rowHeight) : width(0), top(rowTop), height(rowHeight) {} + + unsigned int width; ///< Current width of the row + unsigned int top; ///< Y position of the row into the texture + unsigned int height; ///< Height of the row + }; + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::map GlyphTable; ///< Table mapping a codepoint to its glyph + + //////////////////////////////////////////////////////////// + /// \brief Structure defining a page of glyphs + /// + //////////////////////////////////////////////////////////// + struct Page + { + Page(); + + GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph + sf::Texture texture; ///< Texture containing the pixels of the glyphs + unsigned int nextRow; ///< Y position of the next new row in the texture + std::vector rows; ///< List containing the position of all the existing rows + }; + + //////////////////////////////////////////////////////////// + /// \brief Free all the internal resources + /// + //////////////////////////////////////////////////////////// + void cleanup(); + + //////////////////////////////////////////////////////////// + /// \brief Load a new glyph and store it in the cache + /// + /// \param codePoint Unicode code point of the character to load + /// \param characterSize Reference character size + /// \param bold Retrieve the bold version or the regular one? + /// + /// \return The glyph corresponding to \a codePoint and \a characterSize + /// + //////////////////////////////////////////////////////////// + Glyph loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const; + + //////////////////////////////////////////////////////////// + /// \brief Find a suitable rectangle within the texture for a glyph + /// + /// \param page Page of glyphs to search in + /// \param width Width of the rectangle + /// \param height Height of the rectangle + /// + /// \return Found rectangle within the texture + /// + //////////////////////////////////////////////////////////// + IntRect findGlyphRect(Page& page, unsigned int width, unsigned int height) const; + + //////////////////////////////////////////////////////////// + /// \brief Make sure that the given size is the current one + /// + /// \param characterSize Reference character size + /// + /// \return True on success, false if any error happened + /// + //////////////////////////////////////////////////////////// + bool setCurrentSize(unsigned int characterSize) const; + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::map PageTable; ///< Table mapping a character size to its page (texture) + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + void* m_library; ///< Pointer to the internal library interface (it is typeless to avoid exposing implementation details) + void* m_face; ///< Pointer to the internal font face (it is typeless to avoid exposing implementation details) + void* m_streamRec; ///< Pointer to the stream rec instance (it is typeless to avoid exposing implementation details) + int* m_refCount; ///< Reference counter used by implicit sharing + Info m_info; ///< Information about the font + mutable PageTable m_pages; ///< Table containing the glyphs pages by character size + mutable std::vector m_pixelBuffer; ///< Pixel buffer holding a glyph's pixels before being written to the texture + #ifdef SFML_SYSTEM_ANDROID + void* m_stream; ///< Asset file streamer (if loaded from file) + #endif +}; + +} // namespace sf + + +#endif // SFML_FONT_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Font +/// \ingroup graphics +/// +/// Fonts can be loaded from a file, from memory or from a custom +/// stream, and supports the most common types of fonts. See +/// the loadFromFile function for the complete list of supported formats. +/// +/// Once it is loaded, a sf::Font instance provides three +/// types of information about the font: +/// \li Global metrics, such as the line spacing +/// \li Per-glyph metrics, such as bounding box or kerning +/// \li Pixel representation of glyphs +/// +/// Fonts alone are not very useful: they hold the font data +/// but cannot make anything useful of it. To do so you need to +/// use the sf::Text class, which is able to properly output text +/// with several options such as character size, style, color, +/// position, rotation, etc. +/// This separation allows more flexibility and better performances: +/// indeed a sf::Font is a heavy resource, and any operation on it +/// is slow (often too slow for real-time applications). On the other +/// side, a sf::Text is a lightweight object which can combine the +/// glyphs data and metrics of a sf::Font to display any text on a +/// render target. +/// Note that it is also possible to bind several sf::Text instances +/// to the same sf::Font. +/// +/// It is important to note that the sf::Text instance doesn't +/// copy the font that it uses, it only keeps a reference to it. +/// Thus, a sf::Font must not be destructed while it is +/// used by a sf::Text (i.e. never write a function that +/// uses a local sf::Font instance for creating a text). +/// +/// Usage example: +/// \code +/// // Declare a new font +/// sf::Font font; +/// +/// // Load it from a file +/// if (!font.loadFromFile("arial.ttf")) +/// { +/// // error... +/// } +/// +/// // Create a text which uses our font +/// sf::Text text1; +/// text1.setFont(font); +/// text1.setCharacterSize(30); +/// text1.setStyle(sf::Text::Regular); +/// +/// // Create another text using the same font, but with different parameters +/// sf::Text text2; +/// text2.setFont(font); +/// text2.setCharacterSize(50); +/// text1.setStyle(sf::Text::Italic); +/// \endcode +/// +/// Apart from loading font files, and passing them to instances +/// of sf::Text, you should normally not have to deal directly +/// with this class. However, it may be useful to access the +/// font metrics or rasterized glyphs for advanced usage. +/// +/// Note that if the font is a bitmap font, it is not scalable, +/// thus not all requested sizes will be available to use. This +/// needs to be taken into consideration when using sf::Text. +/// If you need to display text of a certain size, make sure the +/// corresponding bitmap font that supports that size is used. +/// +/// \see sf::Text +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Glyph.hpp b/include/SFML/Graphics/Glyph.hpp index f35f59e6..cdd68354 100644 --- a/include/SFML/Graphics/Glyph.hpp +++ b/include/SFML/Graphics/Glyph.hpp @@ -1,79 +1,79 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_GLYPH_HPP -#define SFML_GLYPH_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Structure describing a glyph -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API Glyph -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - Glyph() : advance(0) {} - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - float advance; ///< Offset to move horizontically to the next character - FloatRect bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline - IntRect textureRect; ///< Texture coordinates of the glyph inside the font's texture -}; - -} // namespace sf - - -#endif // SFML_GLYPH_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Glyph -/// \ingroup graphics -/// -/// A glyph is the visual representation of a character. -/// -/// The sf::Glyph structure provides the information needed -/// to handle the glyph: -/// \li its coordinates in the font's texture -/// \li its bounding rectangle -/// \li the offset to apply to get the starting position of the next glyph -/// -/// \see sf::Font -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GLYPH_HPP +#define SFML_GLYPH_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Structure describing a glyph +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Glyph +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Glyph() : advance(0) {} + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + float advance; ///< Offset to move horizontically to the next character + FloatRect bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline + IntRect textureRect; ///< Texture coordinates of the glyph inside the font's texture +}; + +} // namespace sf + + +#endif // SFML_GLYPH_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Glyph +/// \ingroup graphics +/// +/// A glyph is the visual representation of a character. +/// +/// The sf::Glyph structure provides the information needed +/// to handle the glyph: +/// \li its coordinates in the font's texture +/// \li its bounding rectangle +/// \li the offset to apply to get the starting position of the next glyph +/// +/// \see sf::Font +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Image.hpp b/include/SFML/Graphics/Image.hpp index b09a122f..9e23ad26 100644 --- a/include/SFML/Graphics/Image.hpp +++ b/include/SFML/Graphics/Image.hpp @@ -1,327 +1,327 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_IMAGE_HPP -#define SFML_IMAGE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -class InputStream; - -//////////////////////////////////////////////////////////// -/// \brief Class for loading, manipulating and saving images -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API Image -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Creates an empty image. - /// - //////////////////////////////////////////////////////////// - Image(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~Image(); - - //////////////////////////////////////////////////////////// - /// \brief Create the image and fill it with a unique color - /// - /// \param width Width of the image - /// \param height Height of the image - /// \param color Fill color - /// - //////////////////////////////////////////////////////////// - void create(unsigned int width, unsigned int height, const Color& color = Color(0, 0, 0)); - - //////////////////////////////////////////////////////////// - /// \brief Create the image from an array of pixels - /// - /// The \a pixel array is assumed to contain 32-bits RGBA pixels, - /// and have the given \a width and \a height. If not, this is - /// an undefined behaviour. - /// If \a pixels is null, an empty image is created. - /// - /// \param width Width of the image - /// \param height Height of the image - /// \param pixels Array of pixels to copy to the image - /// - //////////////////////////////////////////////////////////// - void create(unsigned int width, unsigned int height, const Uint8* pixels); - - //////////////////////////////////////////////////////////// - /// \brief Load the image from a file on disk - /// - /// The supported image formats are bmp, png, tga, jpg, gif, - /// psd, hdr and pic. Some format options are not supported, - /// like progressive jpeg. - /// If this function fails, the image is left unchanged. - /// - /// \param filename Path of the image file to load - /// - /// \return True if loading was successful - /// - /// \see loadFromMemory, loadFromStream, saveToFile - /// - //////////////////////////////////////////////////////////// - bool loadFromFile(const std::string& filename); - - //////////////////////////////////////////////////////////// - /// \brief Load the image from a file in memory - /// - /// The supported image formats are bmp, png, tga, jpg, gif, - /// psd, hdr and pic. Some format options are not supported, - /// like progressive jpeg. - /// If this function fails, the image is left unchanged. - /// - /// \param data Pointer to the file data in memory - /// \param size Size of the data to load, in bytes - /// - /// \return True if loading was successful - /// - /// \see loadFromFile, loadFromStream - /// - //////////////////////////////////////////////////////////// - bool loadFromMemory(const void* data, std::size_t size); - - //////////////////////////////////////////////////////////// - /// \brief Load the image from a custom stream - /// - /// The supported image formats are bmp, png, tga, jpg, gif, - /// psd, hdr and pic. Some format options are not supported, - /// like progressive jpeg. - /// If this function fails, the image is left unchanged. - /// - /// \param stream Source stream to read from - /// - /// \return True if loading was successful - /// - /// \see loadFromFile, loadFromMemory - /// - //////////////////////////////////////////////////////////// - bool loadFromStream(InputStream& stream); - - //////////////////////////////////////////////////////////// - /// \brief Save the image to a file on disk - /// - /// The format of the image is automatically deduced from - /// the extension. The supported image formats are bmp, png, - /// tga and jpg. The destination file is overwritten - /// if it already exists. This function fails if the image is empty. - /// - /// \param filename Path of the file to save - /// - /// \return True if saving was successful - /// - /// \see create, loadFromFile, loadFromMemory - /// - //////////////////////////////////////////////////////////// - bool saveToFile(const std::string& filename) const; - - //////////////////////////////////////////////////////////// - /// \brief Return the size (width and height) of the image - /// - /// \return Size of the image, in pixels - /// - //////////////////////////////////////////////////////////// - Vector2u getSize() const; - - //////////////////////////////////////////////////////////// - /// \brief Create a transparency mask from a specified color-key - /// - /// This function sets the alpha value of every pixel matching - /// the given color to \a alpha (0 by default), so that they - /// become transparent. - /// - /// \param color Color to make transparent - /// \param alpha Alpha value to assign to transparent pixels - /// - //////////////////////////////////////////////////////////// - void createMaskFromColor(const Color& color, Uint8 alpha = 0); - - //////////////////////////////////////////////////////////// - /// \brief Copy pixels from another image onto this one - /// - /// This function does a slow pixel copy and should not be - /// used intensively. It can be used to prepare a complex - /// static image from several others, but if you need this - /// kind of feature in real-time you'd better use sf::RenderTexture. - /// - /// If \a sourceRect is empty, the whole image is copied. - /// If \a applyAlpha is set to true, the transparency of - /// source pixels is applied. If it is false, the pixels are - /// copied unchanged with their alpha value. - /// - /// \param source Source image to copy - /// \param destX X coordinate of the destination position - /// \param destY Y coordinate of the destination position - /// \param sourceRect Sub-rectangle of the source image to copy - /// \param applyAlpha Should the copy take in account the source transparency? - /// - //////////////////////////////////////////////////////////// - void copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect = IntRect(0, 0, 0, 0), bool applyAlpha = false); - - //////////////////////////////////////////////////////////// - /// \brief Change the color of a pixel - /// - /// This function doesn't check the validity of the pixel - /// coordinates, using out-of-range values will result in - /// an undefined behaviour. - /// - /// \param x X coordinate of pixel to change - /// \param y Y coordinate of pixel to change - /// \param color New color of the pixel - /// - /// \see getPixel - /// - //////////////////////////////////////////////////////////// - void setPixel(unsigned int x, unsigned int y, const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Get the color of a pixel - /// - /// This function doesn't check the validity of the pixel - /// coordinates, using out-of-range values will result in - /// an undefined behaviour. - /// - /// \param x X coordinate of pixel to get - /// \param y Y coordinate of pixel to get - /// - /// \return Color of the pixel at coordinates (x, y) - /// - /// \see setPixel - /// - //////////////////////////////////////////////////////////// - Color getPixel(unsigned int x, unsigned int y) const; - - //////////////////////////////////////////////////////////// - /// \brief Get a read-only pointer to the array of pixels - /// - /// The returned value points to an array of RGBA pixels made of - /// 8 bits integers components. The size of the array is - /// width * height * 4 (getSize().x * getSize().y * 4). - /// Warning: the returned pointer may become invalid if you - /// modify the image, so you should never store it for too long. - /// If the image is empty, a null pointer is returned. - /// - /// \return Read-only pointer to the array of pixels - /// - //////////////////////////////////////////////////////////// - const Uint8* getPixelsPtr() const; - - //////////////////////////////////////////////////////////// - /// \brief Flip the image horizontally (left <-> right) - /// - //////////////////////////////////////////////////////////// - void flipHorizontally(); - - //////////////////////////////////////////////////////////// - /// \brief Flip the image vertically (top <-> bottom) - /// - //////////////////////////////////////////////////////////// - void flipVertically(); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Vector2u m_size; ///< Image size - std::vector m_pixels; ///< Pixels of the image - #ifdef SFML_SYSTEM_ANDROID - void* m_stream; ///< Asset file streamer (if loaded from file) - #endif -}; - -} // namespace sf - - -#endif // SFML_IMAGE_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Image -/// \ingroup graphics -/// -/// sf::Image is an abstraction to manipulate images -/// as bidimensional arrays of pixels. The class provides -/// functions to load, read, write and save pixels, as well -/// as many other useful functions. -/// -/// sf::Image can handle a unique internal representation of -/// pixels, which is RGBA 32 bits. This means that a pixel -/// must be composed of 8 bits red, green, blue and alpha -/// channels -- just like a sf::Color. -/// All the functions that return an array of pixels follow -/// this rule, and all parameters that you pass to sf::Image -/// functions (such as loadFromMemory) must use this -/// representation as well. -/// -/// A sf::Image can be copied, but it is a heavy resource and -/// if possible you should always use [const] references to -/// pass or return them to avoid useless copies. -/// -/// Usage example: -/// \code -/// // Load an image file from a file -/// sf::Image background; -/// if (!background.loadFromFile("background.jpg")) -/// return -1; -/// -/// // Create a 20x20 image filled with black color -/// sf::Image image; -/// image.create(20, 20, sf::Color::Black); -/// -/// // Copy image1 on image2 at position (10, 10) -/// image.copy(background, 10, 10); -/// -/// // Make the top-left pixel transparent -/// sf::Color color = image.getPixel(0, 0); -/// color.a = 0; -/// image.setPixel(0, 0, color); -/// -/// // Save the image to a file -/// if (!image.saveToFile("result.png")) -/// return -1; -/// \endcode -/// -/// \see sf::Texture -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_IMAGE_HPP +#define SFML_IMAGE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Class for loading, manipulating and saving images +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Image +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty image. + /// + //////////////////////////////////////////////////////////// + Image(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Image(); + + //////////////////////////////////////////////////////////// + /// \brief Create the image and fill it with a unique color + /// + /// \param width Width of the image + /// \param height Height of the image + /// \param color Fill color + /// + //////////////////////////////////////////////////////////// + void create(unsigned int width, unsigned int height, const Color& color = Color(0, 0, 0)); + + //////////////////////////////////////////////////////////// + /// \brief Create the image from an array of pixels + /// + /// The \a pixel array is assumed to contain 32-bits RGBA pixels, + /// and have the given \a width and \a height. If not, this is + /// an undefined behaviour. + /// If \a pixels is null, an empty image is created. + /// + /// \param width Width of the image + /// \param height Height of the image + /// \param pixels Array of pixels to copy to the image + /// + //////////////////////////////////////////////////////////// + void create(unsigned int width, unsigned int height, const Uint8* pixels); + + //////////////////////////////////////////////////////////// + /// \brief Load the image from a file on disk + /// + /// The supported image formats are bmp, png, tga, jpg, gif, + /// psd, hdr and pic. Some format options are not supported, + /// like progressive jpeg. + /// If this function fails, the image is left unchanged. + /// + /// \param filename Path of the image file to load + /// + /// \return True if loading was successful + /// + /// \see loadFromMemory, loadFromStream, saveToFile + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& filename); + + //////////////////////////////////////////////////////////// + /// \brief Load the image from a file in memory + /// + /// The supported image formats are bmp, png, tga, jpg, gif, + /// psd, hdr and pic. Some format options are not supported, + /// like progressive jpeg. + /// If this function fails, the image is left unchanged. + /// + /// \param data Pointer to the file data in memory + /// \param size Size of the data to load, in bytes + /// + /// \return True if loading was successful + /// + /// \see loadFromFile, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const void* data, std::size_t size); + + //////////////////////////////////////////////////////////// + /// \brief Load the image from a custom stream + /// + /// The supported image formats are bmp, png, tga, jpg, gif, + /// psd, hdr and pic. Some format options are not supported, + /// like progressive jpeg. + /// If this function fails, the image is left unchanged. + /// + /// \param stream Source stream to read from + /// + /// \return True if loading was successful + /// + /// \see loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Save the image to a file on disk + /// + /// The format of the image is automatically deduced from + /// the extension. The supported image formats are bmp, png, + /// tga and jpg. The destination file is overwritten + /// if it already exists. This function fails if the image is empty. + /// + /// \param filename Path of the file to save + /// + /// \return True if saving was successful + /// + /// \see create, loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool saveToFile(const std::string& filename) const; + + //////////////////////////////////////////////////////////// + /// \brief Return the size (width and height) of the image + /// + /// \return Size of the image, in pixels + /// + //////////////////////////////////////////////////////////// + Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Create a transparency mask from a specified color-key + /// + /// This function sets the alpha value of every pixel matching + /// the given color to \a alpha (0 by default), so that they + /// become transparent. + /// + /// \param color Color to make transparent + /// \param alpha Alpha value to assign to transparent pixels + /// + //////////////////////////////////////////////////////////// + void createMaskFromColor(const Color& color, Uint8 alpha = 0); + + //////////////////////////////////////////////////////////// + /// \brief Copy pixels from another image onto this one + /// + /// This function does a slow pixel copy and should not be + /// used intensively. It can be used to prepare a complex + /// static image from several others, but if you need this + /// kind of feature in real-time you'd better use sf::RenderTexture. + /// + /// If \a sourceRect is empty, the whole image is copied. + /// If \a applyAlpha is set to true, the transparency of + /// source pixels is applied. If it is false, the pixels are + /// copied unchanged with their alpha value. + /// + /// \param source Source image to copy + /// \param destX X coordinate of the destination position + /// \param destY Y coordinate of the destination position + /// \param sourceRect Sub-rectangle of the source image to copy + /// \param applyAlpha Should the copy take in account the source transparency? + /// + //////////////////////////////////////////////////////////// + void copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect = IntRect(0, 0, 0, 0), bool applyAlpha = false); + + //////////////////////////////////////////////////////////// + /// \brief Change the color of a pixel + /// + /// This function doesn't check the validity of the pixel + /// coordinates, using out-of-range values will result in + /// an undefined behaviour. + /// + /// \param x X coordinate of pixel to change + /// \param y Y coordinate of pixel to change + /// \param color New color of the pixel + /// + /// \see getPixel + /// + //////////////////////////////////////////////////////////// + void setPixel(unsigned int x, unsigned int y, const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Get the color of a pixel + /// + /// This function doesn't check the validity of the pixel + /// coordinates, using out-of-range values will result in + /// an undefined behaviour. + /// + /// \param x X coordinate of pixel to get + /// \param y Y coordinate of pixel to get + /// + /// \return Color of the pixel at coordinates (x, y) + /// + /// \see setPixel + /// + //////////////////////////////////////////////////////////// + Color getPixel(unsigned int x, unsigned int y) const; + + //////////////////////////////////////////////////////////// + /// \brief Get a read-only pointer to the array of pixels + /// + /// The returned value points to an array of RGBA pixels made of + /// 8 bits integers components. The size of the array is + /// width * height * 4 (getSize().x * getSize().y * 4). + /// Warning: the returned pointer may become invalid if you + /// modify the image, so you should never store it for too long. + /// If the image is empty, a null pointer is returned. + /// + /// \return Read-only pointer to the array of pixels + /// + //////////////////////////////////////////////////////////// + const Uint8* getPixelsPtr() const; + + //////////////////////////////////////////////////////////// + /// \brief Flip the image horizontally (left <-> right) + /// + //////////////////////////////////////////////////////////// + void flipHorizontally(); + + //////////////////////////////////////////////////////////// + /// \brief Flip the image vertically (top <-> bottom) + /// + //////////////////////////////////////////////////////////// + void flipVertically(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2u m_size; ///< Image size + std::vector m_pixels; ///< Pixels of the image + #ifdef SFML_SYSTEM_ANDROID + void* m_stream; ///< Asset file streamer (if loaded from file) + #endif +}; + +} // namespace sf + + +#endif // SFML_IMAGE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Image +/// \ingroup graphics +/// +/// sf::Image is an abstraction to manipulate images +/// as bidimensional arrays of pixels. The class provides +/// functions to load, read, write and save pixels, as well +/// as many other useful functions. +/// +/// sf::Image can handle a unique internal representation of +/// pixels, which is RGBA 32 bits. This means that a pixel +/// must be composed of 8 bits red, green, blue and alpha +/// channels -- just like a sf::Color. +/// All the functions that return an array of pixels follow +/// this rule, and all parameters that you pass to sf::Image +/// functions (such as loadFromMemory) must use this +/// representation as well. +/// +/// A sf::Image can be copied, but it is a heavy resource and +/// if possible you should always use [const] references to +/// pass or return them to avoid useless copies. +/// +/// Usage example: +/// \code +/// // Load an image file from a file +/// sf::Image background; +/// if (!background.loadFromFile("background.jpg")) +/// return -1; +/// +/// // Create a 20x20 image filled with black color +/// sf::Image image; +/// image.create(20, 20, sf::Color::Black); +/// +/// // Copy image1 on image2 at position (10, 10) +/// image.copy(background, 10, 10); +/// +/// // Make the top-left pixel transparent +/// sf::Color color = image.getPixel(0, 0); +/// color.a = 0; +/// image.setPixel(0, 0, color); +/// +/// // Save the image to a file +/// if (!image.saveToFile("result.png")) +/// return -1; +/// \endcode +/// +/// \see sf::Texture +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Rect.hpp b/include/SFML/Graphics/Rect.hpp index 28807220..a89398af 100644 --- a/include/SFML/Graphics/Rect.hpp +++ b/include/SFML/Graphics/Rect.hpp @@ -1,248 +1,248 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_RECT_HPP -#define SFML_RECT_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Utility class for manipulating 2D axis aligned rectangles -/// -//////////////////////////////////////////////////////////// -template -class Rect -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Creates an empty rectangle (it is equivalent to calling - /// Rect(0, 0, 0, 0)). - /// - //////////////////////////////////////////////////////////// - Rect(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the rectangle from its coordinates - /// - /// Be careful, the last two parameters are the width - /// and height, not the right and bottom coordinates! - /// - /// \param rectLeft Left coordinate of the rectangle - /// \param rectTop Top coordinate of the rectangle - /// \param rectWidth Width of the rectangle - /// \param rectHeight Height of the rectangle - /// - //////////////////////////////////////////////////////////// - Rect(T rectLeft, T rectTop, T rectWidth, T rectHeight); - - //////////////////////////////////////////////////////////// - /// \brief Construct the rectangle from position and size - /// - /// Be careful, the last parameter is the size, - /// not the bottom-right corner! - /// - /// \param position Position of the top-left corner of the rectangle - /// \param size Size of the rectangle - /// - //////////////////////////////////////////////////////////// - Rect(const Vector2& position, const Vector2& size); - - //////////////////////////////////////////////////////////// - /// \brief Construct the rectangle from another type of rectangle - /// - /// This constructor doesn't replace the copy constructor, - /// it's called only when U != T. - /// A call to this constructor will fail to compile if U - /// is not convertible to T. - /// - /// \param rectangle Rectangle to convert - /// - //////////////////////////////////////////////////////////// - template - explicit Rect(const Rect& rectangle); - - //////////////////////////////////////////////////////////// - /// \brief Check if a point is inside the rectangle's area - /// - /// \param x X coordinate of the point to test - /// \param y Y coordinate of the point to test - /// - /// \return True if the point is inside, false otherwise - /// - /// \see intersects - /// - //////////////////////////////////////////////////////////// - bool contains(T x, T y) const; - - //////////////////////////////////////////////////////////// - /// \brief Check if a point is inside the rectangle's area - /// - /// \param point Point to test - /// - /// \return True if the point is inside, false otherwise - /// - /// \see intersects - /// - //////////////////////////////////////////////////////////// - bool contains(const Vector2& point) const; - - //////////////////////////////////////////////////////////// - /// \brief Check the intersection between two rectangles - /// - /// \param rectangle Rectangle to test - /// - /// \return True if rectangles overlap, false otherwise - /// - /// \see contains - /// - //////////////////////////////////////////////////////////// - bool intersects(const Rect& rectangle) const; - - //////////////////////////////////////////////////////////// - /// \brief Check the intersection between two rectangles - /// - /// This overload returns the overlapped rectangle in the - /// \a intersection parameter. - /// - /// \param rectangle Rectangle to test - /// \param intersection Rectangle to be filled with the intersection - /// - /// \return True if rectangles overlap, false otherwise - /// - /// \see contains - /// - //////////////////////////////////////////////////////////// - bool intersects(const Rect& rectangle, Rect& intersection) const; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - T left; ///< Left coordinate of the rectangle - T top; ///< Top coordinate of the rectangle - T width; ///< Width of the rectangle - T height; ///< Height of the rectangle -}; - -//////////////////////////////////////////////////////////// -/// \relates Rect -/// \brief Overload of binary operator == -/// -/// This operator compares strict equality between two rectangles. -/// -/// \param left Left operand (a rectangle) -/// \param right Right operand (a rectangle) -/// -/// \return True if \a left is equal to \a right -/// -//////////////////////////////////////////////////////////// -template -bool operator ==(const Rect& left, const Rect& right); - -//////////////////////////////////////////////////////////// -/// \relates Rect -/// \brief Overload of binary operator != -/// -/// This operator compares strict difference between two rectangles. -/// -/// \param left Left operand (a rectangle) -/// \param right Right operand (a rectangle) -/// -/// \return True if \a left is not equal to \a right -/// -//////////////////////////////////////////////////////////// -template -bool operator !=(const Rect& left, const Rect& right); - -#include - -// Create typedefs for the most common types -typedef Rect IntRect; -typedef Rect FloatRect; - -} // namespace sf - - -#endif // SFML_RECT_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Rect -/// \ingroup graphics -/// -/// A rectangle is defined by its top-left corner and its size. -/// It is a very simple class defined for convenience, so -/// its member variables (left, top, width and height) are public -/// and can be accessed directly, just like the vector classes -/// (Vector2 and Vector3). -/// -/// To keep things simple, sf::Rect doesn't define -/// functions to emulate the properties that are not directly -/// members (such as right, bottom, center, etc.), it rather -/// only provides intersection functions. -/// -/// sf::Rect uses the usual rules for its boundaries: -/// \li The left and top edges are included in the rectangle's area -/// \li The right (left + width) and bottom (top + height) edges are excluded from the rectangle's area -/// -/// This means that sf::IntRect(0, 0, 1, 1) and sf::IntRect(1, 1, 1, 1) -/// don't intersect. -/// -/// sf::Rect is a template and may be used with any numeric type, but -/// for simplicity the instanciations used by SFML are typedefed: -/// \li sf::Rect is sf::IntRect -/// \li sf::Rect is sf::FloatRect -/// -/// So that you don't have to care about the template syntax. -/// -/// Usage example: -/// \code -/// // Define a rectangle, located at (0, 0) with a size of 20x5 -/// sf::IntRect r1(0, 0, 20, 5); -/// -/// // Define another rectangle, located at (4, 2) with a size of 18x10 -/// sf::Vector2i position(4, 2); -/// sf::Vector2i size(18, 10); -/// sf::IntRect r2(position, size); -/// -/// // Test intersections with the point (3, 1) -/// bool b1 = r1.contains(3, 1); // true -/// bool b2 = r2.contains(3, 1); // false -/// -/// // Test the intersection between r1 and r2 -/// sf::IntRect result; -/// bool b3 = r1.intersects(r2, result); // true -/// // result == (4, 2, 16, 3) -/// \endcode -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RECT_HPP +#define SFML_RECT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility class for manipulating 2D axis aligned rectangles +/// +//////////////////////////////////////////////////////////// +template +class Rect +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty rectangle (it is equivalent to calling + /// Rect(0, 0, 0, 0)). + /// + //////////////////////////////////////////////////////////// + Rect(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the rectangle from its coordinates + /// + /// Be careful, the last two parameters are the width + /// and height, not the right and bottom coordinates! + /// + /// \param rectLeft Left coordinate of the rectangle + /// \param rectTop Top coordinate of the rectangle + /// \param rectWidth Width of the rectangle + /// \param rectHeight Height of the rectangle + /// + //////////////////////////////////////////////////////////// + Rect(T rectLeft, T rectTop, T rectWidth, T rectHeight); + + //////////////////////////////////////////////////////////// + /// \brief Construct the rectangle from position and size + /// + /// Be careful, the last parameter is the size, + /// not the bottom-right corner! + /// + /// \param position Position of the top-left corner of the rectangle + /// \param size Size of the rectangle + /// + //////////////////////////////////////////////////////////// + Rect(const Vector2& position, const Vector2& size); + + //////////////////////////////////////////////////////////// + /// \brief Construct the rectangle from another type of rectangle + /// + /// This constructor doesn't replace the copy constructor, + /// it's called only when U != T. + /// A call to this constructor will fail to compile if U + /// is not convertible to T. + /// + /// \param rectangle Rectangle to convert + /// + //////////////////////////////////////////////////////////// + template + explicit Rect(const Rect& rectangle); + + //////////////////////////////////////////////////////////// + /// \brief Check if a point is inside the rectangle's area + /// + /// \param x X coordinate of the point to test + /// \param y Y coordinate of the point to test + /// + /// \return True if the point is inside, false otherwise + /// + /// \see intersects + /// + //////////////////////////////////////////////////////////// + bool contains(T x, T y) const; + + //////////////////////////////////////////////////////////// + /// \brief Check if a point is inside the rectangle's area + /// + /// \param point Point to test + /// + /// \return True if the point is inside, false otherwise + /// + /// \see intersects + /// + //////////////////////////////////////////////////////////// + bool contains(const Vector2& point) const; + + //////////////////////////////////////////////////////////// + /// \brief Check the intersection between two rectangles + /// + /// \param rectangle Rectangle to test + /// + /// \return True if rectangles overlap, false otherwise + /// + /// \see contains + /// + //////////////////////////////////////////////////////////// + bool intersects(const Rect& rectangle) const; + + //////////////////////////////////////////////////////////// + /// \brief Check the intersection between two rectangles + /// + /// This overload returns the overlapped rectangle in the + /// \a intersection parameter. + /// + /// \param rectangle Rectangle to test + /// \param intersection Rectangle to be filled with the intersection + /// + /// \return True if rectangles overlap, false otherwise + /// + /// \see contains + /// + //////////////////////////////////////////////////////////// + bool intersects(const Rect& rectangle, Rect& intersection) const; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + T left; ///< Left coordinate of the rectangle + T top; ///< Top coordinate of the rectangle + T width; ///< Width of the rectangle + T height; ///< Height of the rectangle +}; + +//////////////////////////////////////////////////////////// +/// \relates Rect +/// \brief Overload of binary operator == +/// +/// This operator compares strict equality between two rectangles. +/// +/// \param left Left operand (a rectangle) +/// \param right Right operand (a rectangle) +/// +/// \return True if \a left is equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator ==(const Rect& left, const Rect& right); + +//////////////////////////////////////////////////////////// +/// \relates Rect +/// \brief Overload of binary operator != +/// +/// This operator compares strict difference between two rectangles. +/// +/// \param left Left operand (a rectangle) +/// \param right Right operand (a rectangle) +/// +/// \return True if \a left is not equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator !=(const Rect& left, const Rect& right); + +#include + +// Create typedefs for the most common types +typedef Rect IntRect; +typedef Rect FloatRect; + +} // namespace sf + + +#endif // SFML_RECT_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Rect +/// \ingroup graphics +/// +/// A rectangle is defined by its top-left corner and its size. +/// It is a very simple class defined for convenience, so +/// its member variables (left, top, width and height) are public +/// and can be accessed directly, just like the vector classes +/// (Vector2 and Vector3). +/// +/// To keep things simple, sf::Rect doesn't define +/// functions to emulate the properties that are not directly +/// members (such as right, bottom, center, etc.), it rather +/// only provides intersection functions. +/// +/// sf::Rect uses the usual rules for its boundaries: +/// \li The left and top edges are included in the rectangle's area +/// \li The right (left + width) and bottom (top + height) edges are excluded from the rectangle's area +/// +/// This means that sf::IntRect(0, 0, 1, 1) and sf::IntRect(1, 1, 1, 1) +/// don't intersect. +/// +/// sf::Rect is a template and may be used with any numeric type, but +/// for simplicity the instanciations used by SFML are typedefed: +/// \li sf::Rect is sf::IntRect +/// \li sf::Rect is sf::FloatRect +/// +/// So that you don't have to care about the template syntax. +/// +/// Usage example: +/// \code +/// // Define a rectangle, located at (0, 0) with a size of 20x5 +/// sf::IntRect r1(0, 0, 20, 5); +/// +/// // Define another rectangle, located at (4, 2) with a size of 18x10 +/// sf::Vector2i position(4, 2); +/// sf::Vector2i size(18, 10); +/// sf::IntRect r2(position, size); +/// +/// // Test intersections with the point (3, 1) +/// bool b1 = r1.contains(3, 1); // true +/// bool b2 = r2.contains(3, 1); // false +/// +/// // Test the intersection between r1 and r2 +/// sf::IntRect result; +/// bool b3 = r1.intersects(r2, result); // true +/// // result == (4, 2, 16, 3) +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Rect.inl b/include/SFML/Graphics/Rect.inl index 4a923975..849fc823 100644 --- a/include/SFML/Graphics/Rect.inl +++ b/include/SFML/Graphics/Rect.inl @@ -1,159 +1,159 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -template -Rect::Rect() : -left (0), -top (0), -width (0), -height(0) -{ - -} - - -//////////////////////////////////////////////////////////// -template -Rect::Rect(T rectLeft, T rectTop, T rectWidth, T rectHeight) : -left (rectLeft), -top (rectTop), -width (rectWidth), -height(rectHeight) -{ - -} - - -//////////////////////////////////////////////////////////// -template -Rect::Rect(const Vector2& position, const Vector2& size) : -left (position.x), -top (position.y), -width (size.x), -height(size.y) -{ - -} - - -//////////////////////////////////////////////////////////// -template -template -Rect::Rect(const Rect& rectangle) : -left (static_cast(rectangle.left)), -top (static_cast(rectangle.top)), -width (static_cast(rectangle.width)), -height(static_cast(rectangle.height)) -{ -} - - -//////////////////////////////////////////////////////////// -template -bool Rect::contains(T x, T y) const -{ - // Rectangles with negative dimensions are allowed, so we must handle them correctly - - // Compute the real min and max of the rectangle on both axes - T minX = std::min(left, static_cast(left + width)); - T maxX = std::max(left, static_cast(left + width)); - T minY = std::min(top, static_cast(top + height)); - T maxY = std::max(top, static_cast(top + height)); - - return (x >= minX) && (x < maxX) && (y >= minY) && (y < maxY); -} - - -//////////////////////////////////////////////////////////// -template -bool Rect::contains(const Vector2& point) const -{ - return contains(point.x, point.y); -} - - -//////////////////////////////////////////////////////////// -template -bool Rect::intersects(const Rect& rectangle) const -{ - Rect intersection; - return intersects(rectangle, intersection); -} - - -//////////////////////////////////////////////////////////// -template -bool Rect::intersects(const Rect& rectangle, Rect& intersection) const -{ - // Rectangles with negative dimensions are allowed, so we must handle them correctly - - // Compute the min and max of the first rectangle on both axes - T r1MinX = std::min(left, static_cast(left + width)); - T r1MaxX = std::max(left, static_cast(left + width)); - T r1MinY = std::min(top, static_cast(top + height)); - T r1MaxY = std::max(top, static_cast(top + height)); - - // Compute the min and max of the second rectangle on both axes - T r2MinX = std::min(rectangle.left, static_cast(rectangle.left + rectangle.width)); - T r2MaxX = std::max(rectangle.left, static_cast(rectangle.left + rectangle.width)); - T r2MinY = std::min(rectangle.top, static_cast(rectangle.top + rectangle.height)); - T r2MaxY = std::max(rectangle.top, static_cast(rectangle.top + rectangle.height)); - - // Compute the intersection boundaries - T interLeft = std::max(r1MinX, r2MinX); - T interTop = std::max(r1MinY, r2MinY); - T interRight = std::min(r1MaxX, r2MaxX); - T interBottom = std::min(r1MaxY, r2MaxY); - - // If the intersection is valid (positive non zero area), then there is an intersection - if ((interLeft < interRight) && (interTop < interBottom)) - { - intersection = Rect(interLeft, interTop, interRight - interLeft, interBottom - interTop); - return true; - } - else - { - intersection = Rect(0, 0, 0, 0); - return false; - } -} - - -//////////////////////////////////////////////////////////// -template -inline bool operator ==(const Rect& left, const Rect& right) -{ - return (left.left == right.left) && (left.width == right.width) && - (left.top == right.top) && (left.height == right.height); -} - - -//////////////////////////////////////////////////////////// -template -inline bool operator !=(const Rect& left, const Rect& right) -{ - return !(left == right); -} +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +template +Rect::Rect() : +left (0), +top (0), +width (0), +height(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template +Rect::Rect(T rectLeft, T rectTop, T rectWidth, T rectHeight) : +left (rectLeft), +top (rectTop), +width (rectWidth), +height(rectHeight) +{ + +} + + +//////////////////////////////////////////////////////////// +template +Rect::Rect(const Vector2& position, const Vector2& size) : +left (position.x), +top (position.y), +width (size.x), +height(size.y) +{ + +} + + +//////////////////////////////////////////////////////////// +template +template +Rect::Rect(const Rect& rectangle) : +left (static_cast(rectangle.left)), +top (static_cast(rectangle.top)), +width (static_cast(rectangle.width)), +height(static_cast(rectangle.height)) +{ +} + + +//////////////////////////////////////////////////////////// +template +bool Rect::contains(T x, T y) const +{ + // Rectangles with negative dimensions are allowed, so we must handle them correctly + + // Compute the real min and max of the rectangle on both axes + T minX = std::min(left, static_cast(left + width)); + T maxX = std::max(left, static_cast(left + width)); + T minY = std::min(top, static_cast(top + height)); + T maxY = std::max(top, static_cast(top + height)); + + return (x >= minX) && (x < maxX) && (y >= minY) && (y < maxY); +} + + +//////////////////////////////////////////////////////////// +template +bool Rect::contains(const Vector2& point) const +{ + return contains(point.x, point.y); +} + + +//////////////////////////////////////////////////////////// +template +bool Rect::intersects(const Rect& rectangle) const +{ + Rect intersection; + return intersects(rectangle, intersection); +} + + +//////////////////////////////////////////////////////////// +template +bool Rect::intersects(const Rect& rectangle, Rect& intersection) const +{ + // Rectangles with negative dimensions are allowed, so we must handle them correctly + + // Compute the min and max of the first rectangle on both axes + T r1MinX = std::min(left, static_cast(left + width)); + T r1MaxX = std::max(left, static_cast(left + width)); + T r1MinY = std::min(top, static_cast(top + height)); + T r1MaxY = std::max(top, static_cast(top + height)); + + // Compute the min and max of the second rectangle on both axes + T r2MinX = std::min(rectangle.left, static_cast(rectangle.left + rectangle.width)); + T r2MaxX = std::max(rectangle.left, static_cast(rectangle.left + rectangle.width)); + T r2MinY = std::min(rectangle.top, static_cast(rectangle.top + rectangle.height)); + T r2MaxY = std::max(rectangle.top, static_cast(rectangle.top + rectangle.height)); + + // Compute the intersection boundaries + T interLeft = std::max(r1MinX, r2MinX); + T interTop = std::max(r1MinY, r2MinY); + T interRight = std::min(r1MaxX, r2MaxX); + T interBottom = std::min(r1MaxY, r2MaxY); + + // If the intersection is valid (positive non zero area), then there is an intersection + if ((interLeft < interRight) && (interTop < interBottom)) + { + intersection = Rect(interLeft, interTop, interRight - interLeft, interBottom - interTop); + return true; + } + else + { + intersection = Rect(0, 0, 0, 0); + return false; + } +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator ==(const Rect& left, const Rect& right) +{ + return (left.left == right.left) && (left.width == right.width) && + (left.top == right.top) && (left.height == right.height); +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator !=(const Rect& left, const Rect& right) +{ + return !(left == right); +} diff --git a/include/SFML/Graphics/RectangleShape.hpp b/include/SFML/Graphics/RectangleShape.hpp index 08bfec7a..8677cc6b 100644 --- a/include/SFML/Graphics/RectangleShape.hpp +++ b/include/SFML/Graphics/RectangleShape.hpp @@ -40,7 +40,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_GRAPHICS_API RectangleShape : public Shape { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -94,7 +94,7 @@ public : //////////////////////////////////////////////////////////// virtual Vector2f getPoint(unsigned int index) const; -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/include/SFML/Graphics/RenderStates.hpp b/include/SFML/Graphics/RenderStates.hpp index 986554b8..d6198368 100644 --- a/include/SFML/Graphics/RenderStates.hpp +++ b/include/SFML/Graphics/RenderStates.hpp @@ -44,7 +44,7 @@ class Texture; //////////////////////////////////////////////////////////// class SFML_GRAPHICS_API RenderStates { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor diff --git a/include/SFML/Graphics/RenderTarget.hpp b/include/SFML/Graphics/RenderTarget.hpp index 033e2c78..b6fafac4 100644 --- a/include/SFML/Graphics/RenderTarget.hpp +++ b/include/SFML/Graphics/RenderTarget.hpp @@ -1,451 +1,451 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_RENDERTARGET_HPP -#define SFML_RENDERTARGET_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -class Drawable; - -//////////////////////////////////////////////////////////// -/// \brief Base class for all render targets (window, texture, ...) -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API RenderTarget : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - virtual ~RenderTarget(); - - //////////////////////////////////////////////////////////// - /// \brief Clear the entire target with a single color - /// - /// This function is usually called once every frame, - /// to clear the previous contents of the target. - /// - /// \param color Fill color to use to clear the render target - /// - //////////////////////////////////////////////////////////// - void clear(const Color& color = Color(0, 0, 0, 255)); - - //////////////////////////////////////////////////////////// - /// \brief Change the current active view - /// - /// The view is like a 2D camera, it controls which part of - /// the 2D scene is visible, and how it is viewed in the - /// render-target. - /// The new view will affect everything that is drawn, until - /// another view is set. - /// The render target keeps its own copy of the view object, - /// so it is not necessary to keep the original one alive - /// after calling this function. - /// To restore the original view of the target, you can pass - /// the result of getDefaultView() to this function. - /// - /// \param view New view to use - /// - /// \see getView, getDefaultView - /// - //////////////////////////////////////////////////////////// - void setView(const View& view); - - //////////////////////////////////////////////////////////// - /// \brief Get the view currently in use in the render target - /// - /// \return The view object that is currently used - /// - /// \see setView, getDefaultView - /// - //////////////////////////////////////////////////////////// - const View& getView() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the default view of the render target - /// - /// The default view has the initial size of the render target, - /// and never changes after the target has been created. - /// - /// \return The default view of the render target - /// - /// \see setView, getView - /// - //////////////////////////////////////////////////////////// - const View& getDefaultView() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the viewport of a view, applied to this render target - /// - /// The viewport is defined in the view as a ratio, this function - /// simply applies this ratio to the current dimensions of the - /// render target to calculate the pixels rectangle that the viewport - /// actually covers in the target. - /// - /// \param view The view for which we want to compute the viewport - /// - /// \return Viewport rectangle, expressed in pixels - /// - //////////////////////////////////////////////////////////// - IntRect getViewport(const View& view) const; - - //////////////////////////////////////////////////////////// - /// \brief Convert a point from target coordinates to world - /// coordinates, using the current view - /// - /// This function is an overload of the mapPixelToCoords - /// function that implicitely uses the current view. - /// It is equivalent to: - /// \code - /// target.mapPixelToCoords(point, target.getView()); - /// \endcode - /// - /// \param point Pixel to convert - /// - /// \return The converted point, in "world" coordinates - /// - /// \see mapCoordsToPixel - /// - //////////////////////////////////////////////////////////// - Vector2f mapPixelToCoords(const Vector2i& point) const; - - //////////////////////////////////////////////////////////// - /// \brief Convert a point from target coordinates to world coordinates - /// - /// This function finds the 2D position that matches the - /// given pixel of the render-target. In other words, it does - /// the inverse of what the graphics card does, to find the - /// initial position of a rendered pixel. - /// - /// Initially, both coordinate systems (world units and target pixels) - /// match perfectly. But if you define a custom view or resize your - /// render-target, this assertion is not true anymore, ie. a point - /// located at (10, 50) in your render-target may map to the point - /// (150, 75) in your 2D world -- if the view is translated by (140, 25). - /// - /// For render-windows, this function is typically used to find - /// which point (or object) is located below the mouse cursor. - /// - /// This version uses a custom view for calculations, see the other - /// overload of the function if you want to use the current view of the - /// render-target. - /// - /// \param point Pixel to convert - /// \param view The view to use for converting the point - /// - /// \return The converted point, in "world" units - /// - /// \see mapCoordsToPixel - /// - //////////////////////////////////////////////////////////// - Vector2f mapPixelToCoords(const Vector2i& point, const View& view) const; - - //////////////////////////////////////////////////////////// - /// \brief Convert a point from world coordinates to target - /// coordinates, using the current view - /// - /// This function is an overload of the mapCoordsToPixel - /// function that implicitely uses the current view. - /// It is equivalent to: - /// \code - /// target.mapCoordsToPixel(point, target.getView()); - /// \endcode - /// - /// \param point Point to convert - /// - /// \return The converted point, in target coordinates (pixels) - /// - /// \see mapPixelToCoords - /// - //////////////////////////////////////////////////////////// - Vector2i mapCoordsToPixel(const Vector2f& point) const; - - //////////////////////////////////////////////////////////// - /// \brief Convert a point from world coordinates to target coordinates - /// - /// This function finds the pixel of the render-target that matches - /// the given 2D point. In other words, it goes through the same process - /// as the graphics card, to compute the final position of a rendered point. - /// - /// Initially, both coordinate systems (world units and target pixels) - /// match perfectly. But if you define a custom view or resize your - /// render-target, this assertion is not true anymore, ie. a point - /// located at (150, 75) in your 2D world may map to the pixel - /// (10, 50) of your render-target -- if the view is translated by (140, 25). - /// - /// This version uses a custom view for calculations, see the other - /// overload of the function if you want to use the current view of the - /// render-target. - /// - /// \param point Point to convert - /// \param view The view to use for converting the point - /// - /// \return The converted point, in target coordinates (pixels) - /// - /// \see mapPixelToCoords - /// - //////////////////////////////////////////////////////////// - Vector2i mapCoordsToPixel(const Vector2f& point, const View& view) const; - - //////////////////////////////////////////////////////////// - /// \brief Draw a drawable object to the render-target - /// - /// \param drawable Object to draw - /// \param states Render states to use for drawing - /// - //////////////////////////////////////////////////////////// - void draw(const Drawable& drawable, const RenderStates& states = RenderStates::Default); - - //////////////////////////////////////////////////////////// - /// \brief Draw primitives defined by an array of vertices - /// - /// \param vertices Pointer to the vertices - /// \param vertexCount Number of vertices in the array - /// \param type Type of primitives to draw - /// \param states Render states to use for drawing - /// - //////////////////////////////////////////////////////////// - void draw(const Vertex* vertices, unsigned int vertexCount, - PrimitiveType type, const RenderStates& states = RenderStates::Default); - - //////////////////////////////////////////////////////////// - /// \brief Return the size of the rendering region of the target - /// - /// \return Size in pixels - /// - //////////////////////////////////////////////////////////// - virtual Vector2u getSize() const = 0; - - //////////////////////////////////////////////////////////// - /// \brief Save the current OpenGL render states and matrices - /// - /// This function can be used when you mix SFML drawing - /// and direct OpenGL rendering. Combined with PopGLStates, - /// it ensures that: - /// \li SFML's internal states are not messed up by your OpenGL code - /// \li your OpenGL states are not modified by a call to a SFML function - /// - /// More specifically, it must be used around code that - /// calls Draw functions. Example: - /// \code - /// // OpenGL code here... - /// window.pushGLStates(); - /// window.draw(...); - /// window.draw(...); - /// window.popGLStates(); - /// // OpenGL code here... - /// \endcode - /// - /// Note that this function is quite expensive: it saves all the - /// possible OpenGL states and matrices, even the ones you - /// don't care about. Therefore it should be used wisely. - /// It is provided for convenience, but the best results will - /// be achieved if you handle OpenGL states yourself (because - /// you know which states have really changed, and need to be - /// saved and restored). Take a look at the ResetGLStates - /// function if you do so. - /// - /// \see popGLStates - /// - //////////////////////////////////////////////////////////// - void pushGLStates(); - - //////////////////////////////////////////////////////////// - /// \brief Restore the previously saved OpenGL render states and matrices - /// - /// See the description of pushGLStates to get a detailed - /// description of these functions. - /// - /// \see pushGLStates - /// - //////////////////////////////////////////////////////////// - void popGLStates(); - - //////////////////////////////////////////////////////////// - /// \brief Reset the internal OpenGL states so that the target is ready for drawing - /// - /// This function can be used when you mix SFML drawing - /// and direct OpenGL rendering, if you choose not to use - /// pushGLStates/popGLStates. It makes sure that all OpenGL - /// states needed by SFML are set, so that subsequent draw() - /// calls will work as expected. - /// - /// Example: - /// \code - /// // OpenGL code here... - /// glPushAttrib(...); - /// window.resetGLStates(); - /// window.draw(...); - /// window.draw(...); - /// glPopAttrib(...); - /// // OpenGL code here... - /// \endcode - /// - //////////////////////////////////////////////////////////// - void resetGLStates(); - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - RenderTarget(); - - //////////////////////////////////////////////////////////// - /// \brief Performs the common initialization step after creation - /// - /// The derived classes must call this function after the - /// target is created and ready for drawing. - /// - //////////////////////////////////////////////////////////// - void initialize(); - -private: - - //////////////////////////////////////////////////////////// - /// \brief Apply the current view - /// - //////////////////////////////////////////////////////////// - void applyCurrentView(); - - //////////////////////////////////////////////////////////// - /// \brief Apply a new blending mode - /// - /// \param mode Blending mode to apply - /// - //////////////////////////////////////////////////////////// - void applyBlendMode(const BlendMode& mode); - - //////////////////////////////////////////////////////////// - /// \brief Apply a new transform - /// - /// \param transform Transform to apply - /// - //////////////////////////////////////////////////////////// - void applyTransform(const Transform& transform); - - //////////////////////////////////////////////////////////// - /// \brief Apply a new texture - /// - /// \param texture Texture to apply - /// - //////////////////////////////////////////////////////////// - void applyTexture(const Texture* texture); - - //////////////////////////////////////////////////////////// - /// \brief Apply a new shader - /// - /// \param shader Shader to apply - /// - //////////////////////////////////////////////////////////// - void applyShader(const Shader* shader); - - //////////////////////////////////////////////////////////// - /// \brief Activate the target for rendering - /// - /// This function must be implemented by derived classes to make - /// their OpenGL context current; it is called by the base class - /// everytime it's going to use OpenGL calls. - /// - /// \param active True to make the target active, false to deactivate it - /// - /// \return True if the function succeeded - /// - //////////////////////////////////////////////////////////// - virtual bool activate(bool active) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Render states cache - /// - //////////////////////////////////////////////////////////// - struct StatesCache - { - enum {VertexCacheSize = 4}; - - bool glStatesSet; ///< Are our internal GL states set yet? - bool viewChanged; ///< Has the current view changed since last draw? - BlendMode lastBlendMode; ///< Cached blending mode - Uint64 lastTextureId; ///< Cached texture - bool useVertexCache; ///< Did we previously use the vertex cache? - Vertex vertexCache[VertexCacheSize]; ///< Pre-transformed vertices cache - }; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - View m_defaultView; ///< Default view - View m_view; ///< Current view - StatesCache m_cache; ///< Render states cache -}; - -} // namespace sf - - -#endif // SFML_RENDERTARGET_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::RenderTarget -/// \ingroup graphics -/// -/// sf::RenderTarget defines the common behaviour of all the -/// 2D render targets usable in the graphics module. It makes -/// it possible to draw 2D entities like sprites, shapes, text -/// without using any OpenGL command directly. -/// -/// A sf::RenderTarget is also able to use views (sf::View), -/// which are a kind of 2D cameras. With views you can globally -/// scroll, rotate or zoom everything that is drawn, -/// without having to transform every single entity. See the -/// documentation of sf::View for more details and sample pieces of -/// code about this class. -/// -/// On top of that, render targets are still able to render direct -/// OpenGL stuff. It is even possible to mix together OpenGL calls -/// and regular SFML drawing commands. When doing so, make sure that -/// OpenGL states are not messed up by calling the -/// pushGLStates/popGLStates functions. -/// -/// \see sf::RenderWindow, sf::RenderTexture, sf::View -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERTARGET_HPP +#define SFML_RENDERTARGET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +class Drawable; + +//////////////////////////////////////////////////////////// +/// \brief Base class for all render targets (window, texture, ...) +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API RenderTarget : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~RenderTarget(); + + //////////////////////////////////////////////////////////// + /// \brief Clear the entire target with a single color + /// + /// This function is usually called once every frame, + /// to clear the previous contents of the target. + /// + /// \param color Fill color to use to clear the render target + /// + //////////////////////////////////////////////////////////// + void clear(const Color& color = Color(0, 0, 0, 255)); + + //////////////////////////////////////////////////////////// + /// \brief Change the current active view + /// + /// The view is like a 2D camera, it controls which part of + /// the 2D scene is visible, and how it is viewed in the + /// render-target. + /// The new view will affect everything that is drawn, until + /// another view is set. + /// The render target keeps its own copy of the view object, + /// so it is not necessary to keep the original one alive + /// after calling this function. + /// To restore the original view of the target, you can pass + /// the result of getDefaultView() to this function. + /// + /// \param view New view to use + /// + /// \see getView, getDefaultView + /// + //////////////////////////////////////////////////////////// + void setView(const View& view); + + //////////////////////////////////////////////////////////// + /// \brief Get the view currently in use in the render target + /// + /// \return The view object that is currently used + /// + /// \see setView, getDefaultView + /// + //////////////////////////////////////////////////////////// + const View& getView() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the default view of the render target + /// + /// The default view has the initial size of the render target, + /// and never changes after the target has been created. + /// + /// \return The default view of the render target + /// + /// \see setView, getView + /// + //////////////////////////////////////////////////////////// + const View& getDefaultView() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the viewport of a view, applied to this render target + /// + /// The viewport is defined in the view as a ratio, this function + /// simply applies this ratio to the current dimensions of the + /// render target to calculate the pixels rectangle that the viewport + /// actually covers in the target. + /// + /// \param view The view for which we want to compute the viewport + /// + /// \return Viewport rectangle, expressed in pixels + /// + //////////////////////////////////////////////////////////// + IntRect getViewport(const View& view) const; + + //////////////////////////////////////////////////////////// + /// \brief Convert a point from target coordinates to world + /// coordinates, using the current view + /// + /// This function is an overload of the mapPixelToCoords + /// function that implicitely uses the current view. + /// It is equivalent to: + /// \code + /// target.mapPixelToCoords(point, target.getView()); + /// \endcode + /// + /// \param point Pixel to convert + /// + /// \return The converted point, in "world" coordinates + /// + /// \see mapCoordsToPixel + /// + //////////////////////////////////////////////////////////// + Vector2f mapPixelToCoords(const Vector2i& point) const; + + //////////////////////////////////////////////////////////// + /// \brief Convert a point from target coordinates to world coordinates + /// + /// This function finds the 2D position that matches the + /// given pixel of the render-target. In other words, it does + /// the inverse of what the graphics card does, to find the + /// initial position of a rendered pixel. + /// + /// Initially, both coordinate systems (world units and target pixels) + /// match perfectly. But if you define a custom view or resize your + /// render-target, this assertion is not true anymore, ie. a point + /// located at (10, 50) in your render-target may map to the point + /// (150, 75) in your 2D world -- if the view is translated by (140, 25). + /// + /// For render-windows, this function is typically used to find + /// which point (or object) is located below the mouse cursor. + /// + /// This version uses a custom view for calculations, see the other + /// overload of the function if you want to use the current view of the + /// render-target. + /// + /// \param point Pixel to convert + /// \param view The view to use for converting the point + /// + /// \return The converted point, in "world" units + /// + /// \see mapCoordsToPixel + /// + //////////////////////////////////////////////////////////// + Vector2f mapPixelToCoords(const Vector2i& point, const View& view) const; + + //////////////////////////////////////////////////////////// + /// \brief Convert a point from world coordinates to target + /// coordinates, using the current view + /// + /// This function is an overload of the mapCoordsToPixel + /// function that implicitely uses the current view. + /// It is equivalent to: + /// \code + /// target.mapCoordsToPixel(point, target.getView()); + /// \endcode + /// + /// \param point Point to convert + /// + /// \return The converted point, in target coordinates (pixels) + /// + /// \see mapPixelToCoords + /// + //////////////////////////////////////////////////////////// + Vector2i mapCoordsToPixel(const Vector2f& point) const; + + //////////////////////////////////////////////////////////// + /// \brief Convert a point from world coordinates to target coordinates + /// + /// This function finds the pixel of the render-target that matches + /// the given 2D point. In other words, it goes through the same process + /// as the graphics card, to compute the final position of a rendered point. + /// + /// Initially, both coordinate systems (world units and target pixels) + /// match perfectly. But if you define a custom view or resize your + /// render-target, this assertion is not true anymore, ie. a point + /// located at (150, 75) in your 2D world may map to the pixel + /// (10, 50) of your render-target -- if the view is translated by (140, 25). + /// + /// This version uses a custom view for calculations, see the other + /// overload of the function if you want to use the current view of the + /// render-target. + /// + /// \param point Point to convert + /// \param view The view to use for converting the point + /// + /// \return The converted point, in target coordinates (pixels) + /// + /// \see mapPixelToCoords + /// + //////////////////////////////////////////////////////////// + Vector2i mapCoordsToPixel(const Vector2f& point, const View& view) const; + + //////////////////////////////////////////////////////////// + /// \brief Draw a drawable object to the render-target + /// + /// \param drawable Object to draw + /// \param states Render states to use for drawing + /// + //////////////////////////////////////////////////////////// + void draw(const Drawable& drawable, const RenderStates& states = RenderStates::Default); + + //////////////////////////////////////////////////////////// + /// \brief Draw primitives defined by an array of vertices + /// + /// \param vertices Pointer to the vertices + /// \param vertexCount Number of vertices in the array + /// \param type Type of primitives to draw + /// \param states Render states to use for drawing + /// + //////////////////////////////////////////////////////////// + void draw(const Vertex* vertices, unsigned int vertexCount, + PrimitiveType type, const RenderStates& states = RenderStates::Default); + + //////////////////////////////////////////////////////////// + /// \brief Return the size of the rendering region of the target + /// + /// \return Size in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2u getSize() const = 0; + + //////////////////////////////////////////////////////////// + /// \brief Save the current OpenGL render states and matrices + /// + /// This function can be used when you mix SFML drawing + /// and direct OpenGL rendering. Combined with PopGLStates, + /// it ensures that: + /// \li SFML's internal states are not messed up by your OpenGL code + /// \li your OpenGL states are not modified by a call to a SFML function + /// + /// More specifically, it must be used around code that + /// calls Draw functions. Example: + /// \code + /// // OpenGL code here... + /// window.pushGLStates(); + /// window.draw(...); + /// window.draw(...); + /// window.popGLStates(); + /// // OpenGL code here... + /// \endcode + /// + /// Note that this function is quite expensive: it saves all the + /// possible OpenGL states and matrices, even the ones you + /// don't care about. Therefore it should be used wisely. + /// It is provided for convenience, but the best results will + /// be achieved if you handle OpenGL states yourself (because + /// you know which states have really changed, and need to be + /// saved and restored). Take a look at the ResetGLStates + /// function if you do so. + /// + /// \see popGLStates + /// + //////////////////////////////////////////////////////////// + void pushGLStates(); + + //////////////////////////////////////////////////////////// + /// \brief Restore the previously saved OpenGL render states and matrices + /// + /// See the description of pushGLStates to get a detailed + /// description of these functions. + /// + /// \see pushGLStates + /// + //////////////////////////////////////////////////////////// + void popGLStates(); + + //////////////////////////////////////////////////////////// + /// \brief Reset the internal OpenGL states so that the target is ready for drawing + /// + /// This function can be used when you mix SFML drawing + /// and direct OpenGL rendering, if you choose not to use + /// pushGLStates/popGLStates. It makes sure that all OpenGL + /// states needed by SFML are set, so that subsequent draw() + /// calls will work as expected. + /// + /// Example: + /// \code + /// // OpenGL code here... + /// glPushAttrib(...); + /// window.resetGLStates(); + /// window.draw(...); + /// window.draw(...); + /// glPopAttrib(...); + /// // OpenGL code here... + /// \endcode + /// + //////////////////////////////////////////////////////////// + void resetGLStates(); + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + RenderTarget(); + + //////////////////////////////////////////////////////////// + /// \brief Performs the common initialization step after creation + /// + /// The derived classes must call this function after the + /// target is created and ready for drawing. + /// + //////////////////////////////////////////////////////////// + void initialize(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Apply the current view + /// + //////////////////////////////////////////////////////////// + void applyCurrentView(); + + //////////////////////////////////////////////////////////// + /// \brief Apply a new blending mode + /// + /// \param mode Blending mode to apply + /// + //////////////////////////////////////////////////////////// + void applyBlendMode(const BlendMode& mode); + + //////////////////////////////////////////////////////////// + /// \brief Apply a new transform + /// + /// \param transform Transform to apply + /// + //////////////////////////////////////////////////////////// + void applyTransform(const Transform& transform); + + //////////////////////////////////////////////////////////// + /// \brief Apply a new texture + /// + /// \param texture Texture to apply + /// + //////////////////////////////////////////////////////////// + void applyTexture(const Texture* texture); + + //////////////////////////////////////////////////////////// + /// \brief Apply a new shader + /// + /// \param shader Shader to apply + /// + //////////////////////////////////////////////////////////// + void applyShader(const Shader* shader); + + //////////////////////////////////////////////////////////// + /// \brief Activate the target for rendering + /// + /// This function must be implemented by derived classes to make + /// their OpenGL context current; it is called by the base class + /// everytime it's going to use OpenGL calls. + /// + /// \param active True to make the target active, false to deactivate it + /// + /// \return True if the function succeeded + /// + //////////////////////////////////////////////////////////// + virtual bool activate(bool active) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Render states cache + /// + //////////////////////////////////////////////////////////// + struct StatesCache + { + enum {VertexCacheSize = 4}; + + bool glStatesSet; ///< Are our internal GL states set yet? + bool viewChanged; ///< Has the current view changed since last draw? + BlendMode lastBlendMode; ///< Cached blending mode + Uint64 lastTextureId; ///< Cached texture + bool useVertexCache; ///< Did we previously use the vertex cache? + Vertex vertexCache[VertexCacheSize]; ///< Pre-transformed vertices cache + }; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + View m_defaultView; ///< Default view + View m_view; ///< Current view + StatesCache m_cache; ///< Render states cache +}; + +} // namespace sf + + +#endif // SFML_RENDERTARGET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RenderTarget +/// \ingroup graphics +/// +/// sf::RenderTarget defines the common behaviour of all the +/// 2D render targets usable in the graphics module. It makes +/// it possible to draw 2D entities like sprites, shapes, text +/// without using any OpenGL command directly. +/// +/// A sf::RenderTarget is also able to use views (sf::View), +/// which are a kind of 2D cameras. With views you can globally +/// scroll, rotate or zoom everything that is drawn, +/// without having to transform every single entity. See the +/// documentation of sf::View for more details and sample pieces of +/// code about this class. +/// +/// On top of that, render targets are still able to render direct +/// OpenGL stuff. It is even possible to mix together OpenGL calls +/// and regular SFML drawing commands. When doing so, make sure that +/// OpenGL states are not messed up by calling the +/// pushGLStates/popGLStates functions. +/// +/// \see sf::RenderWindow, sf::RenderTexture, sf::View +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/RenderTexture.hpp b/include/SFML/Graphics/RenderTexture.hpp index 2bb6b7ea..fb6e1241 100644 --- a/include/SFML/Graphics/RenderTexture.hpp +++ b/include/SFML/Graphics/RenderTexture.hpp @@ -1,280 +1,280 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_RENDERTEXTURE_HPP -#define SFML_RENDERTEXTURE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ - class RenderTextureImpl; -} - -//////////////////////////////////////////////////////////// -/// \brief Target for off-screen 2D rendering into a texture -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API RenderTexture : public RenderTarget -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Constructs an empty, invalid render-texture. You must - /// call create to have a valid render-texture. - /// - /// \see create - /// - //////////////////////////////////////////////////////////// - RenderTexture(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - virtual ~RenderTexture(); - - //////////////////////////////////////////////////////////// - /// \brief Create the render-texture - /// - /// Before calling this function, the render-texture is in - /// an invalid state, thus it is mandatory to call it before - /// doing anything with the render-texture. - /// The last parameter, \a depthBuffer, is useful if you want - /// to use the render-texture for 3D OpenGL rendering that requires - /// a depth-buffer. Otherwise it is unnecessary, and you should - /// leave this parameter to false (which is its default value). - /// - /// \param width Width of the render-texture - /// \param height Height of the render-texture - /// \param depthBuffer Do you want this render-texture to have a depth buffer? - /// - /// \return True if creation has been successful - /// - //////////////////////////////////////////////////////////// - bool create(unsigned int width, unsigned int height, bool depthBuffer = false); - - //////////////////////////////////////////////////////////// - /// \brief Enable or disable texture smoothing - /// - /// This function is similar to Texture::setSmooth. - /// This parameter is disabled by default. - /// - /// \param smooth True to enable smoothing, false to disable it - /// - /// \see isSmooth - /// - //////////////////////////////////////////////////////////// - void setSmooth(bool smooth); - - //////////////////////////////////////////////////////////// - /// \brief Tell whether the smooth filtering is enabled or not - /// - /// \return True if texture smoothing is enabled - /// - /// \see setSmooth - /// - //////////////////////////////////////////////////////////// - bool isSmooth() const; - - //////////////////////////////////////////////////////////// - /// \brief Enable or disable texture repeating - /// - /// This function is similar to Texture::setRepeated. - /// This parameter is disabled by default. - /// - /// \param repeated True to enable repeating, false to disable it - /// - /// \see isRepeated - /// - //////////////////////////////////////////////////////////// - void setRepeated(bool repeated); - - //////////////////////////////////////////////////////////// - /// \brief Tell whether the texture is repeated or not - /// - /// \return True if texture is repeated - /// - /// \see setRepeated - /// - //////////////////////////////////////////////////////////// - bool isRepeated() const; - - //////////////////////////////////////////////////////////// - /// \brief Activate of deactivate the render-texture for rendering - /// - /// This function makes the render-texture's context current for - /// future OpenGL rendering operations (so you shouldn't care - /// about it if you're not doing direct OpenGL stuff). - /// Only one context can be current in a thread, so if you - /// want to draw OpenGL geometry to another render target - /// (like a RenderWindow) don't forget to activate it again. - /// - /// \param active True to activate, false to deactivate - /// - /// \return True if operation was successful, false otherwise - /// - //////////////////////////////////////////////////////////// - bool setActive(bool active = true); - - //////////////////////////////////////////////////////////// - /// \brief Update the contents of the target texture - /// - /// This function updates the target texture with what - /// has been drawn so far. Like for windows, calling this - /// function is mandatory at the end of rendering. Not calling - /// it may leave the texture in an undefined state. - /// - //////////////////////////////////////////////////////////// - void display(); - - //////////////////////////////////////////////////////////// - /// \brief Return the size of the rendering region of the texture - /// - /// The returned value is the size that you passed to - /// the create function. - /// - /// \return Size in pixels - /// - //////////////////////////////////////////////////////////// - virtual Vector2u getSize() const; - - //////////////////////////////////////////////////////////// - /// \brief Get a read-only reference to the target texture - /// - /// After drawing to the render-texture and calling Display, - /// you can retrieve the updated texture using this function, - /// and draw it using a sprite (for example). - /// The internal sf::Texture of a render-texture is always the - /// same instance, so that it is possible to call this function - /// once and keep a reference to the texture even after it is - /// modified. - /// - /// \return Const reference to the texture - /// - //////////////////////////////////////////////////////////// - const Texture& getTexture() const; - -private : - - //////////////////////////////////////////////////////////// - /// \brief Activate the target for rendering - /// - /// This function is called by the base class - /// everytime it's going to use OpenGL calls. - /// - /// \param active True to make the target active, false to deactivate it - /// - /// \return True if the function succeeded - /// - //////////////////////////////////////////////////////////// - virtual bool activate(bool active); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - priv::RenderTextureImpl* m_impl; ///< Platform/hardware specific implementation - Texture m_texture; ///< Target texture to draw on -}; - -} // namespace sf - - -#endif // SFML_RENDERTEXTURE_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::RenderTexture -/// \ingroup graphics -/// -/// sf::RenderTexture is the little brother of sf::RenderWindow. -/// It implements the same 2D drawing and OpenGL-related functions -/// (see their base class sf::RenderTarget for more details), -/// the difference is that the result is stored in an off-screen -/// texture rather than being show in a window. -/// -/// Rendering to a texture can be useful in a variety of situations: -/// \li precomputing a complex static texture (like a level's background from multiple tiles) -/// \li applying post-effects to the whole scene with shaders -/// \li creating a sprite from a 3D object rendered with OpenGL -/// \li etc. -/// -/// Usage example: -/// -/// \code -/// // Create a new render-window -/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); -/// -/// // Create a new render-texture -/// sf::RenderTexture texture; -/// if (!texture.create(500, 500)) -/// return -1; -/// -/// // The main loop -/// while (window.isOpen()) -/// { -/// // Event processing -/// // ... -/// -/// // Clear the whole texture with red color -/// texture.clear(sf::Color::Red); -/// -/// // Draw stuff to the texture -/// texture.draw(sprite); // sprite is a sf::Sprite -/// texture.draw(shape); // shape is a sf::Shape -/// texture.draw(text); // text is a sf::Text -/// -/// // We're done drawing to the texture -/// texture.display(); -/// -/// // Now we start rendering to the window, clear it first -/// window.clear(); -/// -/// // Draw the texture -/// sf::Sprite sprite(texture.getTexture()); -/// window.draw(sprite); -/// -/// // End the current frame and display its contents on screen -/// window.display(); -/// } -/// \endcode -/// -/// Like sf::RenderWindow, sf::RenderTexture is still able to render direct -/// OpenGL stuff. It is even possible to mix together OpenGL calls -/// and regular SFML drawing commands. If you need a depth buffer for -/// 3D rendering, don't forget to request it when calling RenderTexture::create. -/// -/// \see sf::RenderTarget, sf::RenderWindow, sf::View, sf::Texture -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERTEXTURE_HPP +#define SFML_RENDERTEXTURE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class RenderTextureImpl; +} + +//////////////////////////////////////////////////////////// +/// \brief Target for off-screen 2D rendering into a texture +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API RenderTexture : public RenderTarget +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Constructs an empty, invalid render-texture. You must + /// call create to have a valid render-texture. + /// + /// \see create + /// + //////////////////////////////////////////////////////////// + RenderTexture(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~RenderTexture(); + + //////////////////////////////////////////////////////////// + /// \brief Create the render-texture + /// + /// Before calling this function, the render-texture is in + /// an invalid state, thus it is mandatory to call it before + /// doing anything with the render-texture. + /// The last parameter, \a depthBuffer, is useful if you want + /// to use the render-texture for 3D OpenGL rendering that requires + /// a depth-buffer. Otherwise it is unnecessary, and you should + /// leave this parameter to false (which is its default value). + /// + /// \param width Width of the render-texture + /// \param height Height of the render-texture + /// \param depthBuffer Do you want this render-texture to have a depth buffer? + /// + /// \return True if creation has been successful + /// + //////////////////////////////////////////////////////////// + bool create(unsigned int width, unsigned int height, bool depthBuffer = false); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable texture smoothing + /// + /// This function is similar to Texture::setSmooth. + /// This parameter is disabled by default. + /// + /// \param smooth True to enable smoothing, false to disable it + /// + /// \see isSmooth + /// + //////////////////////////////////////////////////////////// + void setSmooth(bool smooth); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the smooth filtering is enabled or not + /// + /// \return True if texture smoothing is enabled + /// + /// \see setSmooth + /// + //////////////////////////////////////////////////////////// + bool isSmooth() const; + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable texture repeating + /// + /// This function is similar to Texture::setRepeated. + /// This parameter is disabled by default. + /// + /// \param repeated True to enable repeating, false to disable it + /// + /// \see isRepeated + /// + //////////////////////////////////////////////////////////// + void setRepeated(bool repeated); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the texture is repeated or not + /// + /// \return True if texture is repeated + /// + /// \see setRepeated + /// + //////////////////////////////////////////////////////////// + bool isRepeated() const; + + //////////////////////////////////////////////////////////// + /// \brief Activate of deactivate the render-texture for rendering + /// + /// This function makes the render-texture's context current for + /// future OpenGL rendering operations (so you shouldn't care + /// about it if you're not doing direct OpenGL stuff). + /// Only one context can be current in a thread, so if you + /// want to draw OpenGL geometry to another render target + /// (like a RenderWindow) don't forget to activate it again. + /// + /// \param active True to activate, false to deactivate + /// + /// \return True if operation was successful, false otherwise + /// + //////////////////////////////////////////////////////////// + bool setActive(bool active = true); + + //////////////////////////////////////////////////////////// + /// \brief Update the contents of the target texture + /// + /// This function updates the target texture with what + /// has been drawn so far. Like for windows, calling this + /// function is mandatory at the end of rendering. Not calling + /// it may leave the texture in an undefined state. + /// + //////////////////////////////////////////////////////////// + void display(); + + //////////////////////////////////////////////////////////// + /// \brief Return the size of the rendering region of the texture + /// + /// The returned value is the size that you passed to + /// the create function. + /// + /// \return Size in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a read-only reference to the target texture + /// + /// After drawing to the render-texture and calling Display, + /// you can retrieve the updated texture using this function, + /// and draw it using a sprite (for example). + /// The internal sf::Texture of a render-texture is always the + /// same instance, so that it is possible to call this function + /// once and keep a reference to the texture even after it is + /// modified. + /// + /// \return Const reference to the texture + /// + //////////////////////////////////////////////////////////// + const Texture& getTexture() const; + +private: + + //////////////////////////////////////////////////////////// + /// \brief Activate the target for rendering + /// + /// This function is called by the base class + /// everytime it's going to use OpenGL calls. + /// + /// \param active True to make the target active, false to deactivate it + /// + /// \return True if the function succeeded + /// + //////////////////////////////////////////////////////////// + virtual bool activate(bool active); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::RenderTextureImpl* m_impl; ///< Platform/hardware specific implementation + Texture m_texture; ///< Target texture to draw on +}; + +} // namespace sf + + +#endif // SFML_RENDERTEXTURE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RenderTexture +/// \ingroup graphics +/// +/// sf::RenderTexture is the little brother of sf::RenderWindow. +/// It implements the same 2D drawing and OpenGL-related functions +/// (see their base class sf::RenderTarget for more details), +/// the difference is that the result is stored in an off-screen +/// texture rather than being show in a window. +/// +/// Rendering to a texture can be useful in a variety of situations: +/// \li precomputing a complex static texture (like a level's background from multiple tiles) +/// \li applying post-effects to the whole scene with shaders +/// \li creating a sprite from a 3D object rendered with OpenGL +/// \li etc. +/// +/// Usage example: +/// +/// \code +/// // Create a new render-window +/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); +/// +/// // Create a new render-texture +/// sf::RenderTexture texture; +/// if (!texture.create(500, 500)) +/// return -1; +/// +/// // The main loop +/// while (window.isOpen()) +/// { +/// // Event processing +/// // ... +/// +/// // Clear the whole texture with red color +/// texture.clear(sf::Color::Red); +/// +/// // Draw stuff to the texture +/// texture.draw(sprite); // sprite is a sf::Sprite +/// texture.draw(shape); // shape is a sf::Shape +/// texture.draw(text); // text is a sf::Text +/// +/// // We're done drawing to the texture +/// texture.display(); +/// +/// // Now we start rendering to the window, clear it first +/// window.clear(); +/// +/// // Draw the texture +/// sf::Sprite sprite(texture.getTexture()); +/// window.draw(sprite); +/// +/// // End the current frame and display its contents on screen +/// window.display(); +/// } +/// \endcode +/// +/// Like sf::RenderWindow, sf::RenderTexture is still able to render direct +/// OpenGL stuff. It is even possible to mix together OpenGL calls +/// and regular SFML drawing commands. If you need a depth buffer for +/// 3D rendering, don't forget to request it when calling RenderTexture::create. +/// +/// \see sf::RenderTarget, sf::RenderWindow, sf::View, sf::Texture +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/RenderWindow.hpp b/include/SFML/Graphics/RenderWindow.hpp index 58776298..c70772db 100644 --- a/include/SFML/Graphics/RenderWindow.hpp +++ b/include/SFML/Graphics/RenderWindow.hpp @@ -1,267 +1,267 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_RENDERWINDOW_HPP -#define SFML_RENDERWINDOW_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Window that can serve as a target for 2D drawing -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API RenderWindow : public Window, public RenderTarget -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor doesn't actually create the window, - /// use the other constructors or call create() to do so. - /// - //////////////////////////////////////////////////////////// - RenderWindow(); - - //////////////////////////////////////////////////////////// - /// \brief Construct a new window - /// - /// This constructor creates the window with the size and pixel - /// depth defined in \a mode. An optional style can be passed to - /// customize the look and behaviour of the window (borders, - /// title bar, resizable, closable, ...). - /// - /// The fourth parameter is an optional structure specifying - /// advanced OpenGL context settings such as antialiasing, - /// depth-buffer bits, etc. You shouldn't care about these - /// parameters for a regular usage of the graphics module. - /// - /// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window) - /// \param title Title of the window - /// \param style %Window style, a bitwise OR combination of sf::Style enumerators - /// \param settings Additional settings for the underlying OpenGL context - /// - //////////////////////////////////////////////////////////// - RenderWindow(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings()); - - //////////////////////////////////////////////////////////// - /// \brief Construct the window from an existing control - /// - /// Use this constructor if you want to create an SFML - /// rendering area into an already existing control. - /// - /// The second parameter is an optional structure specifying - /// advanced OpenGL context settings such as antialiasing, - /// depth-buffer bits, etc. You shouldn't care about these - /// parameters for a regular usage of the graphics module. - /// - /// \param handle Platform-specific handle of the control (\a HWND on - /// Windows, \a %Window on Linux/FreeBSD, \a NSWindow on OS X) - /// \param settings Additional settings for the underlying OpenGL context - /// - //////////////////////////////////////////////////////////// - explicit RenderWindow(WindowHandle handle, const ContextSettings& settings = ContextSettings()); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - /// Closes the window and frees all the resources attached to it. - /// - //////////////////////////////////////////////////////////// - virtual ~RenderWindow(); - - //////////////////////////////////////////////////////////// - /// \brief Get the size of the rendering region of the window - /// - /// The size doesn't include the titlebar and borders - /// of the window. - /// - /// \return Size in pixels - /// - //////////////////////////////////////////////////////////// - virtual Vector2u getSize() const; - - //////////////////////////////////////////////////////////// - /// \brief Copy the current contents of the window to an image - /// - /// This is a slow operation, whose main purpose is to make - /// screenshots of the application. If you want to update an - /// image with the contents of the window and then use it for - /// drawing, you should rather use a sf::Texture and its - /// update(Window&) function. - /// You can also draw things directly to a texture with the - /// sf::RenderTexture class. - /// - /// \return Image containing the captured contents - /// - //////////////////////////////////////////////////////////// - Image capture() const; - -protected: - - //////////////////////////////////////////////////////////// - /// \brief Function called after the window has been created - /// - /// This function is called so that derived classes can - /// perform their own specific initialization as soon as - /// the window is created. - /// - //////////////////////////////////////////////////////////// - virtual void onCreate(); - - //////////////////////////////////////////////////////////// - /// \brief Function called after the window has been resized - /// - /// This function is called so that derived classes can - /// perform custom actions when the size of the window changes. - /// - //////////////////////////////////////////////////////////// - virtual void onResize(); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Activate the target for rendering - /// - /// \param active True to make the target active, false to deactivate it - /// - /// \return True if the function succeeded - /// - //////////////////////////////////////////////////////////// - virtual bool activate(bool active); -}; - -} // namespace sf - - -#endif // SFML_RENDERWINDOW_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::RenderWindow -/// \ingroup graphics -/// -/// sf::RenderWindow is the main class of the Graphics module. -/// It defines an OS window that can be painted using the other -/// classes of the graphics module. -/// -/// sf::RenderWindow is derived from sf::Window, thus it inherits -/// all its features: events, window management, OpenGL rendering, -/// etc. See the documentation of sf::Window for a more complete -/// description of all these features, as well as code examples. -/// -/// On top of that, sf::RenderWindow adds more features related to -/// 2D drawing with the graphics module (see its base class -/// sf::RenderTarget for more details). -/// Here is a typical rendering and event loop with a sf::RenderWindow: -/// -/// \code -/// // Declare and create a new render-window -/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); -/// -/// // Limit the framerate to 60 frames per second (this step is optional) -/// window.setFramerateLimit(60); -/// -/// // The main loop - ends as soon as the window is closed -/// while (window.isOpen()) -/// { -/// // Event processing -/// sf::Event event; -/// while (window.pollEvent(event)) -/// { -/// // Request for closing the window -/// if (event.type == sf::Event::Closed) -/// window.close(); -/// } -/// -/// // Clear the whole window before rendering a new frame -/// window.clear(); -/// -/// // Draw some graphical entities -/// window.draw(sprite); -/// window.draw(circle); -/// window.draw(text); -/// -/// // End the current frame and display its contents on screen -/// window.display(); -/// } -/// \endcode -/// -/// Like sf::Window, sf::RenderWindow is still able to render direct -/// OpenGL stuff. It is even possible to mix together OpenGL calls -/// and regular SFML drawing commands. -/// -/// \code -/// // Create the render window -/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML OpenGL"); -/// -/// // Create a sprite and a text to display -/// sf::Sprite sprite; -/// sf::Text text; -/// ... -/// -/// // Perform OpenGL initializations -/// glMatrixMode(GL_PROJECTION); -/// ... -/// -/// // Start the rendering loop -/// while (window.isOpen()) -/// { -/// // Process events -/// ... -/// -/// // Draw a background sprite -/// window.pushGLStates(); -/// window.draw(sprite); -/// window.popGLStates(); -/// -/// // Draw a 3D object using OpenGL -/// glBegin(GL_QUADS); -/// glVertex3f(...); -/// ... -/// glEnd(); -/// -/// // Draw text on top of the 3D object -/// window.pushGLStates(); -/// window.draw(text); -/// window.popGLStates(); -/// -/// // Finally, display the rendered frame on screen -/// window.display(); -/// } -/// \endcode -/// -/// \see sf::Window, sf::RenderTarget, sf::RenderTexture, sf::View -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERWINDOW_HPP +#define SFML_RENDERWINDOW_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Window that can serve as a target for 2D drawing +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API RenderWindow : public Window, public RenderTarget +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor doesn't actually create the window, + /// use the other constructors or call create() to do so. + /// + //////////////////////////////////////////////////////////// + RenderWindow(); + + //////////////////////////////////////////////////////////// + /// \brief Construct a new window + /// + /// This constructor creates the window with the size and pixel + /// depth defined in \a mode. An optional style can be passed to + /// customize the look and behaviour of the window (borders, + /// title bar, resizable, closable, ...). + /// + /// The fourth parameter is an optional structure specifying + /// advanced OpenGL context settings such as antialiasing, + /// depth-buffer bits, etc. You shouldn't care about these + /// parameters for a regular usage of the graphics module. + /// + /// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window) + /// \param title Title of the window + /// \param style %Window style, a bitwise OR combination of sf::Style enumerators + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + RenderWindow(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Construct the window from an existing control + /// + /// Use this constructor if you want to create an SFML + /// rendering area into an already existing control. + /// + /// The second parameter is an optional structure specifying + /// advanced OpenGL context settings such as antialiasing, + /// depth-buffer bits, etc. You shouldn't care about these + /// parameters for a regular usage of the graphics module. + /// + /// \param handle Platform-specific handle of the control (\a HWND on + /// Windows, \a %Window on Linux/FreeBSD, \a NSWindow on OS X) + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + explicit RenderWindow(WindowHandle handle, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// Closes the window and frees all the resources attached to it. + /// + //////////////////////////////////////////////////////////// + virtual ~RenderWindow(); + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the rendering region of the window + /// + /// The size doesn't include the titlebar and borders + /// of the window. + /// + /// \return Size in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Copy the current contents of the window to an image + /// + /// This is a slow operation, whose main purpose is to make + /// screenshots of the application. If you want to update an + /// image with the contents of the window and then use it for + /// drawing, you should rather use a sf::Texture and its + /// update(Window&) function. + /// You can also draw things directly to a texture with the + /// sf::RenderTexture class. + /// + /// \return Image containing the captured contents + /// + //////////////////////////////////////////////////////////// + Image capture() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Function called after the window has been created + /// + /// This function is called so that derived classes can + /// perform their own specific initialization as soon as + /// the window is created. + /// + //////////////////////////////////////////////////////////// + virtual void onCreate(); + + //////////////////////////////////////////////////////////// + /// \brief Function called after the window has been resized + /// + /// This function is called so that derived classes can + /// perform custom actions when the size of the window changes. + /// + //////////////////////////////////////////////////////////// + virtual void onResize(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Activate the target for rendering + /// + /// \param active True to make the target active, false to deactivate it + /// + /// \return True if the function succeeded + /// + //////////////////////////////////////////////////////////// + virtual bool activate(bool active); +}; + +} // namespace sf + + +#endif // SFML_RENDERWINDOW_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RenderWindow +/// \ingroup graphics +/// +/// sf::RenderWindow is the main class of the Graphics module. +/// It defines an OS window that can be painted using the other +/// classes of the graphics module. +/// +/// sf::RenderWindow is derived from sf::Window, thus it inherits +/// all its features: events, window management, OpenGL rendering, +/// etc. See the documentation of sf::Window for a more complete +/// description of all these features, as well as code examples. +/// +/// On top of that, sf::RenderWindow adds more features related to +/// 2D drawing with the graphics module (see its base class +/// sf::RenderTarget for more details). +/// Here is a typical rendering and event loop with a sf::RenderWindow: +/// +/// \code +/// // Declare and create a new render-window +/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); +/// +/// // Limit the framerate to 60 frames per second (this step is optional) +/// window.setFramerateLimit(60); +/// +/// // The main loop - ends as soon as the window is closed +/// while (window.isOpen()) +/// { +/// // Event processing +/// sf::Event event; +/// while (window.pollEvent(event)) +/// { +/// // Request for closing the window +/// if (event.type == sf::Event::Closed) +/// window.close(); +/// } +/// +/// // Clear the whole window before rendering a new frame +/// window.clear(); +/// +/// // Draw some graphical entities +/// window.draw(sprite); +/// window.draw(circle); +/// window.draw(text); +/// +/// // End the current frame and display its contents on screen +/// window.display(); +/// } +/// \endcode +/// +/// Like sf::Window, sf::RenderWindow is still able to render direct +/// OpenGL stuff. It is even possible to mix together OpenGL calls +/// and regular SFML drawing commands. +/// +/// \code +/// // Create the render window +/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML OpenGL"); +/// +/// // Create a sprite and a text to display +/// sf::Sprite sprite; +/// sf::Text text; +/// ... +/// +/// // Perform OpenGL initializations +/// glMatrixMode(GL_PROJECTION); +/// ... +/// +/// // Start the rendering loop +/// while (window.isOpen()) +/// { +/// // Process events +/// ... +/// +/// // Draw a background sprite +/// window.pushGLStates(); +/// window.draw(sprite); +/// window.popGLStates(); +/// +/// // Draw a 3D object using OpenGL +/// glBegin(GL_QUADS); +/// glVertex3f(...); +/// ... +/// glEnd(); +/// +/// // Draw text on top of the 3D object +/// window.pushGLStates(); +/// window.draw(text); +/// window.popGLStates(); +/// +/// // Finally, display the rendered frame on screen +/// window.display(); +/// } +/// \endcode +/// +/// \see sf::Window, sf::RenderTarget, sf::RenderTexture, sf::View +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Shader.hpp b/include/SFML/Graphics/Shader.hpp index 028dd727..c60db273 100644 --- a/include/SFML/Graphics/Shader.hpp +++ b/include/SFML/Graphics/Shader.hpp @@ -1,647 +1,647 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SHADER_HPP -#define SFML_SHADER_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -class InputStream; -class Texture; - -//////////////////////////////////////////////////////////// -/// \brief Shader class (vertex and fragment) -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API Shader : GlResource, NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Types of shaders - /// - //////////////////////////////////////////////////////////// - enum Type - { - Vertex, ///< Vertex shader - Fragment ///< Fragment (pixel) shader - }; - - //////////////////////////////////////////////////////////// - /// \brief Special type that can be passed to setParameter, - /// and that represents the texture of the object being drawn - /// - /// \see setParameter(const std::string&, CurrentTextureType) - /// - //////////////////////////////////////////////////////////// - struct CurrentTextureType {}; - - //////////////////////////////////////////////////////////// - /// \brief Represents the texture of the object being drawn - /// - /// \see setParameter(const std::string&, CurrentTextureType) - /// - //////////////////////////////////////////////////////////// - static CurrentTextureType CurrentTexture; - -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor creates an invalid shader. - /// - //////////////////////////////////////////////////////////// - Shader(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~Shader(); - - //////////////////////////////////////////////////////////// - /// \brief Load either the vertex or fragment shader from a file - /// - /// This function loads a single shader, either vertex or - /// fragment, identified by the second argument. - /// The source must be a text file containing a valid - /// shader in GLSL language. GLSL is a C-like language - /// dedicated to OpenGL shaders; you'll probably need to - /// read a good documentation for it before writing your - /// own shaders. - /// - /// \param filename Path of the vertex or fragment shader file to load - /// \param type Type of shader (vertex or fragment) - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromMemory, loadFromStream - /// - //////////////////////////////////////////////////////////// - bool loadFromFile(const std::string& filename, Type type); - - //////////////////////////////////////////////////////////// - /// \brief Load both the vertex and fragment shaders from files - /// - /// This function loads both the vertex and the fragment - /// shaders. If one of them fails to load, the shader is left - /// empty (the valid shader is unloaded). - /// The sources must be text files containing valid shaders - /// in GLSL language. GLSL is a C-like language dedicated to - /// OpenGL shaders; you'll probably need to read a good documentation - /// for it before writing your own shaders. - /// - /// \param vertexShaderFilename Path of the vertex shader file to load - /// \param fragmentShaderFilename Path of the fragment shader file to load - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromMemory, loadFromStream - /// - //////////////////////////////////////////////////////////// - bool loadFromFile(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename); - - //////////////////////////////////////////////////////////// - /// \brief Load either the vertex or fragment shader from a source code in memory - /// - /// This function loads a single shader, either vertex or - /// fragment, identified by the second argument. - /// The source code must be a valid shader in GLSL language. - /// GLSL is a C-like language dedicated to OpenGL shaders; - /// you'll probably need to read a good documentation for - /// it before writing your own shaders. - /// - /// \param shader String containing the source code of the shader - /// \param type Type of shader (vertex or fragment) - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromFile, loadFromStream - /// - //////////////////////////////////////////////////////////// - bool loadFromMemory(const std::string& shader, Type type); - - //////////////////////////////////////////////////////////// - /// \brief Load both the vertex and fragment shaders from source codes in memory - /// - /// This function loads both the vertex and the fragment - /// shaders. If one of them fails to load, the shader is left - /// empty (the valid shader is unloaded). - /// The sources must be valid shaders in GLSL language. GLSL is - /// a C-like language dedicated to OpenGL shaders; you'll - /// probably need to read a good documentation for it before - /// writing your own shaders. - /// - /// \param vertexShader String containing the source code of the vertex shader - /// \param fragmentShader String containing the source code of the fragment shader - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromFile, loadFromStream - /// - //////////////////////////////////////////////////////////// - bool loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader); - - //////////////////////////////////////////////////////////// - /// \brief Load either the vertex or fragment shader from a custom stream - /// - /// This function loads a single shader, either vertex or - /// fragment, identified by the second argument. - /// The source code must be a valid shader in GLSL language. - /// GLSL is a C-like language dedicated to OpenGL shaders; - /// you'll probably need to read a good documentation for it - /// before writing your own shaders. - /// - /// \param stream Source stream to read from - /// \param type Type of shader (vertex or fragment) - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromFile, loadFromMemory - /// - //////////////////////////////////////////////////////////// - bool loadFromStream(InputStream& stream, Type type); - - //////////////////////////////////////////////////////////// - /// \brief Load both the vertex and fragment shaders from custom streams - /// - /// This function loads both the vertex and the fragment - /// shaders. If one of them fails to load, the shader is left - /// empty (the valid shader is unloaded). - /// The source codes must be valid shaders in GLSL language. - /// GLSL is a C-like language dedicated to OpenGL shaders; - /// you'll probably need to read a good documentation for - /// it before writing your own shaders. - /// - /// \param vertexShaderStream Source stream to read the vertex shader from - /// \param fragmentShaderStream Source stream to read the fragment shader from - /// - /// \return True if loading succeeded, false if it failed - /// - /// \see loadFromFile, loadFromMemory - /// - //////////////////////////////////////////////////////////// - bool loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream); - - //////////////////////////////////////////////////////////// - /// \brief Change a float parameter of the shader - /// - /// \a name is the name of the variable to change in the shader. - /// The corresponding parameter in the shader must be a float - /// (float GLSL type). - /// - /// Example: - /// \code - /// uniform float myparam; // this is the variable in the shader - /// \endcode - /// \code - /// shader.setParameter("myparam", 5.2f); - /// \endcode - /// - /// \param name Name of the parameter in the shader - /// \param x Value to assign - /// - //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, float x); - - //////////////////////////////////////////////////////////// - /// \brief Change a 2-components vector parameter of the shader - /// - /// \a name is the name of the variable to change in the shader. - /// The corresponding parameter in the shader must be a 2x1 vector - /// (vec2 GLSL type). - /// - /// Example: - /// \code - /// uniform vec2 myparam; // this is the variable in the shader - /// \endcode - /// \code - /// shader.setParameter("myparam", 5.2f, 6.0f); - /// \endcode - /// - /// \param name Name of the parameter in the shader - /// \param x First component of the value to assign - /// \param y Second component of the value to assign - /// - //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, float x, float y); - - //////////////////////////////////////////////////////////// - /// \brief Change a 3-components vector parameter of the shader - /// - /// \a name is the name of the variable to change in the shader. - /// The corresponding parameter in the shader must be a 3x1 vector - /// (vec3 GLSL type). - /// - /// Example: - /// \code - /// uniform vec3 myparam; // this is the variable in the shader - /// \endcode - /// \code - /// shader.setParameter("myparam", 5.2f, 6.0f, -8.1f); - /// \endcode - /// - /// \param name Name of the parameter in the shader - /// \param x First component of the value to assign - /// \param y Second component of the value to assign - /// \param z Third component of the value to assign - /// - //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, float x, float y, float z); - - //////////////////////////////////////////////////////////// - /// \brief Change a 4-components vector parameter of the shader - /// - /// \a name is the name of the variable to change in the shader. - /// The corresponding parameter in the shader must be a 4x1 vector - /// (vec4 GLSL type). - /// - /// Example: - /// \code - /// uniform vec4 myparam; // this is the variable in the shader - /// \endcode - /// \code - /// shader.setParameter("myparam", 5.2f, 6.0f, -8.1f, 0.4f); - /// \endcode - /// - /// \param name Name of the parameter in the shader - /// \param x First component of the value to assign - /// \param y Second component of the value to assign - /// \param z Third component of the value to assign - /// \param w Fourth component of the value to assign - /// - //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, float x, float y, float z, float w); - - //////////////////////////////////////////////////////////// - /// \brief Change a 2-components vector parameter of the shader - /// - /// \a name is the name of the variable to change in the shader. - /// The corresponding parameter in the shader must be a 2x1 vector - /// (vec2 GLSL type). - /// - /// Example: - /// \code - /// uniform vec2 myparam; // this is the variable in the shader - /// \endcode - /// \code - /// shader.setParameter("myparam", sf::Vector2f(5.2f, 6.0f)); - /// \endcode - /// - /// \param name Name of the parameter in the shader - /// \param vector Vector to assign - /// - //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, const Vector2f& vector); - - //////////////////////////////////////////////////////////// - /// \brief Change a 3-components vector parameter of the shader - /// - /// \a name is the name of the variable to change in the shader. - /// The corresponding parameter in the shader must be a 3x1 vector - /// (vec3 GLSL type). - /// - /// Example: - /// \code - /// uniform vec3 myparam; // this is the variable in the shader - /// \endcode - /// \code - /// shader.setParameter("myparam", sf::Vector3f(5.2f, 6.0f, -8.1f)); - /// \endcode - /// - /// \param name Name of the parameter in the shader - /// \param vector Vector to assign - /// - //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, const Vector3f& vector); - - //////////////////////////////////////////////////////////// - /// \brief Change a color parameter of the shader - /// - /// \a name is the name of the variable to change in the shader. - /// The corresponding parameter in the shader must be a 4x1 vector - /// (vec4 GLSL type). - /// - /// It is important to note that the components of the color are - /// normalized before being passed to the shader. Therefore, - /// they are converted from range [0 .. 255] to range [0 .. 1]. - /// For example, a sf::Color(255, 125, 0, 255) will be transformed - /// to a vec4(1.0, 0.5, 0.0, 1.0) in the shader. - /// - /// Example: - /// \code - /// uniform vec4 color; // this is the variable in the shader - /// \endcode - /// \code - /// shader.setParameter("color", sf::Color(255, 128, 0, 255)); - /// \endcode - /// - /// \param name Name of the parameter in the shader - /// \param color Color to assign - /// - //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Change a matrix parameter of the shader - /// - /// \a name is the name of the variable to change in the shader. - /// The corresponding parameter in the shader must be a 4x4 matrix - /// (mat4 GLSL type). - /// - /// Example: - /// \code - /// uniform mat4 matrix; // this is the variable in the shader - /// \endcode - /// \code - /// sf::Transform transform; - /// transform.translate(5, 10); - /// shader.setParameter("matrix", transform); - /// \endcode - /// - /// \param name Name of the parameter in the shader - /// \param transform Transform to assign - /// - //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, const sf::Transform& transform); - - //////////////////////////////////////////////////////////// - /// \brief Change a texture parameter of the shader - /// - /// \a name is the name of the variable to change in the shader. - /// The corresponding parameter in the shader must be a 2D texture - /// (sampler2D GLSL type). - /// - /// Example: - /// \code - /// uniform sampler2D the_texture; // this is the variable in the shader - /// \endcode - /// \code - /// sf::Texture texture; - /// ... - /// shader.setParameter("the_texture", texture); - /// \endcode - /// It is important to note that \a texture must remain alive as long - /// as the shader uses it, no copy is made internally. - /// - /// To use the texture of the object being draw, which cannot be - /// known in advance, you can pass the special value - /// sf::Shader::CurrentTexture: - /// \code - /// shader.setParameter("the_texture", sf::Shader::CurrentTexture). - /// \endcode - /// - /// \param name Name of the texture in the shader - /// \param texture Texture to assign - /// - //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, const Texture& texture); - - //////////////////////////////////////////////////////////// - /// \brief Change a texture parameter of the shader - /// - /// This overload maps a shader texture variable to the - /// texture of the object being drawn, which cannot be - /// known in advance. The second argument must be - /// sf::Shader::CurrentTexture. - /// The corresponding parameter in the shader must be a 2D texture - /// (sampler2D GLSL type). - /// - /// Example: - /// \code - /// uniform sampler2D current; // this is the variable in the shader - /// \endcode - /// \code - /// shader.setParameter("current", sf::Shader::CurrentTexture); - /// \endcode - /// - /// \param name Name of the texture in the shader - /// - //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, CurrentTextureType); - - //////////////////////////////////////////////////////////// - /// \brief Bind a shader for rendering - /// - /// This function is not part of the graphics API, it mustn't be - /// used when drawing SFML entities. It must be used only if you - /// mix sf::Shader with OpenGL code. - /// - /// \code - /// sf::Shader s1, s2; - /// ... - /// sf::Shader::bind(&s1); - /// // draw OpenGL stuff that use s1... - /// sf::Shader::bind(&s2); - /// // draw OpenGL stuff that use s2... - /// sf::Shader::bind(NULL); - /// // draw OpenGL stuff that use no shader... - /// \endcode - /// - /// \param shader Shader to bind, can be null to use no shader - /// - //////////////////////////////////////////////////////////// - static void bind(const Shader* shader); - - //////////////////////////////////////////////////////////// - /// \brief Tell whether or not the system supports shaders - /// - /// This function should always be called before using - /// the shader features. If it returns false, then - /// any attempt to use sf::Shader will fail. - /// - /// Note: The first call to this function, whether by your - /// code or SFML will result in a context switch. - /// - /// \return True if shaders are supported, false otherwise - /// - //////////////////////////////////////////////////////////// - static bool isAvailable(); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Compile the shader(s) and create the program - /// - /// If one of the arguments is NULL, the corresponding shader - /// is not created. - /// - /// \param vertexShaderCode Source code of the vertex shader - /// \param fragmentShaderCode Source code of the fragment shader - /// - /// \return True on success, false if any error happened - /// - //////////////////////////////////////////////////////////// - bool compile(const char* vertexShaderCode, const char* fragmentShaderCode); - - //////////////////////////////////////////////////////////// - /// \brief Bind all the textures used by the shader - /// - /// This function each texture to a different unit, and - /// updates the corresponding variables in the shader accordingly. - /// - //////////////////////////////////////////////////////////// - void bindTextures() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the location ID of a shader parameter - /// - /// \param name Name of the parameter to search - /// - /// \return Location ID of the parameter, or -1 if not found - /// - //////////////////////////////////////////////////////////// - int getParamLocation(const std::string& name); - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef std::map TextureTable; - typedef std::map ParamTable; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - unsigned int m_shaderProgram; ///< OpenGL identifier for the program - int m_currentTexture; ///< Location of the current texture in the shader - TextureTable m_textures; ///< Texture variables in the shader, mapped to their location - ParamTable m_params; ///< Parameters location cache -}; - -} // namespace sf - - -#endif // SFML_SHADER_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Shader -/// \ingroup graphics -/// -/// Shaders are programs written using a specific language, -/// executed directly by the graphics card and allowing -/// to apply real-time operations to the rendered entities. -/// -/// There are two kinds of shaders: -/// \li Vertex shaders, that process vertices -/// \li Fragment (pixel) shaders, that process pixels -/// -/// A sf::Shader can be composed of either a vertex shader -/// alone, a fragment shader alone, or both combined -/// (see the variants of the load functions). -/// -/// Shaders are written in GLSL, which is a C-like -/// language dedicated to OpenGL shaders. You'll probably -/// need to learn its basics before writing your own shaders -/// for SFML. -/// -/// Like any C/C++ program, a shader has its own variables -/// that you can set from your C++ application. sf::Shader -/// handles 5 different types of variables: -/// \li floats -/// \li vectors (2, 3 or 4 components) -/// \li colors -/// \li textures -/// \li transforms (matrices) -/// -/// The value of the variables can be changed at any time -/// with the various overloads of the setParameter function: -/// \code -/// shader.setParameter("offset", 2.f); -/// shader.setParameter("point", 0.5f, 0.8f, 0.3f); -/// shader.setParameter("color", sf::Color(128, 50, 255)); -/// shader.setParameter("matrix", transform); // transform is a sf::Transform -/// shader.setParameter("overlay", texture); // texture is a sf::Texture -/// shader.setParameter("texture", sf::Shader::CurrentTexture); -/// \endcode -/// -/// The special Shader::CurrentTexture argument maps the -/// given texture variable to the current texture of the -/// object being drawn (which cannot be known in advance). -/// -/// To apply a shader to a drawable, you must pass it as an -/// additional parameter to the Draw function: -/// \code -/// window.draw(sprite, &shader); -/// \endcode -/// -/// ... which is in fact just a shortcut for this: -/// \code -/// sf::RenderStates states; -/// states.shader = &shader; -/// window.draw(sprite, states); -/// \endcode -/// -/// In the code above we pass a pointer to the shader, because it may -/// be null (which means "no shader"). -/// -/// Shaders can be used on any drawable, but some combinations are -/// not interesting. For example, using a vertex shader on a sf::Sprite -/// is limited because there are only 4 vertices, the sprite would -/// have to be subdivided in order to apply wave effects. -/// Another bad example is a fragment shader with sf::Text: the texture -/// of the text is not the actual text that you see on screen, it is -/// a big texture containing all the characters of the font in an -/// arbitrary order; thus, texture lookups on pixels other than the -/// current one may not give you the expected result. -/// -/// Shaders can also be used to apply global post-effects to the -/// current contents of the target (like the old sf::PostFx class -/// in SFML 1). This can be done in two different ways: -/// \li draw everything to a sf::RenderTexture, then draw it to -/// the main target using the shader -/// \li draw everything directly to the main target, then use -/// sf::Texture::update(Window&) to copy its contents to a texture -/// and draw it to the main target using the shader -/// -/// The first technique is more optimized because it doesn't involve -/// retrieving the target's pixels to system memory, but the -/// second one doesn't impact the rendering process and can be -/// easily inserted anywhere without impacting all the code. -/// -/// Like sf::Texture that can be used as a raw OpenGL texture, -/// sf::Shader can also be used directly as a raw shader for -/// custom OpenGL geometry. -/// \code -/// sf::Shader::bind(&shader); -/// ... render OpenGL geometry ... -/// sf::Shader::bind(NULL); -/// \endcode -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SHADER_HPP +#define SFML_SHADER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +class InputStream; +class Texture; + +//////////////////////////////////////////////////////////// +/// \brief Shader class (vertex and fragment) +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Shader : GlResource, NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Types of shaders + /// + //////////////////////////////////////////////////////////// + enum Type + { + Vertex, ///< Vertex shader + Fragment ///< Fragment (pixel) shader + }; + + //////////////////////////////////////////////////////////// + /// \brief Special type that can be passed to setParameter, + /// and that represents the texture of the object being drawn + /// + /// \see setParameter(const std::string&, CurrentTextureType) + /// + //////////////////////////////////////////////////////////// + struct CurrentTextureType {}; + + //////////////////////////////////////////////////////////// + /// \brief Represents the texture of the object being drawn + /// + /// \see setParameter(const std::string&, CurrentTextureType) + /// + //////////////////////////////////////////////////////////// + static CurrentTextureType CurrentTexture; + +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor creates an invalid shader. + /// + //////////////////////////////////////////////////////////// + Shader(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Shader(); + + //////////////////////////////////////////////////////////// + /// \brief Load either the vertex or fragment shader from a file + /// + /// This function loads a single shader, either vertex or + /// fragment, identified by the second argument. + /// The source must be a text file containing a valid + /// shader in GLSL language. GLSL is a C-like language + /// dedicated to OpenGL shaders; you'll probably need to + /// read a good documentation for it before writing your + /// own shaders. + /// + /// \param filename Path of the vertex or fragment shader file to load + /// \param type Type of shader (vertex or fragment) + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& filename, Type type); + + //////////////////////////////////////////////////////////// + /// \brief Load both the vertex and fragment shaders from files + /// + /// This function loads both the vertex and the fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The sources must be text files containing valid shaders + /// in GLSL language. GLSL is a C-like language dedicated to + /// OpenGL shaders; you'll probably need to read a good documentation + /// for it before writing your own shaders. + /// + /// \param vertexShaderFilename Path of the vertex shader file to load + /// \param fragmentShaderFilename Path of the fragment shader file to load + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename); + + //////////////////////////////////////////////////////////// + /// \brief Load either the vertex or fragment shader from a source code in memory + /// + /// This function loads a single shader, either vertex or + /// fragment, identified by the second argument. + /// The source code must be a valid shader in GLSL language. + /// GLSL is a C-like language dedicated to OpenGL shaders; + /// you'll probably need to read a good documentation for + /// it before writing your own shaders. + /// + /// \param shader String containing the source code of the shader + /// \param type Type of shader (vertex or fragment) + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const std::string& shader, Type type); + + //////////////////////////////////////////////////////////// + /// \brief Load both the vertex and fragment shaders from source codes in memory + /// + /// This function loads both the vertex and the fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The sources must be valid shaders in GLSL language. GLSL is + /// a C-like language dedicated to OpenGL shaders; you'll + /// probably need to read a good documentation for it before + /// writing your own shaders. + /// + /// \param vertexShader String containing the source code of the vertex shader + /// \param fragmentShader String containing the source code of the fragment shader + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader); + + //////////////////////////////////////////////////////////// + /// \brief Load either the vertex or fragment shader from a custom stream + /// + /// This function loads a single shader, either vertex or + /// fragment, identified by the second argument. + /// The source code must be a valid shader in GLSL language. + /// GLSL is a C-like language dedicated to OpenGL shaders; + /// you'll probably need to read a good documentation for it + /// before writing your own shaders. + /// + /// \param stream Source stream to read from + /// \param type Type of shader (vertex or fragment) + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(InputStream& stream, Type type); + + //////////////////////////////////////////////////////////// + /// \brief Load both the vertex and fragment shaders from custom streams + /// + /// This function loads both the vertex and the fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The source codes must be valid shaders in GLSL language. + /// GLSL is a C-like language dedicated to OpenGL shaders; + /// you'll probably need to read a good documentation for + /// it before writing your own shaders. + /// + /// \param vertexShaderStream Source stream to read the vertex shader from + /// \param fragmentShaderStream Source stream to read the fragment shader from + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream); + + //////////////////////////////////////////////////////////// + /// \brief Change a float parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a float + /// (float GLSL type). + /// + /// Example: + /// \code + /// uniform float myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", 5.2f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x Value to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, float x); + + //////////////////////////////////////////////////////////// + /// \brief Change a 2-components vector parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 2x1 vector + /// (vec2 GLSL type). + /// + /// Example: + /// \code + /// uniform vec2 myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", 5.2f, 6.0f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x First component of the value to assign + /// \param y Second component of the value to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief Change a 3-components vector parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 3x1 vector + /// (vec3 GLSL type). + /// + /// Example: + /// \code + /// uniform vec3 myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", 5.2f, 6.0f, -8.1f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x First component of the value to assign + /// \param y Second component of the value to assign + /// \param z Third component of the value to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, float x, float y, float z); + + //////////////////////////////////////////////////////////// + /// \brief Change a 4-components vector parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 4x1 vector + /// (vec4 GLSL type). + /// + /// Example: + /// \code + /// uniform vec4 myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", 5.2f, 6.0f, -8.1f, 0.4f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x First component of the value to assign + /// \param y Second component of the value to assign + /// \param z Third component of the value to assign + /// \param w Fourth component of the value to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, float x, float y, float z, float w); + + //////////////////////////////////////////////////////////// + /// \brief Change a 2-components vector parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 2x1 vector + /// (vec2 GLSL type). + /// + /// Example: + /// \code + /// uniform vec2 myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", sf::Vector2f(5.2f, 6.0f)); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param vector Vector to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, const Vector2f& vector); + + //////////////////////////////////////////////////////////// + /// \brief Change a 3-components vector parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 3x1 vector + /// (vec3 GLSL type). + /// + /// Example: + /// \code + /// uniform vec3 myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", sf::Vector3f(5.2f, 6.0f, -8.1f)); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param vector Vector to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, const Vector3f& vector); + + //////////////////////////////////////////////////////////// + /// \brief Change a color parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 4x1 vector + /// (vec4 GLSL type). + /// + /// It is important to note that the components of the color are + /// normalized before being passed to the shader. Therefore, + /// they are converted from range [0 .. 255] to range [0 .. 1]. + /// For example, a sf::Color(255, 125, 0, 255) will be transformed + /// to a vec4(1.0, 0.5, 0.0, 1.0) in the shader. + /// + /// Example: + /// \code + /// uniform vec4 color; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("color", sf::Color(255, 128, 0, 255)); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param color Color to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Change a matrix parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 4x4 matrix + /// (mat4 GLSL type). + /// + /// Example: + /// \code + /// uniform mat4 matrix; // this is the variable in the shader + /// \endcode + /// \code + /// sf::Transform transform; + /// transform.translate(5, 10); + /// shader.setParameter("matrix", transform); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param transform Transform to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, const sf::Transform& transform); + + //////////////////////////////////////////////////////////// + /// \brief Change a texture parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 2D texture + /// (sampler2D GLSL type). + /// + /// Example: + /// \code + /// uniform sampler2D the_texture; // this is the variable in the shader + /// \endcode + /// \code + /// sf::Texture texture; + /// ... + /// shader.setParameter("the_texture", texture); + /// \endcode + /// It is important to note that \a texture must remain alive as long + /// as the shader uses it, no copy is made internally. + /// + /// To use the texture of the object being draw, which cannot be + /// known in advance, you can pass the special value + /// sf::Shader::CurrentTexture: + /// \code + /// shader.setParameter("the_texture", sf::Shader::CurrentTexture). + /// \endcode + /// + /// \param name Name of the texture in the shader + /// \param texture Texture to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, const Texture& texture); + + //////////////////////////////////////////////////////////// + /// \brief Change a texture parameter of the shader + /// + /// This overload maps a shader texture variable to the + /// texture of the object being drawn, which cannot be + /// known in advance. The second argument must be + /// sf::Shader::CurrentTexture. + /// The corresponding parameter in the shader must be a 2D texture + /// (sampler2D GLSL type). + /// + /// Example: + /// \code + /// uniform sampler2D current; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("current", sf::Shader::CurrentTexture); + /// \endcode + /// + /// \param name Name of the texture in the shader + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, CurrentTextureType); + + //////////////////////////////////////////////////////////// + /// \brief Bind a shader for rendering + /// + /// This function is not part of the graphics API, it mustn't be + /// used when drawing SFML entities. It must be used only if you + /// mix sf::Shader with OpenGL code. + /// + /// \code + /// sf::Shader s1, s2; + /// ... + /// sf::Shader::bind(&s1); + /// // draw OpenGL stuff that use s1... + /// sf::Shader::bind(&s2); + /// // draw OpenGL stuff that use s2... + /// sf::Shader::bind(NULL); + /// // draw OpenGL stuff that use no shader... + /// \endcode + /// + /// \param shader Shader to bind, can be null to use no shader + /// + //////////////////////////////////////////////////////////// + static void bind(const Shader* shader); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether or not the system supports shaders + /// + /// This function should always be called before using + /// the shader features. If it returns false, then + /// any attempt to use sf::Shader will fail. + /// + /// Note: The first call to this function, whether by your + /// code or SFML will result in a context switch. + /// + /// \return True if shaders are supported, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isAvailable(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Compile the shader(s) and create the program + /// + /// If one of the arguments is NULL, the corresponding shader + /// is not created. + /// + /// \param vertexShaderCode Source code of the vertex shader + /// \param fragmentShaderCode Source code of the fragment shader + /// + /// \return True on success, false if any error happened + /// + //////////////////////////////////////////////////////////// + bool compile(const char* vertexShaderCode, const char* fragmentShaderCode); + + //////////////////////////////////////////////////////////// + /// \brief Bind all the textures used by the shader + /// + /// This function each texture to a different unit, and + /// updates the corresponding variables in the shader accordingly. + /// + //////////////////////////////////////////////////////////// + void bindTextures() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the location ID of a shader parameter + /// + /// \param name Name of the parameter to search + /// + /// \return Location ID of the parameter, or -1 if not found + /// + //////////////////////////////////////////////////////////// + int getParamLocation(const std::string& name); + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::map TextureTable; + typedef std::map ParamTable; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int m_shaderProgram; ///< OpenGL identifier for the program + int m_currentTexture; ///< Location of the current texture in the shader + TextureTable m_textures; ///< Texture variables in the shader, mapped to their location + ParamTable m_params; ///< Parameters location cache +}; + +} // namespace sf + + +#endif // SFML_SHADER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Shader +/// \ingroup graphics +/// +/// Shaders are programs written using a specific language, +/// executed directly by the graphics card and allowing +/// to apply real-time operations to the rendered entities. +/// +/// There are two kinds of shaders: +/// \li Vertex shaders, that process vertices +/// \li Fragment (pixel) shaders, that process pixels +/// +/// A sf::Shader can be composed of either a vertex shader +/// alone, a fragment shader alone, or both combined +/// (see the variants of the load functions). +/// +/// Shaders are written in GLSL, which is a C-like +/// language dedicated to OpenGL shaders. You'll probably +/// need to learn its basics before writing your own shaders +/// for SFML. +/// +/// Like any C/C++ program, a shader has its own variables +/// that you can set from your C++ application. sf::Shader +/// handles 5 different types of variables: +/// \li floats +/// \li vectors (2, 3 or 4 components) +/// \li colors +/// \li textures +/// \li transforms (matrices) +/// +/// The value of the variables can be changed at any time +/// with the various overloads of the setParameter function: +/// \code +/// shader.setParameter("offset", 2.f); +/// shader.setParameter("point", 0.5f, 0.8f, 0.3f); +/// shader.setParameter("color", sf::Color(128, 50, 255)); +/// shader.setParameter("matrix", transform); // transform is a sf::Transform +/// shader.setParameter("overlay", texture); // texture is a sf::Texture +/// shader.setParameter("texture", sf::Shader::CurrentTexture); +/// \endcode +/// +/// The special Shader::CurrentTexture argument maps the +/// given texture variable to the current texture of the +/// object being drawn (which cannot be known in advance). +/// +/// To apply a shader to a drawable, you must pass it as an +/// additional parameter to the Draw function: +/// \code +/// window.draw(sprite, &shader); +/// \endcode +/// +/// ... which is in fact just a shortcut for this: +/// \code +/// sf::RenderStates states; +/// states.shader = &shader; +/// window.draw(sprite, states); +/// \endcode +/// +/// In the code above we pass a pointer to the shader, because it may +/// be null (which means "no shader"). +/// +/// Shaders can be used on any drawable, but some combinations are +/// not interesting. For example, using a vertex shader on a sf::Sprite +/// is limited because there are only 4 vertices, the sprite would +/// have to be subdivided in order to apply wave effects. +/// Another bad example is a fragment shader with sf::Text: the texture +/// of the text is not the actual text that you see on screen, it is +/// a big texture containing all the characters of the font in an +/// arbitrary order; thus, texture lookups on pixels other than the +/// current one may not give you the expected result. +/// +/// Shaders can also be used to apply global post-effects to the +/// current contents of the target (like the old sf::PostFx class +/// in SFML 1). This can be done in two different ways: +/// \li draw everything to a sf::RenderTexture, then draw it to +/// the main target using the shader +/// \li draw everything directly to the main target, then use +/// sf::Texture::update(Window&) to copy its contents to a texture +/// and draw it to the main target using the shader +/// +/// The first technique is more optimized because it doesn't involve +/// retrieving the target's pixels to system memory, but the +/// second one doesn't impact the rendering process and can be +/// easily inserted anywhere without impacting all the code. +/// +/// Like sf::Texture that can be used as a raw OpenGL texture, +/// sf::Shader can also be used directly as a raw shader for +/// custom OpenGL geometry. +/// \code +/// sf::Shader::bind(&shader); +/// ... render OpenGL geometry ... +/// sf::Shader::bind(NULL); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Shape.hpp b/include/SFML/Graphics/Shape.hpp index 2405b18b..61a9f750 100644 --- a/include/SFML/Graphics/Shape.hpp +++ b/include/SFML/Graphics/Shape.hpp @@ -1,348 +1,348 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SHAPE_HPP -#define SFML_SHAPE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Base class for textured shapes with outline -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API Shape : public Drawable, public Transformable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Virtual destructor - /// - //////////////////////////////////////////////////////////// - virtual ~Shape(); - - //////////////////////////////////////////////////////////// - /// \brief Change the source texture of the shape - /// - /// The \a texture argument refers to a texture that must - /// exist as long as the shape uses it. Indeed, the shape - /// doesn't store its own copy of the texture, but rather keeps - /// a pointer to the one that you passed to this function. - /// If the source texture is destroyed and the shape tries to - /// use it, the behaviour is undefined. - /// \a texture can be NULL to disable texturing. - /// If \a resetRect is true, the TextureRect property of - /// the shape is automatically adjusted to the size of the new - /// texture. If it is false, the texture rect is left unchanged. - /// - /// \param texture New texture - /// \param resetRect Should the texture rect be reset to the size of the new texture? - /// - /// \see getTexture, setTextureRect - /// - //////////////////////////////////////////////////////////// - void setTexture(const Texture* texture, bool resetRect = false); - - //////////////////////////////////////////////////////////// - /// \brief Set the sub-rectangle of the texture that the shape will display - /// - /// The texture rect is useful when you don't want to display - /// the whole texture, but rather a part of it. - /// By default, the texture rect covers the entire texture. - /// - /// \param rect Rectangle defining the region of the texture to display - /// - /// \see getTextureRect, setTexture - /// - //////////////////////////////////////////////////////////// - void setTextureRect(const IntRect& rect); - - //////////////////////////////////////////////////////////// - /// \brief Set the fill color of the shape - /// - /// This color is modulated (multiplied) with the shape's - /// texture if any. It can be used to colorize the shape, - /// or change its global opacity. - /// You can use sf::Color::Transparent to make the inside of - /// the shape transparent, and have the outline alone. - /// By default, the shape's fill color is opaque white. - /// - /// \param color New color of the shape - /// - /// \see getFillColor, setOutlineColor - /// - //////////////////////////////////////////////////////////// - void setFillColor(const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Set the outline color of the shape - /// - /// By default, the shape's outline color is opaque white. - /// - /// \param color New outline color of the shape - /// - /// \see getOutlineColor, setFillColor - /// - //////////////////////////////////////////////////////////// - void setOutlineColor(const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Set the thickness of the shape's outline - /// - /// Note that negative values are allowed (so that the outline - /// expands towards the center of the shape), and using zero - /// disables the outline. - /// By default, the outline thickness is 0. - /// - /// \param thickness New outline thickness - /// - /// \see getOutlineThickness - /// - //////////////////////////////////////////////////////////// - void setOutlineThickness(float thickness); - - //////////////////////////////////////////////////////////// - /// \brief Get the source texture of the shape - /// - /// If the shape has no source texture, a NULL pointer is returned. - /// The returned pointer is const, which means that you can't - /// modify the texture when you retrieve it with this function. - /// - /// \return Pointer to the shape's texture - /// - /// \see setTexture - /// - //////////////////////////////////////////////////////////// - const Texture* getTexture() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the sub-rectangle of the texture displayed by the shape - /// - /// \return Texture rectangle of the shape - /// - /// \see setTextureRect - /// - //////////////////////////////////////////////////////////// - const IntRect& getTextureRect() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the fill color of the shape - /// - /// \return Fill color of the shape - /// - /// \see setFillColor - /// - //////////////////////////////////////////////////////////// - const Color& getFillColor() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the outline color of the shape - /// - /// \return Outline color of the shape - /// - /// \see setOutlineColor - /// - //////////////////////////////////////////////////////////// - const Color& getOutlineColor() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the outline thickness of the shape - /// - /// \return Outline thickness of the shape - /// - /// \see setOutlineThickness - /// - //////////////////////////////////////////////////////////// - float getOutlineThickness() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the total number of points of the shape - /// - /// \return Number of points of the shape - /// - /// \see getPoint - /// - //////////////////////////////////////////////////////////// - virtual unsigned int getPointCount() const = 0; - - //////////////////////////////////////////////////////////// - /// \brief Get a point of the shape - /// - /// The returned point is in local coordinates, that is, - /// the shape's transforms (position, rotation, scale) are - /// not taken into account. - /// The result is undefined if \a index is out of the valid range. - /// - /// \param index Index of the point to get, in range [0 .. getPointCount() - 1] - /// - /// \return index-th point of the shape - /// - /// \see getPointCount - /// - //////////////////////////////////////////////////////////// - virtual Vector2f getPoint(unsigned int index) const = 0; - - //////////////////////////////////////////////////////////// - /// \brief Get the local bounding rectangle of the entity - /// - /// The returned rectangle is in local coordinates, which means - /// that it ignores the transformations (translation, rotation, - /// scale, ...) that are applied to the entity. - /// In other words, this function returns the bounds of the - /// entity in the entity's coordinate system. - /// - /// \return Local bounding rectangle of the entity - /// - //////////////////////////////////////////////////////////// - FloatRect getLocalBounds() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the global bounding rectangle of the entity - /// - /// The returned rectangle is in global coordinates, which means - /// that it takes in account the transformations (translation, - /// rotation, scale, ...) that are applied to the entity. - /// In other words, this function returns the bounds of the - /// sprite in the global 2D world's coordinate system. - /// - /// \return Global bounding rectangle of the entity - /// - //////////////////////////////////////////////////////////// - FloatRect getGlobalBounds() const; - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - Shape(); - - //////////////////////////////////////////////////////////// - /// \brief Recompute the internal geometry of the shape - /// - /// This function must be called by the derived class everytime - /// the shape's points change (ie. the result of either - /// getPointCount or getPoint is different). - /// - //////////////////////////////////////////////////////////// - void update(); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Draw the shape to a render target - /// - /// \param target Render target to draw to - /// \param states Current render states - /// - //////////////////////////////////////////////////////////// - virtual void draw(RenderTarget& target, RenderStates states) const; - - //////////////////////////////////////////////////////////// - /// \brief Update the fill vertices' color - /// - //////////////////////////////////////////////////////////// - void updateFillColors(); - - //////////////////////////////////////////////////////////// - /// \brief Update the fill vertices' texture coordinates - /// - //////////////////////////////////////////////////////////// - void updateTexCoords(); - - //////////////////////////////////////////////////////////// - /// \brief Update the outline vertices' position - /// - //////////////////////////////////////////////////////////// - void updateOutline(); - - //////////////////////////////////////////////////////////// - /// \brief Update the outline vertices' color - /// - //////////////////////////////////////////////////////////// - void updateOutlineColors(); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - const Texture* m_texture; ///< Texture of the shape - IntRect m_textureRect; ///< Rectangle defining the area of the source texture to display - Color m_fillColor; ///< Fill color - Color m_outlineColor; ///< Outline color - float m_outlineThickness; ///< Thickness of the shape's outline - VertexArray m_vertices; ///< Vertex array containing the fill geometry - VertexArray m_outlineVertices; ///< Vertex array containing the outline geometry - FloatRect m_insideBounds; ///< Bounding rectangle of the inside (fill) - FloatRect m_bounds; ///< Bounding rectangle of the whole shape (outline + fill) -}; - -} // namespace sf - - -#endif // SFML_SHAPE_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Shape -/// \ingroup graphics -/// -/// sf::Shape is a drawable class that allows to define and -/// display a custom convex shape on a render target. -/// It's only an abstract base, it needs to be specialized for -/// concrete types of shapes (circle, rectangle, convex polygon, -/// star, ...). -/// -/// In addition to the attributes provided by the specialized -/// shape classes, a shape always has the following attributes: -/// \li a texture -/// \li a texture rectangle -/// \li a fill color -/// \li an outline color -/// \li an outline thickness -/// -/// Each feature is optional, and can be disabled easily: -/// \li the texture can be null -/// \li the fill/outline colors can be sf::Color::Transparent -/// \li the outline thickness can be zero -/// -/// You can write your own derived shape class, there are only -/// two virtual functions to override: -/// \li getPointCount must return the number of points of the shape -/// \li getPoint must return the points of the shape -/// -/// \see sf::RectangleShape, sf::CircleShape, sf::ConvexShape, sf::Transformable -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SHAPE_HPP +#define SFML_SHAPE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Base class for textured shapes with outline +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Shape : public Drawable, public Transformable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Shape(); + + //////////////////////////////////////////////////////////// + /// \brief Change the source texture of the shape + /// + /// The \a texture argument refers to a texture that must + /// exist as long as the shape uses it. Indeed, the shape + /// doesn't store its own copy of the texture, but rather keeps + /// a pointer to the one that you passed to this function. + /// If the source texture is destroyed and the shape tries to + /// use it, the behaviour is undefined. + /// \a texture can be NULL to disable texturing. + /// If \a resetRect is true, the TextureRect property of + /// the shape is automatically adjusted to the size of the new + /// texture. If it is false, the texture rect is left unchanged. + /// + /// \param texture New texture + /// \param resetRect Should the texture rect be reset to the size of the new texture? + /// + /// \see getTexture, setTextureRect + /// + //////////////////////////////////////////////////////////// + void setTexture(const Texture* texture, bool resetRect = false); + + //////////////////////////////////////////////////////////// + /// \brief Set the sub-rectangle of the texture that the shape will display + /// + /// The texture rect is useful when you don't want to display + /// the whole texture, but rather a part of it. + /// By default, the texture rect covers the entire texture. + /// + /// \param rect Rectangle defining the region of the texture to display + /// + /// \see getTextureRect, setTexture + /// + //////////////////////////////////////////////////////////// + void setTextureRect(const IntRect& rect); + + //////////////////////////////////////////////////////////// + /// \brief Set the fill color of the shape + /// + /// This color is modulated (multiplied) with the shape's + /// texture if any. It can be used to colorize the shape, + /// or change its global opacity. + /// You can use sf::Color::Transparent to make the inside of + /// the shape transparent, and have the outline alone. + /// By default, the shape's fill color is opaque white. + /// + /// \param color New color of the shape + /// + /// \see getFillColor, setOutlineColor + /// + //////////////////////////////////////////////////////////// + void setFillColor(const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Set the outline color of the shape + /// + /// By default, the shape's outline color is opaque white. + /// + /// \param color New outline color of the shape + /// + /// \see getOutlineColor, setFillColor + /// + //////////////////////////////////////////////////////////// + void setOutlineColor(const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Set the thickness of the shape's outline + /// + /// Note that negative values are allowed (so that the outline + /// expands towards the center of the shape), and using zero + /// disables the outline. + /// By default, the outline thickness is 0. + /// + /// \param thickness New outline thickness + /// + /// \see getOutlineThickness + /// + //////////////////////////////////////////////////////////// + void setOutlineThickness(float thickness); + + //////////////////////////////////////////////////////////// + /// \brief Get the source texture of the shape + /// + /// If the shape has no source texture, a NULL pointer is returned. + /// The returned pointer is const, which means that you can't + /// modify the texture when you retrieve it with this function. + /// + /// \return Pointer to the shape's texture + /// + /// \see setTexture + /// + //////////////////////////////////////////////////////////// + const Texture* getTexture() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the sub-rectangle of the texture displayed by the shape + /// + /// \return Texture rectangle of the shape + /// + /// \see setTextureRect + /// + //////////////////////////////////////////////////////////// + const IntRect& getTextureRect() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the fill color of the shape + /// + /// \return Fill color of the shape + /// + /// \see setFillColor + /// + //////////////////////////////////////////////////////////// + const Color& getFillColor() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the outline color of the shape + /// + /// \return Outline color of the shape + /// + /// \see setOutlineColor + /// + //////////////////////////////////////////////////////////// + const Color& getOutlineColor() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the outline thickness of the shape + /// + /// \return Outline thickness of the shape + /// + /// \see setOutlineThickness + /// + //////////////////////////////////////////////////////////// + float getOutlineThickness() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the total number of points of the shape + /// + /// \return Number of points of the shape + /// + /// \see getPoint + /// + //////////////////////////////////////////////////////////// + virtual unsigned int getPointCount() const = 0; + + //////////////////////////////////////////////////////////// + /// \brief Get a point of the shape + /// + /// The returned point is in local coordinates, that is, + /// the shape's transforms (position, rotation, scale) are + /// not taken into account. + /// The result is undefined if \a index is out of the valid range. + /// + /// \param index Index of the point to get, in range [0 .. getPointCount() - 1] + /// + /// \return index-th point of the shape + /// + /// \see getPointCount + /// + //////////////////////////////////////////////////////////// + virtual Vector2f getPoint(unsigned int index) const = 0; + + //////////////////////////////////////////////////////////// + /// \brief Get the local bounding rectangle of the entity + /// + /// The returned rectangle is in local coordinates, which means + /// that it ignores the transformations (translation, rotation, + /// scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// entity in the entity's coordinate system. + /// + /// \return Local bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getLocalBounds() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global bounding rectangle of the entity + /// + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// \return Global bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getGlobalBounds() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Shape(); + + //////////////////////////////////////////////////////////// + /// \brief Recompute the internal geometry of the shape + /// + /// This function must be called by the derived class everytime + /// the shape's points change (ie. the result of either + /// getPointCount or getPoint is different). + /// + //////////////////////////////////////////////////////////// + void update(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Draw the shape to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void draw(RenderTarget& target, RenderStates states) const; + + //////////////////////////////////////////////////////////// + /// \brief Update the fill vertices' color + /// + //////////////////////////////////////////////////////////// + void updateFillColors(); + + //////////////////////////////////////////////////////////// + /// \brief Update the fill vertices' texture coordinates + /// + //////////////////////////////////////////////////////////// + void updateTexCoords(); + + //////////////////////////////////////////////////////////// + /// \brief Update the outline vertices' position + /// + //////////////////////////////////////////////////////////// + void updateOutline(); + + //////////////////////////////////////////////////////////// + /// \brief Update the outline vertices' color + /// + //////////////////////////////////////////////////////////// + void updateOutlineColors(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + const Texture* m_texture; ///< Texture of the shape + IntRect m_textureRect; ///< Rectangle defining the area of the source texture to display + Color m_fillColor; ///< Fill color + Color m_outlineColor; ///< Outline color + float m_outlineThickness; ///< Thickness of the shape's outline + VertexArray m_vertices; ///< Vertex array containing the fill geometry + VertexArray m_outlineVertices; ///< Vertex array containing the outline geometry + FloatRect m_insideBounds; ///< Bounding rectangle of the inside (fill) + FloatRect m_bounds; ///< Bounding rectangle of the whole shape (outline + fill) +}; + +} // namespace sf + + +#endif // SFML_SHAPE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Shape +/// \ingroup graphics +/// +/// sf::Shape is a drawable class that allows to define and +/// display a custom convex shape on a render target. +/// It's only an abstract base, it needs to be specialized for +/// concrete types of shapes (circle, rectangle, convex polygon, +/// star, ...). +/// +/// In addition to the attributes provided by the specialized +/// shape classes, a shape always has the following attributes: +/// \li a texture +/// \li a texture rectangle +/// \li a fill color +/// \li an outline color +/// \li an outline thickness +/// +/// Each feature is optional, and can be disabled easily: +/// \li the texture can be null +/// \li the fill/outline colors can be sf::Color::Transparent +/// \li the outline thickness can be zero +/// +/// You can write your own derived shape class, there are only +/// two virtual functions to override: +/// \li getPointCount must return the number of points of the shape +/// \li getPoint must return the points of the shape +/// +/// \see sf::RectangleShape, sf::CircleShape, sf::ConvexShape, sf::Transformable +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Sprite.hpp b/include/SFML/Graphics/Sprite.hpp index eb871c57..23cd26d9 100644 --- a/include/SFML/Graphics/Sprite.hpp +++ b/include/SFML/Graphics/Sprite.hpp @@ -1,279 +1,279 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SPRITE_HPP -#define SFML_SPRITE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -class Texture; - -//////////////////////////////////////////////////////////// -/// \brief Drawable representation of a texture, with its -/// own transformations, color, etc. -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API Sprite : public Drawable, public Transformable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Creates an empty sprite with no source texture. - /// - //////////////////////////////////////////////////////////// - Sprite(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the sprite from a source texture - /// - /// \param texture Source texture - /// - /// \see setTexture - /// - //////////////////////////////////////////////////////////// - explicit Sprite(const Texture& texture); - - //////////////////////////////////////////////////////////// - /// \brief Construct the sprite from a sub-rectangle of a source texture - /// - /// \param texture Source texture - /// \param rectangle Sub-rectangle of the texture to assign to the sprite - /// - /// \see setTexture, setTextureRect - /// - //////////////////////////////////////////////////////////// - Sprite(const Texture& texture, const IntRect& rectangle); - - //////////////////////////////////////////////////////////// - /// \brief Change the source texture of the sprite - /// - /// The \a texture argument refers to a texture that must - /// exist as long as the sprite uses it. Indeed, the sprite - /// doesn't store its own copy of the texture, but rather keeps - /// a pointer to the one that you passed to this function. - /// If the source texture is destroyed and the sprite tries to - /// use it, the behaviour is undefined. - /// If \a resetRect is true, the TextureRect property of - /// the sprite is automatically adjusted to the size of the new - /// texture. If it is false, the texture rect is left unchanged. - /// - /// \param texture New texture - /// \param resetRect Should the texture rect be reset to the size of the new texture? - /// - /// \see getTexture, setTextureRect - /// - //////////////////////////////////////////////////////////// - void setTexture(const Texture& texture, bool resetRect = false); - - //////////////////////////////////////////////////////////// - /// \brief Set the sub-rectangle of the texture that the sprite will display - /// - /// The texture rect is useful when you don't want to display - /// the whole texture, but rather a part of it. - /// By default, the texture rect covers the entire texture. - /// - /// \param rectangle Rectangle defining the region of the texture to display - /// - /// \see getTextureRect, setTexture - /// - //////////////////////////////////////////////////////////// - void setTextureRect(const IntRect& rectangle); - - //////////////////////////////////////////////////////////// - /// \brief Set the global color of the sprite - /// - /// This color is modulated (multiplied) with the sprite's - /// texture. It can be used to colorize the sprite, or change - /// its global opacity. - /// By default, the sprite's color is opaque white. - /// - /// \param color New color of the sprite - /// - /// \see getColor - /// - //////////////////////////////////////////////////////////// - void setColor(const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Get the source texture of the sprite - /// - /// If the sprite has no source texture, a NULL pointer is returned. - /// The returned pointer is const, which means that you can't - /// modify the texture when you retrieve it with this function. - /// - /// \return Pointer to the sprite's texture - /// - /// \see setTexture - /// - //////////////////////////////////////////////////////////// - const Texture* getTexture() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the sub-rectangle of the texture displayed by the sprite - /// - /// \return Texture rectangle of the sprite - /// - /// \see setTextureRect - /// - //////////////////////////////////////////////////////////// - const IntRect& getTextureRect() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the global color of the sprite - /// - /// \return Global color of the sprite - /// - /// \see setColor - /// - //////////////////////////////////////////////////////////// - const Color& getColor() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the local bounding rectangle of the entity - /// - /// The returned rectangle is in local coordinates, which means - /// that it ignores the transformations (translation, rotation, - /// scale, ...) that are applied to the entity. - /// In other words, this function returns the bounds of the - /// entity in the entity's coordinate system. - /// - /// \return Local bounding rectangle of the entity - /// - //////////////////////////////////////////////////////////// - FloatRect getLocalBounds() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the global bounding rectangle of the entity - /// - /// The returned rectangle is in global coordinates, which means - /// that it takes in account the transformations (translation, - /// rotation, scale, ...) that are applied to the entity. - /// In other words, this function returns the bounds of the - /// sprite in the global 2D world's coordinate system. - /// - /// \return Global bounding rectangle of the entity - /// - //////////////////////////////////////////////////////////// - FloatRect getGlobalBounds() const; - -private : - - //////////////////////////////////////////////////////////// - /// \brief Draw the sprite to a render target - /// - /// \param target Render target to draw to - /// \param states Current render states - /// - //////////////////////////////////////////////////////////// - virtual void draw(RenderTarget& target, RenderStates states) const; - - //////////////////////////////////////////////////////////// - /// \brief Update the vertices' positions - /// - //////////////////////////////////////////////////////////// - void updatePositions(); - - //////////////////////////////////////////////////////////// - /// \brief Update the vertices' texture coordinates - /// - //////////////////////////////////////////////////////////// - void updateTexCoords(); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Vertex m_vertices[4]; ///< Vertices defining the sprite's geometry - const Texture* m_texture; ///< Texture of the sprite - IntRect m_textureRect; ///< Rectangle defining the area of the source texture to display -}; - -} // namespace sf - - -#endif // SFML_SPRITE_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Sprite -/// \ingroup graphics -/// -/// sf::Sprite is a drawable class that allows to easily display -/// a texture (or a part of it) on a render target. -/// -/// It inherits all the functions from sf::Transformable: -/// position, rotation, scale, origin. It also adds sprite-specific -/// properties such as the texture to use, the part of it to display, -/// and some convenience functions to change the overall color of the -/// sprite, or to get its bounding rectangle. -/// -/// sf::Sprite works in combination with the sf::Texture class, which -/// loads and provides the pixel data of a given texture. -/// -/// The separation of sf::Sprite and sf::Texture allows more flexibility -/// and better performances: indeed a sf::Texture is a heavy resource, -/// and any operation on it is slow (often too slow for real-time -/// applications). On the other side, a sf::Sprite is a lightweight -/// object which can use the pixel data of a sf::Texture and draw -/// it with its own transformation/color/blending attributes. -/// -/// It is important to note that the sf::Sprite instance doesn't -/// copy the texture that it uses, it only keeps a reference to it. -/// Thus, a sf::Texture must not be destroyed while it is -/// used by a sf::Sprite (i.e. never write a function that -/// uses a local sf::Texture instance for creating a sprite). -/// -/// See also the note on coordinates and undistorted rendering in sf::Transformable. -/// -/// Usage example: -/// \code -/// // Declare and load a texture -/// sf::Texture texture; -/// texture.loadFromFile("texture.png"); -/// -/// // Create a sprite -/// sf::Sprite sprite; -/// sprite.setTexture(texture); -/// sprite.setTextureRect(sf::IntRect(10, 10, 50, 30)); -/// sprite.setColor(sf::Color(255, 255, 255, 200)); -/// sprite.setPosition(100, 25); -/// -/// // Draw it -/// window.draw(sprite); -/// \endcode -/// -/// \see sf::Texture, sf::Transformable -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SPRITE_HPP +#define SFML_SPRITE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +class Texture; + +//////////////////////////////////////////////////////////// +/// \brief Drawable representation of a texture, with its +/// own transformations, color, etc. +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Sprite : public Drawable, public Transformable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty sprite with no source texture. + /// + //////////////////////////////////////////////////////////// + Sprite(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the sprite from a source texture + /// + /// \param texture Source texture + /// + /// \see setTexture + /// + //////////////////////////////////////////////////////////// + explicit Sprite(const Texture& texture); + + //////////////////////////////////////////////////////////// + /// \brief Construct the sprite from a sub-rectangle of a source texture + /// + /// \param texture Source texture + /// \param rectangle Sub-rectangle of the texture to assign to the sprite + /// + /// \see setTexture, setTextureRect + /// + //////////////////////////////////////////////////////////// + Sprite(const Texture& texture, const IntRect& rectangle); + + //////////////////////////////////////////////////////////// + /// \brief Change the source texture of the sprite + /// + /// The \a texture argument refers to a texture that must + /// exist as long as the sprite uses it. Indeed, the sprite + /// doesn't store its own copy of the texture, but rather keeps + /// a pointer to the one that you passed to this function. + /// If the source texture is destroyed and the sprite tries to + /// use it, the behaviour is undefined. + /// If \a resetRect is true, the TextureRect property of + /// the sprite is automatically adjusted to the size of the new + /// texture. If it is false, the texture rect is left unchanged. + /// + /// \param texture New texture + /// \param resetRect Should the texture rect be reset to the size of the new texture? + /// + /// \see getTexture, setTextureRect + /// + //////////////////////////////////////////////////////////// + void setTexture(const Texture& texture, bool resetRect = false); + + //////////////////////////////////////////////////////////// + /// \brief Set the sub-rectangle of the texture that the sprite will display + /// + /// The texture rect is useful when you don't want to display + /// the whole texture, but rather a part of it. + /// By default, the texture rect covers the entire texture. + /// + /// \param rectangle Rectangle defining the region of the texture to display + /// + /// \see getTextureRect, setTexture + /// + //////////////////////////////////////////////////////////// + void setTextureRect(const IntRect& rectangle); + + //////////////////////////////////////////////////////////// + /// \brief Set the global color of the sprite + /// + /// This color is modulated (multiplied) with the sprite's + /// texture. It can be used to colorize the sprite, or change + /// its global opacity. + /// By default, the sprite's color is opaque white. + /// + /// \param color New color of the sprite + /// + /// \see getColor + /// + //////////////////////////////////////////////////////////// + void setColor(const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Get the source texture of the sprite + /// + /// If the sprite has no source texture, a NULL pointer is returned. + /// The returned pointer is const, which means that you can't + /// modify the texture when you retrieve it with this function. + /// + /// \return Pointer to the sprite's texture + /// + /// \see setTexture + /// + //////////////////////////////////////////////////////////// + const Texture* getTexture() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the sub-rectangle of the texture displayed by the sprite + /// + /// \return Texture rectangle of the sprite + /// + /// \see setTextureRect + /// + //////////////////////////////////////////////////////////// + const IntRect& getTextureRect() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global color of the sprite + /// + /// \return Global color of the sprite + /// + /// \see setColor + /// + //////////////////////////////////////////////////////////// + const Color& getColor() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the local bounding rectangle of the entity + /// + /// The returned rectangle is in local coordinates, which means + /// that it ignores the transformations (translation, rotation, + /// scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// entity in the entity's coordinate system. + /// + /// \return Local bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getLocalBounds() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global bounding rectangle of the entity + /// + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// \return Global bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getGlobalBounds() const; + +private: + + //////////////////////////////////////////////////////////// + /// \brief Draw the sprite to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void draw(RenderTarget& target, RenderStates states) const; + + //////////////////////////////////////////////////////////// + /// \brief Update the vertices' positions + /// + //////////////////////////////////////////////////////////// + void updatePositions(); + + //////////////////////////////////////////////////////////// + /// \brief Update the vertices' texture coordinates + /// + //////////////////////////////////////////////////////////// + void updateTexCoords(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vertex m_vertices[4]; ///< Vertices defining the sprite's geometry + const Texture* m_texture; ///< Texture of the sprite + IntRect m_textureRect; ///< Rectangle defining the area of the source texture to display +}; + +} // namespace sf + + +#endif // SFML_SPRITE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Sprite +/// \ingroup graphics +/// +/// sf::Sprite is a drawable class that allows to easily display +/// a texture (or a part of it) on a render target. +/// +/// It inherits all the functions from sf::Transformable: +/// position, rotation, scale, origin. It also adds sprite-specific +/// properties such as the texture to use, the part of it to display, +/// and some convenience functions to change the overall color of the +/// sprite, or to get its bounding rectangle. +/// +/// sf::Sprite works in combination with the sf::Texture class, which +/// loads and provides the pixel data of a given texture. +/// +/// The separation of sf::Sprite and sf::Texture allows more flexibility +/// and better performances: indeed a sf::Texture is a heavy resource, +/// and any operation on it is slow (often too slow for real-time +/// applications). On the other side, a sf::Sprite is a lightweight +/// object which can use the pixel data of a sf::Texture and draw +/// it with its own transformation/color/blending attributes. +/// +/// It is important to note that the sf::Sprite instance doesn't +/// copy the texture that it uses, it only keeps a reference to it. +/// Thus, a sf::Texture must not be destroyed while it is +/// used by a sf::Sprite (i.e. never write a function that +/// uses a local sf::Texture instance for creating a sprite). +/// +/// See also the note on coordinates and undistorted rendering in sf::Transformable. +/// +/// Usage example: +/// \code +/// // Declare and load a texture +/// sf::Texture texture; +/// texture.loadFromFile("texture.png"); +/// +/// // Create a sprite +/// sf::Sprite sprite; +/// sprite.setTexture(texture); +/// sprite.setTextureRect(sf::IntRect(10, 10, 50, 30)); +/// sprite.setColor(sf::Color(255, 255, 255, 200)); +/// sprite.setPosition(100, 25); +/// +/// // Draw it +/// window.draw(sprite); +/// \endcode +/// +/// \see sf::Texture, sf::Transformable +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Text.hpp b/include/SFML/Graphics/Text.hpp index 457ca679..5b926242 100644 --- a/include/SFML/Graphics/Text.hpp +++ b/include/SFML/Graphics/Text.hpp @@ -1,372 +1,372 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_TEXT_HPP -#define SFML_TEXT_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Graphical text that can be drawn to a render target -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API Text : public Drawable, public Transformable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Enumeration of the string drawing styles - /// - //////////////////////////////////////////////////////////// - enum Style - { - Regular = 0, ///< Regular characters, no style - Bold = 1 << 0, ///< Bold characters - Italic = 1 << 1, ///< Italic characters - Underlined = 1 << 2, ///< Underlined characters - StrikeThrough = 1 << 3 ///< Strike through characters - }; - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Creates an empty text. - /// - //////////////////////////////////////////////////////////// - Text(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the text from a string, font and size - /// - /// Note that if the used font is a bitmap font, it is not - /// scalable, thus not all requested sizes will be available - /// to use. This needs to be taken into consideration when - /// setting the character size. If you need to display text - /// of a certain size, make sure the corresponding bitmap - /// font that supports that size is used. - /// - /// \param string Text assigned to the string - /// \param font Font used to draw the string - /// \param characterSize Base size of characters, in pixels - /// - //////////////////////////////////////////////////////////// - Text(const String& string, const Font& font, unsigned int characterSize = 30); - - //////////////////////////////////////////////////////////// - /// \brief Set the text's string - /// - /// The \a string argument is a sf::String, which can - /// automatically be constructed from standard string types. - /// So, the following calls are all valid: - /// \code - /// text.setString("hello"); - /// text.setString(L"hello"); - /// text.setString(std::string("hello")); - /// text.setString(std::wstring(L"hello")); - /// \endcode - /// A text's string is empty by default. - /// - /// \param string New string - /// - /// \see getString - /// - //////////////////////////////////////////////////////////// - void setString(const String& string); - - //////////////////////////////////////////////////////////// - /// \brief Set the text's font - /// - /// The \a font argument refers to a font that must - /// exist as long as the text uses it. Indeed, the text - /// doesn't store its own copy of the font, but rather keeps - /// a pointer to the one that you passed to this function. - /// If the font is destroyed and the text tries to - /// use it, the behaviour is undefined. - /// - /// \param font New font - /// - /// \see getFont - /// - //////////////////////////////////////////////////////////// - void setFont(const Font& font); - - //////////////////////////////////////////////////////////// - /// \brief Set the character size - /// - /// The default size is 30. - /// - /// Note that if the used font is a bitmap font, it is not - /// scalable, thus not all requested sizes will be available - /// to use. This needs to be taken into consideration when - /// setting the character size. If you need to display text - /// of a certain size, make sure the corresponding bitmap - /// font that supports that size is used. - /// - /// \param size New character size, in pixels - /// - /// \see getCharacterSize - /// - //////////////////////////////////////////////////////////// - void setCharacterSize(unsigned int size); - - //////////////////////////////////////////////////////////// - /// \brief Set the text's style - /// - /// You can pass a combination of one or more styles, for - /// example sf::Text::Bold | sf::Text::Italic. - /// The default style is sf::Text::Regular. - /// - /// \param style New style - /// - /// \see getStyle - /// - //////////////////////////////////////////////////////////// - void setStyle(Uint32 style); - - //////////////////////////////////////////////////////////// - /// \brief Set the global color of the text - /// - /// By default, the text's color is opaque white. - /// - /// \param color New color of the text - /// - /// \see getColor - /// - //////////////////////////////////////////////////////////// - void setColor(const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Get the text's string - /// - /// The returned string is a sf::String, which can automatically - /// be converted to standard string types. So, the following - /// lines of code are all valid: - /// \code - /// sf::String s1 = text.getString(); - /// std::string s2 = text.getString(); - /// std::wstring s3 = text.getString(); - /// \endcode - /// - /// \return Text's string - /// - /// \see setString - /// - //////////////////////////////////////////////////////////// - const String& getString() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the text's font - /// - /// If the text has no font attached, a NULL pointer is returned. - /// The returned reference is const, which means that you - /// cannot modify the font when you get it from this function. - /// - /// \return Pointer to the text's font - /// - /// \see setFont - /// - //////////////////////////////////////////////////////////// - const Font* getFont() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the character size - /// - /// \return Size of the characters, in pixels - /// - /// \see setCharacterSize - /// - //////////////////////////////////////////////////////////// - unsigned int getCharacterSize() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the text's style - /// - /// \return Text's style - /// - /// \see setStyle - /// - //////////////////////////////////////////////////////////// - Uint32 getStyle() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the global color of the text - /// - /// \return Global color of the text - /// - /// \see setColor - /// - //////////////////////////////////////////////////////////// - const Color& getColor() const; - - //////////////////////////////////////////////////////////// - /// \brief Return the position of the \a index-th character - /// - /// This function computes the visual position of a character - /// from its index in the string. The returned position is - /// in global coordinates (translation, rotation, scale and - /// origin are applied). - /// If \a index is out of range, the position of the end of - /// the string is returned. - /// - /// \param index Index of the character - /// - /// \return Position of the character - /// - //////////////////////////////////////////////////////////// - Vector2f findCharacterPos(std::size_t index) const; - - //////////////////////////////////////////////////////////// - /// \brief Get the local bounding rectangle of the entity - /// - /// The returned rectangle is in local coordinates, which means - /// that it ignores the transformations (translation, rotation, - /// scale, ...) that are applied to the entity. - /// In other words, this function returns the bounds of the - /// entity in the entity's coordinate system. - /// - /// \return Local bounding rectangle of the entity - /// - //////////////////////////////////////////////////////////// - FloatRect getLocalBounds() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the global bounding rectangle of the entity - /// - /// The returned rectangle is in global coordinates, which means - /// that it takes in account the transformations (translation, - /// rotation, scale, ...) that are applied to the entity. - /// In other words, this function returns the bounds of the - /// sprite in the global 2D world's coordinate system. - /// - /// \return Global bounding rectangle of the entity - /// - //////////////////////////////////////////////////////////// - FloatRect getGlobalBounds() const; - -private : - - //////////////////////////////////////////////////////////// - /// \brief Draw the text to a render target - /// - /// \param target Render target to draw to - /// \param states Current render states - /// - //////////////////////////////////////////////////////////// - virtual void draw(RenderTarget& target, RenderStates states) const; - - //////////////////////////////////////////////////////////// - /// \brief Make sure the text's geometry is updated - /// - /// All the attributes related to rendering are cached, such - /// that the geometry is only updated when necessary. - /// - //////////////////////////////////////////////////////////// - void ensureGeometryUpdate() const; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - String m_string; ///< String to display - const Font* m_font; ///< Font used to display the string - unsigned int m_characterSize; ///< Base size of characters, in pixels - Uint32 m_style; ///< Text style (see Style enum) - Color m_color; ///< Text color - mutable VertexArray m_vertices; ///< Vertex array containing the text's geometry - mutable FloatRect m_bounds; ///< Bounding rectangle of the text (in local coordinates) - mutable bool m_geometryNeedUpdate; ///< Does the geometry need to be recomputed? -}; - -} // namespace sf - - -#endif // SFML_TEXT_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Text -/// \ingroup graphics -/// -/// sf::Text is a drawable class that allows to easily display -/// some text with custom style and color on a render target. -/// -/// It inherits all the functions from sf::Transformable: -/// position, rotation, scale, origin. It also adds text-specific -/// properties such as the font to use, the character size, -/// the font style (bold, italic, underlined, strike through), the -/// global color and the text to display of course. -/// It also provides convenience functions to calculate the -/// graphical size of the text, or to get the global position -/// of a given character. -/// -/// sf::Text works in combination with the sf::Font class, which -/// loads and provides the glyphs (visual characters) of a given font. -/// -/// The separation of sf::Font and sf::Text allows more flexibility -/// and better performances: indeed a sf::Font is a heavy resource, -/// and any operation on it is slow (often too slow for real-time -/// applications). On the other side, a sf::Text is a lightweight -/// object which can combine the glyphs data and metrics of a sf::Font -/// to display any text on a render target. -/// -/// It is important to note that the sf::Text instance doesn't -/// copy the font that it uses, it only keeps a reference to it. -/// Thus, a sf::Font must not be destructed while it is -/// used by a sf::Text (i.e. never write a function that -/// uses a local sf::Font instance for creating a text). -/// -/// See also the note on coordinates and undistorted rendering in sf::Transformable. -/// -/// Usage example: -/// \code -/// // Declare and load a font -/// sf::Font font; -/// font.loadFromFile("arial.ttf"); -/// -/// // Create a text -/// sf::Text text("hello", font); -/// text.setCharacterSize(30); -/// text.setStyle(sf::Text::Bold); -/// text.setColor(sf::Color::Red); -/// -/// // Draw it -/// window.draw(text); -/// \endcode -/// -/// \see sf::Font, sf::Transformable -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TEXT_HPP +#define SFML_TEXT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Graphical text that can be drawn to a render target +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Text : public Drawable, public Transformable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Enumeration of the string drawing styles + /// + //////////////////////////////////////////////////////////// + enum Style + { + Regular = 0, ///< Regular characters, no style + Bold = 1 << 0, ///< Bold characters + Italic = 1 << 1, ///< Italic characters + Underlined = 1 << 2, ///< Underlined characters + StrikeThrough = 1 << 3 ///< Strike through characters + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty text. + /// + //////////////////////////////////////////////////////////// + Text(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the text from a string, font and size + /// + /// Note that if the used font is a bitmap font, it is not + /// scalable, thus not all requested sizes will be available + /// to use. This needs to be taken into consideration when + /// setting the character size. If you need to display text + /// of a certain size, make sure the corresponding bitmap + /// font that supports that size is used. + /// + /// \param string Text assigned to the string + /// \param font Font used to draw the string + /// \param characterSize Base size of characters, in pixels + /// + //////////////////////////////////////////////////////////// + Text(const String& string, const Font& font, unsigned int characterSize = 30); + + //////////////////////////////////////////////////////////// + /// \brief Set the text's string + /// + /// The \a string argument is a sf::String, which can + /// automatically be constructed from standard string types. + /// So, the following calls are all valid: + /// \code + /// text.setString("hello"); + /// text.setString(L"hello"); + /// text.setString(std::string("hello")); + /// text.setString(std::wstring(L"hello")); + /// \endcode + /// A text's string is empty by default. + /// + /// \param string New string + /// + /// \see getString + /// + //////////////////////////////////////////////////////////// + void setString(const String& string); + + //////////////////////////////////////////////////////////// + /// \brief Set the text's font + /// + /// The \a font argument refers to a font that must + /// exist as long as the text uses it. Indeed, the text + /// doesn't store its own copy of the font, but rather keeps + /// a pointer to the one that you passed to this function. + /// If the font is destroyed and the text tries to + /// use it, the behaviour is undefined. + /// + /// \param font New font + /// + /// \see getFont + /// + //////////////////////////////////////////////////////////// + void setFont(const Font& font); + + //////////////////////////////////////////////////////////// + /// \brief Set the character size + /// + /// The default size is 30. + /// + /// Note that if the used font is a bitmap font, it is not + /// scalable, thus not all requested sizes will be available + /// to use. This needs to be taken into consideration when + /// setting the character size. If you need to display text + /// of a certain size, make sure the corresponding bitmap + /// font that supports that size is used. + /// + /// \param size New character size, in pixels + /// + /// \see getCharacterSize + /// + //////////////////////////////////////////////////////////// + void setCharacterSize(unsigned int size); + + //////////////////////////////////////////////////////////// + /// \brief Set the text's style + /// + /// You can pass a combination of one or more styles, for + /// example sf::Text::Bold | sf::Text::Italic. + /// The default style is sf::Text::Regular. + /// + /// \param style New style + /// + /// \see getStyle + /// + //////////////////////////////////////////////////////////// + void setStyle(Uint32 style); + + //////////////////////////////////////////////////////////// + /// \brief Set the global color of the text + /// + /// By default, the text's color is opaque white. + /// + /// \param color New color of the text + /// + /// \see getColor + /// + //////////////////////////////////////////////////////////// + void setColor(const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Get the text's string + /// + /// The returned string is a sf::String, which can automatically + /// be converted to standard string types. So, the following + /// lines of code are all valid: + /// \code + /// sf::String s1 = text.getString(); + /// std::string s2 = text.getString(); + /// std::wstring s3 = text.getString(); + /// \endcode + /// + /// \return Text's string + /// + /// \see setString + /// + //////////////////////////////////////////////////////////// + const String& getString() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the text's font + /// + /// If the text has no font attached, a NULL pointer is returned. + /// The returned reference is const, which means that you + /// cannot modify the font when you get it from this function. + /// + /// \return Pointer to the text's font + /// + /// \see setFont + /// + //////////////////////////////////////////////////////////// + const Font* getFont() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the character size + /// + /// \return Size of the characters, in pixels + /// + /// \see setCharacterSize + /// + //////////////////////////////////////////////////////////// + unsigned int getCharacterSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the text's style + /// + /// \return Text's style + /// + /// \see setStyle + /// + //////////////////////////////////////////////////////////// + Uint32 getStyle() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global color of the text + /// + /// \return Global color of the text + /// + /// \see setColor + /// + //////////////////////////////////////////////////////////// + const Color& getColor() const; + + //////////////////////////////////////////////////////////// + /// \brief Return the position of the \a index-th character + /// + /// This function computes the visual position of a character + /// from its index in the string. The returned position is + /// in global coordinates (translation, rotation, scale and + /// origin are applied). + /// If \a index is out of range, the position of the end of + /// the string is returned. + /// + /// \param index Index of the character + /// + /// \return Position of the character + /// + //////////////////////////////////////////////////////////// + Vector2f findCharacterPos(std::size_t index) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the local bounding rectangle of the entity + /// + /// The returned rectangle is in local coordinates, which means + /// that it ignores the transformations (translation, rotation, + /// scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// entity in the entity's coordinate system. + /// + /// \return Local bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getLocalBounds() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global bounding rectangle of the entity + /// + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// \return Global bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getGlobalBounds() const; + +private: + + //////////////////////////////////////////////////////////// + /// \brief Draw the text to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void draw(RenderTarget& target, RenderStates states) const; + + //////////////////////////////////////////////////////////// + /// \brief Make sure the text's geometry is updated + /// + /// All the attributes related to rendering are cached, such + /// that the geometry is only updated when necessary. + /// + //////////////////////////////////////////////////////////// + void ensureGeometryUpdate() const; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + String m_string; ///< String to display + const Font* m_font; ///< Font used to display the string + unsigned int m_characterSize; ///< Base size of characters, in pixels + Uint32 m_style; ///< Text style (see Style enum) + Color m_color; ///< Text color + mutable VertexArray m_vertices; ///< Vertex array containing the text's geometry + mutable FloatRect m_bounds; ///< Bounding rectangle of the text (in local coordinates) + mutable bool m_geometryNeedUpdate; ///< Does the geometry need to be recomputed? +}; + +} // namespace sf + + +#endif // SFML_TEXT_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Text +/// \ingroup graphics +/// +/// sf::Text is a drawable class that allows to easily display +/// some text with custom style and color on a render target. +/// +/// It inherits all the functions from sf::Transformable: +/// position, rotation, scale, origin. It also adds text-specific +/// properties such as the font to use, the character size, +/// the font style (bold, italic, underlined, strike through), the +/// global color and the text to display of course. +/// It also provides convenience functions to calculate the +/// graphical size of the text, or to get the global position +/// of a given character. +/// +/// sf::Text works in combination with the sf::Font class, which +/// loads and provides the glyphs (visual characters) of a given font. +/// +/// The separation of sf::Font and sf::Text allows more flexibility +/// and better performances: indeed a sf::Font is a heavy resource, +/// and any operation on it is slow (often too slow for real-time +/// applications). On the other side, a sf::Text is a lightweight +/// object which can combine the glyphs data and metrics of a sf::Font +/// to display any text on a render target. +/// +/// It is important to note that the sf::Text instance doesn't +/// copy the font that it uses, it only keeps a reference to it. +/// Thus, a sf::Font must not be destructed while it is +/// used by a sf::Text (i.e. never write a function that +/// uses a local sf::Font instance for creating a text). +/// +/// See also the note on coordinates and undistorted rendering in sf::Transformable. +/// +/// Usage example: +/// \code +/// // Declare and load a font +/// sf::Font font; +/// font.loadFromFile("arial.ttf"); +/// +/// // Create a text +/// sf::Text text("hello", font); +/// text.setCharacterSize(30); +/// text.setStyle(sf::Text::Bold); +/// text.setColor(sf::Color::Red); +/// +/// // Draw it +/// window.draw(text); +/// \endcode +/// +/// \see sf::Font, sf::Transformable +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Texture.hpp b/include/SFML/Graphics/Texture.hpp index 8fde8ec0..729fc405 100644 --- a/include/SFML/Graphics/Texture.hpp +++ b/include/SFML/Graphics/Texture.hpp @@ -46,7 +46,7 @@ class InputStream; //////////////////////////////////////////////////////////// class SFML_GRAPHICS_API Texture : GlResource { -public : +public: //////////////////////////////////////////////////////////// /// \brief Types of texture coordinates that can be used for rendering @@ -58,7 +58,7 @@ public : Pixels ///< Texture coordinates in range [0 .. size] }; -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -468,7 +468,7 @@ public : //////////////////////////////////////////////////////////// static unsigned int getMaximumSize(); -private : +private: friend class RenderTexture; friend class RenderTarget; diff --git a/include/SFML/Graphics/Transform.hpp b/include/SFML/Graphics/Transform.hpp index 869bdece..41155fb8 100644 --- a/include/SFML/Graphics/Transform.hpp +++ b/include/SFML/Graphics/Transform.hpp @@ -41,7 +41,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_GRAPHICS_API Transform { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor diff --git a/include/SFML/Graphics/Transformable.hpp b/include/SFML/Graphics/Transformable.hpp index 6fe1033a..d1a92aed 100644 --- a/include/SFML/Graphics/Transformable.hpp +++ b/include/SFML/Graphics/Transformable.hpp @@ -40,7 +40,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_GRAPHICS_API Transformable { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -311,7 +311,7 @@ public : //////////////////////////////////////////////////////////// const Transform& getInverseTransform() const; -private : +private: //////////////////////////////////////////////////////////// // Member data @@ -396,7 +396,7 @@ private : /// \code /// class MyEntity /// { -/// public : +/// public: /// void SetPosition(const MyVector& v) /// { /// myTransform.setPosition(v.x(), v.y()); @@ -407,7 +407,7 @@ private : /// target.draw(..., myTransform.getTransform()); /// } /// -/// private : +/// private: /// sf::Transformable myTransform; /// }; /// \endcode diff --git a/include/SFML/Graphics/Vertex.hpp b/include/SFML/Graphics/Vertex.hpp index 11bb1833..cdd606b8 100644 --- a/include/SFML/Graphics/Vertex.hpp +++ b/include/SFML/Graphics/Vertex.hpp @@ -41,7 +41,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_GRAPHICS_API Vertex { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor diff --git a/include/SFML/Graphics/VertexArray.hpp b/include/SFML/Graphics/VertexArray.hpp index 5615f52e..4144d4f8 100644 --- a/include/SFML/Graphics/VertexArray.hpp +++ b/include/SFML/Graphics/VertexArray.hpp @@ -44,7 +44,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_GRAPHICS_API VertexArray : public Drawable { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -171,7 +171,7 @@ public : //////////////////////////////////////////////////////////// FloatRect getBounds() const; -private : +private: //////////////////////////////////////////////////////////// /// \brief Draw the vertex array to a render target diff --git a/include/SFML/Graphics/View.hpp b/include/SFML/Graphics/View.hpp index 85b531a9..f4ff818f 100644 --- a/include/SFML/Graphics/View.hpp +++ b/include/SFML/Graphics/View.hpp @@ -1,343 +1,343 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_VIEW_HPP -#define SFML_VIEW_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief 2D camera that defines what region is shown on screen -/// -//////////////////////////////////////////////////////////// -class SFML_GRAPHICS_API View -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor creates a default view of (0, 0, 1000, 1000) - /// - //////////////////////////////////////////////////////////// - View(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the view from a rectangle - /// - /// \param rectangle Rectangle defining the zone to display - /// - //////////////////////////////////////////////////////////// - explicit View(const FloatRect& rectangle); - - //////////////////////////////////////////////////////////// - /// \brief Construct the view from its center and size - /// - /// \param center Center of the zone to display - /// \param size Size of zone to display - /// - //////////////////////////////////////////////////////////// - View(const Vector2f& center, const Vector2f& size); - - //////////////////////////////////////////////////////////// - /// \brief Set the center of the view - /// - /// \param x X coordinate of the new center - /// \param y Y coordinate of the new center - /// - /// \see setSize, getCenter - /// - //////////////////////////////////////////////////////////// - void setCenter(float x, float y); - - //////////////////////////////////////////////////////////// - /// \brief Set the center of the view - /// - /// \param center New center - /// - /// \see setSize, getCenter - /// - //////////////////////////////////////////////////////////// - void setCenter(const Vector2f& center); - - //////////////////////////////////////////////////////////// - /// \brief Set the size of the view - /// - /// \param width New width of the view - /// \param height New height of the view - /// - /// \see setCenter, getCenter - /// - //////////////////////////////////////////////////////////// - void setSize(float width, float height); - - //////////////////////////////////////////////////////////// - /// \brief Set the size of the view - /// - /// \param size New size - /// - /// \see setCenter, getCenter - /// - //////////////////////////////////////////////////////////// - void setSize(const Vector2f& size); - - //////////////////////////////////////////////////////////// - /// \brief Set the orientation of the view - /// - /// The default rotation of a view is 0 degree. - /// - /// \param angle New angle, in degrees - /// - /// \see getRotation - /// - //////////////////////////////////////////////////////////// - void setRotation(float angle); - - //////////////////////////////////////////////////////////// - /// \brief Set the target viewport - /// - /// The viewport is the rectangle into which the contents of the - /// view are displayed, expressed as a factor (between 0 and 1) - /// of the size of the RenderTarget to which the view is applied. - /// For example, a view which takes the left side of the target would - /// be defined with View.setViewport(sf::FloatRect(0, 0, 0.5, 1)). - /// By default, a view has a viewport which covers the entire target. - /// - /// \param viewport New viewport rectangle - /// - /// \see getViewport - /// - //////////////////////////////////////////////////////////// - void setViewport(const FloatRect& viewport); - - //////////////////////////////////////////////////////////// - /// \brief Reset the view to the given rectangle - /// - /// Note that this function resets the rotation angle to 0. - /// - /// \param rectangle Rectangle defining the zone to display - /// - /// \see setCenter, setSize, setRotation - /// - //////////////////////////////////////////////////////////// - void reset(const FloatRect& rectangle); - - //////////////////////////////////////////////////////////// - /// \brief Get the center of the view - /// - /// \return Center of the view - /// - /// \see getSize, setCenter - /// - //////////////////////////////////////////////////////////// - const Vector2f& getCenter() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the size of the view - /// - /// \return Size of the view - /// - /// \see getCenter, setSize - /// - //////////////////////////////////////////////////////////// - const Vector2f& getSize() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the current orientation of the view - /// - /// \return Rotation angle of the view, in degrees - /// - /// \see setRotation - /// - //////////////////////////////////////////////////////////// - float getRotation() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the target viewport rectangle of the view - /// - /// \return Viewport rectangle, expressed as a factor of the target size - /// - /// \see setViewport - /// - //////////////////////////////////////////////////////////// - const FloatRect& getViewport() const; - - //////////////////////////////////////////////////////////// - /// \brief Move the view relatively to its current position - /// - /// \param offsetX X coordinate of the move offset - /// \param offsetY Y coordinate of the move offset - /// - /// \see setCenter, rotate, zoom - /// - //////////////////////////////////////////////////////////// - void move(float offsetX, float offsetY); - - //////////////////////////////////////////////////////////// - /// \brief Move the view relatively to its current position - /// - /// \param offset Move offset - /// - /// \see setCenter, rotate, zoom - /// - //////////////////////////////////////////////////////////// - void move(const Vector2f& offset); - - //////////////////////////////////////////////////////////// - /// \brief Rotate the view relatively to its current orientation - /// - /// \param angle Angle to rotate, in degrees - /// - /// \see setRotation, move, zoom - /// - //////////////////////////////////////////////////////////// - void rotate(float angle); - - //////////////////////////////////////////////////////////// - /// \brief Resize the view rectangle relatively to its current size - /// - /// Resizing the view simulates a zoom, as the zone displayed on - /// screen grows or shrinks. - /// \a factor is a multiplier: - /// \li 1 keeps the size unchanged - /// \li > 1 makes the view bigger (objects appear smaller) - /// \li < 1 makes the view smaller (objects appear bigger) - /// - /// \param factor Zoom factor to apply - /// - /// \see setSize, move, rotate - /// - //////////////////////////////////////////////////////////// - void zoom(float factor); - - //////////////////////////////////////////////////////////// - /// \brief Get the projection transform of the view - /// - /// This function is meant for internal use only. - /// - /// \return Projection transform defining the view - /// - /// \see getInverseTransform - /// - //////////////////////////////////////////////////////////// - const Transform& getTransform() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the inverse projection transform of the view - /// - /// This function is meant for internal use only. - /// - /// \return Inverse of the projection transform defining the view - /// - /// \see getTransform - /// - //////////////////////////////////////////////////////////// - const Transform& getInverseTransform() const; - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Vector2f m_center; ///< Center of the view, in scene coordinates - Vector2f m_size; ///< Size of the view, in scene coordinates - float m_rotation; ///< Angle of rotation of the view rectangle, in degrees - FloatRect m_viewport; ///< Viewport rectangle, expressed as a factor of the render-target's size - mutable Transform m_transform; ///< Precomputed projection transform corresponding to the view - mutable Transform m_inverseTransform; ///< Precomputed inverse projection transform corresponding to the view - mutable bool m_transformUpdated; ///< Internal state telling if the transform needs to be updated - mutable bool m_invTransformUpdated; ///< Internal state telling if the inverse transform needs to be updated -}; - -} // namespace sf - - -#endif // SFML_VIEW_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::View -/// \ingroup graphics -/// -/// sf::View defines a camera in the 2D scene. This is a -/// very powerful concept: you can scroll, rotate or zoom -/// the entire scene without altering the way that your -/// drawable objects are drawn. -/// -/// A view is composed of a source rectangle, which defines -/// what part of the 2D scene is shown, and a target viewport, -/// which defines where the contents of the source rectangle -/// will be displayed on the render target (window or texture). -/// -/// The viewport allows to map the scene to a custom part -/// of the render target, and can be used for split-screen -/// or for displaying a minimap, for example. If the source -/// rectangle has not the same size as the viewport, its -/// contents will be stretched to fit in. -/// -/// To apply a view, you have to assign it to the render target. -/// Then, every objects drawn in this render target will be -/// affected by the view until you use another view. -/// -/// Usage example: -/// \code -/// sf::RenderWindow window; -/// sf::View view; -/// -/// // Initialize the view to a rectangle located at (100, 100) and with a size of 400x200 -/// view.reset(sf::FloatRect(100, 100, 400, 200)); -/// -/// // Rotate it by 45 degrees -/// view.rotate(45); -/// -/// // Set its target viewport to be half of the window -/// view.setViewport(sf::FloatRect(0.f, 0.f, 0.5f, 1.f)); -/// -/// // Apply it -/// window.setView(view); -/// -/// // Render stuff -/// window.draw(someSprite); -/// -/// // Set the default view back -/// window.setView(window.getDefaultView()); -/// -/// // Render stuff not affected by the view -/// window.draw(someText); -/// \endcode -/// -/// See also the note on coordinates and undistorted rendering in sf::Transformable. -/// -/// \see sf::RenderWindow, sf::RenderTexture -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VIEW_HPP +#define SFML_VIEW_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief 2D camera that defines what region is shown on screen +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API View +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor creates a default view of (0, 0, 1000, 1000) + /// + //////////////////////////////////////////////////////////// + View(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the view from a rectangle + /// + /// \param rectangle Rectangle defining the zone to display + /// + //////////////////////////////////////////////////////////// + explicit View(const FloatRect& rectangle); + + //////////////////////////////////////////////////////////// + /// \brief Construct the view from its center and size + /// + /// \param center Center of the zone to display + /// \param size Size of zone to display + /// + //////////////////////////////////////////////////////////// + View(const Vector2f& center, const Vector2f& size); + + //////////////////////////////////////////////////////////// + /// \brief Set the center of the view + /// + /// \param x X coordinate of the new center + /// \param y Y coordinate of the new center + /// + /// \see setSize, getCenter + /// + //////////////////////////////////////////////////////////// + void setCenter(float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief Set the center of the view + /// + /// \param center New center + /// + /// \see setSize, getCenter + /// + //////////////////////////////////////////////////////////// + void setCenter(const Vector2f& center); + + //////////////////////////////////////////////////////////// + /// \brief Set the size of the view + /// + /// \param width New width of the view + /// \param height New height of the view + /// + /// \see setCenter, getCenter + /// + //////////////////////////////////////////////////////////// + void setSize(float width, float height); + + //////////////////////////////////////////////////////////// + /// \brief Set the size of the view + /// + /// \param size New size + /// + /// \see setCenter, getCenter + /// + //////////////////////////////////////////////////////////// + void setSize(const Vector2f& size); + + //////////////////////////////////////////////////////////// + /// \brief Set the orientation of the view + /// + /// The default rotation of a view is 0 degree. + /// + /// \param angle New angle, in degrees + /// + /// \see getRotation + /// + //////////////////////////////////////////////////////////// + void setRotation(float angle); + + //////////////////////////////////////////////////////////// + /// \brief Set the target viewport + /// + /// The viewport is the rectangle into which the contents of the + /// view are displayed, expressed as a factor (between 0 and 1) + /// of the size of the RenderTarget to which the view is applied. + /// For example, a view which takes the left side of the target would + /// be defined with View.setViewport(sf::FloatRect(0, 0, 0.5, 1)). + /// By default, a view has a viewport which covers the entire target. + /// + /// \param viewport New viewport rectangle + /// + /// \see getViewport + /// + //////////////////////////////////////////////////////////// + void setViewport(const FloatRect& viewport); + + //////////////////////////////////////////////////////////// + /// \brief Reset the view to the given rectangle + /// + /// Note that this function resets the rotation angle to 0. + /// + /// \param rectangle Rectangle defining the zone to display + /// + /// \see setCenter, setSize, setRotation + /// + //////////////////////////////////////////////////////////// + void reset(const FloatRect& rectangle); + + //////////////////////////////////////////////////////////// + /// \brief Get the center of the view + /// + /// \return Center of the view + /// + /// \see getSize, setCenter + /// + //////////////////////////////////////////////////////////// + const Vector2f& getCenter() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the view + /// + /// \return Size of the view + /// + /// \see getCenter, setSize + /// + //////////////////////////////////////////////////////////// + const Vector2f& getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the current orientation of the view + /// + /// \return Rotation angle of the view, in degrees + /// + /// \see setRotation + /// + //////////////////////////////////////////////////////////// + float getRotation() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the target viewport rectangle of the view + /// + /// \return Viewport rectangle, expressed as a factor of the target size + /// + /// \see setViewport + /// + //////////////////////////////////////////////////////////// + const FloatRect& getViewport() const; + + //////////////////////////////////////////////////////////// + /// \brief Move the view relatively to its current position + /// + /// \param offsetX X coordinate of the move offset + /// \param offsetY Y coordinate of the move offset + /// + /// \see setCenter, rotate, zoom + /// + //////////////////////////////////////////////////////////// + void move(float offsetX, float offsetY); + + //////////////////////////////////////////////////////////// + /// \brief Move the view relatively to its current position + /// + /// \param offset Move offset + /// + /// \see setCenter, rotate, zoom + /// + //////////////////////////////////////////////////////////// + void move(const Vector2f& offset); + + //////////////////////////////////////////////////////////// + /// \brief Rotate the view relatively to its current orientation + /// + /// \param angle Angle to rotate, in degrees + /// + /// \see setRotation, move, zoom + /// + //////////////////////////////////////////////////////////// + void rotate(float angle); + + //////////////////////////////////////////////////////////// + /// \brief Resize the view rectangle relatively to its current size + /// + /// Resizing the view simulates a zoom, as the zone displayed on + /// screen grows or shrinks. + /// \a factor is a multiplier: + /// \li 1 keeps the size unchanged + /// \li > 1 makes the view bigger (objects appear smaller) + /// \li < 1 makes the view smaller (objects appear bigger) + /// + /// \param factor Zoom factor to apply + /// + /// \see setSize, move, rotate + /// + //////////////////////////////////////////////////////////// + void zoom(float factor); + + //////////////////////////////////////////////////////////// + /// \brief Get the projection transform of the view + /// + /// This function is meant for internal use only. + /// + /// \return Projection transform defining the view + /// + /// \see getInverseTransform + /// + //////////////////////////////////////////////////////////// + const Transform& getTransform() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the inverse projection transform of the view + /// + /// This function is meant for internal use only. + /// + /// \return Inverse of the projection transform defining the view + /// + /// \see getTransform + /// + //////////////////////////////////////////////////////////// + const Transform& getInverseTransform() const; + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2f m_center; ///< Center of the view, in scene coordinates + Vector2f m_size; ///< Size of the view, in scene coordinates + float m_rotation; ///< Angle of rotation of the view rectangle, in degrees + FloatRect m_viewport; ///< Viewport rectangle, expressed as a factor of the render-target's size + mutable Transform m_transform; ///< Precomputed projection transform corresponding to the view + mutable Transform m_inverseTransform; ///< Precomputed inverse projection transform corresponding to the view + mutable bool m_transformUpdated; ///< Internal state telling if the transform needs to be updated + mutable bool m_invTransformUpdated; ///< Internal state telling if the inverse transform needs to be updated +}; + +} // namespace sf + + +#endif // SFML_VIEW_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::View +/// \ingroup graphics +/// +/// sf::View defines a camera in the 2D scene. This is a +/// very powerful concept: you can scroll, rotate or zoom +/// the entire scene without altering the way that your +/// drawable objects are drawn. +/// +/// A view is composed of a source rectangle, which defines +/// what part of the 2D scene is shown, and a target viewport, +/// which defines where the contents of the source rectangle +/// will be displayed on the render target (window or texture). +/// +/// The viewport allows to map the scene to a custom part +/// of the render target, and can be used for split-screen +/// or for displaying a minimap, for example. If the source +/// rectangle has not the same size as the viewport, its +/// contents will be stretched to fit in. +/// +/// To apply a view, you have to assign it to the render target. +/// Then, every objects drawn in this render target will be +/// affected by the view until you use another view. +/// +/// Usage example: +/// \code +/// sf::RenderWindow window; +/// sf::View view; +/// +/// // Initialize the view to a rectangle located at (100, 100) and with a size of 400x200 +/// view.reset(sf::FloatRect(100, 100, 400, 200)); +/// +/// // Rotate it by 45 degrees +/// view.rotate(45); +/// +/// // Set its target viewport to be half of the window +/// view.setViewport(sf::FloatRect(0.f, 0.f, 0.5f, 1.f)); +/// +/// // Apply it +/// window.setView(view); +/// +/// // Render stuff +/// window.draw(someSprite); +/// +/// // Set the default view back +/// window.setView(window.getDefaultView()); +/// +/// // Render stuff not affected by the view +/// window.draw(someText); +/// \endcode +/// +/// See also the note on coordinates and undistorted rendering in sf::Transformable. +/// +/// \see sf::RenderWindow, sf::RenderTexture +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Network.hpp b/include/SFML/Network.hpp index a8fc551c..e5e5d067 100644 --- a/include/SFML/Network.hpp +++ b/include/SFML/Network.hpp @@ -1,51 +1,51 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_NETWORK_HPP -#define SFML_NETWORK_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#endif // SFML_NETWORK_HPP - -//////////////////////////////////////////////////////////// -/// \defgroup network Network module -/// -/// Socket-based communication, utilities and higher-level -/// network protocols (HTTP, FTP). -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_NETWORK_HPP +#define SFML_NETWORK_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif // SFML_NETWORK_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup network Network module +/// +/// Socket-based communication, utilities and higher-level +/// network protocols (HTTP, FTP). +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Network/Ftp.hpp b/include/SFML/Network/Ftp.hpp index a9a677ce..b2cd744b 100644 --- a/include/SFML/Network/Ftp.hpp +++ b/include/SFML/Network/Ftp.hpp @@ -1,608 +1,608 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_FTP_HPP -#define SFML_FTP_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -class IpAddress; - -//////////////////////////////////////////////////////////// -/// \brief A FTP client -/// -//////////////////////////////////////////////////////////// -class SFML_NETWORK_API Ftp : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Enumeration of transfer modes - /// - //////////////////////////////////////////////////////////// - enum TransferMode - { - Binary, ///< Binary mode (file is transfered as a sequence of bytes) - Ascii, ///< Text mode using ASCII encoding - Ebcdic ///< Text mode using EBCDIC encoding - }; - - //////////////////////////////////////////////////////////// - /// \brief Define a FTP response - /// - //////////////////////////////////////////////////////////// - class SFML_NETWORK_API Response - { - public : - - //////////////////////////////////////////////////////////// - /// \brief Status codes possibly returned by a FTP response - /// - //////////////////////////////////////////////////////////// - enum Status - { - // 1xx: the requested action is being initiated, - // expect another reply before proceeding with a new command - RestartMarkerReply = 110, ///< Restart marker reply - ServiceReadySoon = 120, ///< Service ready in N minutes - DataConnectionAlreadyOpened = 125, ///< Data connection already opened, transfer starting - OpeningDataConnection = 150, ///< File status ok, about to open data connection - - // 2xx: the requested action has been successfully completed - Ok = 200, ///< Command ok - PointlessCommand = 202, ///< Command not implemented - SystemStatus = 211, ///< System status, or system help reply - DirectoryStatus = 212, ///< Directory status - FileStatus = 213, ///< File status - HelpMessage = 214, ///< Help message - SystemType = 215, ///< NAME system type, where NAME is an official system name from the list in the Assigned Numbers document - ServiceReady = 220, ///< Service ready for new user - ClosingConnection = 221, ///< Service closing control connection - DataConnectionOpened = 225, ///< Data connection open, no transfer in progress - ClosingDataConnection = 226, ///< Closing data connection, requested file action successful - EnteringPassiveMode = 227, ///< Entering passive mode - LoggedIn = 230, ///< User logged in, proceed. Logged out if appropriate - FileActionOk = 250, ///< Requested file action ok - DirectoryOk = 257, ///< PATHNAME created - - // 3xx: the command has been accepted, but the requested action - // is dormant, pending receipt of further information - NeedPassword = 331, ///< User name ok, need password - NeedAccountToLogIn = 332, ///< Need account for login - NeedInformation = 350, ///< Requested file action pending further information - - // 4xx: the command was not accepted and the requested action did not take place, - // but the error condition is temporary and the action may be requested again - ServiceUnavailable = 421, ///< Service not available, closing control connection - DataConnectionUnavailable = 425, ///< Can't open data connection - TransferAborted = 426, ///< Connection closed, transfer aborted - FileActionAborted = 450, ///< Requested file action not taken - LocalError = 451, ///< Requested action aborted, local error in processing - InsufficientStorageSpace = 452, ///< Requested action not taken; insufficient storage space in system, file unavailable - - // 5xx: the command was not accepted and - // the requested action did not take place - CommandUnknown = 500, ///< Syntax error, command unrecognized - ParametersUnknown = 501, ///< Syntax error in parameters or arguments - CommandNotImplemented = 502, ///< Command not implemented - BadCommandSequence = 503, ///< Bad sequence of commands - ParameterNotImplemented = 504, ///< Command not implemented for that parameter - NotLoggedIn = 530, ///< Not logged in - NeedAccountToStore = 532, ///< Need account for storing files - FileUnavailable = 550, ///< Requested action not taken, file unavailable - PageTypeUnknown = 551, ///< Requested action aborted, page type unknown - NotEnoughMemory = 552, ///< Requested file action aborted, exceeded storage allocation - FilenameNotAllowed = 553, ///< Requested action not taken, file name not allowed - - // 10xx: SFML custom codes - InvalidResponse = 1000, ///< Response is not a valid FTP one - ConnectionFailed = 1001, ///< Connection with server failed - ConnectionClosed = 1002, ///< Connection with server closed - InvalidFile = 1003 ///< Invalid file to upload / download - }; - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor is used by the FTP client to build - /// the response. - /// - /// \param code Response status code - /// \param message Response message - /// - //////////////////////////////////////////////////////////// - explicit Response(Status code = InvalidResponse, const std::string& message = ""); - - //////////////////////////////////////////////////////////// - /// \brief Check if the status code means a success - /// - /// This function is defined for convenience, it is - /// equivalent to testing if the status code is < 400. - /// - /// \return True if the status is a success, false if it is a failure - /// - //////////////////////////////////////////////////////////// - bool isOk() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the status code of the response - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Status getStatus() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the full message contained in the response - /// - /// \return The response message - /// - //////////////////////////////////////////////////////////// - const std::string& getMessage() const; - - private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Status m_status; ///< Status code returned from the server - std::string m_message; ///< Last message received from the server - }; - - //////////////////////////////////////////////////////////// - /// \brief Specialization of FTP response returning a directory - /// - //////////////////////////////////////////////////////////// - class SFML_NETWORK_API DirectoryResponse : public Response - { - public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// \param response Source response - /// - //////////////////////////////////////////////////////////// - DirectoryResponse(const Response& response); - - //////////////////////////////////////////////////////////// - /// \brief Get the directory returned in the response - /// - /// \return Directory name - /// - //////////////////////////////////////////////////////////// - const std::string& getDirectory() const; - - private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - std::string m_directory; ///< Directory extracted from the response message - }; - - - //////////////////////////////////////////////////////////// - /// \brief Specialization of FTP response returning a - /// filename lisiting - //////////////////////////////////////////////////////////// - class SFML_NETWORK_API ListingResponse : public Response - { - public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// \param response Source response - /// \param data Data containing the raw listing - /// - //////////////////////////////////////////////////////////// - ListingResponse(const Response& response, const std::string& data); - - //////////////////////////////////////////////////////////// - /// \brief Return the array of directory/file names - /// - /// \return Array containing the requested listing - /// - //////////////////////////////////////////////////////////// - const std::vector& getListing() const; - - private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - std::vector m_listing; ///< Directory/file names extracted from the data - }; - - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - /// Automatically closes the connection with the server if - /// it is still opened. - /// - //////////////////////////////////////////////////////////// - ~Ftp(); - - //////////////////////////////////////////////////////////// - /// \brief Connect to the specified FTP server - /// - /// The port has a default value of 21, which is the standard - /// port used by the FTP protocol. You shouldn't use a different - /// value, unless you really know what you do. - /// This function tries to connect to the server so it may take - /// a while to complete, especially if the server is not - /// reachable. To avoid blocking your application for too long, - /// you can use a timeout. The default value, Time::Zero, means that the - /// system timeout will be used (which is usually pretty long). - /// - /// \param server Name or address of the FTP server to connect to - /// \param port Port used for the connection - /// \param timeout Maximum time to wait - /// - /// \return Server response to the request - /// - /// \see disconnect - /// - //////////////////////////////////////////////////////////// - Response connect(const IpAddress& server, unsigned short port = 21, Time timeout = Time::Zero); - - //////////////////////////////////////////////////////////// - /// \brief Close the connection with the server - /// - /// \return Server response to the request - /// - /// \see connect - /// - //////////////////////////////////////////////////////////// - Response disconnect(); - - //////////////////////////////////////////////////////////// - /// \brief Log in using an anonymous account - /// - /// Logging in is mandatory after connecting to the server. - /// Users that are not logged in cannot perform any operation. - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response login(); - - //////////////////////////////////////////////////////////// - /// \brief Log in using a username and a password - /// - /// Logging in is mandatory after connecting to the server. - /// Users that are not logged in cannot perform any operation. - /// - /// \param name User name - /// \param password Password - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response login(const std::string& name, const std::string& password); - - //////////////////////////////////////////////////////////// - /// \brief Send a null command to keep the connection alive - /// - /// This command is useful because the server may close the - /// connection automatically if no command is sent. - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response keepAlive(); - - //////////////////////////////////////////////////////////// - /// \brief Get the current working directory - /// - /// The working directory is the root path for subsequent - /// operations involving directories and/or filenames. - /// - /// \return Server response to the request - /// - /// \see getDirectoryListing, changeDirectory, parentDirectory - /// - //////////////////////////////////////////////////////////// - DirectoryResponse getWorkingDirectory(); - - //////////////////////////////////////////////////////////// - /// \brief Get the contents of the given directory - /// - /// This function retrieves the sub-directories and files - /// contained in the given directory. It is not recursive. - /// The \a directory parameter is relative to the current - /// working directory. - /// - /// \param directory Directory to list - /// - /// \return Server response to the request - /// - /// \see getWorkingDirectory, changeDirectory, parentDirectory - /// - //////////////////////////////////////////////////////////// - ListingResponse getDirectoryListing(const std::string& directory = ""); - - //////////////////////////////////////////////////////////// - /// \brief Change the current working directory - /// - /// The new directory must be relative to the current one. - /// - /// \param directory New working directory - /// - /// \return Server response to the request - /// - /// \see getWorkingDirectory, getDirectoryListing, parentDirectory - /// - //////////////////////////////////////////////////////////// - Response changeDirectory(const std::string& directory); - - //////////////////////////////////////////////////////////// - /// \brief Go to the parent directory of the current one - /// - /// \return Server response to the request - /// - /// \see getWorkingDirectory, getDirectoryListing, changeDirectory - /// - //////////////////////////////////////////////////////////// - Response parentDirectory(); - - //////////////////////////////////////////////////////////// - /// \brief Create a new directory - /// - /// The new directory is created as a child of the current - /// working directory. - /// - /// \param name Name of the directory to create - /// - /// \return Server response to the request - /// - /// \see deleteDirectory - /// - //////////////////////////////////////////////////////////// - Response createDirectory(const std::string& name); - - //////////////////////////////////////////////////////////// - /// \brief Remove an existing directory - /// - /// The directory to remove must be relative to the - /// current working directory. - /// Use this function with caution, the directory will - /// be removed permanently! - /// - /// \param name Name of the directory to remove - /// - /// \return Server response to the request - /// - /// \see createDirectory - /// - //////////////////////////////////////////////////////////// - Response deleteDirectory(const std::string& name); - - //////////////////////////////////////////////////////////// - /// \brief Rename an existing file - /// - /// The filenames must be relative to the current working - /// directory. - /// - /// \param file File to rename - /// \param newName New name of the file - /// - /// \return Server response to the request - /// - /// \see deleteFile - /// - //////////////////////////////////////////////////////////// - Response renameFile(const std::string& file, const std::string& newName); - - //////////////////////////////////////////////////////////// - /// \brief Remove an existing file - /// - /// The file name must be relative to the current working - /// directory. - /// Use this function with caution, the file will be - /// removed permanently! - /// - /// \param name File to remove - /// - /// \return Server response to the request - /// - /// \see renameFile - /// - //////////////////////////////////////////////////////////// - Response deleteFile(const std::string& name); - - //////////////////////////////////////////////////////////// - /// \brief Download a file from the server - /// - /// The filename of the distant file is relative to the - /// current working directory of the server, and the local - /// destination path is relative to the current directory - /// of your application. - /// If a file with the same filename as the distant file - /// already exists in the local destination path, it will - /// be overwritten. - /// - /// \param remoteFile Filename of the distant file to download - /// \param localPath The directory in which to put the file on the local computer - /// \param mode Transfer mode - /// - /// \return Server response to the request - /// - /// \see upload - /// - //////////////////////////////////////////////////////////// - Response download(const std::string& remoteFile, const std::string& localPath, TransferMode mode = Binary); - - //////////////////////////////////////////////////////////// - /// \brief Upload a file to the server - /// - /// The name of the local file is relative to the current - /// working directory of your application, and the - /// remote path is relative to the current directory of the - /// FTP server. - /// - /// \param localFile Path of the local file to upload - /// \param remotePath The directory in which to put the file on the server - /// \param mode Transfer mode - /// - /// \return Server response to the request - /// - /// \see download - /// - //////////////////////////////////////////////////////////// - Response upload(const std::string& localFile, const std::string& remotePath, TransferMode mode = Binary); - - //////////////////////////////////////////////////////////// - /// \brief Send a command to the FTP server - /// - /// While the most often used commands are provided as member - /// functions in the sf::Ftp class, this method can be used - /// to send any FTP command to the server. If the command - /// requires one or more parameters, they can be specified - /// in \a parameter. If the server returns information, you - /// can extract it from the response using Response::getMessage(). - /// - /// \param command Command to send - /// \param parameter Command parameter - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response sendCommand(const std::string& command, const std::string& parameter = ""); - -private: - - //////////////////////////////////////////////////////////// - /// \brief Receive a response from the server - /// - /// This function must be called after each call to - /// sendCommand that expects a response. - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response getResponse(); - - //////////////////////////////////////////////////////////// - /// \brief Utility class for exchanging datas with the server - /// on the data channel - /// - //////////////////////////////////////////////////////////// - class DataChannel; - - friend class DataChannel; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - TcpSocket m_commandSocket; ///< Socket holding the control connection with the server -}; - -} // namespace sf - - -#endif // SFML_FTP_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Ftp -/// \ingroup network -/// -/// sf::Ftp is a very simple FTP client that allows you -/// to communicate with a FTP server. The FTP protocol allows -/// you to manipulate a remote file system (list files, -/// upload, download, create, remove, ...). -/// -/// Using the FTP client consists of 4 parts: -/// \li Connecting to the FTP server -/// \li Logging in (either as a registered user or anonymously) -/// \li Sending commands to the server -/// \li Disconnecting (this part can be done implicitly by the destructor) -/// -/// Every command returns a FTP response, which contains the -/// status code as well as a message from the server. Some -/// commands such as getWorkingDirectory() and getDirectoryListing() -/// return additional data, and use a class derived from -/// sf::Ftp::Response to provide this data. The most often used -/// commands are directly provided as member functions, but it is -/// also possible to use specific commands with the sendCommand() method. -/// -/// All commands, especially upload and download, may take some -/// time to complete. This is important to know if you don't want -/// to block your application while the server is completing -/// the task. -/// -/// Usage example: -/// \code -/// // Create a new FTP client -/// sf::Ftp ftp; -/// -/// // Connect to the server -/// sf::Ftp::Response response = ftp.connect("ftp://ftp.myserver.com"); -/// if (response.isOk()) -/// std::cout << "Connected" << std::endl; -/// -/// // Log in -/// response = ftp.login("laurent", "dF6Zm89D"); -/// if (response.isOk()) -/// std::cout << "Logged in" << std::endl; -/// -/// // Print the working directory -/// sf::Ftp::DirectoryResponse directory = ftp.getWorkingDirectory(); -/// if (directory.isOk()) -/// std::cout << "Working directory: " << directory.getDirectory() << std::endl; -/// -/// // Create a new directory -/// response = ftp.createDirectory("files"); -/// if (response.isOk()) -/// std::cout << "Created new directory" << std::endl; -/// -/// // Upload a file to this new directory -/// response = ftp.upload("local-path/file.txt", "files", sf::Ftp::Ascii); -/// if (response.isOk()) -/// std::cout << "File uploaded" << std::endl; -/// -/// // Send specific commands (here: FEAT to list supported FTP features) -/// response = ftp.sendCommand("FEAT"); -/// if (response.isOk()) -/// std::cout << "Feature list:\n" << response.getMessage() << std::endl; -/// -/// // Disconnect from the server (optional) -/// ftp.disconnect(); -/// \endcode -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_FTP_HPP +#define SFML_FTP_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +class IpAddress; + +//////////////////////////////////////////////////////////// +/// \brief A FTP client +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API Ftp : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Enumeration of transfer modes + /// + //////////////////////////////////////////////////////////// + enum TransferMode + { + Binary, ///< Binary mode (file is transfered as a sequence of bytes) + Ascii, ///< Text mode using ASCII encoding + Ebcdic ///< Text mode using EBCDIC encoding + }; + + //////////////////////////////////////////////////////////// + /// \brief Define a FTP response + /// + //////////////////////////////////////////////////////////// + class SFML_NETWORK_API Response + { + public: + + //////////////////////////////////////////////////////////// + /// \brief Status codes possibly returned by a FTP response + /// + //////////////////////////////////////////////////////////// + enum Status + { + // 1xx: the requested action is being initiated, + // expect another reply before proceeding with a new command + RestartMarkerReply = 110, ///< Restart marker reply + ServiceReadySoon = 120, ///< Service ready in N minutes + DataConnectionAlreadyOpened = 125, ///< Data connection already opened, transfer starting + OpeningDataConnection = 150, ///< File status ok, about to open data connection + + // 2xx: the requested action has been successfully completed + Ok = 200, ///< Command ok + PointlessCommand = 202, ///< Command not implemented + SystemStatus = 211, ///< System status, or system help reply + DirectoryStatus = 212, ///< Directory status + FileStatus = 213, ///< File status + HelpMessage = 214, ///< Help message + SystemType = 215, ///< NAME system type, where NAME is an official system name from the list in the Assigned Numbers document + ServiceReady = 220, ///< Service ready for new user + ClosingConnection = 221, ///< Service closing control connection + DataConnectionOpened = 225, ///< Data connection open, no transfer in progress + ClosingDataConnection = 226, ///< Closing data connection, requested file action successful + EnteringPassiveMode = 227, ///< Entering passive mode + LoggedIn = 230, ///< User logged in, proceed. Logged out if appropriate + FileActionOk = 250, ///< Requested file action ok + DirectoryOk = 257, ///< PATHNAME created + + // 3xx: the command has been accepted, but the requested action + // is dormant, pending receipt of further information + NeedPassword = 331, ///< User name ok, need password + NeedAccountToLogIn = 332, ///< Need account for login + NeedInformation = 350, ///< Requested file action pending further information + + // 4xx: the command was not accepted and the requested action did not take place, + // but the error condition is temporary and the action may be requested again + ServiceUnavailable = 421, ///< Service not available, closing control connection + DataConnectionUnavailable = 425, ///< Can't open data connection + TransferAborted = 426, ///< Connection closed, transfer aborted + FileActionAborted = 450, ///< Requested file action not taken + LocalError = 451, ///< Requested action aborted, local error in processing + InsufficientStorageSpace = 452, ///< Requested action not taken; insufficient storage space in system, file unavailable + + // 5xx: the command was not accepted and + // the requested action did not take place + CommandUnknown = 500, ///< Syntax error, command unrecognized + ParametersUnknown = 501, ///< Syntax error in parameters or arguments + CommandNotImplemented = 502, ///< Command not implemented + BadCommandSequence = 503, ///< Bad sequence of commands + ParameterNotImplemented = 504, ///< Command not implemented for that parameter + NotLoggedIn = 530, ///< Not logged in + NeedAccountToStore = 532, ///< Need account for storing files + FileUnavailable = 550, ///< Requested action not taken, file unavailable + PageTypeUnknown = 551, ///< Requested action aborted, page type unknown + NotEnoughMemory = 552, ///< Requested file action aborted, exceeded storage allocation + FilenameNotAllowed = 553, ///< Requested action not taken, file name not allowed + + // 10xx: SFML custom codes + InvalidResponse = 1000, ///< Response is not a valid FTP one + ConnectionFailed = 1001, ///< Connection with server failed + ConnectionClosed = 1002, ///< Connection with server closed + InvalidFile = 1003 ///< Invalid file to upload / download + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor is used by the FTP client to build + /// the response. + /// + /// \param code Response status code + /// \param message Response message + /// + //////////////////////////////////////////////////////////// + explicit Response(Status code = InvalidResponse, const std::string& message = ""); + + //////////////////////////////////////////////////////////// + /// \brief Check if the status code means a success + /// + /// This function is defined for convenience, it is + /// equivalent to testing if the status code is < 400. + /// + /// \return True if the status is a success, false if it is a failure + /// + //////////////////////////////////////////////////////////// + bool isOk() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the status code of the response + /// + /// \return Status code + /// + //////////////////////////////////////////////////////////// + Status getStatus() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the full message contained in the response + /// + /// \return The response message + /// + //////////////////////////////////////////////////////////// + const std::string& getMessage() const; + + private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Status m_status; ///< Status code returned from the server + std::string m_message; ///< Last message received from the server + }; + + //////////////////////////////////////////////////////////// + /// \brief Specialization of FTP response returning a directory + /// + //////////////////////////////////////////////////////////// + class SFML_NETWORK_API DirectoryResponse : public Response + { + public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param response Source response + /// + //////////////////////////////////////////////////////////// + DirectoryResponse(const Response& response); + + //////////////////////////////////////////////////////////// + /// \brief Get the directory returned in the response + /// + /// \return Directory name + /// + //////////////////////////////////////////////////////////// + const std::string& getDirectory() const; + + private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::string m_directory; ///< Directory extracted from the response message + }; + + + //////////////////////////////////////////////////////////// + /// \brief Specialization of FTP response returning a + /// filename lisiting + //////////////////////////////////////////////////////////// + class SFML_NETWORK_API ListingResponse : public Response + { + public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param response Source response + /// \param data Data containing the raw listing + /// + //////////////////////////////////////////////////////////// + ListingResponse(const Response& response, const std::string& data); + + //////////////////////////////////////////////////////////// + /// \brief Return the array of directory/file names + /// + /// \return Array containing the requested listing + /// + //////////////////////////////////////////////////////////// + const std::vector& getListing() const; + + private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector m_listing; ///< Directory/file names extracted from the data + }; + + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// Automatically closes the connection with the server if + /// it is still opened. + /// + //////////////////////////////////////////////////////////// + ~Ftp(); + + //////////////////////////////////////////////////////////// + /// \brief Connect to the specified FTP server + /// + /// The port has a default value of 21, which is the standard + /// port used by the FTP protocol. You shouldn't use a different + /// value, unless you really know what you do. + /// This function tries to connect to the server so it may take + /// a while to complete, especially if the server is not + /// reachable. To avoid blocking your application for too long, + /// you can use a timeout. The default value, Time::Zero, means that the + /// system timeout will be used (which is usually pretty long). + /// + /// \param server Name or address of the FTP server to connect to + /// \param port Port used for the connection + /// \param timeout Maximum time to wait + /// + /// \return Server response to the request + /// + /// \see disconnect + /// + //////////////////////////////////////////////////////////// + Response connect(const IpAddress& server, unsigned short port = 21, Time timeout = Time::Zero); + + //////////////////////////////////////////////////////////// + /// \brief Close the connection with the server + /// + /// \return Server response to the request + /// + /// \see connect + /// + //////////////////////////////////////////////////////////// + Response disconnect(); + + //////////////////////////////////////////////////////////// + /// \brief Log in using an anonymous account + /// + /// Logging in is mandatory after connecting to the server. + /// Users that are not logged in cannot perform any operation. + /// + /// \return Server response to the request + /// + //////////////////////////////////////////////////////////// + Response login(); + + //////////////////////////////////////////////////////////// + /// \brief Log in using a username and a password + /// + /// Logging in is mandatory after connecting to the server. + /// Users that are not logged in cannot perform any operation. + /// + /// \param name User name + /// \param password Password + /// + /// \return Server response to the request + /// + //////////////////////////////////////////////////////////// + Response login(const std::string& name, const std::string& password); + + //////////////////////////////////////////////////////////// + /// \brief Send a null command to keep the connection alive + /// + /// This command is useful because the server may close the + /// connection automatically if no command is sent. + /// + /// \return Server response to the request + /// + //////////////////////////////////////////////////////////// + Response keepAlive(); + + //////////////////////////////////////////////////////////// + /// \brief Get the current working directory + /// + /// The working directory is the root path for subsequent + /// operations involving directories and/or filenames. + /// + /// \return Server response to the request + /// + /// \see getDirectoryListing, changeDirectory, parentDirectory + /// + //////////////////////////////////////////////////////////// + DirectoryResponse getWorkingDirectory(); + + //////////////////////////////////////////////////////////// + /// \brief Get the contents of the given directory + /// + /// This function retrieves the sub-directories and files + /// contained in the given directory. It is not recursive. + /// The \a directory parameter is relative to the current + /// working directory. + /// + /// \param directory Directory to list + /// + /// \return Server response to the request + /// + /// \see getWorkingDirectory, changeDirectory, parentDirectory + /// + //////////////////////////////////////////////////////////// + ListingResponse getDirectoryListing(const std::string& directory = ""); + + //////////////////////////////////////////////////////////// + /// \brief Change the current working directory + /// + /// The new directory must be relative to the current one. + /// + /// \param directory New working directory + /// + /// \return Server response to the request + /// + /// \see getWorkingDirectory, getDirectoryListing, parentDirectory + /// + //////////////////////////////////////////////////////////// + Response changeDirectory(const std::string& directory); + + //////////////////////////////////////////////////////////// + /// \brief Go to the parent directory of the current one + /// + /// \return Server response to the request + /// + /// \see getWorkingDirectory, getDirectoryListing, changeDirectory + /// + //////////////////////////////////////////////////////////// + Response parentDirectory(); + + //////////////////////////////////////////////////////////// + /// \brief Create a new directory + /// + /// The new directory is created as a child of the current + /// working directory. + /// + /// \param name Name of the directory to create + /// + /// \return Server response to the request + /// + /// \see deleteDirectory + /// + //////////////////////////////////////////////////////////// + Response createDirectory(const std::string& name); + + //////////////////////////////////////////////////////////// + /// \brief Remove an existing directory + /// + /// The directory to remove must be relative to the + /// current working directory. + /// Use this function with caution, the directory will + /// be removed permanently! + /// + /// \param name Name of the directory to remove + /// + /// \return Server response to the request + /// + /// \see createDirectory + /// + //////////////////////////////////////////////////////////// + Response deleteDirectory(const std::string& name); + + //////////////////////////////////////////////////////////// + /// \brief Rename an existing file + /// + /// The filenames must be relative to the current working + /// directory. + /// + /// \param file File to rename + /// \param newName New name of the file + /// + /// \return Server response to the request + /// + /// \see deleteFile + /// + //////////////////////////////////////////////////////////// + Response renameFile(const std::string& file, const std::string& newName); + + //////////////////////////////////////////////////////////// + /// \brief Remove an existing file + /// + /// The file name must be relative to the current working + /// directory. + /// Use this function with caution, the file will be + /// removed permanently! + /// + /// \param name File to remove + /// + /// \return Server response to the request + /// + /// \see renameFile + /// + //////////////////////////////////////////////////////////// + Response deleteFile(const std::string& name); + + //////////////////////////////////////////////////////////// + /// \brief Download a file from the server + /// + /// The filename of the distant file is relative to the + /// current working directory of the server, and the local + /// destination path is relative to the current directory + /// of your application. + /// If a file with the same filename as the distant file + /// already exists in the local destination path, it will + /// be overwritten. + /// + /// \param remoteFile Filename of the distant file to download + /// \param localPath The directory in which to put the file on the local computer + /// \param mode Transfer mode + /// + /// \return Server response to the request + /// + /// \see upload + /// + //////////////////////////////////////////////////////////// + Response download(const std::string& remoteFile, const std::string& localPath, TransferMode mode = Binary); + + //////////////////////////////////////////////////////////// + /// \brief Upload a file to the server + /// + /// The name of the local file is relative to the current + /// working directory of your application, and the + /// remote path is relative to the current directory of the + /// FTP server. + /// + /// \param localFile Path of the local file to upload + /// \param remotePath The directory in which to put the file on the server + /// \param mode Transfer mode + /// + /// \return Server response to the request + /// + /// \see download + /// + //////////////////////////////////////////////////////////// + Response upload(const std::string& localFile, const std::string& remotePath, TransferMode mode = Binary); + + //////////////////////////////////////////////////////////// + /// \brief Send a command to the FTP server + /// + /// While the most often used commands are provided as member + /// functions in the sf::Ftp class, this method can be used + /// to send any FTP command to the server. If the command + /// requires one or more parameters, they can be specified + /// in \a parameter. If the server returns information, you + /// can extract it from the response using Response::getMessage(). + /// + /// \param command Command to send + /// \param parameter Command parameter + /// + /// \return Server response to the request + /// + //////////////////////////////////////////////////////////// + Response sendCommand(const std::string& command, const std::string& parameter = ""); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Receive a response from the server + /// + /// This function must be called after each call to + /// sendCommand that expects a response. + /// + /// \return Server response to the request + /// + //////////////////////////////////////////////////////////// + Response getResponse(); + + //////////////////////////////////////////////////////////// + /// \brief Utility class for exchanging datas with the server + /// on the data channel + /// + //////////////////////////////////////////////////////////// + class DataChannel; + + friend class DataChannel; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + TcpSocket m_commandSocket; ///< Socket holding the control connection with the server +}; + +} // namespace sf + + +#endif // SFML_FTP_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Ftp +/// \ingroup network +/// +/// sf::Ftp is a very simple FTP client that allows you +/// to communicate with a FTP server. The FTP protocol allows +/// you to manipulate a remote file system (list files, +/// upload, download, create, remove, ...). +/// +/// Using the FTP client consists of 4 parts: +/// \li Connecting to the FTP server +/// \li Logging in (either as a registered user or anonymously) +/// \li Sending commands to the server +/// \li Disconnecting (this part can be done implicitly by the destructor) +/// +/// Every command returns a FTP response, which contains the +/// status code as well as a message from the server. Some +/// commands such as getWorkingDirectory() and getDirectoryListing() +/// return additional data, and use a class derived from +/// sf::Ftp::Response to provide this data. The most often used +/// commands are directly provided as member functions, but it is +/// also possible to use specific commands with the sendCommand() method. +/// +/// All commands, especially upload and download, may take some +/// time to complete. This is important to know if you don't want +/// to block your application while the server is completing +/// the task. +/// +/// Usage example: +/// \code +/// // Create a new FTP client +/// sf::Ftp ftp; +/// +/// // Connect to the server +/// sf::Ftp::Response response = ftp.connect("ftp://ftp.myserver.com"); +/// if (response.isOk()) +/// std::cout << "Connected" << std::endl; +/// +/// // Log in +/// response = ftp.login("laurent", "dF6Zm89D"); +/// if (response.isOk()) +/// std::cout << "Logged in" << std::endl; +/// +/// // Print the working directory +/// sf::Ftp::DirectoryResponse directory = ftp.getWorkingDirectory(); +/// if (directory.isOk()) +/// std::cout << "Working directory: " << directory.getDirectory() << std::endl; +/// +/// // Create a new directory +/// response = ftp.createDirectory("files"); +/// if (response.isOk()) +/// std::cout << "Created new directory" << std::endl; +/// +/// // Upload a file to this new directory +/// response = ftp.upload("local-path/file.txt", "files", sf::Ftp::Ascii); +/// if (response.isOk()) +/// std::cout << "File uploaded" << std::endl; +/// +/// // Send specific commands (here: FEAT to list supported FTP features) +/// response = ftp.sendCommand("FEAT"); +/// if (response.isOk()) +/// std::cout << "Feature list:\n" << response.getMessage() << std::endl; +/// +/// // Disconnect from the server (optional) +/// ftp.disconnect(); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Network/Http.hpp b/include/SFML/Network/Http.hpp index 09e577bf..62ec98e3 100644 --- a/include/SFML/Network/Http.hpp +++ b/include/SFML/Network/Http.hpp @@ -1,482 +1,482 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_HTTP_HPP -#define SFML_HTTP_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief A HTTP client -/// -//////////////////////////////////////////////////////////// -class SFML_NETWORK_API Http : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Define a HTTP request - /// - //////////////////////////////////////////////////////////// - class SFML_NETWORK_API Request - { - public : - - //////////////////////////////////////////////////////////// - /// \brief Enumerate the available HTTP methods for a request - /// - //////////////////////////////////////////////////////////// - enum Method - { - Get, ///< Request in get mode, standard method to retrieve a page - Post, ///< Request in post mode, usually to send data to a page - Head, ///< Request a page's header only - Put, ///< Request in put mode, useful for a REST API - Delete ///< Request in delete mode, useful for a REST API - }; - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor creates a GET request, with the root - /// URI ("/") and an empty body. - /// - /// \param uri Target URI - /// \param method Method to use for the request - /// \param body Content of the request's body - /// - //////////////////////////////////////////////////////////// - Request(const std::string& uri = "/", Method method = Get, const std::string& body = ""); - - //////////////////////////////////////////////////////////// - /// \brief Set the value of a field - /// - /// The field is created if it doesn't exist. The name of - /// the field is case insensitive. - /// By default, a request doesn't contain any field (but the - /// mandatory fields are added later by the HTTP client when - /// sending the request). - /// - /// \param field Name of the field to set - /// \param value Value of the field - /// - //////////////////////////////////////////////////////////// - void setField(const std::string& field, const std::string& value); - - //////////////////////////////////////////////////////////// - /// \brief Set the request method - /// - /// See the Method enumeration for a complete list of all - /// the availale methods. - /// The method is Http::Request::Get by default. - /// - /// \param method Method to use for the request - /// - //////////////////////////////////////////////////////////// - void setMethod(Method method); - - //////////////////////////////////////////////////////////// - /// \brief Set the requested URI - /// - /// The URI is the resource (usually a web page or a file) - /// that you want to get or post. - /// The URI is "/" (the root page) by default. - /// - /// \param uri URI to request, relative to the host - /// - //////////////////////////////////////////////////////////// - void setUri(const std::string& uri); - - //////////////////////////////////////////////////////////// - /// \brief Set the HTTP version for the request - /// - /// The HTTP version is 1.0 by default. - /// - /// \param major Major HTTP version number - /// \param minor Minor HTTP version number - /// - //////////////////////////////////////////////////////////// - void setHttpVersion(unsigned int major, unsigned int minor); - - //////////////////////////////////////////////////////////// - /// \brief Set the body of the request - /// - /// The body of a request is optional and only makes sense - /// for POST requests. It is ignored for all other methods. - /// The body is empty by default. - /// - /// \param body Content of the body - /// - //////////////////////////////////////////////////////////// - void setBody(const std::string& body); - - private : - - friend class Http; - - //////////////////////////////////////////////////////////// - /// \brief Prepare the final request to send to the server - /// - /// This is used internally by Http before sending the - /// request to the web server. - /// - /// \return String containing the request, ready to be sent - /// - //////////////////////////////////////////////////////////// - std::string prepare() const; - - //////////////////////////////////////////////////////////// - /// \brief Check if the request defines a field - /// - /// This function uses case-insensitive comparisons. - /// - /// \param field Name of the field to test - /// - /// \return True if the field exists, false otherwise - /// - //////////////////////////////////////////////////////////// - bool hasField(const std::string& field) const; - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef std::map FieldTable; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - FieldTable m_fields; ///< Fields of the header associated to their value - Method m_method; ///< Method to use for the request - std::string m_uri; ///< Target URI of the request - unsigned int m_majorVersion; ///< Major HTTP version - unsigned int m_minorVersion; ///< Minor HTTP version - std::string m_body; ///< Body of the request - }; - - //////////////////////////////////////////////////////////// - /// \brief Define a HTTP response - /// - //////////////////////////////////////////////////////////// - class SFML_NETWORK_API Response - { - public : - - //////////////////////////////////////////////////////////// - /// \brief Enumerate all the valid status codes for a response - /// - //////////////////////////////////////////////////////////// - enum Status - { - // 2xx: success - Ok = 200, ///< Most common code returned when operation was successful - Created = 201, ///< The resource has successfully been created - Accepted = 202, ///< The request has been accepted, but will be processed later by the server - NoContent = 204, ///< The server didn't send any data in return - ResetContent = 205, ///< The server informs the client that it should clear the view (form) that caused the request to be sent - PartialContent = 206, ///< The server has sent a part of the resource, as a response to a partial GET request - - // 3xx: redirection - MultipleChoices = 300, ///< The requested page can be accessed from several locations - MovedPermanently = 301, ///< The requested page has permanently moved to a new location - MovedTemporarily = 302, ///< The requested page has temporarily moved to a new location - NotModified = 304, ///< For conditionnal requests, means the requested page hasn't changed and doesn't need to be refreshed - - // 4xx: client error - BadRequest = 400, ///< The server couldn't understand the request (syntax error) - Unauthorized = 401, ///< The requested page needs an authentification to be accessed - Forbidden = 403, ///< The requested page cannot be accessed at all, even with authentification - NotFound = 404, ///< The requested page doesn't exist - RangeNotSatisfiable = 407, ///< The server can't satisfy the partial GET request (with a "Range" header field) - - // 5xx: server error - InternalServerError = 500, ///< The server encountered an unexpected error - NotImplemented = 501, ///< The server doesn't implement a requested feature - BadGateway = 502, ///< The gateway server has received an error from the source server - ServiceNotAvailable = 503, ///< The server is temporarily unavailable (overloaded, in maintenance, ...) - GatewayTimeout = 504, ///< The gateway server couldn't receive a response from the source server - VersionNotSupported = 505, ///< The server doesn't support the requested HTTP version - - // 10xx: SFML custom codes - InvalidResponse = 1000, ///< Response is not a valid HTTP one - ConnectionFailed = 1001 ///< Connection with server failed - }; - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Constructs an empty response. - /// - //////////////////////////////////////////////////////////// - Response(); - - //////////////////////////////////////////////////////////// - /// \brief Get the value of a field - /// - /// If the field \a field is not found in the response header, - /// the empty string is returned. This function uses - /// case-insensitive comparisons. - /// - /// \param field Name of the field to get - /// - /// \return Value of the field, or empty string if not found - /// - //////////////////////////////////////////////////////////// - const std::string& getField(const std::string& field) const; - - //////////////////////////////////////////////////////////// - /// \brief Get the response status code - /// - /// The status code should be the first thing to be checked - /// after receiving a response, it defines whether it is a - /// success, a failure or anything else (see the Status - /// enumeration). - /// - /// \return Status code of the response - /// - //////////////////////////////////////////////////////////// - Status getStatus() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the major HTTP version number of the response - /// - /// \return Major HTTP version number - /// - /// \see getMinorHttpVersion - /// - //////////////////////////////////////////////////////////// - unsigned int getMajorHttpVersion() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the minor HTTP version number of the response - /// - /// \return Minor HTTP version number - /// - /// \see getMajorHttpVersion - /// - //////////////////////////////////////////////////////////// - unsigned int getMinorHttpVersion() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the body of the response - /// - /// The body of a response may contain: - /// \li the requested page (for GET requests) - /// \li a response from the server (for POST requests) - /// \li nothing (for HEAD requests) - /// \li an error message (in case of an error) - /// - /// \return The response body - /// - //////////////////////////////////////////////////////////// - const std::string& getBody() const; - - private : - - friend class Http; - - //////////////////////////////////////////////////////////// - /// \brief Construct the header from a response string - /// - /// This function is used by Http to build the response - /// of a request. - /// - /// \param data Content of the response to parse - /// - //////////////////////////////////////////////////////////// - void parse(const std::string& data); - - - //////////////////////////////////////////////////////////// - /// \brief Read values passed in the answer header - /// - /// This function is used by Http to extract values passed - /// in the response. - /// - /// \param in String stream containing the header values - /// - //////////////////////////////////////////////////////////// - void parseFields(std::istream &in); - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef std::map FieldTable; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - FieldTable m_fields; ///< Fields of the header - Status m_status; ///< Status code - unsigned int m_majorVersion; ///< Major HTTP version - unsigned int m_minorVersion; ///< Minor HTTP version - std::string m_body; ///< Body of the response - }; - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - Http(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the HTTP client with the target host - /// - /// This is equivalent to calling setHost(host, port). - /// The port has a default value of 0, which means that the - /// HTTP client will use the right port according to the - /// protocol used (80 for HTTP). You should leave it like - /// this unless you really need a port other than the - /// standard one, or use an unknown protocol. - /// - /// \param host Web server to connect to - /// \param port Port to use for connection - /// - //////////////////////////////////////////////////////////// - Http(const std::string& host, unsigned short port = 0); - - //////////////////////////////////////////////////////////// - /// \brief Set the target host - /// - /// This function just stores the host address and port, it - /// doesn't actually connect to it until you send a request. - /// The port has a default value of 0, which means that the - /// HTTP client will use the right port according to the - /// protocol used (80 for HTTP). You should leave it like - /// this unless you really need a port other than the - /// standard one, or use an unknown protocol. - /// - /// \param host Web server to connect to - /// \param port Port to use for connection - /// - //////////////////////////////////////////////////////////// - void setHost(const std::string& host, unsigned short port = 0); - - //////////////////////////////////////////////////////////// - /// \brief Send a HTTP request and return the server's response. - /// - /// You must have a valid host before sending a request (see setHost). - /// Any missing mandatory header field in the request will be added - /// with an appropriate value. - /// Warning: this function waits for the server's response and may - /// not return instantly; use a thread if you don't want to block your - /// application, or use a timeout to limit the time to wait. A value - /// of Time::Zero means that the client will use the system defaut timeout - /// (which is usually pretty long). - /// - /// \param request Request to send - /// \param timeout Maximum time to wait - /// - /// \return Server's response - /// - //////////////////////////////////////////////////////////// - Response sendRequest(const Request& request, Time timeout = Time::Zero); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - TcpSocket m_connection; ///< Connection to the host - IpAddress m_host; ///< Web host address - std::string m_hostName; ///< Web host name - unsigned short m_port; ///< Port used for connection with host -}; - -} // namespace sf - - -#endif // SFML_HTTP_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Http -/// \ingroup network -/// -/// sf::Http is a very simple HTTP client that allows you -/// to communicate with a web server. You can retrieve -/// web pages, send data to an interactive resource, -/// download a remote file, etc. The HTTPS protocol is -/// not supported. -/// -/// The HTTP client is split into 3 classes: -/// \li sf::Http::Request -/// \li sf::Http::Response -/// \li sf::Http -/// -/// sf::Http::Request builds the request that will be -/// sent to the server. A request is made of: -/// \li a method (what you want to do) -/// \li a target URI (usually the name of the web page or file) -/// \li one or more header fields (options that you can pass to the server) -/// \li an optional body (for POST requests) -/// -/// sf::Http::Response parse the response from the web server -/// and provides getters to read them. The response contains: -/// \li a status code -/// \li header fields (that may be answers to the ones that you requested) -/// \li a body, which contains the contents of the requested resource -/// -/// sf::Http provides a simple function, SendRequest, to send a -/// sf::Http::Request and return the corresponding sf::Http::Response -/// from the server. -/// -/// Usage example: -/// \code -/// // Create a new HTTP client -/// sf::Http http; -/// -/// // We'll work on http://www.sfml-dev.org -/// http.setHost("http://www.sfml-dev.org"); -/// -/// // Prepare a request to get the 'features.php' page -/// sf::Http::Request request("features.php"); -/// -/// // Send the request -/// sf::Http::Response response = http.sendRequest(request); -/// -/// // Check the status code and display the result -/// sf::Http::Response::Status status = response.getStatus(); -/// if (status == sf::Http::Response::Ok) -/// { -/// std::cout << response.getBody() << std::endl; -/// } -/// else -/// { -/// std::cout << "Error " << status << std::endl; -/// } -/// \endcode -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_HTTP_HPP +#define SFML_HTTP_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief A HTTP client +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API Http : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Define a HTTP request + /// + //////////////////////////////////////////////////////////// + class SFML_NETWORK_API Request + { + public: + + //////////////////////////////////////////////////////////// + /// \brief Enumerate the available HTTP methods for a request + /// + //////////////////////////////////////////////////////////// + enum Method + { + Get, ///< Request in get mode, standard method to retrieve a page + Post, ///< Request in post mode, usually to send data to a page + Head, ///< Request a page's header only + Put, ///< Request in put mode, useful for a REST API + Delete ///< Request in delete mode, useful for a REST API + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor creates a GET request, with the root + /// URI ("/") and an empty body. + /// + /// \param uri Target URI + /// \param method Method to use for the request + /// \param body Content of the request's body + /// + //////////////////////////////////////////////////////////// + Request(const std::string& uri = "/", Method method = Get, const std::string& body = ""); + + //////////////////////////////////////////////////////////// + /// \brief Set the value of a field + /// + /// The field is created if it doesn't exist. The name of + /// the field is case insensitive. + /// By default, a request doesn't contain any field (but the + /// mandatory fields are added later by the HTTP client when + /// sending the request). + /// + /// \param field Name of the field to set + /// \param value Value of the field + /// + //////////////////////////////////////////////////////////// + void setField(const std::string& field, const std::string& value); + + //////////////////////////////////////////////////////////// + /// \brief Set the request method + /// + /// See the Method enumeration for a complete list of all + /// the availale methods. + /// The method is Http::Request::Get by default. + /// + /// \param method Method to use for the request + /// + //////////////////////////////////////////////////////////// + void setMethod(Method method); + + //////////////////////////////////////////////////////////// + /// \brief Set the requested URI + /// + /// The URI is the resource (usually a web page or a file) + /// that you want to get or post. + /// The URI is "/" (the root page) by default. + /// + /// \param uri URI to request, relative to the host + /// + //////////////////////////////////////////////////////////// + void setUri(const std::string& uri); + + //////////////////////////////////////////////////////////// + /// \brief Set the HTTP version for the request + /// + /// The HTTP version is 1.0 by default. + /// + /// \param major Major HTTP version number + /// \param minor Minor HTTP version number + /// + //////////////////////////////////////////////////////////// + void setHttpVersion(unsigned int major, unsigned int minor); + + //////////////////////////////////////////////////////////// + /// \brief Set the body of the request + /// + /// The body of a request is optional and only makes sense + /// for POST requests. It is ignored for all other methods. + /// The body is empty by default. + /// + /// \param body Content of the body + /// + //////////////////////////////////////////////////////////// + void setBody(const std::string& body); + + private: + + friend class Http; + + //////////////////////////////////////////////////////////// + /// \brief Prepare the final request to send to the server + /// + /// This is used internally by Http before sending the + /// request to the web server. + /// + /// \return String containing the request, ready to be sent + /// + //////////////////////////////////////////////////////////// + std::string prepare() const; + + //////////////////////////////////////////////////////////// + /// \brief Check if the request defines a field + /// + /// This function uses case-insensitive comparisons. + /// + /// \param field Name of the field to test + /// + /// \return True if the field exists, false otherwise + /// + //////////////////////////////////////////////////////////// + bool hasField(const std::string& field) const; + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::map FieldTable; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + FieldTable m_fields; ///< Fields of the header associated to their value + Method m_method; ///< Method to use for the request + std::string m_uri; ///< Target URI of the request + unsigned int m_majorVersion; ///< Major HTTP version + unsigned int m_minorVersion; ///< Minor HTTP version + std::string m_body; ///< Body of the request + }; + + //////////////////////////////////////////////////////////// + /// \brief Define a HTTP response + /// + //////////////////////////////////////////////////////////// + class SFML_NETWORK_API Response + { + public: + + //////////////////////////////////////////////////////////// + /// \brief Enumerate all the valid status codes for a response + /// + //////////////////////////////////////////////////////////// + enum Status + { + // 2xx: success + Ok = 200, ///< Most common code returned when operation was successful + Created = 201, ///< The resource has successfully been created + Accepted = 202, ///< The request has been accepted, but will be processed later by the server + NoContent = 204, ///< The server didn't send any data in return + ResetContent = 205, ///< The server informs the client that it should clear the view (form) that caused the request to be sent + PartialContent = 206, ///< The server has sent a part of the resource, as a response to a partial GET request + + // 3xx: redirection + MultipleChoices = 300, ///< The requested page can be accessed from several locations + MovedPermanently = 301, ///< The requested page has permanently moved to a new location + MovedTemporarily = 302, ///< The requested page has temporarily moved to a new location + NotModified = 304, ///< For conditionnal requests, means the requested page hasn't changed and doesn't need to be refreshed + + // 4xx: client error + BadRequest = 400, ///< The server couldn't understand the request (syntax error) + Unauthorized = 401, ///< The requested page needs an authentification to be accessed + Forbidden = 403, ///< The requested page cannot be accessed at all, even with authentification + NotFound = 404, ///< The requested page doesn't exist + RangeNotSatisfiable = 407, ///< The server can't satisfy the partial GET request (with a "Range" header field) + + // 5xx: server error + InternalServerError = 500, ///< The server encountered an unexpected error + NotImplemented = 501, ///< The server doesn't implement a requested feature + BadGateway = 502, ///< The gateway server has received an error from the source server + ServiceNotAvailable = 503, ///< The server is temporarily unavailable (overloaded, in maintenance, ...) + GatewayTimeout = 504, ///< The gateway server couldn't receive a response from the source server + VersionNotSupported = 505, ///< The server doesn't support the requested HTTP version + + // 10xx: SFML custom codes + InvalidResponse = 1000, ///< Response is not a valid HTTP one + ConnectionFailed = 1001 ///< Connection with server failed + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Constructs an empty response. + /// + //////////////////////////////////////////////////////////// + Response(); + + //////////////////////////////////////////////////////////// + /// \brief Get the value of a field + /// + /// If the field \a field is not found in the response header, + /// the empty string is returned. This function uses + /// case-insensitive comparisons. + /// + /// \param field Name of the field to get + /// + /// \return Value of the field, or empty string if not found + /// + //////////////////////////////////////////////////////////// + const std::string& getField(const std::string& field) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the response status code + /// + /// The status code should be the first thing to be checked + /// after receiving a response, it defines whether it is a + /// success, a failure or anything else (see the Status + /// enumeration). + /// + /// \return Status code of the response + /// + //////////////////////////////////////////////////////////// + Status getStatus() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the major HTTP version number of the response + /// + /// \return Major HTTP version number + /// + /// \see getMinorHttpVersion + /// + //////////////////////////////////////////////////////////// + unsigned int getMajorHttpVersion() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the minor HTTP version number of the response + /// + /// \return Minor HTTP version number + /// + /// \see getMajorHttpVersion + /// + //////////////////////////////////////////////////////////// + unsigned int getMinorHttpVersion() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the body of the response + /// + /// The body of a response may contain: + /// \li the requested page (for GET requests) + /// \li a response from the server (for POST requests) + /// \li nothing (for HEAD requests) + /// \li an error message (in case of an error) + /// + /// \return The response body + /// + //////////////////////////////////////////////////////////// + const std::string& getBody() const; + + private: + + friend class Http; + + //////////////////////////////////////////////////////////// + /// \brief Construct the header from a response string + /// + /// This function is used by Http to build the response + /// of a request. + /// + /// \param data Content of the response to parse + /// + //////////////////////////////////////////////////////////// + void parse(const std::string& data); + + + //////////////////////////////////////////////////////////// + /// \brief Read values passed in the answer header + /// + /// This function is used by Http to extract values passed + /// in the response. + /// + /// \param in String stream containing the header values + /// + //////////////////////////////////////////////////////////// + void parseFields(std::istream &in); + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::map FieldTable; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + FieldTable m_fields; ///< Fields of the header + Status m_status; ///< Status code + unsigned int m_majorVersion; ///< Major HTTP version + unsigned int m_minorVersion; ///< Minor HTTP version + std::string m_body; ///< Body of the response + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Http(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the HTTP client with the target host + /// + /// This is equivalent to calling setHost(host, port). + /// The port has a default value of 0, which means that the + /// HTTP client will use the right port according to the + /// protocol used (80 for HTTP). You should leave it like + /// this unless you really need a port other than the + /// standard one, or use an unknown protocol. + /// + /// \param host Web server to connect to + /// \param port Port to use for connection + /// + //////////////////////////////////////////////////////////// + Http(const std::string& host, unsigned short port = 0); + + //////////////////////////////////////////////////////////// + /// \brief Set the target host + /// + /// This function just stores the host address and port, it + /// doesn't actually connect to it until you send a request. + /// The port has a default value of 0, which means that the + /// HTTP client will use the right port according to the + /// protocol used (80 for HTTP). You should leave it like + /// this unless you really need a port other than the + /// standard one, or use an unknown protocol. + /// + /// \param host Web server to connect to + /// \param port Port to use for connection + /// + //////////////////////////////////////////////////////////// + void setHost(const std::string& host, unsigned short port = 0); + + //////////////////////////////////////////////////////////// + /// \brief Send a HTTP request and return the server's response. + /// + /// You must have a valid host before sending a request (see setHost). + /// Any missing mandatory header field in the request will be added + /// with an appropriate value. + /// Warning: this function waits for the server's response and may + /// not return instantly; use a thread if you don't want to block your + /// application, or use a timeout to limit the time to wait. A value + /// of Time::Zero means that the client will use the system defaut timeout + /// (which is usually pretty long). + /// + /// \param request Request to send + /// \param timeout Maximum time to wait + /// + /// \return Server's response + /// + //////////////////////////////////////////////////////////// + Response sendRequest(const Request& request, Time timeout = Time::Zero); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + TcpSocket m_connection; ///< Connection to the host + IpAddress m_host; ///< Web host address + std::string m_hostName; ///< Web host name + unsigned short m_port; ///< Port used for connection with host +}; + +} // namespace sf + + +#endif // SFML_HTTP_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Http +/// \ingroup network +/// +/// sf::Http is a very simple HTTP client that allows you +/// to communicate with a web server. You can retrieve +/// web pages, send data to an interactive resource, +/// download a remote file, etc. The HTTPS protocol is +/// not supported. +/// +/// The HTTP client is split into 3 classes: +/// \li sf::Http::Request +/// \li sf::Http::Response +/// \li sf::Http +/// +/// sf::Http::Request builds the request that will be +/// sent to the server. A request is made of: +/// \li a method (what you want to do) +/// \li a target URI (usually the name of the web page or file) +/// \li one or more header fields (options that you can pass to the server) +/// \li an optional body (for POST requests) +/// +/// sf::Http::Response parse the response from the web server +/// and provides getters to read them. The response contains: +/// \li a status code +/// \li header fields (that may be answers to the ones that you requested) +/// \li a body, which contains the contents of the requested resource +/// +/// sf::Http provides a simple function, SendRequest, to send a +/// sf::Http::Request and return the corresponding sf::Http::Response +/// from the server. +/// +/// Usage example: +/// \code +/// // Create a new HTTP client +/// sf::Http http; +/// +/// // We'll work on http://www.sfml-dev.org +/// http.setHost("http://www.sfml-dev.org"); +/// +/// // Prepare a request to get the 'features.php' page +/// sf::Http::Request request("features.php"); +/// +/// // Send the request +/// sf::Http::Response response = http.sendRequest(request); +/// +/// // Check the status code and display the result +/// sf::Http::Response::Status status = response.getStatus(); +/// if (status == sf::Http::Response::Ok) +/// { +/// std::cout << response.getBody() << std::endl; +/// } +/// else +/// { +/// std::cout << "Error " << status << std::endl; +/// } +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Network/IpAddress.hpp b/include/SFML/Network/IpAddress.hpp index 39b8ad66..77b0cf51 100644 --- a/include/SFML/Network/IpAddress.hpp +++ b/include/SFML/Network/IpAddress.hpp @@ -1,316 +1,316 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_IPADDRESS_HPP -#define SFML_IPADDRESS_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Encapsulate an IPv4 network address -/// -//////////////////////////////////////////////////////////// -class SFML_NETWORK_API IpAddress -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor creates an empty (invalid) address - /// - //////////////////////////////////////////////////////////// - IpAddress(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the address from a string - /// - /// Here \a address can be either a decimal address - /// (ex: "192.168.1.56") or a network name (ex: "localhost"). - /// - /// \param address IP address or network name - /// - //////////////////////////////////////////////////////////// - IpAddress(const std::string& address); - - //////////////////////////////////////////////////////////// - /// \brief Construct the address from a string - /// - /// Here \a address can be either a decimal address - /// (ex: "192.168.1.56") or a network name (ex: "localhost"). - /// This is equivalent to the constructor taking a std::string - /// parameter, it is defined for convenience so that the - /// implicit conversions from literal strings to IpAddress work. - /// - /// \param address IP address or network name - /// - //////////////////////////////////////////////////////////// - IpAddress(const char* address); - - //////////////////////////////////////////////////////////// - /// \brief Construct the address from 4 bytes - /// - /// Calling IpAddress(a, b, c, d) is equivalent to calling - /// IpAddress("a.b.c.d"), but safer as it doesn't have to - /// parse a string to get the address components. - /// - /// \param byte0 First byte of the address - /// \param byte1 Second byte of the address - /// \param byte2 Third byte of the address - /// \param byte3 Fourth byte of the address - /// - //////////////////////////////////////////////////////////// - IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3); - - //////////////////////////////////////////////////////////// - /// \brief Construct the address from a 32-bits integer - /// - /// This constructor uses the internal representation of - /// the address directly. It should be used for optimization - /// purposes, and only if you got that representation from - /// IpAddress::ToInteger(). - /// - /// \param address 4 bytes of the address packed into a 32-bits integer - /// - /// \see toInteger - /// - //////////////////////////////////////////////////////////// - explicit IpAddress(Uint32 address); - - //////////////////////////////////////////////////////////// - /// \brief Get a string representation of the address - /// - /// The returned string is the decimal representation of the - /// IP address (like "192.168.1.56"), even if it was constructed - /// from a host name. - /// - /// \return String representation of the address - /// - /// \see toInteger - /// - //////////////////////////////////////////////////////////// - std::string toString() const; - - //////////////////////////////////////////////////////////// - /// \brief Get an integer representation of the address - /// - /// The returned number is the internal representation of the - /// address, and should be used for optimization purposes only - /// (like sending the address through a socket). - /// The integer produced by this function can then be converted - /// back to a sf::IpAddress with the proper constructor. - /// - /// \return 32-bits unsigned integer representation of the address - /// - /// \see toString - /// - //////////////////////////////////////////////////////////// - Uint32 toInteger() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the computer's local address - /// - /// The local address is the address of the computer from the - /// LAN point of view, i.e. something like 192.168.1.56. It is - /// meaningful only for communications over the local network. - /// Unlike getPublicAddress, this function is fast and may be - /// used safely anywhere. - /// - /// \return Local IP address of the computer - /// - /// \see getPublicAddress - /// - //////////////////////////////////////////////////////////// - static IpAddress getLocalAddress(); - - //////////////////////////////////////////////////////////// - /// \brief Get the computer's public address - /// - /// The public address is the address of the computer from the - /// internet point of view, i.e. something like 89.54.1.169. - /// It is necessary for communications over the world wide web. - /// The only way to get a public address is to ask it to a - /// distant website; as a consequence, this function depends on - /// both your network connection and the server, and may be - /// very slow. You should use it as few as possible. Because - /// this function depends on the network connection and on a distant - /// server, you may use a time limit if you don't want your program - /// to be possibly stuck waiting in case there is a problem; this - /// limit is deactivated by default. - /// - /// \param timeout Maximum time to wait - /// - /// \return Public IP address of the computer - /// - /// \see getLocalAddress - /// - //////////////////////////////////////////////////////////// - static IpAddress getPublicAddress(Time timeout = Time::Zero); - - //////////////////////////////////////////////////////////// - // Static member data - //////////////////////////////////////////////////////////// - static const IpAddress None; ///< Value representing an empty/invalid address - static const IpAddress LocalHost; ///< The "localhost" address (for connecting a computer to itself locally) - static const IpAddress Broadcast; ///< The "broadcast" address (for sending UDP messages to everyone on a local network) - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Uint32 m_address; ///< Address stored as an unsigned 32 bits integer -}; - -//////////////////////////////////////////////////////////// -/// \brief Overload of == operator to compare two IP addresses -/// -/// \param left Left operand (a IP address) -/// \param right Right operand (a IP address) -/// -/// \return True if both addresses are equal -/// -//////////////////////////////////////////////////////////// -SFML_NETWORK_API bool operator ==(const IpAddress& left, const IpAddress& right); - -//////////////////////////////////////////////////////////// -/// \brief Overload of != operator to compare two IP addresses -/// -/// \param left Left operand (a IP address) -/// \param right Right operand (a IP address) -/// -/// \return True if both addresses are different -/// -//////////////////////////////////////////////////////////// -SFML_NETWORK_API bool operator !=(const IpAddress& left, const IpAddress& right); - -//////////////////////////////////////////////////////////// -/// \brief Overload of < operator to compare two IP addresses -/// -/// \param left Left operand (a IP address) -/// \param right Right operand (a IP address) -/// -/// \return True if \a left is lesser than \a right -/// -//////////////////////////////////////////////////////////// -SFML_NETWORK_API bool operator <(const IpAddress& left, const IpAddress& right); - -//////////////////////////////////////////////////////////// -/// \brief Overload of > operator to compare two IP addresses -/// -/// \param left Left operand (a IP address) -/// \param right Right operand (a IP address) -/// -/// \return True if \a left is greater than \a right -/// -//////////////////////////////////////////////////////////// -SFML_NETWORK_API bool operator >(const IpAddress& left, const IpAddress& right); - -//////////////////////////////////////////////////////////// -/// \brief Overload of <= operator to compare two IP addresses -/// -/// \param left Left operand (a IP address) -/// \param right Right operand (a IP address) -/// -/// \return True if \a left is lesser or equal than \a right -/// -//////////////////////////////////////////////////////////// -SFML_NETWORK_API bool operator <=(const IpAddress& left, const IpAddress& right); - -//////////////////////////////////////////////////////////// -/// \brief Overload of >= operator to compare two IP addresses -/// -/// \param left Left operand (a IP address) -/// \param right Right operand (a IP address) -/// -/// \return True if \a left is greater or equal than \a right -/// -//////////////////////////////////////////////////////////// -SFML_NETWORK_API bool operator >=(const IpAddress& left, const IpAddress& right); - -//////////////////////////////////////////////////////////// -/// \brief Overload of >> operator to extract an IP address from an input stream -/// -/// \param stream Input stream -/// \param address IP address to extract -/// -/// \return Reference to the input stream -/// -//////////////////////////////////////////////////////////// -SFML_NETWORK_API std::istream& operator >>(std::istream& stream, IpAddress& address); - -//////////////////////////////////////////////////////////// -/// \brief Overload of << operator to print an IP address to an output stream -/// -/// \param stream Output stream -/// \param address IP address to print -/// -/// \return Reference to the output stream -/// -//////////////////////////////////////////////////////////// -SFML_NETWORK_API std::ostream& operator <<(std::ostream& stream, const IpAddress& address); - -} // namespace sf - - -#endif // SFML_IPADDRESS_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::IpAddress -/// \ingroup network -/// -/// sf::IpAddress is a utility class for manipulating network -/// addresses. It provides a set a implicit constructors and -/// conversion functions to easily build or transform an IP -/// address from/to various representations. -/// -/// Usage example: -/// \code -/// sf::IpAddress a0; // an invalid address -/// sf::IpAddress a1 = sf::IpAddress::None; // an invalid address (same as a0) -/// sf::IpAddress a2("127.0.0.1"); // the local host address -/// sf::IpAddress a3 = sf::IpAddress::Broadcast; // the broadcast address -/// sf::IpAddress a4(192, 168, 1, 56); // a local address -/// sf::IpAddress a5("my_computer"); // a local address created from a network name -/// sf::IpAddress a6("89.54.1.169"); // a distant address -/// sf::IpAddress a7("www.google.com"); // a distant address created from a network name -/// sf::IpAddress a8 = sf::IpAddress::getLocalAddress(); // my address on the local network -/// sf::IpAddress a9 = sf::IpAddress::getPublicAddress(); // my address on the internet -/// \endcode -/// -/// Note that sf::IpAddress currently doesn't support IPv6 -/// nor other types of network addresses. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_IPADDRESS_HPP +#define SFML_IPADDRESS_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Encapsulate an IPv4 network address +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API IpAddress +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor creates an empty (invalid) address + /// + //////////////////////////////////////////////////////////// + IpAddress(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the address from a string + /// + /// Here \a address can be either a decimal address + /// (ex: "192.168.1.56") or a network name (ex: "localhost"). + /// + /// \param address IP address or network name + /// + //////////////////////////////////////////////////////////// + IpAddress(const std::string& address); + + //////////////////////////////////////////////////////////// + /// \brief Construct the address from a string + /// + /// Here \a address can be either a decimal address + /// (ex: "192.168.1.56") or a network name (ex: "localhost"). + /// This is equivalent to the constructor taking a std::string + /// parameter, it is defined for convenience so that the + /// implicit conversions from literal strings to IpAddress work. + /// + /// \param address IP address or network name + /// + //////////////////////////////////////////////////////////// + IpAddress(const char* address); + + //////////////////////////////////////////////////////////// + /// \brief Construct the address from 4 bytes + /// + /// Calling IpAddress(a, b, c, d) is equivalent to calling + /// IpAddress("a.b.c.d"), but safer as it doesn't have to + /// parse a string to get the address components. + /// + /// \param byte0 First byte of the address + /// \param byte1 Second byte of the address + /// \param byte2 Third byte of the address + /// \param byte3 Fourth byte of the address + /// + //////////////////////////////////////////////////////////// + IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3); + + //////////////////////////////////////////////////////////// + /// \brief Construct the address from a 32-bits integer + /// + /// This constructor uses the internal representation of + /// the address directly. It should be used for optimization + /// purposes, and only if you got that representation from + /// IpAddress::ToInteger(). + /// + /// \param address 4 bytes of the address packed into a 32-bits integer + /// + /// \see toInteger + /// + //////////////////////////////////////////////////////////// + explicit IpAddress(Uint32 address); + + //////////////////////////////////////////////////////////// + /// \brief Get a string representation of the address + /// + /// The returned string is the decimal representation of the + /// IP address (like "192.168.1.56"), even if it was constructed + /// from a host name. + /// + /// \return String representation of the address + /// + /// \see toInteger + /// + //////////////////////////////////////////////////////////// + std::string toString() const; + + //////////////////////////////////////////////////////////// + /// \brief Get an integer representation of the address + /// + /// The returned number is the internal representation of the + /// address, and should be used for optimization purposes only + /// (like sending the address through a socket). + /// The integer produced by this function can then be converted + /// back to a sf::IpAddress with the proper constructor. + /// + /// \return 32-bits unsigned integer representation of the address + /// + /// \see toString + /// + //////////////////////////////////////////////////////////// + Uint32 toInteger() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the computer's local address + /// + /// The local address is the address of the computer from the + /// LAN point of view, i.e. something like 192.168.1.56. It is + /// meaningful only for communications over the local network. + /// Unlike getPublicAddress, this function is fast and may be + /// used safely anywhere. + /// + /// \return Local IP address of the computer + /// + /// \see getPublicAddress + /// + //////////////////////////////////////////////////////////// + static IpAddress getLocalAddress(); + + //////////////////////////////////////////////////////////// + /// \brief Get the computer's public address + /// + /// The public address is the address of the computer from the + /// internet point of view, i.e. something like 89.54.1.169. + /// It is necessary for communications over the world wide web. + /// The only way to get a public address is to ask it to a + /// distant website; as a consequence, this function depends on + /// both your network connection and the server, and may be + /// very slow. You should use it as few as possible. Because + /// this function depends on the network connection and on a distant + /// server, you may use a time limit if you don't want your program + /// to be possibly stuck waiting in case there is a problem; this + /// limit is deactivated by default. + /// + /// \param timeout Maximum time to wait + /// + /// \return Public IP address of the computer + /// + /// \see getLocalAddress + /// + //////////////////////////////////////////////////////////// + static IpAddress getPublicAddress(Time timeout = Time::Zero); + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const IpAddress None; ///< Value representing an empty/invalid address + static const IpAddress LocalHost; ///< The "localhost" address (for connecting a computer to itself locally) + static const IpAddress Broadcast; ///< The "broadcast" address (for sending UDP messages to everyone on a local network) + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Uint32 m_address; ///< Address stored as an unsigned 32 bits integer +}; + +//////////////////////////////////////////////////////////// +/// \brief Overload of == operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if both addresses are equal +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator ==(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of != operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if both addresses are different +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator !=(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of < operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if \a left is lesser than \a right +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator <(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of > operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if \a left is greater than \a right +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator >(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of <= operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if \a left is lesser or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator <=(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of >= operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if \a left is greater or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator >=(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of >> operator to extract an IP address from an input stream +/// +/// \param stream Input stream +/// \param address IP address to extract +/// +/// \return Reference to the input stream +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API std::istream& operator >>(std::istream& stream, IpAddress& address); + +//////////////////////////////////////////////////////////// +/// \brief Overload of << operator to print an IP address to an output stream +/// +/// \param stream Output stream +/// \param address IP address to print +/// +/// \return Reference to the output stream +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API std::ostream& operator <<(std::ostream& stream, const IpAddress& address); + +} // namespace sf + + +#endif // SFML_IPADDRESS_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::IpAddress +/// \ingroup network +/// +/// sf::IpAddress is a utility class for manipulating network +/// addresses. It provides a set a implicit constructors and +/// conversion functions to easily build or transform an IP +/// address from/to various representations. +/// +/// Usage example: +/// \code +/// sf::IpAddress a0; // an invalid address +/// sf::IpAddress a1 = sf::IpAddress::None; // an invalid address (same as a0) +/// sf::IpAddress a2("127.0.0.1"); // the local host address +/// sf::IpAddress a3 = sf::IpAddress::Broadcast; // the broadcast address +/// sf::IpAddress a4(192, 168, 1, 56); // a local address +/// sf::IpAddress a5("my_computer"); // a local address created from a network name +/// sf::IpAddress a6("89.54.1.169"); // a distant address +/// sf::IpAddress a7("www.google.com"); // a distant address created from a network name +/// sf::IpAddress a8 = sf::IpAddress::getLocalAddress(); // my address on the local network +/// sf::IpAddress a9 = sf::IpAddress::getPublicAddress(); // my address on the internet +/// \endcode +/// +/// Note that sf::IpAddress currently doesn't support IPv6 +/// nor other types of network addresses. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Network/Packet.hpp b/include/SFML/Network/Packet.hpp index 81a9c72c..eacae8a1 100644 --- a/include/SFML/Network/Packet.hpp +++ b/include/SFML/Network/Packet.hpp @@ -1,407 +1,407 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_PACKET_HPP -#define SFML_PACKET_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -class String; -class TcpSocket; -class UdpSocket; - -//////////////////////////////////////////////////////////// -/// \brief Utility class to build blocks of data to transfer -/// over the network -/// -//////////////////////////////////////////////////////////// -class SFML_NETWORK_API Packet -{ - // A bool-like type that cannot be converted to integer or pointer types - typedef bool (Packet::*BoolType)(std::size_t); - -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Creates an empty packet. - /// - //////////////////////////////////////////////////////////// - Packet(); - - //////////////////////////////////////////////////////////// - /// \brief Virtual destructor - /// - //////////////////////////////////////////////////////////// - virtual ~Packet(); - - //////////////////////////////////////////////////////////// - /// \brief Append data to the end of the packet - /// - /// \param data Pointer to the sequence of bytes to append - /// \param sizeInBytes Number of bytes to append - /// - /// \see clear - /// - //////////////////////////////////////////////////////////// - void append(const void* data, std::size_t sizeInBytes); - - //////////////////////////////////////////////////////////// - /// \brief Clear the packet - /// - /// After calling Clear, the packet is empty. - /// - /// \see append - /// - //////////////////////////////////////////////////////////// - void clear(); - - //////////////////////////////////////////////////////////// - /// \brief Get a pointer to the data contained in the packet - /// - /// Warning: the returned pointer may become invalid after - /// you append data to the packet, therefore it should never - /// be stored. - /// The return pointer is NULL if the packet is empty. - /// - /// \return Pointer to the data - /// - /// \see getDataSize - /// - //////////////////////////////////////////////////////////// - const void* getData() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the size of the data contained in the packet - /// - /// This function returns the number of bytes pointed to by - /// what getData returns. - /// - /// \return Data size, in bytes - /// - /// \see getData - /// - //////////////////////////////////////////////////////////// - std::size_t getDataSize() const; - - //////////////////////////////////////////////////////////// - /// \brief Tell if the reading position has reached the - /// end of the packet - /// - /// This function is useful to know if there is some data - /// left to be read, without actually reading it. - /// - /// \return True if all data was read, false otherwise - /// - /// \see operator bool - /// - //////////////////////////////////////////////////////////// - bool endOfPacket() const; - -public: - - //////////////////////////////////////////////////////////// - /// \brief Test the validity of the packet, for reading - /// - /// This operator allows to test the packet as a boolean - /// variable, to check if a reading operation was successful. - /// - /// A packet will be in an invalid state if it has no more - /// data to read. - /// - /// This behaviour is the same as standard C++ streams. - /// - /// Usage example: - /// \code - /// float x; - /// packet >> x; - /// if (packet) - /// { - /// // ok, x was extracted successfully - /// } - /// - /// // -- or -- - /// - /// float x; - /// if (packet >> x) - /// { - /// // ok, x was extracted successfully - /// } - /// \endcode - /// - /// Don't focus on the return type, it's equivalent to bool but - /// it disallows unwanted implicit conversions to integer or - /// pointer types. - /// - /// \return True if last data extraction from packet was successful - /// - /// \see endOfPacket - /// - //////////////////////////////////////////////////////////// - operator BoolType() const; - - //////////////////////////////////////////////////////////// - /// Overloads of operator >> to read data from the packet - /// - //////////////////////////////////////////////////////////// - Packet& operator >>(bool& data); - Packet& operator >>(Int8& data); - Packet& operator >>(Uint8& data); - Packet& operator >>(Int16& data); - Packet& operator >>(Uint16& data); - Packet& operator >>(Int32& data); - Packet& operator >>(Uint32& data); - Packet& operator >>(float& data); - Packet& operator >>(double& data); - Packet& operator >>(char* data); - Packet& operator >>(std::string& data); - Packet& operator >>(wchar_t* data); - Packet& operator >>(std::wstring& data); - Packet& operator >>(String& data); - - //////////////////////////////////////////////////////////// - /// Overloads of operator << to write data into the packet - /// - //////////////////////////////////////////////////////////// - Packet& operator <<(bool data); - Packet& operator <<(Int8 data); - Packet& operator <<(Uint8 data); - Packet& operator <<(Int16 data); - Packet& operator <<(Uint16 data); - Packet& operator <<(Int32 data); - Packet& operator <<(Uint32 data); - Packet& operator <<(float data); - Packet& operator <<(double data); - Packet& operator <<(const char* data); - Packet& operator <<(const std::string& data); - Packet& operator <<(const wchar_t* data); - Packet& operator <<(const std::wstring& data); - Packet& operator <<(const String& data); - -protected: - - friend class TcpSocket; - friend class UdpSocket; - - //////////////////////////////////////////////////////////// - /// \brief Called before the packet is sent over the network - /// - /// This function can be defined by derived classes to - /// transform the data before it is sent; this can be - /// used for compression, encryption, etc. - /// The function must return a pointer to the modified data, - /// as well as the number of bytes pointed. - /// The default implementation provides the packet's data - /// without transforming it. - /// - /// \param size Variable to fill with the size of data to send - /// - /// \return Pointer to the array of bytes to send - /// - /// \see onReceive - /// - //////////////////////////////////////////////////////////// - virtual const void* onSend(std::size_t& size); - - //////////////////////////////////////////////////////////// - /// \brief Called after the packet is received over the network - /// - /// This function can be defined by derived classes to - /// transform the data after it is received; this can be - /// used for uncompression, decryption, etc. - /// The function receives a pointer to the received data, - /// and must fill the packet with the transformed bytes. - /// The default implementation fills the packet directly - /// without transforming the data. - /// - /// \param data Pointer to the received bytes - /// \param size Number of bytes - /// - /// \see onSend - /// - //////////////////////////////////////////////////////////// - virtual void onReceive(const void* data, std::size_t size); - -private : - - //////////////////////////////////////////////////////////// - /// Disallow comparisons between packets - /// - //////////////////////////////////////////////////////////// - bool operator ==(const Packet& right) const; - bool operator !=(const Packet& right) const; - - //////////////////////////////////////////////////////////// - /// \brief Check if the packet can extract a given number of bytes - /// - /// This function updates accordingly the state of the packet. - /// - /// \param size Size to check - /// - /// \return True if \a size bytes can be read from the packet - /// - //////////////////////////////////////////////////////////// - bool checkSize(std::size_t size); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - std::vector m_data; ///< Data stored in the packet - std::size_t m_readPos; ///< Current reading position in the packet - bool m_isValid; ///< Reading state of the packet -}; - -} // namespace sf - - -#endif // SFML_PACKET_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Packet -/// \ingroup network -/// -/// Packets provide a safe and easy way to serialize data, -/// in order to send it over the network using sockets -/// (sf::TcpSocket, sf::UdpSocket). -/// -/// Packets solve 2 fundamental problems that arise when -/// transfering data over the network: -/// \li data is interpreted correctly according to the endianness -/// \li the bounds of the packet are preserved (one send == one receive) -/// -/// The sf::Packet class provides both input and output modes. -/// It is designed to follow the behaviour of standard C++ streams, -/// using operators >> and << to extract and insert data. -/// -/// It is recommended to use only fixed-size types (like sf::Int32, etc.), -/// to avoid possible differences between the sender and the receiver. -/// Indeed, the native C++ types may have different sizes on two platforms -/// and your data may be corrupted if that happens. -/// -/// Usage example: -/// \code -/// sf::Uint32 x = 24; -/// std::string s = "hello"; -/// double d = 5.89; -/// -/// // Group the variables to send into a packet -/// sf::Packet packet; -/// packet << x << s << d; -/// -/// // Send it over the network (socket is a valid sf::TcpSocket) -/// socket.send(packet); -/// -/// ----------------------------------------------------------------- -/// -/// // Receive the packet at the other end -/// sf::Packet packet; -/// socket.receive(packet); -/// -/// // Extract the variables contained in the packet -/// sf::Uint32 x; -/// std::string s; -/// double d; -/// if (packet >> x >> s >> d) -/// { -/// // Data extracted successfully... -/// } -/// \endcode -/// -/// Packets have built-in operator >> and << overloads for -/// standard types: -/// \li bool -/// \li fixed-size integer types (sf::Int8/16/32, sf::Uint8/16/32) -/// \li floating point numbers (float, double) -/// \li string types (char*, wchar_t*, std::string, std::wstring, sf::String) -/// -/// Like standard streams, it is also possible to define your own -/// overloads of operators >> and << in order to handle your -/// custom types. -/// -/// \code -/// struct MyStruct -/// { -/// float number; -/// sf::Int8 integer; -/// std::string str; -/// }; -/// -/// sf::Packet& operator <<(sf::Packet& packet, const MyStruct& m) -/// { -/// return packet << m.number << m.integer << m.str; -/// } -/// -/// sf::Packet& operator >>(sf::Packet& packet, MyStruct& m) -/// { -/// return packet >> m.number >> m.integer >> m.str; -/// } -/// \endcode -/// -/// Packets also provide an extra feature that allows to apply -/// custom transformations to the data before it is sent, -/// and after it is received. This is typically used to -/// handle automatic compression or encryption of the data. -/// This is achieved by inheriting from sf::Packet, and overriding -/// the onSend and onReceive functions. -/// -/// Here is an example: -/// \code -/// class ZipPacket : public sf::Packet -/// { -/// virtual const void* onSend(std::size_t& size) -/// { -/// const void* srcData = getData(); -/// std::size_t srcSize = getDataSize(); -/// -/// return MySuperZipFunction(srcData, srcSize, &size); -/// } -/// -/// virtual void onReceive(const void* data, std::size_t size) -/// { -/// std::size_t dstSize; -/// const void* dstData = MySuperUnzipFunction(data, size, &dstSize); -/// -/// append(dstData, dstSize); -/// } -/// }; -/// -/// // Use like regular packets: -/// ZipPacket packet; -/// packet << x << s << d; -/// ... -/// \endcode -/// -/// \see sf::TcpSocket, sf::UdpSocket -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_PACKET_HPP +#define SFML_PACKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class String; +class TcpSocket; +class UdpSocket; + +//////////////////////////////////////////////////////////// +/// \brief Utility class to build blocks of data to transfer +/// over the network +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API Packet +{ + // A bool-like type that cannot be converted to integer or pointer types + typedef bool (Packet::*BoolType)(std::size_t); + +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty packet. + /// + //////////////////////////////////////////////////////////// + Packet(); + + //////////////////////////////////////////////////////////// + /// \brief Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Packet(); + + //////////////////////////////////////////////////////////// + /// \brief Append data to the end of the packet + /// + /// \param data Pointer to the sequence of bytes to append + /// \param sizeInBytes Number of bytes to append + /// + /// \see clear + /// + //////////////////////////////////////////////////////////// + void append(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Clear the packet + /// + /// After calling Clear, the packet is empty. + /// + /// \see append + /// + //////////////////////////////////////////////////////////// + void clear(); + + //////////////////////////////////////////////////////////// + /// \brief Get a pointer to the data contained in the packet + /// + /// Warning: the returned pointer may become invalid after + /// you append data to the packet, therefore it should never + /// be stored. + /// The return pointer is NULL if the packet is empty. + /// + /// \return Pointer to the data + /// + /// \see getDataSize + /// + //////////////////////////////////////////////////////////// + const void* getData() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the data contained in the packet + /// + /// This function returns the number of bytes pointed to by + /// what getData returns. + /// + /// \return Data size, in bytes + /// + /// \see getData + /// + //////////////////////////////////////////////////////////// + std::size_t getDataSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Tell if the reading position has reached the + /// end of the packet + /// + /// This function is useful to know if there is some data + /// left to be read, without actually reading it. + /// + /// \return True if all data was read, false otherwise + /// + /// \see operator bool + /// + //////////////////////////////////////////////////////////// + bool endOfPacket() const; + +public: + + //////////////////////////////////////////////////////////// + /// \brief Test the validity of the packet, for reading + /// + /// This operator allows to test the packet as a boolean + /// variable, to check if a reading operation was successful. + /// + /// A packet will be in an invalid state if it has no more + /// data to read. + /// + /// This behaviour is the same as standard C++ streams. + /// + /// Usage example: + /// \code + /// float x; + /// packet >> x; + /// if (packet) + /// { + /// // ok, x was extracted successfully + /// } + /// + /// // -- or -- + /// + /// float x; + /// if (packet >> x) + /// { + /// // ok, x was extracted successfully + /// } + /// \endcode + /// + /// Don't focus on the return type, it's equivalent to bool but + /// it disallows unwanted implicit conversions to integer or + /// pointer types. + /// + /// \return True if last data extraction from packet was successful + /// + /// \see endOfPacket + /// + //////////////////////////////////////////////////////////// + operator BoolType() const; + + //////////////////////////////////////////////////////////// + /// Overloads of operator >> to read data from the packet + /// + //////////////////////////////////////////////////////////// + Packet& operator >>(bool& data); + Packet& operator >>(Int8& data); + Packet& operator >>(Uint8& data); + Packet& operator >>(Int16& data); + Packet& operator >>(Uint16& data); + Packet& operator >>(Int32& data); + Packet& operator >>(Uint32& data); + Packet& operator >>(float& data); + Packet& operator >>(double& data); + Packet& operator >>(char* data); + Packet& operator >>(std::string& data); + Packet& operator >>(wchar_t* data); + Packet& operator >>(std::wstring& data); + Packet& operator >>(String& data); + + //////////////////////////////////////////////////////////// + /// Overloads of operator << to write data into the packet + /// + //////////////////////////////////////////////////////////// + Packet& operator <<(bool data); + Packet& operator <<(Int8 data); + Packet& operator <<(Uint8 data); + Packet& operator <<(Int16 data); + Packet& operator <<(Uint16 data); + Packet& operator <<(Int32 data); + Packet& operator <<(Uint32 data); + Packet& operator <<(float data); + Packet& operator <<(double data); + Packet& operator <<(const char* data); + Packet& operator <<(const std::string& data); + Packet& operator <<(const wchar_t* data); + Packet& operator <<(const std::wstring& data); + Packet& operator <<(const String& data); + +protected: + + friend class TcpSocket; + friend class UdpSocket; + + //////////////////////////////////////////////////////////// + /// \brief Called before the packet is sent over the network + /// + /// This function can be defined by derived classes to + /// transform the data before it is sent; this can be + /// used for compression, encryption, etc. + /// The function must return a pointer to the modified data, + /// as well as the number of bytes pointed. + /// The default implementation provides the packet's data + /// without transforming it. + /// + /// \param size Variable to fill with the size of data to send + /// + /// \return Pointer to the array of bytes to send + /// + /// \see onReceive + /// + //////////////////////////////////////////////////////////// + virtual const void* onSend(std::size_t& size); + + //////////////////////////////////////////////////////////// + /// \brief Called after the packet is received over the network + /// + /// This function can be defined by derived classes to + /// transform the data after it is received; this can be + /// used for uncompression, decryption, etc. + /// The function receives a pointer to the received data, + /// and must fill the packet with the transformed bytes. + /// The default implementation fills the packet directly + /// without transforming the data. + /// + /// \param data Pointer to the received bytes + /// \param size Number of bytes + /// + /// \see onSend + /// + //////////////////////////////////////////////////////////// + virtual void onReceive(const void* data, std::size_t size); + +private: + + //////////////////////////////////////////////////////////// + /// Disallow comparisons between packets + /// + //////////////////////////////////////////////////////////// + bool operator ==(const Packet& right) const; + bool operator !=(const Packet& right) const; + + //////////////////////////////////////////////////////////// + /// \brief Check if the packet can extract a given number of bytes + /// + /// This function updates accordingly the state of the packet. + /// + /// \param size Size to check + /// + /// \return True if \a size bytes can be read from the packet + /// + //////////////////////////////////////////////////////////// + bool checkSize(std::size_t size); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector m_data; ///< Data stored in the packet + std::size_t m_readPos; ///< Current reading position in the packet + bool m_isValid; ///< Reading state of the packet +}; + +} // namespace sf + + +#endif // SFML_PACKET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Packet +/// \ingroup network +/// +/// Packets provide a safe and easy way to serialize data, +/// in order to send it over the network using sockets +/// (sf::TcpSocket, sf::UdpSocket). +/// +/// Packets solve 2 fundamental problems that arise when +/// transfering data over the network: +/// \li data is interpreted correctly according to the endianness +/// \li the bounds of the packet are preserved (one send == one receive) +/// +/// The sf::Packet class provides both input and output modes. +/// It is designed to follow the behaviour of standard C++ streams, +/// using operators >> and << to extract and insert data. +/// +/// It is recommended to use only fixed-size types (like sf::Int32, etc.), +/// to avoid possible differences between the sender and the receiver. +/// Indeed, the native C++ types may have different sizes on two platforms +/// and your data may be corrupted if that happens. +/// +/// Usage example: +/// \code +/// sf::Uint32 x = 24; +/// std::string s = "hello"; +/// double d = 5.89; +/// +/// // Group the variables to send into a packet +/// sf::Packet packet; +/// packet << x << s << d; +/// +/// // Send it over the network (socket is a valid sf::TcpSocket) +/// socket.send(packet); +/// +/// ----------------------------------------------------------------- +/// +/// // Receive the packet at the other end +/// sf::Packet packet; +/// socket.receive(packet); +/// +/// // Extract the variables contained in the packet +/// sf::Uint32 x; +/// std::string s; +/// double d; +/// if (packet >> x >> s >> d) +/// { +/// // Data extracted successfully... +/// } +/// \endcode +/// +/// Packets have built-in operator >> and << overloads for +/// standard types: +/// \li bool +/// \li fixed-size integer types (sf::Int8/16/32, sf::Uint8/16/32) +/// \li floating point numbers (float, double) +/// \li string types (char*, wchar_t*, std::string, std::wstring, sf::String) +/// +/// Like standard streams, it is also possible to define your own +/// overloads of operators >> and << in order to handle your +/// custom types. +/// +/// \code +/// struct MyStruct +/// { +/// float number; +/// sf::Int8 integer; +/// std::string str; +/// }; +/// +/// sf::Packet& operator <<(sf::Packet& packet, const MyStruct& m) +/// { +/// return packet << m.number << m.integer << m.str; +/// } +/// +/// sf::Packet& operator >>(sf::Packet& packet, MyStruct& m) +/// { +/// return packet >> m.number >> m.integer >> m.str; +/// } +/// \endcode +/// +/// Packets also provide an extra feature that allows to apply +/// custom transformations to the data before it is sent, +/// and after it is received. This is typically used to +/// handle automatic compression or encryption of the data. +/// This is achieved by inheriting from sf::Packet, and overriding +/// the onSend and onReceive functions. +/// +/// Here is an example: +/// \code +/// class ZipPacket : public sf::Packet +/// { +/// virtual const void* onSend(std::size_t& size) +/// { +/// const void* srcData = getData(); +/// std::size_t srcSize = getDataSize(); +/// +/// return MySuperZipFunction(srcData, srcSize, &size); +/// } +/// +/// virtual void onReceive(const void* data, std::size_t size) +/// { +/// std::size_t dstSize; +/// const void* dstData = MySuperUnzipFunction(data, size, &dstSize); +/// +/// append(dstData, dstSize); +/// } +/// }; +/// +/// // Use like regular packets: +/// ZipPacket packet; +/// packet << x << s << d; +/// ... +/// \endcode +/// +/// \see sf::TcpSocket, sf::UdpSocket +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Network/Socket.hpp b/include/SFML/Network/Socket.hpp index 374667dc..8b664530 100644 --- a/include/SFML/Network/Socket.hpp +++ b/include/SFML/Network/Socket.hpp @@ -1,218 +1,218 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOCKET_HPP -#define SFML_SOCKET_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -class SocketSelector; - -//////////////////////////////////////////////////////////// -/// \brief Base class for all the socket types -/// -//////////////////////////////////////////////////////////// -class SFML_NETWORK_API Socket : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Status codes that may be returned by socket functions - /// - //////////////////////////////////////////////////////////// - enum Status - { - Done, ///< The socket has sent / received the data - NotReady, ///< The socket is not ready to send / receive data yet - Disconnected, ///< The TCP socket has been disconnected - Error ///< An unexpected error happened - }; - - //////////////////////////////////////////////////////////// - /// \brief Some special values used by sockets - /// - //////////////////////////////////////////////////////////// - enum - { - AnyPort = 0 ///< Special value that tells the system to pick any available port - }; - -public : - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - virtual ~Socket(); - - //////////////////////////////////////////////////////////// - /// \brief Set the blocking state of the socket - /// - /// In blocking mode, calls will not return until they have - /// completed their task. For example, a call to Receive in - /// blocking mode won't return until some data was actually - /// received. - /// In non-blocking mode, calls will always return immediately, - /// using the return code to signal whether there was data - /// available or not. - /// By default, all sockets are blocking. - /// - /// \param blocking True to set the socket as blocking, false for non-blocking - /// - /// \see isBlocking - /// - //////////////////////////////////////////////////////////// - void setBlocking(bool blocking); - - //////////////////////////////////////////////////////////// - /// \brief Tell whether the socket is in blocking or non-blocking mode - /// - /// \return True if the socket is blocking, false otherwise - /// - /// \see setBlocking - /// - //////////////////////////////////////////////////////////// - bool isBlocking() const; - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Types of protocols that the socket can use - /// - //////////////////////////////////////////////////////////// - enum Type - { - Tcp, ///< TCP protocol - Udp ///< UDP protocol - }; - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor can only be accessed by derived classes. - /// - /// \param type Type of the socket (TCP or UDP) - /// - //////////////////////////////////////////////////////////// - Socket(Type type); - - //////////////////////////////////////////////////////////// - /// \brief Return the internal handle of the socket - /// - /// The returned handle may be invalid if the socket - /// was not created yet (or already destroyed). - /// This function can only be accessed by derived classes. - /// - /// \return The internal (OS-specific) handle of the socket - /// - //////////////////////////////////////////////////////////// - SocketHandle getHandle() const; - - //////////////////////////////////////////////////////////// - /// \brief Create the internal representation of the socket - /// - /// This function can only be accessed by derived classes. - /// - //////////////////////////////////////////////////////////// - void create(); - - //////////////////////////////////////////////////////////// - /// \brief Create the internal representation of the socket - /// from a socket handle - /// - /// This function can only be accessed by derived classes. - /// - /// \param handle OS-specific handle of the socket to wrap - /// - //////////////////////////////////////////////////////////// - void create(SocketHandle handle); - - //////////////////////////////////////////////////////////// - /// \brief Close the socket gracefully - /// - /// This function can only be accessed by derived classes. - /// - //////////////////////////////////////////////////////////// - void close(); - -private : - - friend class SocketSelector; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Type m_type; ///< Type of the socket (TCP or UDP) - SocketHandle m_socket; ///< Socket descriptor - bool m_isBlocking; ///< Current blocking mode of the socket -}; - -} // namespace sf - - -#endif // SFML_SOCKET_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Socket -/// \ingroup network -/// -/// This class mainly defines internal stuff to be used by -/// derived classes. -/// -/// The only public features that it defines, and which -/// is therefore common to all the socket classes, is the -/// blocking state. All sockets can be set as blocking or -/// non-blocking. -/// -/// In blocking mode, socket functions will hang until -/// the operation completes, which means that the entire -/// program (well, in fact the current thread if you use -/// multiple ones) will be stuck waiting for your socket -/// operation to complete. -/// -/// In non-blocking mode, all the socket functions will -/// return immediately. If the socket is not ready to complete -/// the requested operation, the function simply returns -/// the proper status code (Socket::NotReady). -/// -/// The default mode, which is blocking, is the one that is -/// generally used, in combination with threads or selectors. -/// The non-blocking mode is rather used in real-time -/// applications that run an endless loop that can poll -/// the socket often enough, and cannot afford blocking -/// this loop. -/// -/// \see sf::TcpListener, sf::TcpSocket, sf::UdpSocket -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOCKET_HPP +#define SFML_SOCKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +class SocketSelector; + +//////////////////////////////////////////////////////////// +/// \brief Base class for all the socket types +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API Socket : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Status codes that may be returned by socket functions + /// + //////////////////////////////////////////////////////////// + enum Status + { + Done, ///< The socket has sent / received the data + NotReady, ///< The socket is not ready to send / receive data yet + Disconnected, ///< The TCP socket has been disconnected + Error ///< An unexpected error happened + }; + + //////////////////////////////////////////////////////////// + /// \brief Some special values used by sockets + /// + //////////////////////////////////////////////////////////// + enum + { + AnyPort = 0 ///< Special value that tells the system to pick any available port + }; + +public: + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Socket(); + + //////////////////////////////////////////////////////////// + /// \brief Set the blocking state of the socket + /// + /// In blocking mode, calls will not return until they have + /// completed their task. For example, a call to Receive in + /// blocking mode won't return until some data was actually + /// received. + /// In non-blocking mode, calls will always return immediately, + /// using the return code to signal whether there was data + /// available or not. + /// By default, all sockets are blocking. + /// + /// \param blocking True to set the socket as blocking, false for non-blocking + /// + /// \see isBlocking + /// + //////////////////////////////////////////////////////////// + void setBlocking(bool blocking); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the socket is in blocking or non-blocking mode + /// + /// \return True if the socket is blocking, false otherwise + /// + /// \see setBlocking + /// + //////////////////////////////////////////////////////////// + bool isBlocking() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Types of protocols that the socket can use + /// + //////////////////////////////////////////////////////////// + enum Type + { + Tcp, ///< TCP protocol + Udp ///< UDP protocol + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor can only be accessed by derived classes. + /// + /// \param type Type of the socket (TCP or UDP) + /// + //////////////////////////////////////////////////////////// + Socket(Type type); + + //////////////////////////////////////////////////////////// + /// \brief Return the internal handle of the socket + /// + /// The returned handle may be invalid if the socket + /// was not created yet (or already destroyed). + /// This function can only be accessed by derived classes. + /// + /// \return The internal (OS-specific) handle of the socket + /// + //////////////////////////////////////////////////////////// + SocketHandle getHandle() const; + + //////////////////////////////////////////////////////////// + /// \brief Create the internal representation of the socket + /// + /// This function can only be accessed by derived classes. + /// + //////////////////////////////////////////////////////////// + void create(); + + //////////////////////////////////////////////////////////// + /// \brief Create the internal representation of the socket + /// from a socket handle + /// + /// This function can only be accessed by derived classes. + /// + /// \param handle OS-specific handle of the socket to wrap + /// + //////////////////////////////////////////////////////////// + void create(SocketHandle handle); + + //////////////////////////////////////////////////////////// + /// \brief Close the socket gracefully + /// + /// This function can only be accessed by derived classes. + /// + //////////////////////////////////////////////////////////// + void close(); + +private: + + friend class SocketSelector; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Type m_type; ///< Type of the socket (TCP or UDP) + SocketHandle m_socket; ///< Socket descriptor + bool m_isBlocking; ///< Current blocking mode of the socket +}; + +} // namespace sf + + +#endif // SFML_SOCKET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Socket +/// \ingroup network +/// +/// This class mainly defines internal stuff to be used by +/// derived classes. +/// +/// The only public features that it defines, and which +/// is therefore common to all the socket classes, is the +/// blocking state. All sockets can be set as blocking or +/// non-blocking. +/// +/// In blocking mode, socket functions will hang until +/// the operation completes, which means that the entire +/// program (well, in fact the current thread if you use +/// multiple ones) will be stuck waiting for your socket +/// operation to complete. +/// +/// In non-blocking mode, all the socket functions will +/// return immediately. If the socket is not ready to complete +/// the requested operation, the function simply returns +/// the proper status code (Socket::NotReady). +/// +/// The default mode, which is blocking, is the one that is +/// generally used, in combination with threads or selectors. +/// The non-blocking mode is rather used in real-time +/// applications that run an endless loop that can poll +/// the socket often enough, and cannot afford blocking +/// this loop. +/// +/// \see sf::TcpListener, sf::TcpSocket, sf::UdpSocket +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Network/SocketHandle.hpp b/include/SFML/Network/SocketHandle.hpp index 51bfb89c..83c2422f 100644 --- a/include/SFML/Network/SocketHandle.hpp +++ b/include/SFML/Network/SocketHandle.hpp @@ -1,57 +1,57 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOCKETHANDLE_HPP -#define SFML_SOCKETHANDLE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#if defined(SFML_SYSTEM_WINDOWS) - #include -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -// Define the low-level socket handle type, specific to -// each platform -//////////////////////////////////////////////////////////// -#if defined(SFML_SYSTEM_WINDOWS) - - typedef UINT_PTR SocketHandle; - -#else - - typedef int SocketHandle; - -#endif - -} // namespace sf - - -#endif // SFML_SOCKETHANDLE_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOCKETHANDLE_HPP +#define SFML_SOCKETHANDLE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#if defined(SFML_SYSTEM_WINDOWS) + #include +#endif + + +namespace sf +{ +//////////////////////////////////////////////////////////// +// Define the low-level socket handle type, specific to +// each platform +//////////////////////////////////////////////////////////// +#if defined(SFML_SYSTEM_WINDOWS) + + typedef UINT_PTR SocketHandle; + +#else + + typedef int SocketHandle; + +#endif + +} // namespace sf + + +#endif // SFML_SOCKETHANDLE_HPP diff --git a/include/SFML/Network/SocketSelector.hpp b/include/SFML/Network/SocketSelector.hpp index 480c10f3..382b8c6b 100644 --- a/include/SFML/Network/SocketSelector.hpp +++ b/include/SFML/Network/SocketSelector.hpp @@ -1,263 +1,263 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOCKETSELECTOR_HPP -#define SFML_SOCKETSELECTOR_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -class Socket; - -//////////////////////////////////////////////////////////// -/// \brief Multiplexer that allows to read from multiple sockets -/// -//////////////////////////////////////////////////////////// -class SFML_NETWORK_API SocketSelector -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - SocketSelector(); - - //////////////////////////////////////////////////////////// - /// \brief Copy constructor - /// - /// \param copy Instance to copy - /// - //////////////////////////////////////////////////////////// - SocketSelector(const SocketSelector& copy); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~SocketSelector(); - - //////////////////////////////////////////////////////////// - /// \brief Add a new socket to the selector - /// - /// This function keeps a weak reference to the socket, - /// so you have to make sure that the socket is not destroyed - /// while it is stored in the selector. - /// This function does nothing if the socket is not valid. - /// - /// \param socket Reference to the socket to add - /// - /// \see remove, clear - /// - //////////////////////////////////////////////////////////// - void add(Socket& socket); - - //////////////////////////////////////////////////////////// - /// \brief Remove a socket from the selector - /// - /// This function doesn't destroy the socket, it simply - /// removes the reference that the selector has to it. - /// - /// \param socket Reference to the socket to remove - /// - /// \see add, clear - /// - //////////////////////////////////////////////////////////// - void remove(Socket& socket); - - //////////////////////////////////////////////////////////// - /// \brief Remove all the sockets stored in the selector - /// - /// This function doesn't destroy any instance, it simply - /// removes all the references that the selector has to - /// external sockets. - /// - /// \see add, remove - /// - //////////////////////////////////////////////////////////// - void clear(); - - //////////////////////////////////////////////////////////// - /// \brief Wait until one or more sockets are ready to receive - /// - /// This function returns as soon as at least one socket has - /// some data available to be received. To know which sockets are - /// ready, use the isReady function. - /// If you use a timeout and no socket is ready before the timeout - /// is over, the function returns false. - /// - /// \param timeout Maximum time to wait, (use Time::Zero for infinity) - /// - /// \return True if there are sockets ready, false otherwise - /// - /// \see isReady - /// - //////////////////////////////////////////////////////////// - bool wait(Time timeout = Time::Zero); - - //////////////////////////////////////////////////////////// - /// \brief Test a socket to know if it is ready to receive data - /// - /// This function must be used after a call to Wait, to know - /// which sockets are ready to receive data. If a socket is - /// ready, a call to receive will never block because we know - /// that there is data available to read. - /// Note that if this function returns true for a TcpListener, - /// this means that it is ready to accept a new connection. - /// - /// \param socket Socket to test - /// - /// \return True if the socket is ready to read, false otherwise - /// - /// \see isReady - /// - //////////////////////////////////////////////////////////// - bool isReady(Socket& socket) const; - - //////////////////////////////////////////////////////////// - /// \brief Overload of assignment operator - /// - /// \param right Instance to assign - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - SocketSelector& operator =(const SocketSelector& right); - -private : - - struct SocketSelectorImpl; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - SocketSelectorImpl* m_impl; ///< Opaque pointer to the implementation (which requires OS-specific types) -}; - -} // namespace sf - - -#endif // SFML_SOCKETSELECTOR_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::SocketSelector -/// \ingroup network -/// -/// Socket selectors provide a way to wait until some data is -/// available on a set of sockets, instead of just one. This -/// is convenient when you have multiple sockets that may -/// possibly receive data, but you don't know which one will -/// be ready first. In particular, it avoids to use a thread -/// for each socket; with selectors, a single thread can handle -/// all the sockets. -/// -/// All types of sockets can be used in a selector: -/// \li sf::TcpListener -/// \li sf::TcpSocket -/// \li sf::UdpSocket -/// -/// A selector doesn't store its own copies of the sockets -/// (socket classes are not copyable anyway), it simply keeps -/// a reference to the original sockets that you pass to the -/// "add" function. Therefore, you can't use the selector as a -/// socket container, you must store them oustide and make sure -/// that they are alive as long as they are used in the selector. -/// -/// Using a selector is simple: -/// \li populate the selector with all the sockets that you want to observe -/// \li make it wait until there is data available on any of the sockets -/// \li test each socket to find out which ones are ready -/// -/// Usage example: -/// \code -/// // Create a socket to listen to new connections -/// sf::TcpListener listener; -/// listener.listen(55001); -/// -/// // Create a list to store the future clients -/// std::list clients; -/// -/// // Create a selector -/// sf::SocketSelector selector; -/// -/// // Add the listener to the selector -/// selector.add(listener); -/// -/// // Endless loop that waits for new connections -/// while (running) -/// { -/// // Make the selector wait for data on any socket -/// if (selector.wait()) -/// { -/// // Test the listener -/// if (selector.isReady(listener)) -/// { -/// // The listener is ready: there is a pending connection -/// sf::TcpSocket* client = new sf::TcpSocket; -/// if (listener.accept(*client) == sf::Socket::Done) -/// { -/// // Add the new client to the clients list -/// clients.push_back(client); -/// -/// // Add the new client to the selector so that we will -/// // be notified when he sends something -/// selector.add(*client); -/// } -/// else -/// { -/// // Error, we won't get a new connection, delete the socket -/// delete client; -/// } -/// } -/// else -/// { -/// // The listener socket is not ready, test all other sockets (the clients) -/// for (std::list::iterator it = clients.begin(); it != clients.end(); ++it) -/// { -/// sf::TcpSocket& client = **it; -/// if (selector.isReady(client)) -/// { -/// // The client has sent some data, we can receive it -/// sf::Packet packet; -/// if (client.receive(packet) == sf::Socket::Done) -/// { -/// ... -/// } -/// } -/// } -/// } -/// } -/// } -/// \endcode -/// -/// \see sf::Socket -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOCKETSELECTOR_HPP +#define SFML_SOCKETSELECTOR_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +class Socket; + +//////////////////////////////////////////////////////////// +/// \brief Multiplexer that allows to read from multiple sockets +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API SocketSelector +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + SocketSelector(); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + SocketSelector(const SocketSelector& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~SocketSelector(); + + //////////////////////////////////////////////////////////// + /// \brief Add a new socket to the selector + /// + /// This function keeps a weak reference to the socket, + /// so you have to make sure that the socket is not destroyed + /// while it is stored in the selector. + /// This function does nothing if the socket is not valid. + /// + /// \param socket Reference to the socket to add + /// + /// \see remove, clear + /// + //////////////////////////////////////////////////////////// + void add(Socket& socket); + + //////////////////////////////////////////////////////////// + /// \brief Remove a socket from the selector + /// + /// This function doesn't destroy the socket, it simply + /// removes the reference that the selector has to it. + /// + /// \param socket Reference to the socket to remove + /// + /// \see add, clear + /// + //////////////////////////////////////////////////////////// + void remove(Socket& socket); + + //////////////////////////////////////////////////////////// + /// \brief Remove all the sockets stored in the selector + /// + /// This function doesn't destroy any instance, it simply + /// removes all the references that the selector has to + /// external sockets. + /// + /// \see add, remove + /// + //////////////////////////////////////////////////////////// + void clear(); + + //////////////////////////////////////////////////////////// + /// \brief Wait until one or more sockets are ready to receive + /// + /// This function returns as soon as at least one socket has + /// some data available to be received. To know which sockets are + /// ready, use the isReady function. + /// If you use a timeout and no socket is ready before the timeout + /// is over, the function returns false. + /// + /// \param timeout Maximum time to wait, (use Time::Zero for infinity) + /// + /// \return True if there are sockets ready, false otherwise + /// + /// \see isReady + /// + //////////////////////////////////////////////////////////// + bool wait(Time timeout = Time::Zero); + + //////////////////////////////////////////////////////////// + /// \brief Test a socket to know if it is ready to receive data + /// + /// This function must be used after a call to Wait, to know + /// which sockets are ready to receive data. If a socket is + /// ready, a call to receive will never block because we know + /// that there is data available to read. + /// Note that if this function returns true for a TcpListener, + /// this means that it is ready to accept a new connection. + /// + /// \param socket Socket to test + /// + /// \return True if the socket is ready to read, false otherwise + /// + /// \see isReady + /// + //////////////////////////////////////////////////////////// + bool isReady(Socket& socket) const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + SocketSelector& operator =(const SocketSelector& right); + +private: + + struct SocketSelectorImpl; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + SocketSelectorImpl* m_impl; ///< Opaque pointer to the implementation (which requires OS-specific types) +}; + +} // namespace sf + + +#endif // SFML_SOCKETSELECTOR_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SocketSelector +/// \ingroup network +/// +/// Socket selectors provide a way to wait until some data is +/// available on a set of sockets, instead of just one. This +/// is convenient when you have multiple sockets that may +/// possibly receive data, but you don't know which one will +/// be ready first. In particular, it avoids to use a thread +/// for each socket; with selectors, a single thread can handle +/// all the sockets. +/// +/// All types of sockets can be used in a selector: +/// \li sf::TcpListener +/// \li sf::TcpSocket +/// \li sf::UdpSocket +/// +/// A selector doesn't store its own copies of the sockets +/// (socket classes are not copyable anyway), it simply keeps +/// a reference to the original sockets that you pass to the +/// "add" function. Therefore, you can't use the selector as a +/// socket container, you must store them oustide and make sure +/// that they are alive as long as they are used in the selector. +/// +/// Using a selector is simple: +/// \li populate the selector with all the sockets that you want to observe +/// \li make it wait until there is data available on any of the sockets +/// \li test each socket to find out which ones are ready +/// +/// Usage example: +/// \code +/// // Create a socket to listen to new connections +/// sf::TcpListener listener; +/// listener.listen(55001); +/// +/// // Create a list to store the future clients +/// std::list clients; +/// +/// // Create a selector +/// sf::SocketSelector selector; +/// +/// // Add the listener to the selector +/// selector.add(listener); +/// +/// // Endless loop that waits for new connections +/// while (running) +/// { +/// // Make the selector wait for data on any socket +/// if (selector.wait()) +/// { +/// // Test the listener +/// if (selector.isReady(listener)) +/// { +/// // The listener is ready: there is a pending connection +/// sf::TcpSocket* client = new sf::TcpSocket; +/// if (listener.accept(*client) == sf::Socket::Done) +/// { +/// // Add the new client to the clients list +/// clients.push_back(client); +/// +/// // Add the new client to the selector so that we will +/// // be notified when he sends something +/// selector.add(*client); +/// } +/// else +/// { +/// // Error, we won't get a new connection, delete the socket +/// delete client; +/// } +/// } +/// else +/// { +/// // The listener socket is not ready, test all other sockets (the clients) +/// for (std::list::iterator it = clients.begin(); it != clients.end(); ++it) +/// { +/// sf::TcpSocket& client = **it; +/// if (selector.isReady(client)) +/// { +/// // The client has sent some data, we can receive it +/// sf::Packet packet; +/// if (client.receive(packet) == sf::Socket::Done) +/// { +/// ... +/// } +/// } +/// } +/// } +/// } +/// } +/// \endcode +/// +/// \see sf::Socket +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Network/TcpListener.hpp b/include/SFML/Network/TcpListener.hpp index 8b49ab29..db93a6ce 100644 --- a/include/SFML/Network/TcpListener.hpp +++ b/include/SFML/Network/TcpListener.hpp @@ -1,162 +1,162 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_TCPLISTENER_HPP -#define SFML_TCPLISTENER_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -class TcpSocket; - -//////////////////////////////////////////////////////////// -/// \brief Socket that listens to new TCP connections -/// -//////////////////////////////////////////////////////////// -class SFML_NETWORK_API TcpListener : public Socket -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - TcpListener(); - - //////////////////////////////////////////////////////////// - /// \brief Get the port to which the socket is bound locally - /// - /// If the socket is not listening to a port, this function - /// returns 0. - /// - /// \return Port to which the socket is bound - /// - /// \see listen - /// - //////////////////////////////////////////////////////////// - unsigned short getLocalPort() const; - - //////////////////////////////////////////////////////////// - /// \brief Start listening for connections - /// - /// This functions makes the socket listen to the specified - /// port, waiting for new connections. - /// If the socket was previously listening to another port, - /// it will be stopped first and bound to the new port. - /// - /// \param port Port to listen for new connections - /// - /// \return Status code - /// - /// \see accept, close - /// - //////////////////////////////////////////////////////////// - Status listen(unsigned short port); - - //////////////////////////////////////////////////////////// - /// \brief Stop listening and close the socket - /// - /// This function gracefully stops the listener. If the - /// socket is not listening, this function has no effect. - /// - /// \see listen - /// - //////////////////////////////////////////////////////////// - void close(); - - //////////////////////////////////////////////////////////// - /// \brief Accept a new connection - /// - /// If the socket is in blocking mode, this function will - /// not return until a connection is actually received. - /// - /// \param socket Socket that will hold the new connection - /// - /// \return Status code - /// - /// \see listen - /// - //////////////////////////////////////////////////////////// - Status accept(TcpSocket& socket); -}; - - -} // namespace sf - - -#endif // SFML_TCPLISTENER_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::TcpListener -/// \ingroup network -/// -/// A listener socket is a special type of socket that listens to -/// a given port and waits for connections on that port. -/// This is all it can do. -/// -/// When a new connection is received, you must call accept and -/// the listener returns a new instance of sf::TcpSocket that -/// is properly initialized and can be used to communicate with -/// the new client. -/// -/// Listener sockets are specific to the TCP protocol, -/// UDP sockets are connectionless and can therefore communicate -/// directly. As a consequence, a listener socket will always -/// return the new connections as sf::TcpSocket instances. -/// -/// A listener is automatically closed on destruction, like all -/// other types of socket. However if you want to stop listening -/// before the socket is destroyed, you can call its close() -/// function. -/// -/// Usage example: -/// \code -/// // Create a listener socket and make it wait for new -/// // connections on port 55001 -/// sf::TcpListener listener; -/// listener.listen(55001); -/// -/// // Endless loop that waits for new connections -/// while (running) -/// { -/// sf::TcpSocket client; -/// if (listener.accept(client) == sf::Socket::Done) -/// { -/// // A new client just connected! -/// std::cout << "New connection received from " << client.getRemoteAddress() << std::endl; -/// doSomethingWith(client); -/// } -/// } -/// \endcode -/// -/// \see sf::TcpSocket, sf::Socket -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TCPLISTENER_HPP +#define SFML_TCPLISTENER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +class TcpSocket; + +//////////////////////////////////////////////////////////// +/// \brief Socket that listens to new TCP connections +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API TcpListener : public Socket +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + TcpListener(); + + //////////////////////////////////////////////////////////// + /// \brief Get the port to which the socket is bound locally + /// + /// If the socket is not listening to a port, this function + /// returns 0. + /// + /// \return Port to which the socket is bound + /// + /// \see listen + /// + //////////////////////////////////////////////////////////// + unsigned short getLocalPort() const; + + //////////////////////////////////////////////////////////// + /// \brief Start listening for connections + /// + /// This functions makes the socket listen to the specified + /// port, waiting for new connections. + /// If the socket was previously listening to another port, + /// it will be stopped first and bound to the new port. + /// + /// \param port Port to listen for new connections + /// + /// \return Status code + /// + /// \see accept, close + /// + //////////////////////////////////////////////////////////// + Status listen(unsigned short port); + + //////////////////////////////////////////////////////////// + /// \brief Stop listening and close the socket + /// + /// This function gracefully stops the listener. If the + /// socket is not listening, this function has no effect. + /// + /// \see listen + /// + //////////////////////////////////////////////////////////// + void close(); + + //////////////////////////////////////////////////////////// + /// \brief Accept a new connection + /// + /// If the socket is in blocking mode, this function will + /// not return until a connection is actually received. + /// + /// \param socket Socket that will hold the new connection + /// + /// \return Status code + /// + /// \see listen + /// + //////////////////////////////////////////////////////////// + Status accept(TcpSocket& socket); +}; + + +} // namespace sf + + +#endif // SFML_TCPLISTENER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::TcpListener +/// \ingroup network +/// +/// A listener socket is a special type of socket that listens to +/// a given port and waits for connections on that port. +/// This is all it can do. +/// +/// When a new connection is received, you must call accept and +/// the listener returns a new instance of sf::TcpSocket that +/// is properly initialized and can be used to communicate with +/// the new client. +/// +/// Listener sockets are specific to the TCP protocol, +/// UDP sockets are connectionless and can therefore communicate +/// directly. As a consequence, a listener socket will always +/// return the new connections as sf::TcpSocket instances. +/// +/// A listener is automatically closed on destruction, like all +/// other types of socket. However if you want to stop listening +/// before the socket is destroyed, you can call its close() +/// function. +/// +/// Usage example: +/// \code +/// // Create a listener socket and make it wait for new +/// // connections on port 55001 +/// sf::TcpListener listener; +/// listener.listen(55001); +/// +/// // Endless loop that waits for new connections +/// while (running) +/// { +/// sf::TcpSocket client; +/// if (listener.accept(client) == sf::Socket::Done) +/// { +/// // A new client just connected! +/// std::cout << "New connection received from " << client.getRemoteAddress() << std::endl; +/// doSomethingWith(client); +/// } +/// } +/// \endcode +/// +/// \see sf::TcpSocket, sf::Socket +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Network/TcpSocket.hpp b/include/SFML/Network/TcpSocket.hpp index 8d083efd..f4c31044 100644 --- a/include/SFML/Network/TcpSocket.hpp +++ b/include/SFML/Network/TcpSocket.hpp @@ -1,292 +1,292 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_TCPSOCKET_HPP -#define SFML_TCPSOCKET_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -class TcpListener; -class IpAddress; -class Packet; - -//////////////////////////////////////////////////////////// -/// \brief Specialized socket using the TCP protocol -/// -//////////////////////////////////////////////////////////// -class SFML_NETWORK_API TcpSocket : public Socket -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - TcpSocket(); - - //////////////////////////////////////////////////////////// - /// \brief Get the port to which the socket is bound locally - /// - /// If the socket is not connected, this function returns 0. - /// - /// \return Port to which the socket is bound - /// - /// \see connect, getRemotePort - /// - //////////////////////////////////////////////////////////// - unsigned short getLocalPort() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the address of the connected peer - /// - /// It the socket is not connected, this function returns - /// sf::IpAddress::None. - /// - /// \return Address of the remote peer - /// - /// \see getRemotePort - /// - //////////////////////////////////////////////////////////// - IpAddress getRemoteAddress() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the port of the connected peer to which - /// the socket is connected - /// - /// If the socket is not connected, this function returns 0. - /// - /// \return Remote port to which the socket is connected - /// - /// \see getRemoteAddress - /// - //////////////////////////////////////////////////////////// - unsigned short getRemotePort() const; - - //////////////////////////////////////////////////////////// - /// \brief Connect the socket to a remote peer - /// - /// In blocking mode, this function may take a while, especially - /// if the remote peer is not reachable. The last parameter allows - /// you to stop trying to connect after a given timeout. - /// If the socket was previously connected, it is first disconnected. - /// - /// \param remoteAddress Address of the remote peer - /// \param remotePort Port of the remote peer - /// \param timeout Optional maximum time to wait - /// - /// \return Status code - /// - /// \see disconnect - /// - //////////////////////////////////////////////////////////// - Status connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout = Time::Zero); - - //////////////////////////////////////////////////////////// - /// \brief Disconnect the socket from its remote peer - /// - /// This function gracefully closes the connection. If the - /// socket is not connected, this function has no effect. - /// - /// \see connect - /// - //////////////////////////////////////////////////////////// - void disconnect(); - - //////////////////////////////////////////////////////////// - /// \brief Send raw data to the remote peer - /// - /// This function will fail if the socket is not connected. - /// - /// \param data Pointer to the sequence of bytes to send - /// \param size Number of bytes to send - /// - /// \return Status code - /// - /// \see receive - /// - //////////////////////////////////////////////////////////// - Status send(const void* data, std::size_t size); - - //////////////////////////////////////////////////////////// - /// \brief Receive raw data from the remote peer - /// - /// In blocking mode, this function will wait until some - /// bytes are actually received. - /// This function will fail if the socket is not connected. - /// - /// \param data Pointer to the array to fill with the received bytes - /// \param size Maximum number of bytes that can be received - /// \param received This variable is filled with the actual number of bytes received - /// - /// \return Status code - /// - /// \see send - /// - //////////////////////////////////////////////////////////// - Status receive(void* data, std::size_t size, std::size_t& received); - - //////////////////////////////////////////////////////////// - /// \brief Send a formatted packet of data to the remote peer - /// - /// This function will fail if the socket is not connected. - /// - /// \param packet Packet to send - /// - /// \return Status code - /// - /// \see receive - /// - //////////////////////////////////////////////////////////// - Status send(Packet& packet); - - //////////////////////////////////////////////////////////// - /// \brief Receive a formatted packet of data from the remote peer - /// - /// In blocking mode, this function will wait until the whole packet - /// has been received. - /// This function will fail if the socket is not connected. - /// - /// \param packet Packet to fill with the received data - /// - /// \return Status code - /// - /// \see send - /// - //////////////////////////////////////////////////////////// - Status receive(Packet& packet); - -private: - - friend class TcpListener; - - //////////////////////////////////////////////////////////// - /// \brief Structure holding the data of a pending packet - /// - //////////////////////////////////////////////////////////// - struct PendingPacket - { - PendingPacket(); - - Uint32 Size; ///< Data of packet size - std::size_t SizeReceived; ///< Number of size bytes received so far - std::vector Data; ///< Data of the packet - }; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - PendingPacket m_pendingPacket; ///< Temporary data of the packet currently being received -}; - -} // namespace sf - - -#endif // SFML_TCPSOCKET_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::TcpSocket -/// \ingroup network -/// -/// TCP is a connected protocol, which means that a TCP -/// socket can only communicate with the host it is connected -/// to. It can't send or receive anything if it is not connected. -/// -/// The TCP protocol is reliable but adds a slight overhead. -/// It ensures that your data will always be received in order -/// and without errors (no data corrupted, lost or duplicated). -/// -/// When a socket is connected to a remote host, you can -/// retrieve informations about this host with the -/// getRemoteAddress and getRemotePort functions. You can -/// also get the local port to which the socket is bound -/// (which is automatically chosen when the socket is connected), -/// with the getLocalPort function. -/// -/// Sending and receiving data can use either the low-level -/// or the high-level functions. The low-level functions -/// process a raw sequence of bytes, and cannot ensure that -/// one call to Send will exactly match one call to Receive -/// at the other end of the socket. -/// -/// The high-level interface uses packets (see sf::Packet), -/// which are easier to use and provide more safety regarding -/// the data that is exchanged. You can look at the sf::Packet -/// class to get more details about how they work. -/// -/// The socket is automatically disconnected when it is destroyed, -/// but if you want to explicitely close the connection while -/// the socket instance is still alive, you can call disconnect. -/// -/// Usage example: -/// \code -/// // ----- The client ----- -/// -/// // Create a socket and connect it to 192.168.1.50 on port 55001 -/// sf::TcpSocket socket; -/// socket.connect("192.168.1.50", 55001); -/// -/// // Send a message to the connected host -/// std::string message = "Hi, I am a client"; -/// socket.send(message.c_str(), message.size() + 1); -/// -/// // Receive an answer from the server -/// char buffer[1024]; -/// std::size_t received = 0; -/// socket.receive(buffer, sizeof(buffer), received); -/// std::cout << "The server said: " << buffer << std::endl; -/// -/// // ----- The server ----- -/// -/// // Create a listener to wait for incoming connections on port 55001 -/// sf::TcpListener listener; -/// listener.listen(55001); -/// -/// // Wait for a connection -/// sf::TcpSocket socket; -/// listener.accept(socket); -/// std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl; -/// -/// // Receive a message from the client -/// char buffer[1024]; -/// std::size_t received = 0; -/// socket.receive(buffer, sizeof(buffer), received); -/// std::cout << "The client said: " << buffer << std::endl; -/// -/// // Send an answer -/// std::string message = "Welcome, client"; -/// socket.send(message.c_str(), message.size() + 1); -/// \endcode -/// -/// \see sf::Socket, sf::UdpSocket, sf::Packet -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TCPSOCKET_HPP +#define SFML_TCPSOCKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class TcpListener; +class IpAddress; +class Packet; + +//////////////////////////////////////////////////////////// +/// \brief Specialized socket using the TCP protocol +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API TcpSocket : public Socket +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + TcpSocket(); + + //////////////////////////////////////////////////////////// + /// \brief Get the port to which the socket is bound locally + /// + /// If the socket is not connected, this function returns 0. + /// + /// \return Port to which the socket is bound + /// + /// \see connect, getRemotePort + /// + //////////////////////////////////////////////////////////// + unsigned short getLocalPort() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the address of the connected peer + /// + /// It the socket is not connected, this function returns + /// sf::IpAddress::None. + /// + /// \return Address of the remote peer + /// + /// \see getRemotePort + /// + //////////////////////////////////////////////////////////// + IpAddress getRemoteAddress() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the port of the connected peer to which + /// the socket is connected + /// + /// If the socket is not connected, this function returns 0. + /// + /// \return Remote port to which the socket is connected + /// + /// \see getRemoteAddress + /// + //////////////////////////////////////////////////////////// + unsigned short getRemotePort() const; + + //////////////////////////////////////////////////////////// + /// \brief Connect the socket to a remote peer + /// + /// In blocking mode, this function may take a while, especially + /// if the remote peer is not reachable. The last parameter allows + /// you to stop trying to connect after a given timeout. + /// If the socket was previously connected, it is first disconnected. + /// + /// \param remoteAddress Address of the remote peer + /// \param remotePort Port of the remote peer + /// \param timeout Optional maximum time to wait + /// + /// \return Status code + /// + /// \see disconnect + /// + //////////////////////////////////////////////////////////// + Status connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout = Time::Zero); + + //////////////////////////////////////////////////////////// + /// \brief Disconnect the socket from its remote peer + /// + /// This function gracefully closes the connection. If the + /// socket is not connected, this function has no effect. + /// + /// \see connect + /// + //////////////////////////////////////////////////////////// + void disconnect(); + + //////////////////////////////////////////////////////////// + /// \brief Send raw data to the remote peer + /// + /// This function will fail if the socket is not connected. + /// + /// \param data Pointer to the sequence of bytes to send + /// \param size Number of bytes to send + /// + /// \return Status code + /// + /// \see receive + /// + //////////////////////////////////////////////////////////// + Status send(const void* data, std::size_t size); + + //////////////////////////////////////////////////////////// + /// \brief Receive raw data from the remote peer + /// + /// In blocking mode, this function will wait until some + /// bytes are actually received. + /// This function will fail if the socket is not connected. + /// + /// \param data Pointer to the array to fill with the received bytes + /// \param size Maximum number of bytes that can be received + /// \param received This variable is filled with the actual number of bytes received + /// + /// \return Status code + /// + /// \see send + /// + //////////////////////////////////////////////////////////// + Status receive(void* data, std::size_t size, std::size_t& received); + + //////////////////////////////////////////////////////////// + /// \brief Send a formatted packet of data to the remote peer + /// + /// This function will fail if the socket is not connected. + /// + /// \param packet Packet to send + /// + /// \return Status code + /// + /// \see receive + /// + //////////////////////////////////////////////////////////// + Status send(Packet& packet); + + //////////////////////////////////////////////////////////// + /// \brief Receive a formatted packet of data from the remote peer + /// + /// In blocking mode, this function will wait until the whole packet + /// has been received. + /// This function will fail if the socket is not connected. + /// + /// \param packet Packet to fill with the received data + /// + /// \return Status code + /// + /// \see send + /// + //////////////////////////////////////////////////////////// + Status receive(Packet& packet); + +private: + + friend class TcpListener; + + //////////////////////////////////////////////////////////// + /// \brief Structure holding the data of a pending packet + /// + //////////////////////////////////////////////////////////// + struct PendingPacket + { + PendingPacket(); + + Uint32 Size; ///< Data of packet size + std::size_t SizeReceived; ///< Number of size bytes received so far + std::vector Data; ///< Data of the packet + }; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + PendingPacket m_pendingPacket; ///< Temporary data of the packet currently being received +}; + +} // namespace sf + + +#endif // SFML_TCPSOCKET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::TcpSocket +/// \ingroup network +/// +/// TCP is a connected protocol, which means that a TCP +/// socket can only communicate with the host it is connected +/// to. It can't send or receive anything if it is not connected. +/// +/// The TCP protocol is reliable but adds a slight overhead. +/// It ensures that your data will always be received in order +/// and without errors (no data corrupted, lost or duplicated). +/// +/// When a socket is connected to a remote host, you can +/// retrieve informations about this host with the +/// getRemoteAddress and getRemotePort functions. You can +/// also get the local port to which the socket is bound +/// (which is automatically chosen when the socket is connected), +/// with the getLocalPort function. +/// +/// Sending and receiving data can use either the low-level +/// or the high-level functions. The low-level functions +/// process a raw sequence of bytes, and cannot ensure that +/// one call to Send will exactly match one call to Receive +/// at the other end of the socket. +/// +/// The high-level interface uses packets (see sf::Packet), +/// which are easier to use and provide more safety regarding +/// the data that is exchanged. You can look at the sf::Packet +/// class to get more details about how they work. +/// +/// The socket is automatically disconnected when it is destroyed, +/// but if you want to explicitely close the connection while +/// the socket instance is still alive, you can call disconnect. +/// +/// Usage example: +/// \code +/// // ----- The client ----- +/// +/// // Create a socket and connect it to 192.168.1.50 on port 55001 +/// sf::TcpSocket socket; +/// socket.connect("192.168.1.50", 55001); +/// +/// // Send a message to the connected host +/// std::string message = "Hi, I am a client"; +/// socket.send(message.c_str(), message.size() + 1); +/// +/// // Receive an answer from the server +/// char buffer[1024]; +/// std::size_t received = 0; +/// socket.receive(buffer, sizeof(buffer), received); +/// std::cout << "The server said: " << buffer << std::endl; +/// +/// // ----- The server ----- +/// +/// // Create a listener to wait for incoming connections on port 55001 +/// sf::TcpListener listener; +/// listener.listen(55001); +/// +/// // Wait for a connection +/// sf::TcpSocket socket; +/// listener.accept(socket); +/// std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl; +/// +/// // Receive a message from the client +/// char buffer[1024]; +/// std::size_t received = 0; +/// socket.receive(buffer, sizeof(buffer), received); +/// std::cout << "The client said: " << buffer << std::endl; +/// +/// // Send an answer +/// std::string message = "Welcome, client"; +/// socket.send(message.c_str(), message.size() + 1); +/// \endcode +/// +/// \see sf::Socket, sf::UdpSocket, sf::Packet +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Network/UdpSocket.hpp b/include/SFML/Network/UdpSocket.hpp index b6ae5e5f..814e349c 100644 --- a/include/SFML/Network/UdpSocket.hpp +++ b/include/SFML/Network/UdpSocket.hpp @@ -1,283 +1,283 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_UDPSOCKET_HPP -#define SFML_UDPSOCKET_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -class IpAddress; -class Packet; - -//////////////////////////////////////////////////////////// -/// \brief Specialized socket using the UDP protocol -/// -//////////////////////////////////////////////////////////// -class SFML_NETWORK_API UdpSocket : public Socket -{ -public : - - //////////////////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////////////////// - enum - { - MaxDatagramSize = 65507 ///< The maximum number of bytes that can be sent in a single UDP datagram - }; - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - UdpSocket(); - - //////////////////////////////////////////////////////////// - /// \brief Get the port to which the socket is bound locally - /// - /// If the socket is not bound to a port, this function - /// returns 0. - /// - /// \return Port to which the socket is bound - /// - /// \see bind - /// - //////////////////////////////////////////////////////////// - unsigned short getLocalPort() const; - - //////////////////////////////////////////////////////////// - /// \brief Bind the socket to a specific port - /// - /// Binding the socket to a port is necessary for being - /// able to receive data on that port. - /// You can use the special value Socket::AnyPort to tell the - /// system to automatically pick an available port, and then - /// call getLocalPort to retrieve the chosen port. - /// - /// \param port Port to bind the socket to - /// - /// \return Status code - /// - /// \see unbind, getLocalPort - /// - //////////////////////////////////////////////////////////// - Status bind(unsigned short port); - - //////////////////////////////////////////////////////////// - /// \brief Unbind the socket from the local port to which it is bound - /// - /// The port that the socket was previously using is immediately - /// available after this function is called. If the - /// socket is not bound to a port, this function has no effect. - /// - /// \see bind - /// - //////////////////////////////////////////////////////////// - void unbind(); - - //////////////////////////////////////////////////////////// - /// \brief Send raw data to a remote peer - /// - /// Make sure that \a size is not greater than - /// UdpSocket::MaxDatagramSize, otherwise this function will - /// fail and no data will be sent. - /// - /// \param data Pointer to the sequence of bytes to send - /// \param size Number of bytes to send - /// \param remoteAddress Address of the receiver - /// \param remotePort Port of the receiver to send the data to - /// - /// \return Status code - /// - /// \see receive - /// - //////////////////////////////////////////////////////////// - Status send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort); - - //////////////////////////////////////////////////////////// - /// \brief Receive raw data from a remote peer - /// - /// In blocking mode, this function will wait until some - /// bytes are actually received. - /// Be careful to use a buffer which is large enough for - /// the data that you intend to receive, if it is too small - /// then an error will be returned and *all* the data will - /// be lost. - /// - /// \param data Pointer to the array to fill with the received bytes - /// \param size Maximum number of bytes that can be received - /// \param received This variable is filled with the actual number of bytes received - /// \param remoteAddress Address of the peer that sent the data - /// \param remotePort Port of the peer that sent the data - /// - /// \return Status code - /// - /// \see send - /// - //////////////////////////////////////////////////////////// - Status receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort); - - //////////////////////////////////////////////////////////// - /// \brief Send a formatted packet of data to a remote peer - /// - /// Make sure that the packet size is not greater than - /// UdpSocket::MaxDatagramSize, otherwise this function will - /// fail and no data will be sent. - /// - /// \param packet Packet to send - /// \param remoteAddress Address of the receiver - /// \param remotePort Port of the receiver to send the data to - /// - /// \return Status code - /// - /// \see receive - /// - //////////////////////////////////////////////////////////// - Status send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort); - - //////////////////////////////////////////////////////////// - /// \brief Receive a formatted packet of data from a remote peer - /// - /// In blocking mode, this function will wait until the whole packet - /// has been received. - /// - /// \param packet Packet to fill with the received data - /// \param remoteAddress Address of the peer that sent the data - /// \param remotePort Port of the peer that sent the data - /// - /// \return Status code - /// - /// \see send - /// - //////////////////////////////////////////////////////////// - Status receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort); - -private: - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - std::vector m_buffer; ///< Temporary buffer holding the received data in Receive(Packet) -}; - -} // namespace sf - - -#endif // SFML_UDPSOCKET_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::UdpSocket -/// \ingroup network -/// -/// A UDP socket is a connectionless socket. Instead of -/// connecting once to a remote host, like TCP sockets, -/// it can send to and receive from any host at any time. -/// -/// It is a datagram protocol: bounded blocks of data (datagrams) -/// are transfered over the network rather than a continuous -/// stream of data (TCP). Therefore, one call to send will always -/// match one call to receive (if the datagram is not lost), -/// with the same data that was sent. -/// -/// The UDP protocol is lightweight but unreliable. Unreliable -/// means that datagrams may be duplicated, be lost or -/// arrive reordered. However, if a datagram arrives, its -/// data is guaranteed to be valid. -/// -/// UDP is generally used for real-time communication -/// (audio or video streaming, real-time games, etc.) where -/// speed is crucial and lost data doesn't matter much. -/// -/// Sending and receiving data can use either the low-level -/// or the high-level functions. The low-level functions -/// process a raw sequence of bytes, whereas the high-level -/// interface uses packets (see sf::Packet), which are easier -/// to use and provide more safety regarding the data that is -/// exchanged. You can look at the sf::Packet class to get -/// more details about how they work. -/// -/// It is important to note that UdpSocket is unable to send -/// datagrams bigger than MaxDatagramSize. In this case, it -/// returns an error and doesn't send anything. This applies -/// to both raw data and packets. Indeed, even packets are -/// unable to split and recompose data, due to the unreliability -/// of the protocol (dropped, mixed or duplicated datagrams may -/// lead to a big mess when trying to recompose a packet). -/// -/// If the socket is bound to a port, it is automatically -/// unbound from it when the socket is destroyed. However, -/// you can unbind the socket explicitely with the Unbind -/// function if necessary, to stop receiving messages or -/// make the port available for other sockets. -/// -/// Usage example: -/// \code -/// // ----- The client ----- -/// -/// // Create a socket and bind it to the port 55001 -/// sf::UdpSocket socket; -/// socket.bind(55001); -/// -/// // Send a message to 192.168.1.50 on port 55002 -/// std::string message = "Hi, I am " + sf::IpAddress::getLocalAddress().toString(); -/// socket.send(message.c_str(), message.size() + 1, "192.168.1.50", 55002); -/// -/// // Receive an answer (most likely from 192.168.1.50, but could be anyone else) -/// char buffer[1024]; -/// std::size_t received = 0; -/// sf::IpAddress sender; -/// unsigned short port; -/// socket.receive(buffer, sizeof(buffer), received, sender, port); -/// std::cout << sender.ToString() << " said: " << buffer << std::endl; -/// -/// // ----- The server ----- -/// -/// // Create a socket and bind it to the port 55002 -/// sf::UdpSocket socket; -/// socket.bind(55002); -/// -/// // Receive a message from anyone -/// char buffer[1024]; -/// std::size_t received = 0; -/// sf::IpAddress sender; -/// unsigned short port; -/// socket.receive(buffer, sizeof(buffer), received, sender, port); -/// std::cout << sender.ToString() << " said: " << buffer << std::endl; -/// -/// // Send an answer -/// std::string message = "Welcome " + sender.toString(); -/// socket.send(message.c_str(), message.size() + 1, sender, port); -/// \endcode -/// -/// \see sf::Socket, sf::TcpSocket, sf::Packet -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_UDPSOCKET_HPP +#define SFML_UDPSOCKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class IpAddress; +class Packet; + +//////////////////////////////////////////////////////////// +/// \brief Specialized socket using the UDP protocol +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API UdpSocket : public Socket +{ +public: + + //////////////////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////////////////// + enum + { + MaxDatagramSize = 65507 ///< The maximum number of bytes that can be sent in a single UDP datagram + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + UdpSocket(); + + //////////////////////////////////////////////////////////// + /// \brief Get the port to which the socket is bound locally + /// + /// If the socket is not bound to a port, this function + /// returns 0. + /// + /// \return Port to which the socket is bound + /// + /// \see bind + /// + //////////////////////////////////////////////////////////// + unsigned short getLocalPort() const; + + //////////////////////////////////////////////////////////// + /// \brief Bind the socket to a specific port + /// + /// Binding the socket to a port is necessary for being + /// able to receive data on that port. + /// You can use the special value Socket::AnyPort to tell the + /// system to automatically pick an available port, and then + /// call getLocalPort to retrieve the chosen port. + /// + /// \param port Port to bind the socket to + /// + /// \return Status code + /// + /// \see unbind, getLocalPort + /// + //////////////////////////////////////////////////////////// + Status bind(unsigned short port); + + //////////////////////////////////////////////////////////// + /// \brief Unbind the socket from the local port to which it is bound + /// + /// The port that the socket was previously using is immediately + /// available after this function is called. If the + /// socket is not bound to a port, this function has no effect. + /// + /// \see bind + /// + //////////////////////////////////////////////////////////// + void unbind(); + + //////////////////////////////////////////////////////////// + /// \brief Send raw data to a remote peer + /// + /// Make sure that \a size is not greater than + /// UdpSocket::MaxDatagramSize, otherwise this function will + /// fail and no data will be sent. + /// + /// \param data Pointer to the sequence of bytes to send + /// \param size Number of bytes to send + /// \param remoteAddress Address of the receiver + /// \param remotePort Port of the receiver to send the data to + /// + /// \return Status code + /// + /// \see receive + /// + //////////////////////////////////////////////////////////// + Status send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort); + + //////////////////////////////////////////////////////////// + /// \brief Receive raw data from a remote peer + /// + /// In blocking mode, this function will wait until some + /// bytes are actually received. + /// Be careful to use a buffer which is large enough for + /// the data that you intend to receive, if it is too small + /// then an error will be returned and *all* the data will + /// be lost. + /// + /// \param data Pointer to the array to fill with the received bytes + /// \param size Maximum number of bytes that can be received + /// \param received This variable is filled with the actual number of bytes received + /// \param remoteAddress Address of the peer that sent the data + /// \param remotePort Port of the peer that sent the data + /// + /// \return Status code + /// + /// \see send + /// + //////////////////////////////////////////////////////////// + Status receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort); + + //////////////////////////////////////////////////////////// + /// \brief Send a formatted packet of data to a remote peer + /// + /// Make sure that the packet size is not greater than + /// UdpSocket::MaxDatagramSize, otherwise this function will + /// fail and no data will be sent. + /// + /// \param packet Packet to send + /// \param remoteAddress Address of the receiver + /// \param remotePort Port of the receiver to send the data to + /// + /// \return Status code + /// + /// \see receive + /// + //////////////////////////////////////////////////////////// + Status send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort); + + //////////////////////////////////////////////////////////// + /// \brief Receive a formatted packet of data from a remote peer + /// + /// In blocking mode, this function will wait until the whole packet + /// has been received. + /// + /// \param packet Packet to fill with the received data + /// \param remoteAddress Address of the peer that sent the data + /// \param remotePort Port of the peer that sent the data + /// + /// \return Status code + /// + /// \see send + /// + //////////////////////////////////////////////////////////// + Status receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector m_buffer; ///< Temporary buffer holding the received data in Receive(Packet) +}; + +} // namespace sf + + +#endif // SFML_UDPSOCKET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::UdpSocket +/// \ingroup network +/// +/// A UDP socket is a connectionless socket. Instead of +/// connecting once to a remote host, like TCP sockets, +/// it can send to and receive from any host at any time. +/// +/// It is a datagram protocol: bounded blocks of data (datagrams) +/// are transfered over the network rather than a continuous +/// stream of data (TCP). Therefore, one call to send will always +/// match one call to receive (if the datagram is not lost), +/// with the same data that was sent. +/// +/// The UDP protocol is lightweight but unreliable. Unreliable +/// means that datagrams may be duplicated, be lost or +/// arrive reordered. However, if a datagram arrives, its +/// data is guaranteed to be valid. +/// +/// UDP is generally used for real-time communication +/// (audio or video streaming, real-time games, etc.) where +/// speed is crucial and lost data doesn't matter much. +/// +/// Sending and receiving data can use either the low-level +/// or the high-level functions. The low-level functions +/// process a raw sequence of bytes, whereas the high-level +/// interface uses packets (see sf::Packet), which are easier +/// to use and provide more safety regarding the data that is +/// exchanged. You can look at the sf::Packet class to get +/// more details about how they work. +/// +/// It is important to note that UdpSocket is unable to send +/// datagrams bigger than MaxDatagramSize. In this case, it +/// returns an error and doesn't send anything. This applies +/// to both raw data and packets. Indeed, even packets are +/// unable to split and recompose data, due to the unreliability +/// of the protocol (dropped, mixed or duplicated datagrams may +/// lead to a big mess when trying to recompose a packet). +/// +/// If the socket is bound to a port, it is automatically +/// unbound from it when the socket is destroyed. However, +/// you can unbind the socket explicitely with the Unbind +/// function if necessary, to stop receiving messages or +/// make the port available for other sockets. +/// +/// Usage example: +/// \code +/// // ----- The client ----- +/// +/// // Create a socket and bind it to the port 55001 +/// sf::UdpSocket socket; +/// socket.bind(55001); +/// +/// // Send a message to 192.168.1.50 on port 55002 +/// std::string message = "Hi, I am " + sf::IpAddress::getLocalAddress().toString(); +/// socket.send(message.c_str(), message.size() + 1, "192.168.1.50", 55002); +/// +/// // Receive an answer (most likely from 192.168.1.50, but could be anyone else) +/// char buffer[1024]; +/// std::size_t received = 0; +/// sf::IpAddress sender; +/// unsigned short port; +/// socket.receive(buffer, sizeof(buffer), received, sender, port); +/// std::cout << sender.ToString() << " said: " << buffer << std::endl; +/// +/// // ----- The server ----- +/// +/// // Create a socket and bind it to the port 55002 +/// sf::UdpSocket socket; +/// socket.bind(55002); +/// +/// // Receive a message from anyone +/// char buffer[1024]; +/// std::size_t received = 0; +/// sf::IpAddress sender; +/// unsigned short port; +/// socket.receive(buffer, sizeof(buffer), received, sender, port); +/// std::cout << sender.ToString() << " said: " << buffer << std::endl; +/// +/// // Send an answer +/// std::string message = "Welcome " + sender.toString(); +/// socket.send(message.c_str(), message.size() + 1, sender, port); +/// \endcode +/// +/// \see sf::Socket, sf::TcpSocket, sf::Packet +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/OpenGL.hpp b/include/SFML/OpenGL.hpp index 3295eb9b..00bdd8eb 100644 --- a/include/SFML/OpenGL.hpp +++ b/include/SFML/OpenGL.hpp @@ -1,77 +1,77 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_OPENGL_HPP -#define SFML_OPENGL_HPP - - -//////////////////////////////////////////////////////////// -/// Headers -//////////////////////////////////////////////////////////// -#include - - -//////////////////////////////////////////////////////////// -/// This file just includes the OpenGL (GL and GLU) headers, -/// which have actually different paths on each system -//////////////////////////////////////////////////////////// -#if defined(SFML_SYSTEM_WINDOWS) - - // The Visual C++ version of gl.h uses WINGDIAPI and APIENTRY but doesn't define them - #ifdef _MSC_VER - #include - #endif - - #include - #include - -#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) - - #if defined(SFML_OPENGL_ES) - #include - #include - #else - #include - #include - #endif - -#elif defined(SFML_SYSTEM_MACOS) - - #include - #include - -#elif defined (SFML_SYSTEM_IOS) - - #include - #include - -#elif defined (SFML_SYSTEM_ANDROID) - - #include - #include - -#endif - - -#endif // SFML_OPENGL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_OPENGL_HPP +#define SFML_OPENGL_HPP + + +//////////////////////////////////////////////////////////// +/// Headers +//////////////////////////////////////////////////////////// +#include + + +//////////////////////////////////////////////////////////// +/// This file just includes the OpenGL (GL and GLU) headers, +/// which have actually different paths on each system +//////////////////////////////////////////////////////////// +#if defined(SFML_SYSTEM_WINDOWS) + + // The Visual C++ version of gl.h uses WINGDIAPI and APIENTRY but doesn't define them + #ifdef _MSC_VER + #include + #endif + + #include + #include + +#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) + + #if defined(SFML_OPENGL_ES) + #include + #include + #else + #include + #include + #endif + +#elif defined(SFML_SYSTEM_MACOS) + + #include + #include + +#elif defined (SFML_SYSTEM_IOS) + + #include + #include + +#elif defined (SFML_SYSTEM_ANDROID) + + #include + #include + +#endif + + +#endif // SFML_OPENGL_HPP diff --git a/include/SFML/System.hpp b/include/SFML/System.hpp index 221320f9..675fbb0a 100644 --- a/include/SFML/System.hpp +++ b/include/SFML/System.hpp @@ -1,56 +1,56 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SYSTEM_HPP -#define SFML_SYSTEM_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif // SFML_SYSTEM_HPP - -//////////////////////////////////////////////////////////// -/// \defgroup system System module -/// -/// Base module of SFML, defining various utilities. It provides -/// vector classes, unicode strings and conversion functions, -/// threads and mutexes, timing classes. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SYSTEM_HPP +#define SFML_SYSTEM_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // SFML_SYSTEM_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup system System module +/// +/// Base module of SFML, defining various utilities. It provides +/// vector classes, unicode strings and conversion functions, +/// threads and mutexes, timing classes. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Clock.hpp b/include/SFML/System/Clock.hpp index 6e7023ea..1ff63cb4 100644 --- a/include/SFML/System/Clock.hpp +++ b/include/SFML/System/Clock.hpp @@ -1,117 +1,117 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_CLOCK_HPP -#define SFML_CLOCK_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Utility class that measures the elapsed time -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API Clock -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// The clock starts automatically after being constructed. - /// - //////////////////////////////////////////////////////////// - Clock(); - - //////////////////////////////////////////////////////////// - /// \brief Get the elapsed time - /// - /// This function returns the time elapsed since the last call - /// to restart() (or the construction of the instance if restart() - /// has not been called). - /// - /// \return Time elapsed - /// - //////////////////////////////////////////////////////////// - Time getElapsedTime() const; - - //////////////////////////////////////////////////////////// - /// \brief Restart the clock - /// - /// This function puts the time counter back to zero. - /// It also returns the time elapsed since the clock was started. - /// - /// \return Time elapsed - /// - //////////////////////////////////////////////////////////// - Time restart(); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Time m_startTime; ///< Time of last reset, in microseconds -}; - -} // namespace sf - - -#endif // SFML_CLOCK_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Clock -/// \ingroup system -/// -/// sf::Clock is a lightweight class for measuring time. -/// -/// Its provides the most precise time that the underlying -/// OS can achieve (generally microseconds or nanoseconds). -/// It also ensures monotonicity, which means that the returned -/// time can never go backward, even if the system time is -/// changed. -/// -/// Usage example: -/// \code -/// sf::Clock clock; -/// ... -/// Time time1 = clock.getElapsedTime(); -/// ... -/// Time time2 = clock.restart(); -/// \endcode -/// -/// The sf::Time value returned by the clock can then be -/// converted to a number of seconds, milliseconds or even -/// microseconds. -/// -/// \see sf::Time -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CLOCK_HPP +#define SFML_CLOCK_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility class that measures the elapsed time +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API Clock +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// The clock starts automatically after being constructed. + /// + //////////////////////////////////////////////////////////// + Clock(); + + //////////////////////////////////////////////////////////// + /// \brief Get the elapsed time + /// + /// This function returns the time elapsed since the last call + /// to restart() (or the construction of the instance if restart() + /// has not been called). + /// + /// \return Time elapsed + /// + //////////////////////////////////////////////////////////// + Time getElapsedTime() const; + + //////////////////////////////////////////////////////////// + /// \brief Restart the clock + /// + /// This function puts the time counter back to zero. + /// It also returns the time elapsed since the clock was started. + /// + /// \return Time elapsed + /// + //////////////////////////////////////////////////////////// + Time restart(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Time m_startTime; ///< Time of last reset, in microseconds +}; + +} // namespace sf + + +#endif // SFML_CLOCK_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Clock +/// \ingroup system +/// +/// sf::Clock is a lightweight class for measuring time. +/// +/// Its provides the most precise time that the underlying +/// OS can achieve (generally microseconds or nanoseconds). +/// It also ensures monotonicity, which means that the returned +/// time can never go backward, even if the system time is +/// changed. +/// +/// Usage example: +/// \code +/// sf::Clock clock; +/// ... +/// Time time1 = clock.getElapsedTime(); +/// ... +/// Time time2 = clock.restart(); +/// \endcode +/// +/// The sf::Time value returned by the clock can then be +/// converted to a number of seconds, milliseconds or even +/// microseconds. +/// +/// \see sf::Time +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Err.hpp b/include/SFML/System/Err.hpp index 3e845add..74d56f26 100644 --- a/include/SFML/System/Err.hpp +++ b/include/SFML/System/Err.hpp @@ -1,80 +1,80 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_ERR_HPP -#define SFML_ERR_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Standard stream used by SFML to output warnings and errors -/// -//////////////////////////////////////////////////////////// -SFML_SYSTEM_API std::ostream& err(); - -} // namespace sf - - -#endif // SFML_ERR_HPP - - -//////////////////////////////////////////////////////////// -/// \fn sf::err -/// \ingroup system -/// -/// By default, sf::err() outputs to the same location as std::cerr, -/// (-> the stderr descriptor) which is the console if there's -/// one available. -/// -/// It is a standard std::ostream instance, so it supports all the -/// insertion operations defined by the STL -/// (operator <<, manipulators, etc.). -/// -/// sf::err() can be redirected to write to another output, independently -/// of std::cerr, by using the rdbuf() function provided by the -/// std::ostream class. -/// -/// Example: -/// \code -/// // Redirect to a file -/// std::ofstream file("sfml-log.txt"); -/// std::streambuf* previous = sf::err().rdbuf(file.rdbuf()); -/// -/// // Redirect to nothing -/// sf::err().rdbuf(NULL); -/// -/// // Restore the original output -/// sf::err().rdbuf(previous); -/// \endcode -/// -/// \return Reference to std::ostream representing the SFML error stream -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_ERR_HPP +#define SFML_ERR_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Standard stream used by SFML to output warnings and errors +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API std::ostream& err(); + +} // namespace sf + + +#endif // SFML_ERR_HPP + + +//////////////////////////////////////////////////////////// +/// \fn sf::err +/// \ingroup system +/// +/// By default, sf::err() outputs to the same location as std::cerr, +/// (-> the stderr descriptor) which is the console if there's +/// one available. +/// +/// It is a standard std::ostream instance, so it supports all the +/// insertion operations defined by the STL +/// (operator <<, manipulators, etc.). +/// +/// sf::err() can be redirected to write to another output, independently +/// of std::cerr, by using the rdbuf() function provided by the +/// std::ostream class. +/// +/// Example: +/// \code +/// // Redirect to a file +/// std::ofstream file("sfml-log.txt"); +/// std::streambuf* previous = sf::err().rdbuf(file.rdbuf()); +/// +/// // Redirect to nothing +/// sf::err().rdbuf(NULL); +/// +/// // Restore the original output +/// sf::err().rdbuf(previous); +/// \endcode +/// +/// \return Reference to std::ostream representing the SFML error stream +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/InputStream.hpp b/include/SFML/System/InputStream.hpp index fb587e7a..ccf1d9ff 100644 --- a/include/SFML/System/InputStream.hpp +++ b/include/SFML/System/InputStream.hpp @@ -39,7 +39,7 @@ namespace sf //////////////////////////////////////////////////////////// class InputStream { -public : +public: //////////////////////////////////////////////////////////// /// \brief Virtual destructor @@ -114,7 +114,7 @@ public : /// // custom stream class that reads from inside a zip file /// class ZipStream : public sf::InputStream /// { -/// public : +/// public: /// /// ZipStream(std::string archive); /// @@ -128,7 +128,7 @@ public : /// /// Int64 getSize(); /// -/// private : +/// private: /// /// ... /// }; diff --git a/include/SFML/System/Lock.hpp b/include/SFML/System/Lock.hpp index d5b8bdf2..84810e77 100644 --- a/include/SFML/System/Lock.hpp +++ b/include/SFML/System/Lock.hpp @@ -1,139 +1,139 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_LOCK_HPP -#define SFML_LOCK_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -class Mutex; - -//////////////////////////////////////////////////////////// -/// \brief Automatic wrapper for locking and unlocking mutexes -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API Lock : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Construct the lock with a target mutex - /// - /// The mutex passed to sf::Lock is automatically locked. - /// - /// \param mutex Mutex to lock - /// - //////////////////////////////////////////////////////////// - explicit Lock(Mutex& mutex); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - /// The destructor of sf::Lock automatically unlocks its mutex. - /// - //////////////////////////////////////////////////////////// - ~Lock(); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Mutex& m_mutex; ///< Mutex to lock / unlock -}; - -} // namespace sf - - -#endif // SFML_LOCK_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Lock -/// \ingroup system -/// -/// sf::Lock is a RAII wrapper for sf::Mutex. By unlocking -/// it in its destructor, it ensures that the mutex will -/// always be released when the current scope (most likely -/// a function) ends. -/// This is even more important when an exception or an early -/// return statement can interrupt the execution flow of the -/// function. -/// -/// For maximum robustness, sf::Lock should always be used -/// to lock/unlock a mutex. -/// -/// Usage example: -/// \code -/// sf::Mutex mutex; -/// -/// void function() -/// { -/// sf::Lock lock(mutex); // mutex is now locked -/// -/// functionThatMayThrowAnException(); // mutex is unlocked if this function throws -/// -/// if (someCondition) -/// return; // mutex is unlocked -/// -/// } // mutex is unlocked -/// \endcode -/// -/// Because the mutex is not explicitely unlocked in the code, -/// it may remain locked longer than needed. If the region -/// of the code that needs to be protected by the mutex is -/// not the entire function, a good practice is to create a -/// smaller, inner scope so that the lock is limited to this -/// part of the code. -/// -/// \code -/// sf::Mutex mutex; -/// -/// void function() -/// { -/// { -/// sf::Lock lock(mutex); -/// codeThatRequiresProtection(); -/// -/// } // mutex is unlocked here -/// -/// codeThatDoesntCareAboutTheMutex(); -/// } -/// \endcode -/// -/// Having a mutex locked longer than required is a bad practice -/// which can lead to bad performances. Don't forget that when -/// a mutex is locked, other threads may be waiting doing nothing -/// until it is released. -/// -/// \see sf::Mutex -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_LOCK_HPP +#define SFML_LOCK_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +class Mutex; + +//////////////////////////////////////////////////////////// +/// \brief Automatic wrapper for locking and unlocking mutexes +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API Lock : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Construct the lock with a target mutex + /// + /// The mutex passed to sf::Lock is automatically locked. + /// + /// \param mutex Mutex to lock + /// + //////////////////////////////////////////////////////////// + explicit Lock(Mutex& mutex); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// The destructor of sf::Lock automatically unlocks its mutex. + /// + //////////////////////////////////////////////////////////// + ~Lock(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Mutex& m_mutex; ///< Mutex to lock / unlock +}; + +} // namespace sf + + +#endif // SFML_LOCK_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Lock +/// \ingroup system +/// +/// sf::Lock is a RAII wrapper for sf::Mutex. By unlocking +/// it in its destructor, it ensures that the mutex will +/// always be released when the current scope (most likely +/// a function) ends. +/// This is even more important when an exception or an early +/// return statement can interrupt the execution flow of the +/// function. +/// +/// For maximum robustness, sf::Lock should always be used +/// to lock/unlock a mutex. +/// +/// Usage example: +/// \code +/// sf::Mutex mutex; +/// +/// void function() +/// { +/// sf::Lock lock(mutex); // mutex is now locked +/// +/// functionThatMayThrowAnException(); // mutex is unlocked if this function throws +/// +/// if (someCondition) +/// return; // mutex is unlocked +/// +/// } // mutex is unlocked +/// \endcode +/// +/// Because the mutex is not explicitely unlocked in the code, +/// it may remain locked longer than needed. If the region +/// of the code that needs to be protected by the mutex is +/// not the entire function, a good practice is to create a +/// smaller, inner scope so that the lock is limited to this +/// part of the code. +/// +/// \code +/// sf::Mutex mutex; +/// +/// void function() +/// { +/// { +/// sf::Lock lock(mutex); +/// codeThatRequiresProtection(); +/// +/// } // mutex is unlocked here +/// +/// codeThatDoesntCareAboutTheMutex(); +/// } +/// \endcode +/// +/// Having a mutex locked longer than required is a bad practice +/// which can lead to bad performances. Don't forget that when +/// a mutex is locked, other threads may be waiting doing nothing +/// until it is released. +/// +/// \see sf::Mutex +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Mutex.hpp b/include/SFML/System/Mutex.hpp index f8c73244..2bee74dc 100644 --- a/include/SFML/System/Mutex.hpp +++ b/include/SFML/System/Mutex.hpp @@ -1,148 +1,148 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_MUTEX_HPP -#define SFML_MUTEX_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ - class MutexImpl; -} - -//////////////////////////////////////////////////////////// -/// \brief Blocks concurrent access to shared resources -/// from multiple threads -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API Mutex : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - Mutex(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~Mutex(); - - //////////////////////////////////////////////////////////// - /// \brief Lock the mutex - /// - /// If the mutex is already locked in another thread, - /// this call will block the execution until the mutex - /// is released. - /// - /// \see unlock - /// - //////////////////////////////////////////////////////////// - void lock(); - - //////////////////////////////////////////////////////////// - /// \brief Unlock the mutex - /// - /// \see lock - /// - //////////////////////////////////////////////////////////// - void unlock(); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - priv::MutexImpl* m_mutexImpl; ///< OS-specific implementation -}; - -} // namespace sf - - -#endif // SFML_MUTEX_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Mutex -/// \ingroup system -/// -/// Mutex stands for "MUTual EXclusion". A mutex is a -/// synchronization object, used when multiple threads are involved. -/// -/// When you want to protect a part of the code from being accessed -/// simultaneously by multiple threads, you typically use a -/// mutex. When a thread is locked by a mutex, any other thread -/// trying to lock it will be blocked until the mutex is released -/// by the thread that locked it. This way, you can allow only -/// one thread at a time to access a critical region of your code. -/// -/// Usage example: -/// \code -/// Database database; // this is a critical resource that needs some protection -/// sf::Mutex mutex; -/// -/// void thread1() -/// { -/// mutex.lock(); // this call will block the thread if the mutex is already locked by thread2 -/// database.write(...); -/// mutex.unlock(); // if thread2 was waiting, it will now be unblocked -/// } -/// -/// void thread2() -/// { -/// mutex.lock(); // this call will block the thread if the mutex is already locked by thread1 -/// database.write(...); -/// mutex.unlock(); // if thread1 was waiting, it will now be unblocked -/// } -/// \endcode -/// -/// Be very careful with mutexes. A bad usage can lead to bad problems, -/// like deadlocks (two threads are waiting for each other and the -/// application is globally stuck). -/// -/// To make the usage of mutexes more robust, particularly in -/// environments where exceptions can be thrown, you should -/// use the helper class sf::Lock to lock/unlock mutexes. -/// -/// SFML mutexes are recursive, which means that you can lock -/// a mutex multiple times in the same thread without creating -/// a deadlock. In this case, the first call to lock() behaves -/// as usual, and the following ones have no effect. -/// However, you must call unlock() exactly as many times as you -/// called lock(). If you don't, the mutex won't be released. -/// -/// \see sf::Lock -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_MUTEX_HPP +#define SFML_MUTEX_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ + class MutexImpl; +} + +//////////////////////////////////////////////////////////// +/// \brief Blocks concurrent access to shared resources +/// from multiple threads +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API Mutex : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Mutex(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Mutex(); + + //////////////////////////////////////////////////////////// + /// \brief Lock the mutex + /// + /// If the mutex is already locked in another thread, + /// this call will block the execution until the mutex + /// is released. + /// + /// \see unlock + /// + //////////////////////////////////////////////////////////// + void lock(); + + //////////////////////////////////////////////////////////// + /// \brief Unlock the mutex + /// + /// \see lock + /// + //////////////////////////////////////////////////////////// + void unlock(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::MutexImpl* m_mutexImpl; ///< OS-specific implementation +}; + +} // namespace sf + + +#endif // SFML_MUTEX_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Mutex +/// \ingroup system +/// +/// Mutex stands for "MUTual EXclusion". A mutex is a +/// synchronization object, used when multiple threads are involved. +/// +/// When you want to protect a part of the code from being accessed +/// simultaneously by multiple threads, you typically use a +/// mutex. When a thread is locked by a mutex, any other thread +/// trying to lock it will be blocked until the mutex is released +/// by the thread that locked it. This way, you can allow only +/// one thread at a time to access a critical region of your code. +/// +/// Usage example: +/// \code +/// Database database; // this is a critical resource that needs some protection +/// sf::Mutex mutex; +/// +/// void thread1() +/// { +/// mutex.lock(); // this call will block the thread if the mutex is already locked by thread2 +/// database.write(...); +/// mutex.unlock(); // if thread2 was waiting, it will now be unblocked +/// } +/// +/// void thread2() +/// { +/// mutex.lock(); // this call will block the thread if the mutex is already locked by thread1 +/// database.write(...); +/// mutex.unlock(); // if thread1 was waiting, it will now be unblocked +/// } +/// \endcode +/// +/// Be very careful with mutexes. A bad usage can lead to bad problems, +/// like deadlocks (two threads are waiting for each other and the +/// application is globally stuck). +/// +/// To make the usage of mutexes more robust, particularly in +/// environments where exceptions can be thrown, you should +/// use the helper class sf::Lock to lock/unlock mutexes. +/// +/// SFML mutexes are recursive, which means that you can lock +/// a mutex multiple times in the same thread without creating +/// a deadlock. In this case, the first call to lock() behaves +/// as usual, and the following ones have no effect. +/// However, you must call unlock() exactly as many times as you +/// called lock(). If you don't, the mutex won't be released. +/// +/// \see sf::Lock +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/NonCopyable.hpp b/include/SFML/System/NonCopyable.hpp index 58e33e55..81c17945 100644 --- a/include/SFML/System/NonCopyable.hpp +++ b/include/SFML/System/NonCopyable.hpp @@ -1,119 +1,119 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_NONCOPYABLE_HPP -#define SFML_NONCOPYABLE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Utility class that makes any derived -/// class non-copyable -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API NonCopyable -{ -protected : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Because this class has a copy constructor, the compiler - /// will not automatically generate the default constructor. - /// That's why we must define it explicitely. - /// - //////////////////////////////////////////////////////////// - NonCopyable() {} - -private : - - //////////////////////////////////////////////////////////// - /// \brief Disabled copy constructor - /// - /// By making the copy constructor private, the compiler will - /// trigger an error if anyone outside tries to use it. - /// To prevent NonCopyable or friend classes from using it, - /// we also give no definition, so that the linker will - /// produce an error if the first protection was inefficient. - /// - //////////////////////////////////////////////////////////// - NonCopyable(const NonCopyable&); - - //////////////////////////////////////////////////////////// - /// \brief Disabled assignment operator - /// - /// By making the assignment operator private, the compiler will - /// trigger an error if anyone outside tries to use it. - /// To prevent NonCopyable or friend classes from using it, - /// we also give no definition, so that the linker will - /// produce an error if the first protection was inefficient. - /// - //////////////////////////////////////////////////////////// - NonCopyable& operator =(const NonCopyable&); -}; - -} // namespace sf - - -#endif // SFML_NONCOPYABLE_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::NonCopyable -/// \ingroup system -/// -/// This class makes its instances non-copyable, by explicitely -/// disabling its copy constructor and its assignment operator. -/// -/// To create a non-copyable class, simply inherit from -/// sf::NonCopyable. -/// -/// The type of inheritance (public or private) doesn't matter, -/// the copy constructor and assignment operator are declared private -/// in sf::NonCopyable so they will end up being inaccessible in both -/// cases. Thus you can use a shorter syntax for inheriting from it -/// (see below). -/// -/// Usage example: -/// \code -/// class MyNonCopyableClass : sf::NonCopyable -/// { -/// ... -/// }; -/// \endcode -/// -/// Deciding whether the instances of a class can be copied -/// or not is a very important design choice. You are strongly -/// encouraged to think about it before writing a class, -/// and to use sf::NonCopyable when necessary to prevent -/// many potential future errors when using it. This is also -/// a very important indication to users of your class. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_NONCOPYABLE_HPP +#define SFML_NONCOPYABLE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility class that makes any derived +/// class non-copyable +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API NonCopyable +{ +protected: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Because this class has a copy constructor, the compiler + /// will not automatically generate the default constructor. + /// That's why we must define it explicitely. + /// + //////////////////////////////////////////////////////////// + NonCopyable() {} + +private: + + //////////////////////////////////////////////////////////// + /// \brief Disabled copy constructor + /// + /// By making the copy constructor private, the compiler will + /// trigger an error if anyone outside tries to use it. + /// To prevent NonCopyable or friend classes from using it, + /// we also give no definition, so that the linker will + /// produce an error if the first protection was inefficient. + /// + //////////////////////////////////////////////////////////// + NonCopyable(const NonCopyable&); + + //////////////////////////////////////////////////////////// + /// \brief Disabled assignment operator + /// + /// By making the assignment operator private, the compiler will + /// trigger an error if anyone outside tries to use it. + /// To prevent NonCopyable or friend classes from using it, + /// we also give no definition, so that the linker will + /// produce an error if the first protection was inefficient. + /// + //////////////////////////////////////////////////////////// + NonCopyable& operator =(const NonCopyable&); +}; + +} // namespace sf + + +#endif // SFML_NONCOPYABLE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::NonCopyable +/// \ingroup system +/// +/// This class makes its instances non-copyable, by explicitely +/// disabling its copy constructor and its assignment operator. +/// +/// To create a non-copyable class, simply inherit from +/// sf::NonCopyable. +/// +/// The type of inheritance (public or private) doesn't matter, +/// the copy constructor and assignment operator are declared private +/// in sf::NonCopyable so they will end up being inaccessible in both +/// cases. Thus you can use a shorter syntax for inheriting from it +/// (see below). +/// +/// Usage example: +/// \code +/// class MyNonCopyableClass : sf::NonCopyable +/// { +/// ... +/// }; +/// \endcode +/// +/// Deciding whether the instances of a class can be copied +/// or not is a very important design choice. You are strongly +/// encouraged to think about it before writing a class, +/// and to use sf::NonCopyable when necessary to prevent +/// many potential future errors when using it. This is also +/// a very important indication to users of your class. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Sleep.hpp b/include/SFML/System/Sleep.hpp index 27097aa5..fd7fb5ad 100644 --- a/include/SFML/System/Sleep.hpp +++ b/include/SFML/System/Sleep.hpp @@ -1,52 +1,52 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SLEEP_HPP -#define SFML_SLEEP_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \ingroup system -/// \brief Make the current thread sleep for a given duration -/// -/// sf::sleep is the best way to block a program or one of its -/// threads, as it doesn't consume any CPU power. -/// -/// \param duration Time to sleep -/// -//////////////////////////////////////////////////////////// -void SFML_SYSTEM_API sleep(Time duration); - -} // namespace sf - - -#endif // SFML_SLEEP_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SLEEP_HPP +#define SFML_SLEEP_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \ingroup system +/// \brief Make the current thread sleep for a given duration +/// +/// sf::sleep is the best way to block a program or one of its +/// threads, as it doesn't consume any CPU power. +/// +/// \param duration Time to sleep +/// +//////////////////////////////////////////////////////////// +void SFML_SYSTEM_API sleep(Time duration); + +} // namespace sf + + +#endif // SFML_SLEEP_HPP diff --git a/include/SFML/System/String.hpp b/include/SFML/System/String.hpp index 53d85fcf..19351d8e 100644 --- a/include/SFML/System/String.hpp +++ b/include/SFML/System/String.hpp @@ -1,668 +1,668 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_STRING_HPP -#define SFML_STRING_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Utility string class that automatically handles -/// conversions between types and encodings -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API String -{ -public : - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef std::basic_string::iterator Iterator; ///< Iterator type - typedef std::basic_string::const_iterator ConstIterator; ///< Constant iterator type - - //////////////////////////////////////////////////////////// - // Static member data - //////////////////////////////////////////////////////////// - static const std::size_t InvalidPos; ///< Represents an invalid position in the string - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor creates an empty string. - /// - //////////////////////////////////////////////////////////// - String(); - - //////////////////////////////////////////////////////////// - /// \brief Construct from a single ANSI character and a locale - /// - /// The source character is converted to UTF-32 according - /// to the given locale. - /// - /// \param ansiChar ANSI character to convert - /// \param locale Locale to use for conversion - /// - //////////////////////////////////////////////////////////// - String(char ansiChar, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Construct from single wide character - /// - /// \param wideChar Wide character to convert - /// - //////////////////////////////////////////////////////////// - String(wchar_t wideChar); - - //////////////////////////////////////////////////////////// - /// \brief Construct from single UTF-32 character - /// - /// \param utf32Char UTF-32 character to convert - /// - //////////////////////////////////////////////////////////// - String(Uint32 utf32Char); - - //////////////////////////////////////////////////////////// - /// \brief Construct from a null-terminated C-style ANSI string and a locale - /// - /// The source string is converted to UTF-32 according - /// to the given locale. - /// - /// \param ansiString ANSI string to convert - /// \param locale Locale to use for conversion - /// - //////////////////////////////////////////////////////////// - String(const char* ansiString, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Construct from an ANSI string and a locale - /// - /// The source string is converted to UTF-32 according - /// to the given locale. - /// - /// \param ansiString ANSI string to convert - /// \param locale Locale to use for conversion - /// - //////////////////////////////////////////////////////////// - String(const std::string& ansiString, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Construct from null-terminated C-style wide string - /// - /// \param wideString Wide string to convert - /// - //////////////////////////////////////////////////////////// - String(const wchar_t* wideString); - - //////////////////////////////////////////////////////////// - /// \brief Construct from a wide string - /// - /// \param wideString Wide string to convert - /// - //////////////////////////////////////////////////////////// - String(const std::wstring& wideString); - - //////////////////////////////////////////////////////////// - /// \brief Construct from a null-terminated C-style UTF-32 string - /// - /// \param utf32String UTF-32 string to assign - /// - //////////////////////////////////////////////////////////// - String(const Uint32* utf32String); - - //////////////////////////////////////////////////////////// - /// \brief Construct from an UTF-32 string - /// - /// \param utf32String UTF-32 string to assign - /// - //////////////////////////////////////////////////////////// - String(const std::basic_string& utf32String); - - //////////////////////////////////////////////////////////// - /// \brief Copy constructor - /// - /// \param copy Instance to copy - /// - //////////////////////////////////////////////////////////// - String(const String& copy); - - //////////////////////////////////////////////////////////// - /// \brief Create a new sf::String from a UTF-8 encoded string - /// - /// \param begin Forward iterator to the begining of the UTF-8 sequence - /// \param end Forward iterator to the end of the UTF-8 sequence - /// - /// \return A sf::String containing the source string - /// - /// \see fromUtf16, fromUtf32 - /// - //////////////////////////////////////////////////////////// - template - static String fromUtf8(T begin, T end); - - //////////////////////////////////////////////////////////// - /// \brief Create a new sf::String from a UTF-16 encoded string - /// - /// \param begin Forward iterator to the begining of the UTF-16 sequence - /// \param end Forward iterator to the end of the UTF-16 sequence - /// - /// \return A sf::String containing the source string - /// - /// \see fromUtf8, fromUtf32 - /// - //////////////////////////////////////////////////////////// - template - static String fromUtf16(T begin, T end); - - //////////////////////////////////////////////////////////// - /// \brief Create a new sf::String from a UTF-32 encoded string - /// - /// This function is provided for consistency, it is equivalent to - /// using the constructors that takes a const sf::Uint32* or - /// a std::basic_string. - /// - /// \param begin Forward iterator to the begining of the UTF-32 sequence - /// \param end Forward iterator to the end of the UTF-32 sequence - /// - /// \return A sf::String containing the source string - /// - /// \see fromUtf8, fromUtf16 - /// - //////////////////////////////////////////////////////////// - template - static String fromUtf32(T begin, T end); - - //////////////////////////////////////////////////////////// - /// \brief Implicit cast operator to std::string (ANSI string) - /// - /// The current global locale is used for conversion. If you - /// want to explicitely specify a locale, see toAnsiString. - /// Characters that do not fit in the target encoding are - /// discarded from the returned string. - /// This operator is defined for convenience, and is equivalent - /// to calling toAnsiString(). - /// - /// \return Converted ANSI string - /// - /// \see toAnsiString, operator std::wstring - /// - //////////////////////////////////////////////////////////// - operator std::string() const; - - //////////////////////////////////////////////////////////// - /// \brief Implicit cast operator to std::wstring (wide string) - /// - /// Characters that do not fit in the target encoding are - /// discarded from the returned string. - /// This operator is defined for convenience, and is equivalent - /// to calling toWideString(). - /// - /// \return Converted wide string - /// - /// \see toWideString, operator std::string - /// - //////////////////////////////////////////////////////////// - operator std::wstring() const; - - //////////////////////////////////////////////////////////// - /// \brief Convert the unicode string to an ANSI string - /// - /// The UTF-32 string is converted to an ANSI string in - /// the encoding defined by \a locale. - /// Characters that do not fit in the target encoding are - /// discarded from the returned string. - /// - /// \param locale Locale to use for conversion - /// - /// \return Converted ANSI string - /// - /// \see toWideString, operator std::string - /// - //////////////////////////////////////////////////////////// - std::string toAnsiString(const std::locale& locale = std::locale()) const; - - //////////////////////////////////////////////////////////// - /// \brief Convert the unicode string to a wide string - /// - /// Characters that do not fit in the target encoding are - /// discarded from the returned string. - /// - /// \return Converted wide string - /// - /// \see toAnsiString, operator std::wstring - /// - //////////////////////////////////////////////////////////// - std::wstring toWideString() const; - - //////////////////////////////////////////////////////////// - /// \brief Convert the unicode string to a UTF-8 string - /// - /// \return Converted UTF-8 string - /// - /// \see toUtf16, toUtf32 - /// - //////////////////////////////////////////////////////////// - std::basic_string toUtf8() const; - - //////////////////////////////////////////////////////////// - /// \brief Convert the unicode string to a UTF-16 string - /// - /// \return Converted UTF-16 string - /// - /// \see toUtf8, toUtf32 - /// - //////////////////////////////////////////////////////////// - std::basic_string toUtf16() const; - - //////////////////////////////////////////////////////////// - /// \brief Convert the unicode string to a UTF-32 string - /// - /// This function doesn't perform any conversion, since the - /// string is already stored as UTF-32 internally. - /// - /// \return Converted UTF-32 string - /// - /// \see toUtf8, toUtf16 - /// - //////////////////////////////////////////////////////////// - std::basic_string toUtf32() const; - - //////////////////////////////////////////////////////////// - /// \brief Overload of assignment operator - /// - /// \param right Instance to assign - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - String& operator =(const String& right); - - //////////////////////////////////////////////////////////// - /// \brief Overload of += operator to append an UTF-32 string - /// - /// \param right String to append - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - String& operator +=(const String& right); - - //////////////////////////////////////////////////////////// - /// \brief Overload of [] operator to access a character by its position - /// - /// This function provides read-only access to characters. - /// Note: this function doesn't throw if \a index is out of range. - /// - /// \param index Index of the character to get - /// - /// \return Character at position \a index - /// - //////////////////////////////////////////////////////////// - Uint32 operator [](std::size_t index) const; - - //////////////////////////////////////////////////////////// - /// \brief Overload of [] operator to access a character by its position - /// - /// This function provides read and write access to characters. - /// Note: this function doesn't throw if \a index is out of range. - /// - /// \param index Index of the character to get - /// - /// \return Reference to the character at position \a index - /// - //////////////////////////////////////////////////////////// - Uint32& operator [](std::size_t index); - - //////////////////////////////////////////////////////////// - /// \brief Clear the string - /// - /// This function removes all the characters from the string. - /// - /// \see isEmpty, erase - /// - //////////////////////////////////////////////////////////// - void clear(); - - //////////////////////////////////////////////////////////// - /// \brief Get the size of the string - /// - /// \return Number of characters in the string - /// - /// \see isEmpty - /// - //////////////////////////////////////////////////////////// - std::size_t getSize() const; - - //////////////////////////////////////////////////////////// - /// \brief Check whether the string is empty or not - /// - /// \return True if the string is empty (i.e. contains no character) - /// - /// \see clear, getSize - /// - //////////////////////////////////////////////////////////// - bool isEmpty() const; - - //////////////////////////////////////////////////////////// - /// \brief Erase one or more characters from the string - /// - /// This function removes a sequence of \a count characters - /// starting from \a position. - /// - /// \param position Position of the first character to erase - /// \param count Number of characters to erase - /// - //////////////////////////////////////////////////////////// - void erase(std::size_t position, std::size_t count = 1); - - //////////////////////////////////////////////////////////// - /// \brief Insert one or more characters into the string - /// - /// This function inserts the characters of \a str - /// into the string, starting from \a position. - /// - /// \param position Position of insertion - /// \param str Characters to insert - /// - //////////////////////////////////////////////////////////// - void insert(std::size_t position, const String& str); - - //////////////////////////////////////////////////////////// - /// \brief Find a sequence of one or more characters in the string - /// - /// This function searches for the characters of \a str - /// into the string, starting from \a start. - /// - /// \param str Characters to find - /// \param start Where to begin searching - /// - /// \return Position of \a str in the string, or String::InvalidPos if not found - /// - //////////////////////////////////////////////////////////// - std::size_t find(const String& str, std::size_t start = 0) const; - - //////////////////////////////////////////////////////////// - /// \brief Replace a substring with another string - /// - /// This function replaces the substring that starts at index \a position - /// and spans \a length characters with the string \a replaceWith. - /// - /// \param position Index of the first character to be replaced - /// \param length Number of characters to replace. You can pass InvalidPos to - /// replace all characters until the end of the string. - /// \param replaceWith String that replaces the given substring. - /// - //////////////////////////////////////////////////////////// - void replace(std::size_t position, std::size_t length, const String& replaceWith); - - //////////////////////////////////////////////////////////// - /// \brief Replace all occurrences of a substring with a replacement string - /// - /// This function replaces all occurences of \a searchFor in this string - /// with the string \a replaceWith. - /// - /// \param searchFor The value being searched for - /// \param replaceWith The value that replaces found \a searchFor values - /// - //////////////////////////////////////////////////////////// - void replace(const String& searchFor, const String& replaceWith); - - //////////////////////////////////////////////////////////// - /// \brief Return a part of the string - /// - /// This function returns the substring that starts at index \a position - /// and spans \a length characters. - /// - /// \param position Index of the first character - /// \param length Number of characters to include in the substring (if - /// the string is shorter, as many characters as possible - /// are included). \ref InvalidPos can be used to include all - /// characters until the end of the string. - /// - /// \return String object containing a substring of this object - /// - //////////////////////////////////////////////////////////// - String substring(std::size_t position, std::size_t length = InvalidPos) const; - - //////////////////////////////////////////////////////////// - /// \brief Get a pointer to the C-style array of characters - /// - /// This functions provides a read-only access to a - /// null-terminated C-style representation of the string. - /// The returned pointer is temporary and is meant only for - /// immediate use, thus it is not recommended to store it. - /// - /// \return Read-only pointer to the array of characters - /// - //////////////////////////////////////////////////////////// - const Uint32* getData() const; - - //////////////////////////////////////////////////////////// - /// \brief Return an iterator to the beginning of the string - /// - /// \return Read-write iterator to the beginning of the string characters - /// - /// \see end - /// - //////////////////////////////////////////////////////////// - Iterator begin(); - - //////////////////////////////////////////////////////////// - /// \brief Return an iterator to the beginning of the string - /// - /// \return Read-only iterator to the beginning of the string characters - /// - /// \see end - /// - //////////////////////////////////////////////////////////// - ConstIterator begin() const; - - //////////////////////////////////////////////////////////// - /// \brief Return an iterator to the beginning of the string - /// - /// The end iterator refers to 1 position past the last character; - /// thus it represents an invalid character and should never be - /// accessed. - /// - /// \return Read-write iterator to the end of the string characters - /// - /// \see begin - /// - //////////////////////////////////////////////////////////// - Iterator end(); - - //////////////////////////////////////////////////////////// - /// \brief Return an iterator to the beginning of the string - /// - /// The end iterator refers to 1 position past the last character; - /// thus it represents an invalid character and should never be - /// accessed. - /// - /// \return Read-only iterator to the end of the string characters - /// - /// \see begin - /// - //////////////////////////////////////////////////////////// - ConstIterator end() const; - -private : - - friend SFML_SYSTEM_API bool operator ==(const String& left, const String& right); - friend SFML_SYSTEM_API bool operator <(const String& left, const String& right); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - std::basic_string m_string; ///< Internal string of UTF-32 characters -}; - -//////////////////////////////////////////////////////////// -/// \relates String -/// \brief Overload of == operator to compare two UTF-32 strings -/// -/// \param left Left operand (a string) -/// \param right Right operand (a string) -/// -/// \return True if both strings are equal -/// -//////////////////////////////////////////////////////////// -SFML_SYSTEM_API bool operator ==(const String& left, const String& right); - -//////////////////////////////////////////////////////////// -/// \relates String -/// \brief Overload of != operator to compare two UTF-32 strings -/// -/// \param left Left operand (a string) -/// \param right Right operand (a string) -/// -/// \return True if both strings are different -/// -//////////////////////////////////////////////////////////// -SFML_SYSTEM_API bool operator !=(const String& left, const String& right); - -//////////////////////////////////////////////////////////// -/// \relates String -/// \brief Overload of < operator to compare two UTF-32 strings -/// -/// \param left Left operand (a string) -/// \param right Right operand (a string) -/// -/// \return True if \a left is alphabetically lesser than \a right -/// -//////////////////////////////////////////////////////////// -SFML_SYSTEM_API bool operator <(const String& left, const String& right); - -//////////////////////////////////////////////////////////// -/// \relates String -/// \brief Overload of > operator to compare two UTF-32 strings -/// -/// \param left Left operand (a string) -/// \param right Right operand (a string) -/// -/// \return True if \a left is alphabetically greater than \a right -/// -//////////////////////////////////////////////////////////// -SFML_SYSTEM_API bool operator >(const String& left, const String& right); - -//////////////////////////////////////////////////////////// -/// \relates String -/// \brief Overload of <= operator to compare two UTF-32 strings -/// -/// \param left Left operand (a string) -/// \param right Right operand (a string) -/// -/// \return True if \a left is alphabetically lesser or equal than \a right -/// -//////////////////////////////////////////////////////////// -SFML_SYSTEM_API bool operator <=(const String& left, const String& right); - -//////////////////////////////////////////////////////////// -/// \relates String -/// \brief Overload of >= operator to compare two UTF-32 strings -/// -/// \param left Left operand (a string) -/// \param right Right operand (a string) -/// -/// \return True if \a left is alphabetically greater or equal than \a right -/// -//////////////////////////////////////////////////////////// -SFML_SYSTEM_API bool operator >=(const String& left, const String& right); - -//////////////////////////////////////////////////////////// -/// \relates String -/// \brief Overload of binary + operator to concatenate two strings -/// -/// \param left Left operand (a string) -/// \param right Right operand (a string) -/// -/// \return Concatenated string -/// -//////////////////////////////////////////////////////////// -SFML_SYSTEM_API String operator +(const String& left, const String& right); - -#include - -} // namespace sf - - -#endif // SFML_STRING_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::String -/// \ingroup system -/// -/// sf::String is a utility string class defined mainly for -/// convenience. It is a Unicode string (implemented using -/// UTF-32), thus it can store any character in the world -/// (european, chinese, arabic, hebrew, etc.). -/// -/// It automatically handles conversions from/to ANSI and -/// wide strings, so that you can work with standard string -/// classes and still be compatible with functions taking a -/// sf::String. -/// -/// \code -/// sf::String s; -/// -/// std::string s1 = s; // automatically converted to ANSI string -/// std::wstring s2 = s; // automatically converted to wide string -/// s = "hello"; // automatically converted from ANSI string -/// s = L"hello"; // automatically converted from wide string -/// s += 'a'; // automatically converted from ANSI string -/// s += L'a'; // automatically converted from wide string -/// \endcode -/// -/// Conversions involving ANSI strings use the default user locale. However -/// it is possible to use a custom locale if necessary: -/// \code -/// std::locale locale; -/// sf::String s; -/// ... -/// std::string s1 = s.toAnsiString(locale); -/// s = sf::String("hello", locale); -/// \endcode -/// -/// sf::String defines the most important functions of the -/// standard std::string class: removing, random access, iterating, -/// appending, comparing, etc. However it is a simple class -/// provided for convenience, and you may have to consider using -/// a more optimized class if your program requires complex string -/// handling. The automatic conversion functions will then take -/// care of converting your string to sf::String whenever SFML -/// requires it. -/// -/// Please note that SFML also defines a low-level, generic -/// interface for Unicode handling, see the sf::Utf classes. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_STRING_HPP +#define SFML_STRING_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility string class that automatically handles +/// conversions between types and encodings +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API String +{ +public: + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::basic_string::iterator Iterator; ///< Iterator type + typedef std::basic_string::const_iterator ConstIterator; ///< Constant iterator type + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const std::size_t InvalidPos; ///< Represents an invalid position in the string + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor creates an empty string. + /// + //////////////////////////////////////////////////////////// + String(); + + //////////////////////////////////////////////////////////// + /// \brief Construct from a single ANSI character and a locale + /// + /// The source character is converted to UTF-32 according + /// to the given locale. + /// + /// \param ansiChar ANSI character to convert + /// \param locale Locale to use for conversion + /// + //////////////////////////////////////////////////////////// + String(char ansiChar, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Construct from single wide character + /// + /// \param wideChar Wide character to convert + /// + //////////////////////////////////////////////////////////// + String(wchar_t wideChar); + + //////////////////////////////////////////////////////////// + /// \brief Construct from single UTF-32 character + /// + /// \param utf32Char UTF-32 character to convert + /// + //////////////////////////////////////////////////////////// + String(Uint32 utf32Char); + + //////////////////////////////////////////////////////////// + /// \brief Construct from a null-terminated C-style ANSI string and a locale + /// + /// The source string is converted to UTF-32 according + /// to the given locale. + /// + /// \param ansiString ANSI string to convert + /// \param locale Locale to use for conversion + /// + //////////////////////////////////////////////////////////// + String(const char* ansiString, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Construct from an ANSI string and a locale + /// + /// The source string is converted to UTF-32 according + /// to the given locale. + /// + /// \param ansiString ANSI string to convert + /// \param locale Locale to use for conversion + /// + //////////////////////////////////////////////////////////// + String(const std::string& ansiString, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Construct from null-terminated C-style wide string + /// + /// \param wideString Wide string to convert + /// + //////////////////////////////////////////////////////////// + String(const wchar_t* wideString); + + //////////////////////////////////////////////////////////// + /// \brief Construct from a wide string + /// + /// \param wideString Wide string to convert + /// + //////////////////////////////////////////////////////////// + String(const std::wstring& wideString); + + //////////////////////////////////////////////////////////// + /// \brief Construct from a null-terminated C-style UTF-32 string + /// + /// \param utf32String UTF-32 string to assign + /// + //////////////////////////////////////////////////////////// + String(const Uint32* utf32String); + + //////////////////////////////////////////////////////////// + /// \brief Construct from an UTF-32 string + /// + /// \param utf32String UTF-32 string to assign + /// + //////////////////////////////////////////////////////////// + String(const std::basic_string& utf32String); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + String(const String& copy); + + //////////////////////////////////////////////////////////// + /// \brief Create a new sf::String from a UTF-8 encoded string + /// + /// \param begin Forward iterator to the begining of the UTF-8 sequence + /// \param end Forward iterator to the end of the UTF-8 sequence + /// + /// \return A sf::String containing the source string + /// + /// \see fromUtf16, fromUtf32 + /// + //////////////////////////////////////////////////////////// + template + static String fromUtf8(T begin, T end); + + //////////////////////////////////////////////////////////// + /// \brief Create a new sf::String from a UTF-16 encoded string + /// + /// \param begin Forward iterator to the begining of the UTF-16 sequence + /// \param end Forward iterator to the end of the UTF-16 sequence + /// + /// \return A sf::String containing the source string + /// + /// \see fromUtf8, fromUtf32 + /// + //////////////////////////////////////////////////////////// + template + static String fromUtf16(T begin, T end); + + //////////////////////////////////////////////////////////// + /// \brief Create a new sf::String from a UTF-32 encoded string + /// + /// This function is provided for consistency, it is equivalent to + /// using the constructors that takes a const sf::Uint32* or + /// a std::basic_string. + /// + /// \param begin Forward iterator to the begining of the UTF-32 sequence + /// \param end Forward iterator to the end of the UTF-32 sequence + /// + /// \return A sf::String containing the source string + /// + /// \see fromUtf8, fromUtf16 + /// + //////////////////////////////////////////////////////////// + template + static String fromUtf32(T begin, T end); + + //////////////////////////////////////////////////////////// + /// \brief Implicit cast operator to std::string (ANSI string) + /// + /// The current global locale is used for conversion. If you + /// want to explicitely specify a locale, see toAnsiString. + /// Characters that do not fit in the target encoding are + /// discarded from the returned string. + /// This operator is defined for convenience, and is equivalent + /// to calling toAnsiString(). + /// + /// \return Converted ANSI string + /// + /// \see toAnsiString, operator std::wstring + /// + //////////////////////////////////////////////////////////// + operator std::string() const; + + //////////////////////////////////////////////////////////// + /// \brief Implicit cast operator to std::wstring (wide string) + /// + /// Characters that do not fit in the target encoding are + /// discarded from the returned string. + /// This operator is defined for convenience, and is equivalent + /// to calling toWideString(). + /// + /// \return Converted wide string + /// + /// \see toWideString, operator std::string + /// + //////////////////////////////////////////////////////////// + operator std::wstring() const; + + //////////////////////////////////////////////////////////// + /// \brief Convert the unicode string to an ANSI string + /// + /// The UTF-32 string is converted to an ANSI string in + /// the encoding defined by \a locale. + /// Characters that do not fit in the target encoding are + /// discarded from the returned string. + /// + /// \param locale Locale to use for conversion + /// + /// \return Converted ANSI string + /// + /// \see toWideString, operator std::string + /// + //////////////////////////////////////////////////////////// + std::string toAnsiString(const std::locale& locale = std::locale()) const; + + //////////////////////////////////////////////////////////// + /// \brief Convert the unicode string to a wide string + /// + /// Characters that do not fit in the target encoding are + /// discarded from the returned string. + /// + /// \return Converted wide string + /// + /// \see toAnsiString, operator std::wstring + /// + //////////////////////////////////////////////////////////// + std::wstring toWideString() const; + + //////////////////////////////////////////////////////////// + /// \brief Convert the unicode string to a UTF-8 string + /// + /// \return Converted UTF-8 string + /// + /// \see toUtf16, toUtf32 + /// + //////////////////////////////////////////////////////////// + std::basic_string toUtf8() const; + + //////////////////////////////////////////////////////////// + /// \brief Convert the unicode string to a UTF-16 string + /// + /// \return Converted UTF-16 string + /// + /// \see toUtf8, toUtf32 + /// + //////////////////////////////////////////////////////////// + std::basic_string toUtf16() const; + + //////////////////////////////////////////////////////////// + /// \brief Convert the unicode string to a UTF-32 string + /// + /// This function doesn't perform any conversion, since the + /// string is already stored as UTF-32 internally. + /// + /// \return Converted UTF-32 string + /// + /// \see toUtf8, toUtf16 + /// + //////////////////////////////////////////////////////////// + std::basic_string toUtf32() const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + String& operator =(const String& right); + + //////////////////////////////////////////////////////////// + /// \brief Overload of += operator to append an UTF-32 string + /// + /// \param right String to append + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + String& operator +=(const String& right); + + //////////////////////////////////////////////////////////// + /// \brief Overload of [] operator to access a character by its position + /// + /// This function provides read-only access to characters. + /// Note: this function doesn't throw if \a index is out of range. + /// + /// \param index Index of the character to get + /// + /// \return Character at position \a index + /// + //////////////////////////////////////////////////////////// + Uint32 operator [](std::size_t index) const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of [] operator to access a character by its position + /// + /// This function provides read and write access to characters. + /// Note: this function doesn't throw if \a index is out of range. + /// + /// \param index Index of the character to get + /// + /// \return Reference to the character at position \a index + /// + //////////////////////////////////////////////////////////// + Uint32& operator [](std::size_t index); + + //////////////////////////////////////////////////////////// + /// \brief Clear the string + /// + /// This function removes all the characters from the string. + /// + /// \see isEmpty, erase + /// + //////////////////////////////////////////////////////////// + void clear(); + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the string + /// + /// \return Number of characters in the string + /// + /// \see isEmpty + /// + //////////////////////////////////////////////////////////// + std::size_t getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Check whether the string is empty or not + /// + /// \return True if the string is empty (i.e. contains no character) + /// + /// \see clear, getSize + /// + //////////////////////////////////////////////////////////// + bool isEmpty() const; + + //////////////////////////////////////////////////////////// + /// \brief Erase one or more characters from the string + /// + /// This function removes a sequence of \a count characters + /// starting from \a position. + /// + /// \param position Position of the first character to erase + /// \param count Number of characters to erase + /// + //////////////////////////////////////////////////////////// + void erase(std::size_t position, std::size_t count = 1); + + //////////////////////////////////////////////////////////// + /// \brief Insert one or more characters into the string + /// + /// This function inserts the characters of \a str + /// into the string, starting from \a position. + /// + /// \param position Position of insertion + /// \param str Characters to insert + /// + //////////////////////////////////////////////////////////// + void insert(std::size_t position, const String& str); + + //////////////////////////////////////////////////////////// + /// \brief Find a sequence of one or more characters in the string + /// + /// This function searches for the characters of \a str + /// into the string, starting from \a start. + /// + /// \param str Characters to find + /// \param start Where to begin searching + /// + /// \return Position of \a str in the string, or String::InvalidPos if not found + /// + //////////////////////////////////////////////////////////// + std::size_t find(const String& str, std::size_t start = 0) const; + + //////////////////////////////////////////////////////////// + /// \brief Replace a substring with another string + /// + /// This function replaces the substring that starts at index \a position + /// and spans \a length characters with the string \a replaceWith. + /// + /// \param position Index of the first character to be replaced + /// \param length Number of characters to replace. You can pass InvalidPos to + /// replace all characters until the end of the string. + /// \param replaceWith String that replaces the given substring. + /// + //////////////////////////////////////////////////////////// + void replace(std::size_t position, std::size_t length, const String& replaceWith); + + //////////////////////////////////////////////////////////// + /// \brief Replace all occurrences of a substring with a replacement string + /// + /// This function replaces all occurences of \a searchFor in this string + /// with the string \a replaceWith. + /// + /// \param searchFor The value being searched for + /// \param replaceWith The value that replaces found \a searchFor values + /// + //////////////////////////////////////////////////////////// + void replace(const String& searchFor, const String& replaceWith); + + //////////////////////////////////////////////////////////// + /// \brief Return a part of the string + /// + /// This function returns the substring that starts at index \a position + /// and spans \a length characters. + /// + /// \param position Index of the first character + /// \param length Number of characters to include in the substring (if + /// the string is shorter, as many characters as possible + /// are included). \ref InvalidPos can be used to include all + /// characters until the end of the string. + /// + /// \return String object containing a substring of this object + /// + //////////////////////////////////////////////////////////// + String substring(std::size_t position, std::size_t length = InvalidPos) const; + + //////////////////////////////////////////////////////////// + /// \brief Get a pointer to the C-style array of characters + /// + /// This functions provides a read-only access to a + /// null-terminated C-style representation of the string. + /// The returned pointer is temporary and is meant only for + /// immediate use, thus it is not recommended to store it. + /// + /// \return Read-only pointer to the array of characters + /// + //////////////////////////////////////////////////////////// + const Uint32* getData() const; + + //////////////////////////////////////////////////////////// + /// \brief Return an iterator to the beginning of the string + /// + /// \return Read-write iterator to the beginning of the string characters + /// + /// \see end + /// + //////////////////////////////////////////////////////////// + Iterator begin(); + + //////////////////////////////////////////////////////////// + /// \brief Return an iterator to the beginning of the string + /// + /// \return Read-only iterator to the beginning of the string characters + /// + /// \see end + /// + //////////////////////////////////////////////////////////// + ConstIterator begin() const; + + //////////////////////////////////////////////////////////// + /// \brief Return an iterator to the beginning of the string + /// + /// The end iterator refers to 1 position past the last character; + /// thus it represents an invalid character and should never be + /// accessed. + /// + /// \return Read-write iterator to the end of the string characters + /// + /// \see begin + /// + //////////////////////////////////////////////////////////// + Iterator end(); + + //////////////////////////////////////////////////////////// + /// \brief Return an iterator to the beginning of the string + /// + /// The end iterator refers to 1 position past the last character; + /// thus it represents an invalid character and should never be + /// accessed. + /// + /// \return Read-only iterator to the end of the string characters + /// + /// \see begin + /// + //////////////////////////////////////////////////////////// + ConstIterator end() const; + +private: + + friend SFML_SYSTEM_API bool operator ==(const String& left, const String& right); + friend SFML_SYSTEM_API bool operator <(const String& left, const String& right); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::basic_string m_string; ///< Internal string of UTF-32 characters +}; + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of == operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if both strings are equal +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator ==(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of != operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if both strings are different +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator !=(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of < operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if \a left is alphabetically lesser than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator <(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of > operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if \a left is alphabetically greater than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator >(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of <= operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if \a left is alphabetically lesser or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator <=(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of >= operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if \a left is alphabetically greater or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator >=(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of binary + operator to concatenate two strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return Concatenated string +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API String operator +(const String& left, const String& right); + +#include + +} // namespace sf + + +#endif // SFML_STRING_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::String +/// \ingroup system +/// +/// sf::String is a utility string class defined mainly for +/// convenience. It is a Unicode string (implemented using +/// UTF-32), thus it can store any character in the world +/// (european, chinese, arabic, hebrew, etc.). +/// +/// It automatically handles conversions from/to ANSI and +/// wide strings, so that you can work with standard string +/// classes and still be compatible with functions taking a +/// sf::String. +/// +/// \code +/// sf::String s; +/// +/// std::string s1 = s; // automatically converted to ANSI string +/// std::wstring s2 = s; // automatically converted to wide string +/// s = "hello"; // automatically converted from ANSI string +/// s = L"hello"; // automatically converted from wide string +/// s += 'a'; // automatically converted from ANSI string +/// s += L'a'; // automatically converted from wide string +/// \endcode +/// +/// Conversions involving ANSI strings use the default user locale. However +/// it is possible to use a custom locale if necessary: +/// \code +/// std::locale locale; +/// sf::String s; +/// ... +/// std::string s1 = s.toAnsiString(locale); +/// s = sf::String("hello", locale); +/// \endcode +/// +/// sf::String defines the most important functions of the +/// standard std::string class: removing, random access, iterating, +/// appending, comparing, etc. However it is a simple class +/// provided for convenience, and you may have to consider using +/// a more optimized class if your program requires complex string +/// handling. The automatic conversion functions will then take +/// care of converting your string to sf::String whenever SFML +/// requires it. +/// +/// Please note that SFML also defines a low-level, generic +/// interface for Unicode handling, see the sf::Utf classes. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Thread.hpp b/include/SFML/System/Thread.hpp index c2b4eb2c..b9352a31 100644 --- a/include/SFML/System/Thread.hpp +++ b/include/SFML/System/Thread.hpp @@ -1,282 +1,282 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREAD_HPP -#define SFML_THREAD_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ - class ThreadImpl; - struct ThreadFunc; -} - -//////////////////////////////////////////////////////////// -/// \brief Utility class to manipulate threads -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API Thread : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Construct the thread from a functor with no argument - /// - /// This constructor works for function objects, as well - /// as free function. - /// - /// Use this constructor for this kind of function: - /// \code - /// void function(); - /// - /// // --- or ---- - /// - /// struct Functor - /// { - /// void operator()(); - /// }; - /// \endcode - /// Note: this does *not* run the thread, use Launch(). - /// - /// \param function Functor or free function to use as the entry point of the thread - /// - //////////////////////////////////////////////////////////// - template - Thread(F function); - - //////////////////////////////////////////////////////////// - /// \brief Construct the thread from a functor with an argument - /// - /// This constructor works for function objects, as well - /// as free function. - /// It is a template, which means that the argument can - /// have any type (int, std::string, void*, Toto, ...). - /// - /// Use this constructor for this kind of function: - /// \code - /// void function(int arg); - /// - /// // --- or ---- - /// - /// struct Functor - /// { - /// void operator()(std::string arg); - /// }; - /// \endcode - /// Note: this does *not* run the thread, use Launch(). - /// - /// \param function Functor or free function to use as the entry point of the thread - /// \param argument argument to forward to the function - /// - //////////////////////////////////////////////////////////// - template - Thread(F function, A argument); - - //////////////////////////////////////////////////////////// - /// \brief Construct the thread from a member function and an object - /// - /// This constructor is template, which means that you can - /// use it with any class. - /// Use this constructor for this kind of function: - /// \code - /// class MyClass - /// { - /// public : - /// - /// void function(); - /// }; - /// \endcode - /// Note: this does *not* run the thread, use Launch(). - /// - /// \param function Entry point of the thread - /// \param object Pointer to the object to use - /// - //////////////////////////////////////////////////////////// - template - Thread(void(C::*function)(), C* object); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - /// This destructor calls Wait(), so that the internal thread - /// cannot survive after its sf::Thread instance is destroyed. - /// - //////////////////////////////////////////////////////////// - ~Thread(); - - //////////////////////////////////////////////////////////// - /// \brief Run the thread - /// - /// This function starts the entry point passed to the - /// thread's constructor, and returns immediately. - /// After this function returns, the thread's function is - /// running in parallel to the calling code. - /// - //////////////////////////////////////////////////////////// - void launch(); - - //////////////////////////////////////////////////////////// - /// \brief Wait until the thread finishes - /// - /// This function will block the execution until the - /// thread's function ends. - /// Warning: if the thread function never ends, the calling - /// thread will block forever. - /// If this function is called from its owner thread, it - /// returns without doing anything. - /// - //////////////////////////////////////////////////////////// - void wait(); - - //////////////////////////////////////////////////////////// - /// \brief Terminate the thread - /// - /// This function immediately stops the thread, without waiting - /// for its function to finish. - /// Terminating a thread with this function is not safe, - /// and can lead to local variables not being destroyed - /// on some operating systems. You should rather try to make - /// the thread function terminate by itself. - /// - //////////////////////////////////////////////////////////// - void terminate(); - -private : - - friend class priv::ThreadImpl; - - //////////////////////////////////////////////////////////// - /// \brief Internal entry point of the thread - /// - /// This function is called by the thread implementation. - /// - //////////////////////////////////////////////////////////// - void run(); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - priv::ThreadImpl* m_impl; ///< OS-specific implementation of the thread - priv::ThreadFunc* m_entryPoint; ///< Abstraction of the function to run -}; - -#include - -} // namespace sf - -#endif // SFML_THREAD_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Thread -/// \ingroup system -/// -/// Threads provide a way to run multiple parts of the code -/// in parallel. When you launch a new thread, the execution -/// is split and both the new thread and the caller run -/// in parallel. -/// -/// To use a sf::Thread, you construct it directly with the -/// function to execute as the entry point of the thread. -/// sf::Thread has multiple template constructors, which means -/// that you can use several types of entry points: -/// \li non-member functions with no argument -/// \li non-member functions with one argument of any type -/// \li functors with no argument (this one is particularly useful for compatibility with boost/std::%bind) -/// \li functors with one argument of any type -/// \li member functions from any class with no argument -/// -/// The function argument, if any, is copied in the sf::Thread -/// instance, as well as the functor (if the corresponding -/// constructor is used). Class instances, however, are passed -/// by pointer so you must make sure that the object won't be -/// destroyed while the thread is still using it. -/// -/// The thread ends when its function is terminated. If the -/// owner sf::Thread instance is destroyed before the -/// thread is finished, the destructor will wait (see wait()) -/// -/// Usage examples: -/// \code -/// // example 1: non member function with one argument -/// -/// void threadFunc(int argument) -/// { -/// ... -/// } -/// -/// sf::Thread thread(&threadFunc, 5); -/// thread.launch(); // start the thread (internally calls threadFunc(5)) -/// \endcode -/// -/// \code -/// // example 2: member function -/// -/// class Task -/// { -/// public : -/// void run() -/// { -/// ... -/// } -/// }; -/// -/// Task task; -/// sf::Thread thread(&Task::run, &task); -/// thread.launch(); // start the thread (internally calls task.run()) -/// \endcode -/// -/// \code -/// // example 3: functor -/// -/// struct Task -/// { -/// void operator()() -/// { -/// ... -/// } -/// }; -/// -/// sf::Thread thread(Task()); -/// thread.launch(); // start the thread (internally calls operator() on the Task instance) -/// \endcode -/// -/// Creating parallel threads of execution can be dangerous: -/// all threads inside the same process share the same memory space, -/// which means that you may end up accessing the same variable -/// from multiple threads at the same time. To prevent this -/// kind of situations, you can use mutexes (see sf::Mutex). -/// -/// \see sf::Mutex -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_THREAD_HPP +#define SFML_THREAD_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class ThreadImpl; + struct ThreadFunc; +} + +//////////////////////////////////////////////////////////// +/// \brief Utility class to manipulate threads +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API Thread : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Construct the thread from a functor with no argument + /// + /// This constructor works for function objects, as well + /// as free function. + /// + /// Use this constructor for this kind of function: + /// \code + /// void function(); + /// + /// // --- or ---- + /// + /// struct Functor + /// { + /// void operator()(); + /// }; + /// \endcode + /// Note: this does *not* run the thread, use Launch(). + /// + /// \param function Functor or free function to use as the entry point of the thread + /// + //////////////////////////////////////////////////////////// + template + Thread(F function); + + //////////////////////////////////////////////////////////// + /// \brief Construct the thread from a functor with an argument + /// + /// This constructor works for function objects, as well + /// as free function. + /// It is a template, which means that the argument can + /// have any type (int, std::string, void*, Toto, ...). + /// + /// Use this constructor for this kind of function: + /// \code + /// void function(int arg); + /// + /// // --- or ---- + /// + /// struct Functor + /// { + /// void operator()(std::string arg); + /// }; + /// \endcode + /// Note: this does *not* run the thread, use Launch(). + /// + /// \param function Functor or free function to use as the entry point of the thread + /// \param argument argument to forward to the function + /// + //////////////////////////////////////////////////////////// + template + Thread(F function, A argument); + + //////////////////////////////////////////////////////////// + /// \brief Construct the thread from a member function and an object + /// + /// This constructor is template, which means that you can + /// use it with any class. + /// Use this constructor for this kind of function: + /// \code + /// class MyClass + /// { + /// public: + /// + /// void function(); + /// }; + /// \endcode + /// Note: this does *not* run the thread, use Launch(). + /// + /// \param function Entry point of the thread + /// \param object Pointer to the object to use + /// + //////////////////////////////////////////////////////////// + template + Thread(void(C::*function)(), C* object); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// This destructor calls Wait(), so that the internal thread + /// cannot survive after its sf::Thread instance is destroyed. + /// + //////////////////////////////////////////////////////////// + ~Thread(); + + //////////////////////////////////////////////////////////// + /// \brief Run the thread + /// + /// This function starts the entry point passed to the + /// thread's constructor, and returns immediately. + /// After this function returns, the thread's function is + /// running in parallel to the calling code. + /// + //////////////////////////////////////////////////////////// + void launch(); + + //////////////////////////////////////////////////////////// + /// \brief Wait until the thread finishes + /// + /// This function will block the execution until the + /// thread's function ends. + /// Warning: if the thread function never ends, the calling + /// thread will block forever. + /// If this function is called from its owner thread, it + /// returns without doing anything. + /// + //////////////////////////////////////////////////////////// + void wait(); + + //////////////////////////////////////////////////////////// + /// \brief Terminate the thread + /// + /// This function immediately stops the thread, without waiting + /// for its function to finish. + /// Terminating a thread with this function is not safe, + /// and can lead to local variables not being destroyed + /// on some operating systems. You should rather try to make + /// the thread function terminate by itself. + /// + //////////////////////////////////////////////////////////// + void terminate(); + +private: + + friend class priv::ThreadImpl; + + //////////////////////////////////////////////////////////// + /// \brief Internal entry point of the thread + /// + /// This function is called by the thread implementation. + /// + //////////////////////////////////////////////////////////// + void run(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::ThreadImpl* m_impl; ///< OS-specific implementation of the thread + priv::ThreadFunc* m_entryPoint; ///< Abstraction of the function to run +}; + +#include + +} // namespace sf + +#endif // SFML_THREAD_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Thread +/// \ingroup system +/// +/// Threads provide a way to run multiple parts of the code +/// in parallel. When you launch a new thread, the execution +/// is split and both the new thread and the caller run +/// in parallel. +/// +/// To use a sf::Thread, you construct it directly with the +/// function to execute as the entry point of the thread. +/// sf::Thread has multiple template constructors, which means +/// that you can use several types of entry points: +/// \li non-member functions with no argument +/// \li non-member functions with one argument of any type +/// \li functors with no argument (this one is particularly useful for compatibility with boost/std::%bind) +/// \li functors with one argument of any type +/// \li member functions from any class with no argument +/// +/// The function argument, if any, is copied in the sf::Thread +/// instance, as well as the functor (if the corresponding +/// constructor is used). Class instances, however, are passed +/// by pointer so you must make sure that the object won't be +/// destroyed while the thread is still using it. +/// +/// The thread ends when its function is terminated. If the +/// owner sf::Thread instance is destroyed before the +/// thread is finished, the destructor will wait (see wait()) +/// +/// Usage examples: +/// \code +/// // example 1: non member function with one argument +/// +/// void threadFunc(int argument) +/// { +/// ... +/// } +/// +/// sf::Thread thread(&threadFunc, 5); +/// thread.launch(); // start the thread (internally calls threadFunc(5)) +/// \endcode +/// +/// \code +/// // example 2: member function +/// +/// class Task +/// { +/// public: +/// void run() +/// { +/// ... +/// } +/// }; +/// +/// Task task; +/// sf::Thread thread(&Task::run, &task); +/// thread.launch(); // start the thread (internally calls task.run()) +/// \endcode +/// +/// \code +/// // example 3: functor +/// +/// struct Task +/// { +/// void operator()() +/// { +/// ... +/// } +/// }; +/// +/// sf::Thread thread(Task()); +/// thread.launch(); // start the thread (internally calls operator() on the Task instance) +/// \endcode +/// +/// Creating parallel threads of execution can be dangerous: +/// all threads inside the same process share the same memory space, +/// which means that you may end up accessing the same variable +/// from multiple threads at the same time. To prevent this +/// kind of situations, you can use mutexes (see sf::Mutex). +/// +/// \see sf::Mutex +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Thread.inl b/include/SFML/System/Thread.inl index 1c7fb5cf..9df4d2ca 100644 --- a/include/SFML/System/Thread.inl +++ b/include/SFML/System/Thread.inl @@ -1,90 +1,90 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -namespace priv -{ -// Base class for abstract thread functions -struct ThreadFunc -{ - virtual ~ThreadFunc() {} - virtual void run() = 0; -}; - -// Specialization using a functor (including free functions) with no argument -template -struct ThreadFunctor : ThreadFunc -{ - ThreadFunctor(T functor) : m_functor(functor) {} - virtual void run() {m_functor();} - T m_functor; -}; - -// Specialization using a functor (including free functions) with one argument -template -struct ThreadFunctorWithArg : ThreadFunc -{ - ThreadFunctorWithArg(F function, A arg) : m_function(function), m_arg(arg) {} - virtual void run() {m_function(m_arg);} - F m_function; - A m_arg; -}; - -// Specialization using a member function -template -struct ThreadMemberFunc : ThreadFunc -{ - ThreadMemberFunc(void(C::*function)(), C* object) : m_function(function), m_object(object) {} - virtual void run() {(m_object->*m_function)();} - void(C::*m_function)(); - C* m_object; -}; - -} // namespace priv - - -//////////////////////////////////////////////////////////// -template -Thread::Thread(F functor) : -m_impl (NULL), -m_entryPoint(new priv::ThreadFunctor(functor)) -{ -} - - -//////////////////////////////////////////////////////////// -template -Thread::Thread(F function, A argument) : -m_impl (NULL), -m_entryPoint(new priv::ThreadFunctorWithArg(function, argument)) -{ -} - - -//////////////////////////////////////////////////////////// -template -Thread::Thread(void(C::*function)(), C* object) : -m_impl (NULL), -m_entryPoint(new priv::ThreadMemberFunc(function, object)) -{ -} +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +namespace priv +{ +// Base class for abstract thread functions +struct ThreadFunc +{ + virtual ~ThreadFunc() {} + virtual void run() = 0; +}; + +// Specialization using a functor (including free functions) with no argument +template +struct ThreadFunctor : ThreadFunc +{ + ThreadFunctor(T functor) : m_functor(functor) {} + virtual void run() {m_functor();} + T m_functor; +}; + +// Specialization using a functor (including free functions) with one argument +template +struct ThreadFunctorWithArg : ThreadFunc +{ + ThreadFunctorWithArg(F function, A arg) : m_function(function), m_arg(arg) {} + virtual void run() {m_function(m_arg);} + F m_function; + A m_arg; +}; + +// Specialization using a member function +template +struct ThreadMemberFunc : ThreadFunc +{ + ThreadMemberFunc(void(C::*function)(), C* object) : m_function(function), m_object(object) {} + virtual void run() {(m_object->*m_function)();} + void(C::*m_function)(); + C* m_object; +}; + +} // namespace priv + + +//////////////////////////////////////////////////////////// +template +Thread::Thread(F functor) : +m_impl (NULL), +m_entryPoint(new priv::ThreadFunctor(functor)) +{ +} + + +//////////////////////////////////////////////////////////// +template +Thread::Thread(F function, A argument) : +m_impl (NULL), +m_entryPoint(new priv::ThreadFunctorWithArg(function, argument)) +{ +} + + +//////////////////////////////////////////////////////////// +template +Thread::Thread(void(C::*function)(), C* object) : +m_impl (NULL), +m_entryPoint(new priv::ThreadMemberFunc(function, object)) +{ +} diff --git a/include/SFML/System/ThreadLocal.hpp b/include/SFML/System/ThreadLocal.hpp index 11ed943c..755a842f 100644 --- a/include/SFML/System/ThreadLocal.hpp +++ b/include/SFML/System/ThreadLocal.hpp @@ -1,103 +1,103 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADLOCAL_HPP -#define SFML_THREADLOCAL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ - class ThreadLocalImpl; -} - -//////////////////////////////////////////////////////////// -/// \brief Defines variables with thread-local storage -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API ThreadLocal : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// \param value Optional value to initalize the variable - /// - //////////////////////////////////////////////////////////// - ThreadLocal(void* value = NULL); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~ThreadLocal(); - - //////////////////////////////////////////////////////////// - /// \brief Set the thread-specific value of the variable - /// - /// \param value Value of the variable for the current thread - /// - //////////////////////////////////////////////////////////// - void setValue(void* value); - - //////////////////////////////////////////////////////////// - /// \brief Retrieve the thread-specific value of the variable - /// - /// \return Value of the variable for the current thread - /// - //////////////////////////////////////////////////////////// - void* getValue() const; - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - priv::ThreadLocalImpl* m_impl; ///< Pointer to the OS specific implementation -}; - -} // namespace sf - - -#endif // SFML_THREADLOCAL_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::ThreadLocal -/// \ingroup system -/// -/// This class manipulates void* parameters and thus is not -/// appropriate for strongly-typed variables. You should rather -/// use the sf::ThreadLocalPtr template class. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_THREADLOCAL_HPP +#define SFML_THREADLOCAL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class ThreadLocalImpl; +} + +//////////////////////////////////////////////////////////// +/// \brief Defines variables with thread-local storage +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API ThreadLocal : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param value Optional value to initalize the variable + /// + //////////////////////////////////////////////////////////// + ThreadLocal(void* value = NULL); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~ThreadLocal(); + + //////////////////////////////////////////////////////////// + /// \brief Set the thread-specific value of the variable + /// + /// \param value Value of the variable for the current thread + /// + //////////////////////////////////////////////////////////// + void setValue(void* value); + + //////////////////////////////////////////////////////////// + /// \brief Retrieve the thread-specific value of the variable + /// + /// \return Value of the variable for the current thread + /// + //////////////////////////////////////////////////////////// + void* getValue() const; + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::ThreadLocalImpl* m_impl; ///< Pointer to the OS specific implementation +}; + +} // namespace sf + + +#endif // SFML_THREADLOCAL_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::ThreadLocal +/// \ingroup system +/// +/// This class manipulates void* parameters and thus is not +/// appropriate for strongly-typed variables. You should rather +/// use the sf::ThreadLocalPtr template class. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/ThreadLocalPtr.hpp b/include/SFML/System/ThreadLocalPtr.hpp index f51f908b..f51f5d6f 100644 --- a/include/SFML/System/ThreadLocalPtr.hpp +++ b/include/SFML/System/ThreadLocalPtr.hpp @@ -1,158 +1,158 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADLOCALPTR_HPP -#define SFML_THREADLOCALPTR_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Pointer to a thread-local variable -/// -//////////////////////////////////////////////////////////// -template -class ThreadLocalPtr : private ThreadLocal -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// \param value Optional value to initalize the variable - /// - //////////////////////////////////////////////////////////// - ThreadLocalPtr(T* value = NULL); - - //////////////////////////////////////////////////////////// - /// \brief Overload of unary operator * - /// - /// Like raw pointers, applying the * operator returns a - /// reference to the pointed object. - /// - /// \return Reference to the pointed object - /// - //////////////////////////////////////////////////////////// - T& operator *() const; - - //////////////////////////////////////////////////////////// - /// \brief Overload of operator -> - /// - /// Like raw pointers, applying the -> operator returns the - /// pointed object. - /// - /// \return Pointed object - /// - //////////////////////////////////////////////////////////// - T* operator ->() const; - - //////////////////////////////////////////////////////////// - /// \brief Cast operator to implicitely convert the - /// pointer to its raw pointer type (T*) - /// - /// \return Pointer to the actual object - /// - //////////////////////////////////////////////////////////// - operator T*() const; - - //////////////////////////////////////////////////////////// - /// \brief Assignment operator for a raw pointer parameter - /// - /// \param value Pointer to assign - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - ThreadLocalPtr& operator =(T* value); - - //////////////////////////////////////////////////////////// - /// \brief Assignment operator for a ThreadLocalPtr parameter - /// - /// \param right ThreadLocalPtr to assign - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - ThreadLocalPtr& operator =(const ThreadLocalPtr& right); -}; - -} // namespace sf - -#include - - -#endif // SFML_THREADLOCALPTR_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::ThreadLocalPtr -/// \ingroup system -/// -/// sf::ThreadLocalPtr is a type-safe wrapper for storing -/// pointers to thread-local variables. A thread-local -/// variable holds a different value for each different -/// thread, unlike normal variable that are shared. -/// -/// Its usage is completely transparent, so that it is similar -/// to manipulating the raw pointer directly (like any smart pointer). -/// -/// Usage example: -/// \code -/// MyClass object1; -/// MyClass object2; -/// sf::ThreadLocalPtr objectPtr; -/// -/// void thread1() -/// { -/// objectPtr = &object1; // doesn't impact thread2 -/// ... -/// } -/// -/// void thread2() -/// { -/// objectPtr = &object2; // doesn't impact thread1 -/// ... -/// } -/// -/// int main() -/// { -/// // Create and launch the two threads -/// sf::Thread t1(&thread1); -/// sf::Thread t2(&thread2); -/// t1.launch(); -/// t2.launch(); -/// -/// return 0; -/// } -/// \endcode -/// -/// ThreadLocalPtr is designed for internal use; however you -/// can use it if you feel like it fits well your implementation. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_THREADLOCALPTR_HPP +#define SFML_THREADLOCALPTR_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Pointer to a thread-local variable +/// +//////////////////////////////////////////////////////////// +template +class ThreadLocalPtr : private ThreadLocal +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param value Optional value to initalize the variable + /// + //////////////////////////////////////////////////////////// + ThreadLocalPtr(T* value = NULL); + + //////////////////////////////////////////////////////////// + /// \brief Overload of unary operator * + /// + /// Like raw pointers, applying the * operator returns a + /// reference to the pointed object. + /// + /// \return Reference to the pointed object + /// + //////////////////////////////////////////////////////////// + T& operator *() const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of operator -> + /// + /// Like raw pointers, applying the -> operator returns the + /// pointed object. + /// + /// \return Pointed object + /// + //////////////////////////////////////////////////////////// + T* operator ->() const; + + //////////////////////////////////////////////////////////// + /// \brief Cast operator to implicitely convert the + /// pointer to its raw pointer type (T*) + /// + /// \return Pointer to the actual object + /// + //////////////////////////////////////////////////////////// + operator T*() const; + + //////////////////////////////////////////////////////////// + /// \brief Assignment operator for a raw pointer parameter + /// + /// \param value Pointer to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + ThreadLocalPtr& operator =(T* value); + + //////////////////////////////////////////////////////////// + /// \brief Assignment operator for a ThreadLocalPtr parameter + /// + /// \param right ThreadLocalPtr to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + ThreadLocalPtr& operator =(const ThreadLocalPtr& right); +}; + +} // namespace sf + +#include + + +#endif // SFML_THREADLOCALPTR_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::ThreadLocalPtr +/// \ingroup system +/// +/// sf::ThreadLocalPtr is a type-safe wrapper for storing +/// pointers to thread-local variables. A thread-local +/// variable holds a different value for each different +/// thread, unlike normal variable that are shared. +/// +/// Its usage is completely transparent, so that it is similar +/// to manipulating the raw pointer directly (like any smart pointer). +/// +/// Usage example: +/// \code +/// MyClass object1; +/// MyClass object2; +/// sf::ThreadLocalPtr objectPtr; +/// +/// void thread1() +/// { +/// objectPtr = &object1; // doesn't impact thread2 +/// ... +/// } +/// +/// void thread2() +/// { +/// objectPtr = &object2; // doesn't impact thread1 +/// ... +/// } +/// +/// int main() +/// { +/// // Create and launch the two threads +/// sf::Thread t1(&thread1); +/// sf::Thread t2(&thread2); +/// t1.launch(); +/// t2.launch(); +/// +/// return 0; +/// } +/// \endcode +/// +/// ThreadLocalPtr is designed for internal use; however you +/// can use it if you feel like it fits well your implementation. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/ThreadLocalPtr.inl b/include/SFML/System/ThreadLocalPtr.inl index 3006f8d0..e378c621 100644 --- a/include/SFML/System/ThreadLocalPtr.inl +++ b/include/SFML/System/ThreadLocalPtr.inl @@ -1,77 +1,77 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - - -namespace sf -{ -//////////////////////////////////////////////////////////// -template -ThreadLocalPtr::ThreadLocalPtr(T* value) : -ThreadLocal(value) -{ -} - - -//////////////////////////////////////////////////////////// -template -T& ThreadLocalPtr::operator *() const -{ - return *static_cast(getValue()); -} - - -//////////////////////////////////////////////////////////// -template -T* ThreadLocalPtr::operator ->() const -{ - return static_cast(getValue()); -} - - -//////////////////////////////////////////////////////////// -template -ThreadLocalPtr::operator T*() const -{ - return static_cast(getValue()); -} - - -//////////////////////////////////////////////////////////// -template -ThreadLocalPtr& ThreadLocalPtr::operator =(T* value) -{ - setValue(value); - return *this; -} - - -//////////////////////////////////////////////////////////// -template -ThreadLocalPtr& ThreadLocalPtr::operator =(const ThreadLocalPtr& right) -{ - setValue(right.getValue()); - return *this; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +namespace sf +{ +//////////////////////////////////////////////////////////// +template +ThreadLocalPtr::ThreadLocalPtr(T* value) : +ThreadLocal(value) +{ +} + + +//////////////////////////////////////////////////////////// +template +T& ThreadLocalPtr::operator *() const +{ + return *static_cast(getValue()); +} + + +//////////////////////////////////////////////////////////// +template +T* ThreadLocalPtr::operator ->() const +{ + return static_cast(getValue()); +} + + +//////////////////////////////////////////////////////////// +template +ThreadLocalPtr::operator T*() const +{ + return static_cast(getValue()); +} + + +//////////////////////////////////////////////////////////// +template +ThreadLocalPtr& ThreadLocalPtr::operator =(T* value) +{ + setValue(value); + return *this; +} + + +//////////////////////////////////////////////////////////// +template +ThreadLocalPtr& ThreadLocalPtr::operator =(const ThreadLocalPtr& right) +{ + setValue(right.getValue()); + return *this; +} + +} // namespace sf diff --git a/include/SFML/System/Time.hpp b/include/SFML/System/Time.hpp index af87d147..1268afc3 100644 --- a/include/SFML/System/Time.hpp +++ b/include/SFML/System/Time.hpp @@ -39,7 +39,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_SYSTEM_API Time { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -84,7 +84,7 @@ public : //////////////////////////////////////////////////////////// static const Time Zero; ///< Predefined "zero" time value -private : +private: friend SFML_SYSTEM_API Time seconds(float); friend SFML_SYSTEM_API Time milliseconds(Int32); @@ -101,7 +101,7 @@ private : //////////////////////////////////////////////////////////// explicit Time(Int64 microseconds); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/include/SFML/System/Utf.hpp b/include/SFML/System/Utf.hpp index edb7ebb1..8ffae992 100644 --- a/include/SFML/System/Utf.hpp +++ b/include/SFML/System/Utf.hpp @@ -1,763 +1,763 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_UTF_HPP -#define SFML_UTF_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -template -class Utf; - -//////////////////////////////////////////////////////////// -/// \brief Specialization of the Utf template for UTF-8 -/// -//////////////////////////////////////////////////////////// -template <> -class Utf<8> -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Decode a single UTF-8 character - /// - /// Decoding a character means finding its unique 32-bits - /// code (called the codepoint) in the Unicode standard. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Codepoint of the decoded UTF-8 character - /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template - static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Encode a single UTF-8 character - /// - /// Encoding a character means converting a unique 32-bits - /// code (called the codepoint) in the target encoding, UTF-8. - /// - /// \param input Codepoint to encode as UTF-8 - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out encode(Uint32 input, Out output, Uint8 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Advance to the next UTF-8 character - /// - /// This function is necessary for multi-elements encodings, as - /// a single character may use more than 1 storage element. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template - static In next(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Count the number of characters of a UTF-8 sequence - /// - /// This function is necessary for multi-elements encodings, as - /// a single character may use more than 1 storage element, thus the - /// total size can be different from (begin - end). - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template - static std::size_t count(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Convert an ANSI characters range to UTF-8 - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Convert a wide characters range to UTF-8 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out fromWide(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out fromLatin1(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-8 characters range to ANSI characters - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-8 characters range to wide characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toWide(In begin, In end, Out output, wchar_t replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toLatin1(In begin, In end, Out output, char replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-8 characters range to UTF-8 - /// - /// This functions does nothing more than a direct copy; - /// it is defined only to provide the same interface as other - /// specializations of the sf::Utf<> template, and allow - /// generic code to be written on top of it. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toUtf8(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-8 characters range to UTF-16 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toUtf16(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-8 characters range to UTF-32 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toUtf32(In begin, In end, Out output); -}; - -//////////////////////////////////////////////////////////// -/// \brief Specialization of the Utf template for UTF-16 -/// -//////////////////////////////////////////////////////////// -template <> -class Utf<16> -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Decode a single UTF-16 character - /// - /// Decoding a character means finding its unique 32-bits - /// code (called the codepoint) in the Unicode standard. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Codepoint of the decoded UTF-16 character - /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template - static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Encode a single UTF-16 character - /// - /// Encoding a character means converting a unique 32-bits - /// code (called the codepoint) in the target encoding, UTF-16. - /// - /// \param input Codepoint to encode as UTF-16 - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out encode(Uint32 input, Out output, Uint16 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Advance to the next UTF-16 character - /// - /// This function is necessary for multi-elements encodings, as - /// a single character may use more than 1 storage element. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template - static In next(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Count the number of characters of a UTF-16 sequence - /// - /// This function is necessary for multi-elements encodings, as - /// a single character may use more than 1 storage element, thus the - /// total size can be different from (begin - end). - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template - static std::size_t count(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Convert an ANSI characters range to UTF-16 - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Convert a wide characters range to UTF-16 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out fromWide(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out fromLatin1(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-16 characters range to ANSI characters - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-16 characters range to wide characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toWide(In begin, In end, Out output, wchar_t replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toLatin1(In begin, In end, Out output, char replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-16 characters range to UTF-8 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toUtf8(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-16 characters range to UTF-16 - /// - /// This functions does nothing more than a direct copy; - /// it is defined only to provide the same interface as other - /// specializations of the sf::Utf<> template, and allow - /// generic code to be written on top of it. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toUtf16(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-16 characters range to UTF-32 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toUtf32(In begin, In end, Out output); -}; - -//////////////////////////////////////////////////////////// -/// \brief Specialization of the Utf template for UTF-32 -/// -//////////////////////////////////////////////////////////// -template <> -class Utf<32> -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Decode a single UTF-32 character - /// - /// Decoding a character means finding its unique 32-bits - /// code (called the codepoint) in the Unicode standard. - /// For UTF-32, the character value is the same as the codepoint. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Codepoint of the decoded UTF-32 character - /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template - static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Encode a single UTF-32 character - /// - /// Encoding a character means converting a unique 32-bits - /// code (called the codepoint) in the target encoding, UTF-32. - /// For UTF-32, the codepoint is the same as the character value. - /// - /// \param input Codepoint to encode as UTF-32 - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out encode(Uint32 input, Out output, Uint32 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Advance to the next UTF-32 character - /// - /// This function is trivial for UTF-32, which can store - /// every character in a single storage element. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template - static In next(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Count the number of characters of a UTF-32 sequence - /// - /// This function is trivial for UTF-32, which can store - /// every character in a single storage element. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template - static std::size_t count(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Convert an ANSI characters range to UTF-32 - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Convert a wide characters range to UTF-32 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out fromWide(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out fromLatin1(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-32 characters range to ANSI characters - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-32 characters range to wide characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toWide(In begin, In end, Out output, wchar_t replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toLatin1(In begin, In end, Out output, char replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-32 characters range to UTF-8 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toUtf8(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-32 characters range to UTF-16 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toUtf16(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-32 characters range to UTF-32 - /// - /// This functions does nothing more than a direct copy; - /// it is defined only to provide the same interface as other - /// specializations of the sf::Utf<> template, and allow - /// generic code to be written on top of it. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out toUtf32(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Decode a single ANSI character to UTF-32 - /// - /// This function does not exist in other specializations - /// of sf::Utf<>, it is defined for convenience (it is used by - /// several other conversion functions). - /// - /// \param input Input ANSI character - /// \param locale Locale to use for conversion - /// - /// \return Converted character - /// - //////////////////////////////////////////////////////////// - template - static Uint32 decodeAnsi(In input, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Decode a single wide character to UTF-32 - /// - /// This function does not exist in other specializations - /// of sf::Utf<>, it is defined for convenience (it is used by - /// several other conversion functions). - /// - /// \param input Input wide character - /// - /// \return Converted character - /// - //////////////////////////////////////////////////////////// - template - static Uint32 decodeWide(In input); - - //////////////////////////////////////////////////////////// - /// \brief Encode a single UTF-32 character to ANSI - /// - /// This function does not exist in other specializations - /// of sf::Utf<>, it is defined for convenience (it is used by - /// several other conversion functions). - /// - /// \param codepoint Iterator pointing to the beginning of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it) - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out encodeAnsi(Uint32 codepoint, Out output, char replacement = 0, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Encode a single UTF-32 character to wide - /// - /// This function does not exist in other specializations - /// of sf::Utf<>, it is defined for convenience (it is used by - /// several other conversion functions). - /// - /// \param codepoint Iterator pointing to the beginning of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template - static Out encodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0); -}; - -#include - -// Make typedefs to get rid of the template syntax -typedef Utf<8> Utf8; -typedef Utf<16> Utf16; -typedef Utf<32> Utf32; - -} // namespace sf - - -#endif // SFML_UTF_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Utf -/// \ingroup system -/// -/// Utility class providing generic functions for UTF conversions. -/// -/// sf::Utf is a low-level, generic interface for counting, iterating, -/// encoding and decoding Unicode characters and strings. It is able -/// to handle ANSI, wide, latin-1, UTF-8, UTF-16 and UTF-32 encodings. -/// -/// sf::Utf functions are all static, these classes are not meant to -/// be instantiated. All the functions are template, so that you -/// can use any character / string type for a given encoding. -/// -/// It has 3 specializations: -/// \li sf::Utf<8> (typedef'd to sf::Utf8) -/// \li sf::Utf<16> (typedef'd to sf::Utf16) -/// \li sf::Utf<32> (typedef'd to sf::Utf32) -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_UTF_HPP +#define SFML_UTF_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +template +class Utf; + +//////////////////////////////////////////////////////////// +/// \brief Specialization of the Utf template for UTF-8 +/// +//////////////////////////////////////////////////////////// +template <> +class Utf<8> +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-8 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-8 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-8 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-8. + /// + /// \param input Codepoint to encode as UTF-8 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out encode(Uint32 input, Out output, Uint8 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-8 character + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In next(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-8 sequence + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element, thus the + /// total size can be different from (begin - end). + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static std::size_t count(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-8 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromWide(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromLatin1(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toWide(In begin, In end, Out output, wchar_t replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toLatin1(In begin, In end, Out output, char replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-8 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other + /// specializations of the sf::Utf<> template, and allow + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf8(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf16(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf32(In begin, In end, Out output); +}; + +//////////////////////////////////////////////////////////// +/// \brief Specialization of the Utf template for UTF-16 +/// +//////////////////////////////////////////////////////////// +template <> +class Utf<16> +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-16 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-16 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-16 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-16. + /// + /// \param input Codepoint to encode as UTF-16 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out encode(Uint32 input, Out output, Uint16 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-16 character + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In next(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-16 sequence + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element, thus the + /// total size can be different from (begin - end). + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static std::size_t count(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-16 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromWide(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromLatin1(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toWide(In begin, In end, Out output, wchar_t replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toLatin1(In begin, In end, Out output, char replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf8(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-16 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other + /// specializations of the sf::Utf<> template, and allow + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf16(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf32(In begin, In end, Out output); +}; + +//////////////////////////////////////////////////////////// +/// \brief Specialization of the Utf template for UTF-32 +/// +//////////////////////////////////////////////////////////// +template <> +class Utf<32> +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-32 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// For UTF-32, the character value is the same as the codepoint. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-32 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-32. + /// For UTF-32, the codepoint is the same as the character value. + /// + /// \param input Codepoint to encode as UTF-32 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out encode(Uint32 input, Out output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-32 character + /// + /// This function is trivial for UTF-32, which can store + /// every character in a single storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In next(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-32 sequence + /// + /// This function is trivial for UTF-32, which can store + /// every character in a single storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static std::size_t count(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-32 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromWide(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromLatin1(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-32 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-32 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toWide(In begin, In end, Out output, wchar_t replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toLatin1(In begin, In end, Out output, char replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf8(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf16(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-32 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other + /// specializations of the sf::Utf<> template, and allow + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf32(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Decode a single ANSI character to UTF-32 + /// + /// This function does not exist in other specializations + /// of sf::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param input Input ANSI character + /// \param locale Locale to use for conversion + /// + /// \return Converted character + /// + //////////////////////////////////////////////////////////// + template + static Uint32 decodeAnsi(In input, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Decode a single wide character to UTF-32 + /// + /// This function does not exist in other specializations + /// of sf::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param input Input wide character + /// + /// \return Converted character + /// + //////////////////////////////////////////////////////////// + template + static Uint32 decodeWide(In input); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character to ANSI + /// + /// This function does not exist in other specializations + /// of sf::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param codepoint Iterator pointing to the beginning of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out encodeAnsi(Uint32 codepoint, Out output, char replacement = 0, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character to wide + /// + /// This function does not exist in other specializations + /// of sf::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param codepoint Iterator pointing to the beginning of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out encodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0); +}; + +#include + +// Make typedefs to get rid of the template syntax +typedef Utf<8> Utf8; +typedef Utf<16> Utf16; +typedef Utf<32> Utf32; + +} // namespace sf + + +#endif // SFML_UTF_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Utf +/// \ingroup system +/// +/// Utility class providing generic functions for UTF conversions. +/// +/// sf::Utf is a low-level, generic interface for counting, iterating, +/// encoding and decoding Unicode characters and strings. It is able +/// to handle ANSI, wide, latin-1, UTF-8, UTF-16 and UTF-32 encodings. +/// +/// sf::Utf functions are all static, these classes are not meant to +/// be instantiated. All the functions are template, so that you +/// can use any character / string type for a given encoding. +/// +/// It has 3 specializations: +/// \li sf::Utf<8> (typedef'd to sf::Utf8) +/// \li sf::Utf<16> (typedef'd to sf::Utf16) +/// \li sf::Utf<32> (typedef'd to sf::Utf32) +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Utf.inl b/include/SFML/System/Utf.inl index dd24db66..80dfd827 100644 --- a/include/SFML/System/Utf.inl +++ b/include/SFML/System/Utf.inl @@ -1,752 +1,752 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -// References : -// -// http://www.unicode.org/ -// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c -// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h -// http://people.w3.org/rishida/scripts/uniview/conversion -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -template -In Utf<8>::decode(In begin, In end, Uint32& output, Uint32 replacement) -{ - // Some useful precomputed data - static const int trailing[256] = - { - 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, 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, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 - }; - static const Uint32 offsets[6] = - { - 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080 - }; - - // decode the character - int trailingBytes = trailing[static_cast(*begin)]; - if (begin + trailingBytes < end) - { - output = 0; - switch (trailingBytes) - { - case 5 : output += static_cast(*begin++); output <<= 6; - case 4 : output += static_cast(*begin++); output <<= 6; - case 3 : output += static_cast(*begin++); output <<= 6; - case 2 : output += static_cast(*begin++); output <<= 6; - case 1 : output += static_cast(*begin++); output <<= 6; - case 0 : output += static_cast(*begin++); - } - output -= offsets[trailingBytes]; - } - else - { - // Incomplete character - begin = end; - output = replacement; - } - - return begin; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<8>::encode(Uint32 input, Out output, Uint8 replacement) -{ - // Some useful precomputed data - static const Uint8 firstBytes[7] = - { - 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC - }; - - // encode the character - if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF))) - { - // Invalid character - if (replacement) - *output++ = replacement; - } - else - { - // Valid character - - // Get the number of bytes to write - std::size_t bytestoWrite = 1; - if (input < 0x80) bytestoWrite = 1; - else if (input < 0x800) bytestoWrite = 2; - else if (input < 0x10000) bytestoWrite = 3; - else if (input <= 0x0010FFFF) bytestoWrite = 4; - - // Extract the bytes to write - Uint8 bytes[4]; - switch (bytestoWrite) - { - case 4 : bytes[3] = static_cast((input | 0x80) & 0xBF); input >>= 6; - case 3 : bytes[2] = static_cast((input | 0x80) & 0xBF); input >>= 6; - case 2 : bytes[1] = static_cast((input | 0x80) & 0xBF); input >>= 6; - case 1 : bytes[0] = static_cast (input | firstBytes[bytestoWrite]); - } - - // Add them to the output - output = std::copy(bytes, bytes + bytestoWrite, output); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -In Utf<8>::next(In begin, In end) -{ - Uint32 codepoint; - return decode(begin, end, codepoint); -} - - -//////////////////////////////////////////////////////////// -template -std::size_t Utf<8>::count(In begin, In end) -{ - std::size_t length = 0; - while (begin < end) - { - begin = next(begin, end); - ++length; - } - - return length; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<8>::fromAnsi(In begin, In end, Out output, const std::locale& locale) -{ - while (begin < end) - { - Uint32 codepoint = Utf<32>::decodeAnsi(*begin++, locale); - output = encode(codepoint, output); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<8>::fromWide(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint = Utf<32>::decodeWide(*begin++); - output = encode(codepoint, output); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<8>::fromLatin1(In begin, In end, Out output) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - while (begin < end) - output = encode(*begin++, output); - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<8>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) -{ - while (begin < end) - { - Uint32 codepoint; - begin = decode(begin, end, codepoint); - output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<8>::toWide(In begin, In end, Out output, wchar_t replacement) -{ - while (begin < end) - { - Uint32 codepoint; - begin = decode(begin, end, codepoint); - output = Utf<32>::encodeWide(codepoint, output, replacement); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<8>::toLatin1(In begin, In end, Out output, char replacement) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - while (begin < end) - { - Uint32 codepoint; - begin = decode(begin, end, codepoint); - *output++ = codepoint < 256 ? static_cast(codepoint) : replacement; - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<8>::toUtf8(In begin, In end, Out output) -{ - return std::copy(begin, end, output); -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<8>::toUtf16(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint; - begin = decode(begin, end, codepoint); - output = Utf<16>::encode(codepoint, output); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<8>::toUtf32(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint; - begin = decode(begin, end, codepoint); - *output++ = codepoint; - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -In Utf<16>::decode(In begin, In end, Uint32& output, Uint32 replacement) -{ - Uint16 first = *begin++; - - // If it's a surrogate pair, first convert to a single UTF-32 character - if ((first >= 0xD800) && (first <= 0xDBFF)) - { - if (begin < end) - { - Uint32 second = *begin++; - if ((second >= 0xDC00) && (second <= 0xDFFF)) - { - // The second element is valid: convert the two elements to a UTF-32 character - output = static_cast(((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000); - } - else - { - // Invalid character - output = replacement; - } - } - else - { - // Invalid character - begin = end; - output = replacement; - } - } - else - { - // We can make a direct copy - output = first; - } - - return begin; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<16>::encode(Uint32 input, Out output, Uint16 replacement) -{ - if (input < 0xFFFF) - { - // The character can be copied directly, we just need to check if it's in the valid range - if ((input >= 0xD800) && (input <= 0xDFFF)) - { - // Invalid character (this range is reserved) - if (replacement) - *output++ = replacement; - } - else - { - // Valid character directly convertible to a single UTF-16 character - *output++ = static_cast(input); - } - } - else if (input > 0x0010FFFF) - { - // Invalid character (greater than the maximum unicode value) - if (replacement) - *output++ = replacement; - } - else - { - // The input character will be converted to two UTF-16 elements - input -= 0x0010000; - *output++ = static_cast((input >> 10) + 0xD800); - *output++ = static_cast((input & 0x3FFUL) + 0xDC00); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -In Utf<16>::next(In begin, In end) -{ - Uint32 codepoint; - return decode(begin, end, codepoint); -} - - -//////////////////////////////////////////////////////////// -template -std::size_t Utf<16>::count(In begin, In end) -{ - std::size_t length = 0; - while (begin < end) - { - begin = next(begin, end); - ++length; - } - - return length; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<16>::fromAnsi(In begin, In end, Out output, const std::locale& locale) -{ - while (begin < end) - { - Uint32 codepoint = Utf<32>::decodeAnsi(*begin++, locale); - output = encode(codepoint, output); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<16>::fromWide(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint = Utf<32>::decodeWide(*begin++); - output = encode(codepoint, output); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<16>::fromLatin1(In begin, In end, Out output) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - return std::copy(begin, end, output); -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<16>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) -{ - while (begin < end) - { - Uint32 codepoint; - begin = decode(begin, end, codepoint); - output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<16>::toWide(In begin, In end, Out output, wchar_t replacement) -{ - while (begin < end) - { - Uint32 codepoint; - begin = decode(begin, end, codepoint); - output = Utf<32>::encodeWide(codepoint, output, replacement); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<16>::toLatin1(In begin, In end, Out output, char replacement) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - while (begin < end) - { - *output++ = *begin < 256 ? static_cast(*begin) : replacement; - begin++; - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<16>::toUtf8(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint; - begin = decode(begin, end, codepoint); - output = Utf<8>::encode(codepoint, output); - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<16>::toUtf16(In begin, In end, Out output) -{ - return std::copy(begin, end, output); -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<16>::toUtf32(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint; - begin = decode(begin, end, codepoint); - *output++ = codepoint; - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -In Utf<32>::decode(In begin, In /*end*/, Uint32& output, Uint32 /*replacement*/) -{ - output = *begin++; - return begin; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::encode(Uint32 input, Out output, Uint32 /*replacement*/) -{ - *output++ = input; - return output; -} - - -//////////////////////////////////////////////////////////// -template -In Utf<32>::next(In begin, In /*end*/) -{ - return ++begin; -} - - -//////////////////////////////////////////////////////////// -template -std::size_t Utf<32>::count(In begin, In end) -{ - return begin - end; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::fromAnsi(In begin, In end, Out output, const std::locale& locale) -{ - while (begin < end) - *output++ = decodeAnsi(*begin++, locale); - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::fromWide(In begin, In end, Out output) -{ - while (begin < end) - *output++ = decodeWide(*begin++); - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::fromLatin1(In begin, In end, Out output) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - return std::copy(begin, end, output); -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) -{ - while (begin < end) - output = encodeAnsi(*begin++, output, replacement, locale); - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::toWide(In begin, In end, Out output, wchar_t replacement) -{ - while (begin < end) - output = encodeWide(*begin++, output, replacement); - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::toLatin1(In begin, In end, Out output, char replacement) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - while (begin < end) - { - *output++ = *begin < 256 ? static_cast(*begin) : replacement; - begin++; - } - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::toUtf8(In begin, In end, Out output) -{ - while (begin < end) - output = Utf<8>::encode(*begin++, output); - - return output; -} - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::toUtf16(In begin, In end, Out output) -{ - while (begin < end) - output = Utf<16>::encode(*begin++, output); - - return output; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::toUtf32(In begin, In end, Out output) -{ - return std::copy(begin, end, output); -} - - -//////////////////////////////////////////////////////////// -template -Uint32 Utf<32>::decodeAnsi(In input, const std::locale& locale) -{ - // On Windows, gcc's standard library (glibc++) has almost - // no support for Unicode stuff. As a consequence, in this - // context we can only use the default locale and ignore - // the one passed as parameter. - - #if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \ - (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \ - !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */ - - (void)locale; // to avoid warnings - - wchar_t character = 0; - mbtowc(&character, &input, 1); - return static_cast(character); - - #else - - // Get the facet of the locale which deals with character conversion - const std::ctype& facet = std::use_facet< std::ctype >(locale); - - // Use the facet to convert each character of the input string - return static_cast(facet.widen(input)); - - #endif -} - - -//////////////////////////////////////////////////////////// -template -Uint32 Utf<32>::decodeWide(In input) -{ - // The encoding of wide characters is not well defined and is left to the system; - // however we can safely assume that it is UCS-2 on Windows and - // UCS-4 on Unix systems. - // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4, - // and UCS-4 *is* UTF-32). - - return input; -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::encodeAnsi(Uint32 codepoint, Out output, char replacement, const std::locale& locale) -{ - // On Windows, gcc's standard library (glibc++) has almost - // no support for Unicode stuff. As a consequence, in this - // context we can only use the default locale and ignore - // the one passed as parameter. - - #if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \ - (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \ - !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */ - - (void)locale; // to avoid warnings - - char character = 0; - if (wctomb(&character, static_cast(codepoint)) >= 0) - *output++ = character; - else if (replacement) - *output++ = replacement; - - return output; - - #else - - // Get the facet of the locale which deals with character conversion - const std::ctype& facet = std::use_facet< std::ctype >(locale); - - // Use the facet to convert each character of the input string - *output++ = facet.narrow(static_cast(codepoint), replacement); - - return output; - - #endif -} - - -//////////////////////////////////////////////////////////// -template -Out Utf<32>::encodeWide(Uint32 codepoint, Out output, wchar_t replacement) -{ - // The encoding of wide characters is not well defined and is left to the system; - // however we can safely assume that it is UCS-2 on Windows and - // UCS-4 on Unix systems. - // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4). - // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32). - - switch (sizeof(wchar_t)) - { - case 4: - { - *output++ = static_cast(codepoint); - break; - } - - default: - { - if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF))) - { - *output++ = static_cast(codepoint); - } - else if (replacement) - { - *output++ = replacement; - } - break; - } - } - - return output; -} +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +// References: +// +// http://www.unicode.org/ +// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c +// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h +// http://people.w3.org/rishida/scripts/uniview/conversion +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +template +In Utf<8>::decode(In begin, In end, Uint32& output, Uint32 replacement) +{ + // Some useful precomputed data + static const int trailing[256] = + { + 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, 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, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 + }; + static const Uint32 offsets[6] = + { + 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080 + }; + + // decode the character + int trailingBytes = trailing[static_cast(*begin)]; + if (begin + trailingBytes < end) + { + output = 0; + switch (trailingBytes) + { + case 5: output += static_cast(*begin++); output <<= 6; + case 4: output += static_cast(*begin++); output <<= 6; + case 3: output += static_cast(*begin++); output <<= 6; + case 2: output += static_cast(*begin++); output <<= 6; + case 1: output += static_cast(*begin++); output <<= 6; + case 0: output += static_cast(*begin++); + } + output -= offsets[trailingBytes]; + } + else + { + // Incomplete character + begin = end; + output = replacement; + } + + return begin; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::encode(Uint32 input, Out output, Uint8 replacement) +{ + // Some useful precomputed data + static const Uint8 firstBytes[7] = + { + 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC + }; + + // encode the character + if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF))) + { + // Invalid character + if (replacement) + *output++ = replacement; + } + else + { + // Valid character + + // Get the number of bytes to write + std::size_t bytestoWrite = 1; + if (input < 0x80) bytestoWrite = 1; + else if (input < 0x800) bytestoWrite = 2; + else if (input < 0x10000) bytestoWrite = 3; + else if (input <= 0x0010FFFF) bytestoWrite = 4; + + // Extract the bytes to write + Uint8 bytes[4]; + switch (bytestoWrite) + { + case 4: bytes[3] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 3: bytes[2] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 2: bytes[1] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 1: bytes[0] = static_cast (input | firstBytes[bytestoWrite]); + } + + // Add them to the output + output = std::copy(bytes, bytes + bytestoWrite, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<8>::next(In begin, In end) +{ + Uint32 codepoint; + return decode(begin, end, codepoint); +} + + +//////////////////////////////////////////////////////////// +template +std::size_t Utf<8>::count(In begin, In end) +{ + std::size_t length = 0; + while (begin < end) + { + begin = next(begin, end); + ++length; + } + + return length; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::fromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::decodeAnsi(*begin++, locale); + output = encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::fromWide(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::decodeWide(*begin++); + output = encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::fromLatin1(In begin, In end, Out output) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + output = encode(*begin++, output); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<32>::encodeWide(codepoint, output, replacement); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toLatin1(In begin, In end, Out output, char replacement) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + *output++ = codepoint < 256 ? static_cast(codepoint) : replacement; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toUtf8(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toUtf16(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<16>::encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toUtf32(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + *output++ = codepoint; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<16>::decode(In begin, In end, Uint32& output, Uint32 replacement) +{ + Uint16 first = *begin++; + + // If it's a surrogate pair, first convert to a single UTF-32 character + if ((first >= 0xD800) && (first <= 0xDBFF)) + { + if (begin < end) + { + Uint32 second = *begin++; + if ((second >= 0xDC00) && (second <= 0xDFFF)) + { + // The second element is valid: convert the two elements to a UTF-32 character + output = static_cast(((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000); + } + else + { + // Invalid character + output = replacement; + } + } + else + { + // Invalid character + begin = end; + output = replacement; + } + } + else + { + // We can make a direct copy + output = first; + } + + return begin; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::encode(Uint32 input, Out output, Uint16 replacement) +{ + if (input < 0xFFFF) + { + // The character can be copied directly, we just need to check if it's in the valid range + if ((input >= 0xD800) && (input <= 0xDFFF)) + { + // Invalid character (this range is reserved) + if (replacement) + *output++ = replacement; + } + else + { + // Valid character directly convertible to a single UTF-16 character + *output++ = static_cast(input); + } + } + else if (input > 0x0010FFFF) + { + // Invalid character (greater than the maximum unicode value) + if (replacement) + *output++ = replacement; + } + else + { + // The input character will be converted to two UTF-16 elements + input -= 0x0010000; + *output++ = static_cast((input >> 10) + 0xD800); + *output++ = static_cast((input & 0x3FFUL) + 0xDC00); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<16>::next(In begin, In end) +{ + Uint32 codepoint; + return decode(begin, end, codepoint); +} + + +//////////////////////////////////////////////////////////// +template +std::size_t Utf<16>::count(In begin, In end) +{ + std::size_t length = 0; + while (begin < end) + { + begin = next(begin, end); + ++length; + } + + return length; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::fromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::decodeAnsi(*begin++, locale); + output = encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::fromWide(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::decodeWide(*begin++); + output = encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::fromLatin1(In begin, In end, Out output) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<32>::encodeWide(codepoint, output, replacement); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toLatin1(In begin, In end, Out output, char replacement) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + { + *output++ = *begin < 256 ? static_cast(*begin) : replacement; + begin++; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toUtf8(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<8>::encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toUtf16(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toUtf32(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + *output++ = codepoint; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<32>::decode(In begin, In /*end*/, Uint32& output, Uint32 /*replacement*/) +{ + output = *begin++; + return begin; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::encode(Uint32 input, Out output, Uint32 /*replacement*/) +{ + *output++ = input; + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<32>::next(In begin, In /*end*/) +{ + return ++begin; +} + + +//////////////////////////////////////////////////////////// +template +std::size_t Utf<32>::count(In begin, In end) +{ + return begin - end; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::fromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + *output++ = decodeAnsi(*begin++, locale); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::fromWide(In begin, In end, Out output) +{ + while (begin < end) + *output++ = decodeWide(*begin++); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::fromLatin1(In begin, In end, Out output) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) +{ + while (begin < end) + output = encodeAnsi(*begin++, output, replacement, locale); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + output = encodeWide(*begin++, output, replacement); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toLatin1(In begin, In end, Out output, char replacement) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + { + *output++ = *begin < 256 ? static_cast(*begin) : replacement; + begin++; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toUtf8(In begin, In end, Out output) +{ + while (begin < end) + output = Utf<8>::encode(*begin++, output); + + return output; +} + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toUtf16(In begin, In end, Out output) +{ + while (begin < end) + output = Utf<16>::encode(*begin++, output); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toUtf32(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +Uint32 Utf<32>::decodeAnsi(In input, const std::locale& locale) +{ + // On Windows, gcc's standard library (glibc++) has almost + // no support for Unicode stuff. As a consequence, in this + // context we can only use the default locale and ignore + // the one passed as parameter. + + #if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \ + (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \ + !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */ + + (void)locale; // to avoid warnings + + wchar_t character = 0; + mbtowc(&character, &input, 1); + return static_cast(character); + + #else + + // Get the facet of the locale which deals with character conversion + const std::ctype& facet = std::use_facet< std::ctype >(locale); + + // Use the facet to convert each character of the input string + return static_cast(facet.widen(input)); + + #endif +} + + +//////////////////////////////////////////////////////////// +template +Uint32 Utf<32>::decodeWide(In input) +{ + // The encoding of wide characters is not well defined and is left to the system; + // however we can safely assume that it is UCS-2 on Windows and + // UCS-4 on Unix systems. + // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4, + // and UCS-4 *is* UTF-32). + + return input; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::encodeAnsi(Uint32 codepoint, Out output, char replacement, const std::locale& locale) +{ + // On Windows, gcc's standard library (glibc++) has almost + // no support for Unicode stuff. As a consequence, in this + // context we can only use the default locale and ignore + // the one passed as parameter. + + #if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \ + (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \ + !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */ + + (void)locale; // to avoid warnings + + char character = 0; + if (wctomb(&character, static_cast(codepoint)) >= 0) + *output++ = character; + else if (replacement) + *output++ = replacement; + + return output; + + #else + + // Get the facet of the locale which deals with character conversion + const std::ctype& facet = std::use_facet< std::ctype >(locale); + + // Use the facet to convert each character of the input string + *output++ = facet.narrow(static_cast(codepoint), replacement); + + return output; + + #endif +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::encodeWide(Uint32 codepoint, Out output, wchar_t replacement) +{ + // The encoding of wide characters is not well defined and is left to the system; + // however we can safely assume that it is UCS-2 on Windows and + // UCS-4 on Unix systems. + // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4). + // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32). + + switch (sizeof(wchar_t)) + { + case 4: + { + *output++ = static_cast(codepoint); + break; + } + + default: + { + if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF))) + { + *output++ = static_cast(codepoint); + } + else if (replacement) + { + *output++ = replacement; + } + break; + } + } + + return output; +} diff --git a/include/SFML/System/Vector2.hpp b/include/SFML/System/Vector2.hpp index bdb2ed9d..668aab8d 100644 --- a/include/SFML/System/Vector2.hpp +++ b/include/SFML/System/Vector2.hpp @@ -1,301 +1,301 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_VECTOR2_HPP -#define SFML_VECTOR2_HPP - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Utility template class for manipulating -/// 2-dimensional vectors -/// -//////////////////////////////////////////////////////////// -template -class Vector2 -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Creates a Vector2(0, 0). - /// - //////////////////////////////////////////////////////////// - Vector2(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the vector from its coordinates - /// - /// \param X X coordinate - /// \param Y Y coordinate - /// - //////////////////////////////////////////////////////////// - Vector2(T X, T Y); - - //////////////////////////////////////////////////////////// - /// \brief Construct the vector from another type of vector - /// - /// This constructor doesn't replace the copy constructor, - /// it's called only when U != T. - /// A call to this constructor will fail to compile if U - /// is not convertible to T. - /// - /// \param vector Vector to convert - /// - //////////////////////////////////////////////////////////// - template - explicit Vector2(const Vector2& vector); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - T x; ///< X coordinate of the vector - T y; ///< Y coordinate of the vector -}; - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of unary operator - -/// -/// \param right Vector to negate -/// -/// \return Memberwise opposite of the vector -/// -//////////////////////////////////////////////////////////// -template -Vector2 operator -(const Vector2& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator += -/// -/// This operator performs a memberwise addition of both vectors, -/// and assigns the result to \a left. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -template -Vector2& operator +=(Vector2& left, const Vector2& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator -= -/// -/// This operator performs a memberwise subtraction of both vectors, -/// and assigns the result to \a left. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -template -Vector2& operator -=(Vector2& left, const Vector2& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator + -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return Memberwise addition of both vectors -/// -//////////////////////////////////////////////////////////// -template -Vector2 operator +(const Vector2& left, const Vector2& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator - -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return Memberwise subtraction of both vectors -/// -//////////////////////////////////////////////////////////// -template -Vector2 operator -(const Vector2& left, const Vector2& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator * -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a scalar value) -/// -/// \return Memberwise multiplication by \a right -/// -//////////////////////////////////////////////////////////// -template -Vector2 operator *(const Vector2& left, T right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator * -/// -/// \param left Left operand (a scalar value) -/// \param right Right operand (a vector) -/// -/// \return Memberwise multiplication by \a left -/// -//////////////////////////////////////////////////////////// -template -Vector2 operator *(T left, const Vector2& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator *= -/// -/// This operator performs a memberwise multiplication by \a right, -/// and assigns the result to \a left. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a scalar value) -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -template -Vector2& operator *=(Vector2& left, T right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator / -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a scalar value) -/// -/// \return Memberwise division by \a right -/// -//////////////////////////////////////////////////////////// -template -Vector2 operator /(const Vector2& left, T right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator /= -/// -/// This operator performs a memberwise division by \a right, -/// and assigns the result to \a left. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a scalar value) -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -template -Vector2& operator /=(Vector2& left, T right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator == -/// -/// This operator compares strict equality between two vectors. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return True if \a left is equal to \a right -/// -//////////////////////////////////////////////////////////// -template -bool operator ==(const Vector2& left, const Vector2& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector2 -/// \brief Overload of binary operator != -/// -/// This operator compares strict difference between two vectors. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return True if \a left is not equal to \a right -/// -//////////////////////////////////////////////////////////// -template -bool operator !=(const Vector2& left, const Vector2& right); - -#include - -// Define the most common types -typedef Vector2 Vector2i; -typedef Vector2 Vector2u; -typedef Vector2 Vector2f; - -} // namespace sf - - -#endif // SFML_VECTOR2_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Vector2 -/// \ingroup system -/// -/// sf::Vector2 is a simple class that defines a mathematical -/// vector with two coordinates (x and y). It can be used to -/// represent anything that has two dimensions: a size, a point, -/// a velocity, etc. -/// -/// The template parameter T is the type of the coordinates. It -/// can be any type that supports arithmetic operations (+, -, /, *) -/// and comparisons (==, !=), for example int or float. -/// -/// You generally don't have to care about the templated form (sf::Vector2), -/// the most common specializations have special typedefs: -/// \li sf::Vector2 is sf::Vector2f -/// \li sf::Vector2 is sf::Vector2i -/// \li sf::Vector2 is sf::Vector2u -/// -/// The sf::Vector2 class has a small and simple interface, its x and y members -/// can be accessed directly (there's no accessor like setX(), getX()) and it -/// contains no mathematical function like dot product, cross product, length, etc. -/// -/// Usage example: -/// \code -/// sf::Vector2f v1(16.5f, 24.f); -/// v1.x = 18.2f; -/// float y = v1.y; -/// -/// sf::Vector2f v2 = v1 * 5.f; -/// sf::Vector2f v3; -/// v3 = v1 + v2; -/// -/// bool different = (v2 != v3); -/// \endcode -/// -/// Note: for 3-dimensional vectors, see sf::Vector3. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VECTOR2_HPP +#define SFML_VECTOR2_HPP + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility template class for manipulating +/// 2-dimensional vectors +/// +//////////////////////////////////////////////////////////// +template +class Vector2 +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates a Vector2(0, 0). + /// + //////////////////////////////////////////////////////////// + Vector2(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from its coordinates + /// + /// \param X X coordinate + /// \param Y Y coordinate + /// + //////////////////////////////////////////////////////////// + Vector2(T X, T Y); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from another type of vector + /// + /// This constructor doesn't replace the copy constructor, + /// it's called only when U != T. + /// A call to this constructor will fail to compile if U + /// is not convertible to T. + /// + /// \param vector Vector to convert + /// + //////////////////////////////////////////////////////////// + template + explicit Vector2(const Vector2& vector); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + T x; ///< X coordinate of the vector + T y; ///< Y coordinate of the vector +}; + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of unary operator - +/// +/// \param right Vector to negate +/// +/// \return Memberwise opposite of the vector +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator -(const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator += +/// +/// This operator performs a memberwise addition of both vectors, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector2& operator +=(Vector2& left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator -= +/// +/// This operator performs a memberwise subtraction of both vectors, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector2& operator -=(Vector2& left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator + +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Memberwise addition of both vectors +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator +(const Vector2& left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator - +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Memberwise subtraction of both vectors +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator -(const Vector2& left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator * +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Memberwise multiplication by \a right +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator *(const Vector2& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator * +/// +/// \param left Left operand (a scalar value) +/// \param right Right operand (a vector) +/// +/// \return Memberwise multiplication by \a left +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator *(T left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator *= +/// +/// This operator performs a memberwise multiplication by \a right, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector2& operator *=(Vector2& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator / +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Memberwise division by \a right +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator /(const Vector2& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator /= +/// +/// This operator performs a memberwise division by \a right, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector2& operator /=(Vector2& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator == +/// +/// This operator compares strict equality between two vectors. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return True if \a left is equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator ==(const Vector2& left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator != +/// +/// This operator compares strict difference between two vectors. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return True if \a left is not equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator !=(const Vector2& left, const Vector2& right); + +#include + +// Define the most common types +typedef Vector2 Vector2i; +typedef Vector2 Vector2u; +typedef Vector2 Vector2f; + +} // namespace sf + + +#endif // SFML_VECTOR2_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Vector2 +/// \ingroup system +/// +/// sf::Vector2 is a simple class that defines a mathematical +/// vector with two coordinates (x and y). It can be used to +/// represent anything that has two dimensions: a size, a point, +/// a velocity, etc. +/// +/// The template parameter T is the type of the coordinates. It +/// can be any type that supports arithmetic operations (+, -, /, *) +/// and comparisons (==, !=), for example int or float. +/// +/// You generally don't have to care about the templated form (sf::Vector2), +/// the most common specializations have special typedefs: +/// \li sf::Vector2 is sf::Vector2f +/// \li sf::Vector2 is sf::Vector2i +/// \li sf::Vector2 is sf::Vector2u +/// +/// The sf::Vector2 class has a small and simple interface, its x and y members +/// can be accessed directly (there's no accessor like setX(), getX()) and it +/// contains no mathematical function like dot product, cross product, length, etc. +/// +/// Usage example: +/// \code +/// sf::Vector2f v1(16.5f, 24.f); +/// v1.x = 18.2f; +/// float y = v1.y; +/// +/// sf::Vector2f v2 = v1 * 5.f; +/// sf::Vector2f v3; +/// v3 = v1 + v2; +/// +/// bool different = (v2 != v3); +/// \endcode +/// +/// Note: for 3-dimensional vectors, see sf::Vector3. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Vector2.inl b/include/SFML/System/Vector2.inl index 05b9d9d0..07b96f5a 100644 --- a/include/SFML/System/Vector2.inl +++ b/include/SFML/System/Vector2.inl @@ -1,161 +1,161 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -template -inline Vector2::Vector2() : -x(0), -y(0) -{ - -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2::Vector2(T X, T Y) : -x(X), -y(Y) -{ - -} - - -//////////////////////////////////////////////////////////// -template -template -inline Vector2::Vector2(const Vector2& vector) : -x(static_cast(vector.x)), -y(static_cast(vector.y)) -{ -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2 operator -(const Vector2& right) -{ - return Vector2(-right.x, -right.y); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2& operator +=(Vector2& left, const Vector2& right) -{ - left.x += right.x; - left.y += right.y; - - return left; -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2& operator -=(Vector2& left, const Vector2& right) -{ - left.x -= right.x; - left.y -= right.y; - - return left; -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2 operator +(const Vector2& left, const Vector2& right) -{ - return Vector2(left.x + right.x, left.y + right.y); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2 operator -(const Vector2& left, const Vector2& right) -{ - return Vector2(left.x - right.x, left.y - right.y); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2 operator *(const Vector2& left, T right) -{ - return Vector2(left.x * right, left.y * right); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2 operator *(T left, const Vector2& right) -{ - return Vector2(right.x * left, right.y * left); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2& operator *=(Vector2& left, T right) -{ - left.x *= right; - left.y *= right; - - return left; -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2 operator /(const Vector2& left, T right) -{ - return Vector2(left.x / right, left.y / right); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector2& operator /=(Vector2& left, T right) -{ - left.x /= right; - left.y /= right; - - return left; -} - - -//////////////////////////////////////////////////////////// -template -inline bool operator ==(const Vector2& left, const Vector2& right) -{ - return (left.x == right.x) && (left.y == right.y); -} - - -//////////////////////////////////////////////////////////// -template -inline bool operator !=(const Vector2& left, const Vector2& right) -{ - return (left.x != right.x) || (left.y != right.y); -} +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +template +inline Vector2::Vector2() : +x(0), +y(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2::Vector2(T X, T Y) : +x(X), +y(Y) +{ + +} + + +//////////////////////////////////////////////////////////// +template +template +inline Vector2::Vector2(const Vector2& vector) : +x(static_cast(vector.x)), +y(static_cast(vector.y)) +{ +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator -(const Vector2& right) +{ + return Vector2(-right.x, -right.y); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2& operator +=(Vector2& left, const Vector2& right) +{ + left.x += right.x; + left.y += right.y; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2& operator -=(Vector2& left, const Vector2& right) +{ + left.x -= right.x; + left.y -= right.y; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator +(const Vector2& left, const Vector2& right) +{ + return Vector2(left.x + right.x, left.y + right.y); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator -(const Vector2& left, const Vector2& right) +{ + return Vector2(left.x - right.x, left.y - right.y); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator *(const Vector2& left, T right) +{ + return Vector2(left.x * right, left.y * right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator *(T left, const Vector2& right) +{ + return Vector2(right.x * left, right.y * left); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2& operator *=(Vector2& left, T right) +{ + left.x *= right; + left.y *= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator /(const Vector2& left, T right) +{ + return Vector2(left.x / right, left.y / right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2& operator /=(Vector2& left, T right) +{ + left.x /= right; + left.y /= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator ==(const Vector2& left, const Vector2& right) +{ + return (left.x == right.x) && (left.y == right.y); +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator !=(const Vector2& left, const Vector2& right) +{ + return (left.x != right.x) || (left.y != right.y); +} diff --git a/include/SFML/System/Vector3.hpp b/include/SFML/System/Vector3.hpp index 8b53cc6a..84cf9fc0 100644 --- a/include/SFML/System/Vector3.hpp +++ b/include/SFML/System/Vector3.hpp @@ -1,302 +1,302 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_VECTOR3_HPP -#define SFML_VECTOR3_HPP - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Utility template class for manipulating -/// 3-dimensional vectors -/// -//////////////////////////////////////////////////////////// -template -class Vector3 -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Creates a Vector3(0, 0, 0). - /// - //////////////////////////////////////////////////////////// - Vector3(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the vector from its coordinates - /// - /// \param X X coordinate - /// \param Y Y coordinate - /// \param Z Z coordinate - /// - //////////////////////////////////////////////////////////// - Vector3(T X, T Y, T Z); - - //////////////////////////////////////////////////////////// - /// \brief Construct the vector from another type of vector - /// - /// This constructor doesn't replace the copy constructor, - /// it's called only when U != T. - /// A call to this constructor will fail to compile if U - /// is not convertible to T. - /// - /// \param vector Vector to convert - /// - //////////////////////////////////////////////////////////// - template - explicit Vector3(const Vector3& vector); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - T x; ///< X coordinate of the vector - T y; ///< Y coordinate of the vector - T z; ///< Z coordinate of the vector -}; - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of unary operator - -/// -/// \param left Vector to negate -/// -/// \return Memberwise opposite of the vector -/// -//////////////////////////////////////////////////////////// -template -Vector3 operator -(const Vector3& left); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator += -/// -/// This operator performs a memberwise addition of both vectors, -/// and assigns the result to \a left. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -template -Vector3& operator +=(Vector3& left, const Vector3& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator -= -/// -/// This operator performs a memberwise subtraction of both vectors, -/// and assigns the result to \a left. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -template -Vector3& operator -=(Vector3& left, const Vector3& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator + -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return Memberwise addition of both vectors -/// -//////////////////////////////////////////////////////////// -template -Vector3 operator +(const Vector3& left, const Vector3& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator - -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return Memberwise subtraction of both vectors -/// -//////////////////////////////////////////////////////////// -template -Vector3 operator -(const Vector3& left, const Vector3& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator * -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a scalar value) -/// -/// \return Memberwise multiplication by \a right -/// -//////////////////////////////////////////////////////////// -template -Vector3 operator *(const Vector3& left, T right); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator * -/// -/// \param left Left operand (a scalar value) -/// \param right Right operand (a vector) -/// -/// \return Memberwise multiplication by \a left -/// -//////////////////////////////////////////////////////////// -template -Vector3 operator *(T left, const Vector3& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator *= -/// -/// This operator performs a memberwise multiplication by \a right, -/// and assigns the result to \a left. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a scalar value) -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -template -Vector3& operator *=(Vector3& left, T right); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator / -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a scalar value) -/// -/// \return Memberwise division by \a right -/// -//////////////////////////////////////////////////////////// -template -Vector3 operator /(const Vector3& left, T right); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator /= -/// -/// This operator performs a memberwise division by \a right, -/// and assigns the result to \a left. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a scalar value) -/// -/// \return Reference to \a left -/// -//////////////////////////////////////////////////////////// -template -Vector3& operator /=(Vector3& left, T right); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator == -/// -/// This operator compares strict equality between two vectors. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return True if \a left is equal to \a right -/// -//////////////////////////////////////////////////////////// -template -bool operator ==(const Vector3& left, const Vector3& right); - -//////////////////////////////////////////////////////////// -/// \relates Vector3 -/// \brief Overload of binary operator != -/// -/// This operator compares strict difference between two vectors. -/// -/// \param left Left operand (a vector) -/// \param right Right operand (a vector) -/// -/// \return True if \a left is not equal to \a right -/// -//////////////////////////////////////////////////////////// -template -bool operator !=(const Vector3& left, const Vector3& right); - -#include - -// Define the most common types -typedef Vector3 Vector3i; -typedef Vector3 Vector3f; - -} // namespace sf - - -#endif // SFML_VECTOR3_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Vector3 -/// \ingroup system -/// -/// sf::Vector3 is a simple class that defines a mathematical -/// vector with three coordinates (x, y and z). It can be used to -/// represent anything that has three dimensions: a size, a point, -/// a velocity, etc. -/// -/// The template parameter T is the type of the coordinates. It -/// can be any type that supports arithmetic operations (+, -, /, *) -/// and comparisons (==, !=), for example int or float. -/// -/// You generally don't have to care about the templated form (sf::Vector3), -/// the most common specializations have special typedefs: -/// \li sf::Vector3 is sf::Vector3f -/// \li sf::Vector3 is sf::Vector3i -/// -/// The sf::Vector3 class has a small and simple interface, its x and y members -/// can be accessed directly (there's no accessor like setX(), getX()) and it -/// contains no mathematical function like dot product, cross product, length, etc. -/// -/// Usage example: -/// \code -/// sf::Vector3f v1(16.5f, 24.f, -8.2f); -/// v1.x = 18.2f; -/// float y = v1.y; -/// float z = v1.z; -/// -/// sf::Vector3f v2 = v1 * 5.f; -/// sf::Vector3f v3; -/// v3 = v1 + v2; -/// -/// bool different = (v2 != v3); -/// \endcode -/// -/// Note: for 2-dimensional vectors, see sf::Vector2. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VECTOR3_HPP +#define SFML_VECTOR3_HPP + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility template class for manipulating +/// 3-dimensional vectors +/// +//////////////////////////////////////////////////////////// +template +class Vector3 +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates a Vector3(0, 0, 0). + /// + //////////////////////////////////////////////////////////// + Vector3(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from its coordinates + /// + /// \param X X coordinate + /// \param Y Y coordinate + /// \param Z Z coordinate + /// + //////////////////////////////////////////////////////////// + Vector3(T X, T Y, T Z); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from another type of vector + /// + /// This constructor doesn't replace the copy constructor, + /// it's called only when U != T. + /// A call to this constructor will fail to compile if U + /// is not convertible to T. + /// + /// \param vector Vector to convert + /// + //////////////////////////////////////////////////////////// + template + explicit Vector3(const Vector3& vector); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + T x; ///< X coordinate of the vector + T y; ///< Y coordinate of the vector + T z; ///< Z coordinate of the vector +}; + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of unary operator - +/// +/// \param left Vector to negate +/// +/// \return Memberwise opposite of the vector +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator -(const Vector3& left); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator += +/// +/// This operator performs a memberwise addition of both vectors, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector3& operator +=(Vector3& left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator -= +/// +/// This operator performs a memberwise subtraction of both vectors, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector3& operator -=(Vector3& left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator + +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Memberwise addition of both vectors +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator +(const Vector3& left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator - +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Memberwise subtraction of both vectors +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator -(const Vector3& left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator * +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Memberwise multiplication by \a right +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator *(const Vector3& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator * +/// +/// \param left Left operand (a scalar value) +/// \param right Right operand (a vector) +/// +/// \return Memberwise multiplication by \a left +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator *(T left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator *= +/// +/// This operator performs a memberwise multiplication by \a right, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector3& operator *=(Vector3& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator / +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Memberwise division by \a right +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator /(const Vector3& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator /= +/// +/// This operator performs a memberwise division by \a right, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector3& operator /=(Vector3& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator == +/// +/// This operator compares strict equality between two vectors. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return True if \a left is equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator ==(const Vector3& left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator != +/// +/// This operator compares strict difference between two vectors. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return True if \a left is not equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator !=(const Vector3& left, const Vector3& right); + +#include + +// Define the most common types +typedef Vector3 Vector3i; +typedef Vector3 Vector3f; + +} // namespace sf + + +#endif // SFML_VECTOR3_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Vector3 +/// \ingroup system +/// +/// sf::Vector3 is a simple class that defines a mathematical +/// vector with three coordinates (x, y and z). It can be used to +/// represent anything that has three dimensions: a size, a point, +/// a velocity, etc. +/// +/// The template parameter T is the type of the coordinates. It +/// can be any type that supports arithmetic operations (+, -, /, *) +/// and comparisons (==, !=), for example int or float. +/// +/// You generally don't have to care about the templated form (sf::Vector3), +/// the most common specializations have special typedefs: +/// \li sf::Vector3 is sf::Vector3f +/// \li sf::Vector3 is sf::Vector3i +/// +/// The sf::Vector3 class has a small and simple interface, its x and y members +/// can be accessed directly (there's no accessor like setX(), getX()) and it +/// contains no mathematical function like dot product, cross product, length, etc. +/// +/// Usage example: +/// \code +/// sf::Vector3f v1(16.5f, 24.f, -8.2f); +/// v1.x = 18.2f; +/// float y = v1.y; +/// float z = v1.z; +/// +/// sf::Vector3f v2 = v1 * 5.f; +/// sf::Vector3f v3; +/// v3 = v1 + v2; +/// +/// bool different = (v2 != v3); +/// \endcode +/// +/// Note: for 2-dimensional vectors, see sf::Vector2. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Vector3.inl b/include/SFML/System/Vector3.inl index 4c3d9d55..af8dae35 100644 --- a/include/SFML/System/Vector3.inl +++ b/include/SFML/System/Vector3.inl @@ -1,168 +1,168 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -template -inline Vector3::Vector3() : -x(0), -y(0), -z(0) -{ - -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3::Vector3(T X, T Y, T Z) : -x(X), -y(Y), -z(Z) -{ - -} - - -//////////////////////////////////////////////////////////// -template -template -inline Vector3::Vector3(const Vector3& vector) : -x(static_cast(vector.x)), -y(static_cast(vector.y)), -z(static_cast(vector.z)) -{ -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3 operator -(const Vector3& left) -{ - return Vector3(-left.x, -left.y, -left.z); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3& operator +=(Vector3& left, const Vector3& right) -{ - left.x += right.x; - left.y += right.y; - left.z += right.z; - - return left; -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3& operator -=(Vector3& left, const Vector3& right) -{ - left.x -= right.x; - left.y -= right.y; - left.z -= right.z; - - return left; -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3 operator +(const Vector3& left, const Vector3& right) -{ - return Vector3(left.x + right.x, left.y + right.y, left.z + right.z); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3 operator -(const Vector3& left, const Vector3& right) -{ - return Vector3(left.x - right.x, left.y - right.y, left.z - right.z); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3 operator *(const Vector3& left, T right) -{ - return Vector3(left.x * right, left.y * right, left.z * right); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3 operator *(T left, const Vector3& right) -{ - return Vector3(right.x * left, right.y * left, right.z * left); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3& operator *=(Vector3& left, T right) -{ - left.x *= right; - left.y *= right; - left.z *= right; - - return left; -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3 operator /(const Vector3& left, T right) -{ - return Vector3(left.x / right, left.y / right, left.z / right); -} - - -//////////////////////////////////////////////////////////// -template -inline Vector3& operator /=(Vector3& left, T right) -{ - left.x /= right; - left.y /= right; - left.z /= right; - - return left; -} - - -//////////////////////////////////////////////////////////// -template -inline bool operator ==(const Vector3& left, const Vector3& right) -{ - return (left.x == right.x) && (left.y == right.y) && (left.z == right.z); -} - - -//////////////////////////////////////////////////////////// -template -inline bool operator !=(const Vector3& left, const Vector3& right) -{ - return (left.x != right.x) || (left.y != right.y) || (left.z != right.z); -} +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +template +inline Vector3::Vector3() : +x(0), +y(0), +z(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3::Vector3(T X, T Y, T Z) : +x(X), +y(Y), +z(Z) +{ + +} + + +//////////////////////////////////////////////////////////// +template +template +inline Vector3::Vector3(const Vector3& vector) : +x(static_cast(vector.x)), +y(static_cast(vector.y)), +z(static_cast(vector.z)) +{ +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator -(const Vector3& left) +{ + return Vector3(-left.x, -left.y, -left.z); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator +=(Vector3& left, const Vector3& right) +{ + left.x += right.x; + left.y += right.y; + left.z += right.z; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator -=(Vector3& left, const Vector3& right) +{ + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator +(const Vector3& left, const Vector3& right) +{ + return Vector3(left.x + right.x, left.y + right.y, left.z + right.z); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator -(const Vector3& left, const Vector3& right) +{ + return Vector3(left.x - right.x, left.y - right.y, left.z - right.z); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator *(const Vector3& left, T right) +{ + return Vector3(left.x * right, left.y * right, left.z * right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator *(T left, const Vector3& right) +{ + return Vector3(right.x * left, right.y * left, right.z * left); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator *=(Vector3& left, T right) +{ + left.x *= right; + left.y *= right; + left.z *= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator /(const Vector3& left, T right) +{ + return Vector3(left.x / right, left.y / right, left.z / right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator /=(Vector3& left, T right) +{ + left.x /= right; + left.y /= right; + left.z /= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator ==(const Vector3& left, const Vector3& right) +{ + return (left.x == right.x) && (left.y == right.y) && (left.z == right.z); +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator !=(const Vector3& left, const Vector3& right) +{ + return (left.x != right.x) || (left.y != right.y) || (left.z != right.z); +} diff --git a/include/SFML/Window.hpp b/include/SFML/Window.hpp index 49f45f83..30b317ba 100644 --- a/include/SFML/Window.hpp +++ b/include/SFML/Window.hpp @@ -1,55 +1,55 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SFML_WINDOW_HPP -#define SFML_SFML_WINDOW_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -#endif // SFML_SFML_WINDOW_HPP - -//////////////////////////////////////////////////////////// -/// \defgroup window Window module -/// -/// Provides OpenGL-based windows, and abstractions for -/// events and input handling. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SFML_WINDOW_HPP +#define SFML_SFML_WINDOW_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#endif // SFML_SFML_WINDOW_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup window Window module +/// +/// Provides OpenGL-based windows, and abstractions for +/// events and input handling. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Window/Context.hpp b/include/SFML/Window/Context.hpp index ecbe7998..828ba6f7 100644 --- a/include/SFML/Window/Context.hpp +++ b/include/SFML/Window/Context.hpp @@ -1,140 +1,140 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_CONTEXT_HPP -#define SFML_CONTEXT_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ - class GlContext; -} - -//////////////////////////////////////////////////////////// -/// \brief Class holding a valid drawing context -/// -//////////////////////////////////////////////////////////// -class SFML_WINDOW_API Context : GlResource, NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// The constructor creates and activates the context - /// - //////////////////////////////////////////////////////////// - Context(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - /// The destructor deactivates and destroys the context - /// - //////////////////////////////////////////////////////////// - ~Context(); - - //////////////////////////////////////////////////////////// - /// \brief Activate or deactivate explicitely the context - /// - /// \param active True to activate, false to deactivate - /// - /// \return True on success, false on failure - /// - //////////////////////////////////////////////////////////// - bool setActive(bool active); - -public : - - //////////////////////////////////////////////////////////// - /// \brief Construct a in-memory context - /// - /// This constructor is for internal use, you don't need - /// to bother with it. - /// - /// \param settings Creation parameters - /// \param width Back buffer width - /// \param height Back buffer height - /// - //////////////////////////////////////////////////////////// - Context(const ContextSettings& settings, unsigned int width, unsigned int height); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - priv::GlContext* m_context; ///< Internal OpenGL context -}; - -} // namespace sf - - -#endif // SFML_CONTEXT_HPP - -//////////////////////////////////////////////////////////// -/// \class sf::Context -/// \ingroup window -/// -/// If you need to make OpenGL calls without having an -/// active window (like in a thread), you can use an -/// instance of this class to get a valid context. -/// -/// Having a valid context is necessary for *every* OpenGL call. -/// -/// Note that a context is only active in its current thread, -/// if you create a new thread it will have no valid context -/// by default. -/// -/// To use a sf::Context instance, just construct it and let it -/// live as long as you need a valid context. No explicit activation -/// is needed, all it has to do is to exist. Its destructor -/// will take care of deactivating and freeing all the attached -/// resources. -/// -/// Usage example: -/// \code -/// void threadFunction(void*) -/// { -/// sf::Context context; -/// // from now on, you have a valid context -/// -/// // you can make OpenGL calls -/// glClear(GL_DEPTH_BUFFER_BIT); -/// } -/// // the context is automatically deactivated and destroyed -/// // by the sf::Context destructor -/// \endcode -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CONTEXT_HPP +#define SFML_CONTEXT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class GlContext; +} + +//////////////////////////////////////////////////////////// +/// \brief Class holding a valid drawing context +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API Context : GlResource, NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// The constructor creates and activates the context + /// + //////////////////////////////////////////////////////////// + Context(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// The destructor deactivates and destroys the context + /// + //////////////////////////////////////////////////////////// + ~Context(); + + //////////////////////////////////////////////////////////// + /// \brief Activate or deactivate explicitely the context + /// + /// \param active True to activate, false to deactivate + /// + /// \return True on success, false on failure + /// + //////////////////////////////////////////////////////////// + bool setActive(bool active); + +public: + + //////////////////////////////////////////////////////////// + /// \brief Construct a in-memory context + /// + /// This constructor is for internal use, you don't need + /// to bother with it. + /// + /// \param settings Creation parameters + /// \param width Back buffer width + /// \param height Back buffer height + /// + //////////////////////////////////////////////////////////// + Context(const ContextSettings& settings, unsigned int width, unsigned int height); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::GlContext* m_context; ///< Internal OpenGL context +}; + +} // namespace sf + + +#endif // SFML_CONTEXT_HPP + +//////////////////////////////////////////////////////////// +/// \class sf::Context +/// \ingroup window +/// +/// If you need to make OpenGL calls without having an +/// active window (like in a thread), you can use an +/// instance of this class to get a valid context. +/// +/// Having a valid context is necessary for *every* OpenGL call. +/// +/// Note that a context is only active in its current thread, +/// if you create a new thread it will have no valid context +/// by default. +/// +/// To use a sf::Context instance, just construct it and let it +/// live as long as you need a valid context. No explicit activation +/// is needed, all it has to do is to exist. Its destructor +/// will take care of deactivating and freeing all the attached +/// resources. +/// +/// Usage example: +/// \code +/// void threadFunction(void*) +/// { +/// sf::Context context; +/// // from now on, you have a valid context +/// +/// // you can make OpenGL calls +/// glClear(GL_DEPTH_BUFFER_BIT); +/// } +/// // the context is automatically deactivated and destroyed +/// // by the sf::Context destructor +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Window/ContextSettings.hpp b/include/SFML/Window/ContextSettings.hpp index d1d4fd4a..da89b2fd 100644 --- a/include/SFML/Window/ContextSettings.hpp +++ b/include/SFML/Window/ContextSettings.hpp @@ -1,104 +1,104 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_CONTEXTSETTINGS_HPP -#define SFML_CONTEXTSETTINGS_HPP - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Structure defining the settings of the OpenGL -/// context attached to a window -/// -//////////////////////////////////////////////////////////// -struct ContextSettings -{ - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// \param depth Depth buffer bits - /// \param stencil Stencil buffer bits - /// \param antialiasing Antialiasing level - /// \param major Major number of the context version - /// \param minor Minor number of the context version - /// - //////////////////////////////////////////////////////////// - explicit ContextSettings(unsigned int depth = 0, unsigned int stencil = 0, unsigned int antialiasing = 0, unsigned int major = 2, unsigned int minor = 0) : - depthBits (depth), - stencilBits (stencil), - antialiasingLevel(antialiasing), - majorVersion (major), - minorVersion (minor) - { - } - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - unsigned int depthBits; ///< Bits of the depth buffer - unsigned int stencilBits; ///< Bits of the stencil buffer - unsigned int antialiasingLevel; ///< Level of antialiasing - unsigned int majorVersion; ///< Major number of the context version to create - unsigned int minorVersion; ///< Minor number of the context version to create -}; - -} // namespace sf - - -#endif // SFML_CONTEXTSETTINGS_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::ContextSettings -/// \ingroup window -/// -/// ContextSettings allows to define several advanced settings -/// of the OpenGL context attached to a window. All these -/// settings have no impact on the regular SFML rendering -/// (graphics module) -- except the anti-aliasing level, so -/// you may need to use this structure only if you're using -/// SFML as a windowing system for custom OpenGL rendering. -/// -/// The depthBits and stencilBits members define the number -/// of bits per pixel requested for the (respectively) depth -/// and stencil buffers. -/// -/// antialiasingLevel represents the requested number of -/// multisampling levels for anti-aliasing. -/// -/// majorVersion and minorVersion define the version of the -/// OpenGL context that you want. Only versions greater or -/// equal to 3.0 are relevant; versions lesser than 3.0 are -/// all handled the same way (i.e. you can use any version -/// < 3.0 if you don't want an OpenGL 3 context). -/// -/// Please note that these values are only a hint. -/// No failure will be reported if one or more of these values -/// are not supported by the system; instead, SFML will try to -/// find the closest valid match. You can then retrieve the -/// settings that the window actually used to create its context, -/// with Window::getSettings(). -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CONTEXTSETTINGS_HPP +#define SFML_CONTEXTSETTINGS_HPP + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Structure defining the settings of the OpenGL +/// context attached to a window +/// +//////////////////////////////////////////////////////////// +struct ContextSettings +{ + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param depth Depth buffer bits + /// \param stencil Stencil buffer bits + /// \param antialiasing Antialiasing level + /// \param major Major number of the context version + /// \param minor Minor number of the context version + /// + //////////////////////////////////////////////////////////// + explicit ContextSettings(unsigned int depth = 0, unsigned int stencil = 0, unsigned int antialiasing = 0, unsigned int major = 2, unsigned int minor = 0) : + depthBits (depth), + stencilBits (stencil), + antialiasingLevel(antialiasing), + majorVersion (major), + minorVersion (minor) + { + } + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int depthBits; ///< Bits of the depth buffer + unsigned int stencilBits; ///< Bits of the stencil buffer + unsigned int antialiasingLevel; ///< Level of antialiasing + unsigned int majorVersion; ///< Major number of the context version to create + unsigned int minorVersion; ///< Minor number of the context version to create +}; + +} // namespace sf + + +#endif // SFML_CONTEXTSETTINGS_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::ContextSettings +/// \ingroup window +/// +/// ContextSettings allows to define several advanced settings +/// of the OpenGL context attached to a window. All these +/// settings have no impact on the regular SFML rendering +/// (graphics module) -- except the anti-aliasing level, so +/// you may need to use this structure only if you're using +/// SFML as a windowing system for custom OpenGL rendering. +/// +/// The depthBits and stencilBits members define the number +/// of bits per pixel requested for the (respectively) depth +/// and stencil buffers. +/// +/// antialiasingLevel represents the requested number of +/// multisampling levels for anti-aliasing. +/// +/// majorVersion and minorVersion define the version of the +/// OpenGL context that you want. Only versions greater or +/// equal to 3.0 are relevant; versions lesser than 3.0 are +/// all handled the same way (i.e. you can use any version +/// < 3.0 if you don't want an OpenGL 3 context). +/// +/// Please note that these values are only a hint. +/// No failure will be reported if one or more of these values +/// are not supported by the system; instead, SFML will try to +/// find the closest valid match. You can then retrieve the +/// settings that the window actually used to create its context, +/// with Window::getSettings(). +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Window/Event.hpp b/include/SFML/Window/Event.hpp index 7e2f1f02..85293540 100644 --- a/include/SFML/Window/Event.hpp +++ b/include/SFML/Window/Event.hpp @@ -1,267 +1,267 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_EVENT_HPP -#define SFML_EVENT_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Defines a system event and its parameters -/// -//////////////////////////////////////////////////////////// -class Event -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Size events parameters (Resized) - /// - //////////////////////////////////////////////////////////// - struct SizeEvent - { - unsigned int width; ///< New width, in pixels - unsigned int height; ///< New height, in pixels - }; - - //////////////////////////////////////////////////////////// - /// \brief Keyboard event parameters (KeyPressed, KeyReleased) - /// - //////////////////////////////////////////////////////////// - struct KeyEvent - { - Keyboard::Key code; ///< Code of the key that has been pressed - bool alt; ///< Is the Alt key pressed? - bool control; ///< Is the Control key pressed? - bool shift; ///< Is the Shift key pressed? - bool system; ///< Is the System key pressed? - }; - - //////////////////////////////////////////////////////////// - /// \brief Text event parameters (TextEntered) - /// - //////////////////////////////////////////////////////////// - struct TextEvent - { - Uint32 unicode; ///< UTF-32 unicode value of the character - }; - - //////////////////////////////////////////////////////////// - /// \brief Mouse move event parameters (MouseMoved) - /// - //////////////////////////////////////////////////////////// - struct MouseMoveEvent - { - int x; ///< X position of the mouse pointer, relative to the left of the owner window - int y; ///< Y position of the mouse pointer, relative to the top of the owner window - }; - - //////////////////////////////////////////////////////////// - /// \brief Mouse buttons events parameters - /// (MouseButtonPressed, MouseButtonReleased) - /// - //////////////////////////////////////////////////////////// - struct MouseButtonEvent - { - Mouse::Button button; ///< Code of the button that has been pressed - int x; ///< X position of the mouse pointer, relative to the left of the owner window - int y; ///< Y position of the mouse pointer, relative to the top of the owner window - }; - - //////////////////////////////////////////////////////////// - /// \brief Mouse wheel events parameters (MouseWheelMoved) - /// - //////////////////////////////////////////////////////////// - struct MouseWheelEvent - { - int delta; ///< Number of ticks the wheel has moved (positive is up, negative is down) - int x; ///< X position of the mouse pointer, relative to the left of the owner window - int y; ///< Y position of the mouse pointer, relative to the top of the owner window - }; - - //////////////////////////////////////////////////////////// - /// \brief Joystick connection events parameters - /// (JoystickConnected, JoystickDisconnected) - /// - //////////////////////////////////////////////////////////// - struct JoystickConnectEvent - { - unsigned int joystickId; ///< Index of the joystick (in range [0 .. Joystick::Count - 1]) - }; - - //////////////////////////////////////////////////////////// - /// \brief Joystick axis move event parameters (JoystickMoved) - /// - //////////////////////////////////////////////////////////// - struct JoystickMoveEvent - { - unsigned int joystickId; ///< Index of the joystick (in range [0 .. Joystick::Count - 1]) - Joystick::Axis axis; ///< Axis on which the joystick moved - float position; ///< New position on the axis (in range [-100 .. 100]) - }; - - //////////////////////////////////////////////////////////// - /// \brief Joystick buttons events parameters - /// (JoystickButtonPressed, JoystickButtonReleased) - /// - //////////////////////////////////////////////////////////// - struct JoystickButtonEvent - { - unsigned int joystickId; ///< Index of the joystick (in range [0 .. Joystick::Count - 1]) - unsigned int button; ///< Index of the button that has been pressed (in range [0 .. Joystick::ButtonCount - 1]) - }; - - //////////////////////////////////////////////////////////// - /// \brief Touch events parameters (TouchBegan, TouchMoved, TouchEnded) - /// - //////////////////////////////////////////////////////////// - struct TouchEvent - { - unsigned int finger; ///< Index of the finger in case of multi-touch events - int x; ///< X position of the touch, relative to the left of the owner window - int y; ///< Y position of the touch, relative to the top of the owner window - }; - - //////////////////////////////////////////////////////////// - /// \brief Sensor event parameters (SensorChanged) - /// - //////////////////////////////////////////////////////////// - struct SensorEvent - { - Sensor::Type type; ///< Type of the sensor - float x; ///< Current value of the sensor on X axis - float y; ///< Current value of the sensor on Y axis - float z; ///< Current value of the sensor on Z axis - }; - - //////////////////////////////////////////////////////////// - /// \brief Enumeration of the different types of events - /// - //////////////////////////////////////////////////////////// - enum EventType - { - Closed, ///< The window requested to be closed (no data) - Resized, ///< The window was resized (data in event.size) - LostFocus, ///< The window lost the focus (no data) - GainedFocus, ///< The window gained the focus (no data) - TextEntered, ///< A character was entered (data in event.text) - KeyPressed, ///< A key was pressed (data in event.key) - KeyReleased, ///< A key was released (data in event.key) - MouseWheelMoved, ///< The mouse wheel was scrolled (data in event.mouseWheel) - MouseButtonPressed, ///< A mouse button was pressed (data in event.mouseButton) - MouseButtonReleased, ///< A mouse button was released (data in event.mouseButton) - MouseMoved, ///< The mouse cursor moved (data in event.mouseMove) - MouseEntered, ///< The mouse cursor entered the area of the window (no data) - MouseLeft, ///< The mouse cursor left the area of the window (no data) - JoystickButtonPressed, ///< A joystick button was pressed (data in event.joystickButton) - JoystickButtonReleased, ///< A joystick button was released (data in event.joystickButton) - JoystickMoved, ///< The joystick moved along an axis (data in event.joystickMove) - JoystickConnected, ///< A joystick was connected (data in event.joystickConnect) - JoystickDisconnected, ///< A joystick was disconnected (data in event.joystickConnect) - TouchBegan, ///< A touch event began (data in event.touch) - TouchMoved, ///< A touch moved (data in event.touch) - TouchEnded, ///< A touch event ended (data in event.touch) - SensorChanged, ///< A sensor value changed (data in event.sensor) - - Count ///< Keep last -- the total number of event types - }; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - EventType type; ///< Type of the event - - union - { - SizeEvent size; ///< Size event parameters (Event::Resized) - KeyEvent key; ///< Key event parameters (Event::KeyPressed, Event::KeyReleased) - TextEvent text; ///< Text event parameters (Event::TextEntered) - MouseMoveEvent mouseMove; ///< Mouse move event parameters (Event::MouseMoved) - MouseButtonEvent mouseButton; ///< Mouse button event parameters (Event::MouseButtonPressed, Event::MouseButtonReleased) - MouseWheelEvent mouseWheel; ///< Mouse wheel event parameters (Event::MouseWheelMoved) - JoystickMoveEvent joystickMove; ///< Joystick move event parameters (Event::JoystickMoved) - JoystickButtonEvent joystickButton; ///< Joystick button event parameters (Event::JoystickButtonPressed, Event::JoystickButtonReleased) - JoystickConnectEvent joystickConnect; ///< Joystick (dis)connect event parameters (Event::JoystickConnected, Event::JoystickDisconnected) - TouchEvent touch; ///< Touch events parameters (Event::TouchBegan, Event::TouchMoved, Event::TouchEnded) - SensorEvent sensor; ///< Sensor event parameters (Event::SensorChanged) - }; -}; - -} // namespace sf - - -#endif // SFML_EVENT_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Event -/// \ingroup window -/// -/// sf::Event holds all the informations about a system event -/// that just happened. Events are retrieved using the -/// sf::Window::pollEvent and sf::Window::waitEvent functions. -/// -/// A sf::Event instance contains the type of the event -/// (mouse moved, key pressed, window closed, ...) as well -/// as the details about this particular event. Please note that -/// the event parameters are defined in a union, which means that -/// only the member matching the type of the event will be properly -/// filled; all other members will have undefined values and must not -/// be read if the type of the event doesn't match. For example, -/// if you received a KeyPressed event, then you must read the -/// event.key member, all other members such as event.MouseMove -/// or event.text will have undefined values. -/// -/// Usage example: -/// \code -/// sf::Event event; -/// while (window.pollEvent(event)) -/// { -/// // Request for closing the window -/// if (event.type == sf::Event::Closed) -/// window.close(); -/// -/// // The escape key was pressed -/// if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) -/// window.close(); -/// -/// // The window was resized -/// if (event.type == sf::Event::Resized) -/// doSomethingWithTheNewSize(event.size.width, event.size.height); -/// -/// // etc ... -/// } -/// \endcode -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_EVENT_HPP +#define SFML_EVENT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Defines a system event and its parameters +/// +//////////////////////////////////////////////////////////// +class Event +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Size events parameters (Resized) + /// + //////////////////////////////////////////////////////////// + struct SizeEvent + { + unsigned int width; ///< New width, in pixels + unsigned int height; ///< New height, in pixels + }; + + //////////////////////////////////////////////////////////// + /// \brief Keyboard event parameters (KeyPressed, KeyReleased) + /// + //////////////////////////////////////////////////////////// + struct KeyEvent + { + Keyboard::Key code; ///< Code of the key that has been pressed + bool alt; ///< Is the Alt key pressed? + bool control; ///< Is the Control key pressed? + bool shift; ///< Is the Shift key pressed? + bool system; ///< Is the System key pressed? + }; + + //////////////////////////////////////////////////////////// + /// \brief Text event parameters (TextEntered) + /// + //////////////////////////////////////////////////////////// + struct TextEvent + { + Uint32 unicode; ///< UTF-32 unicode value of the character + }; + + //////////////////////////////////////////////////////////// + /// \brief Mouse move event parameters (MouseMoved) + /// + //////////////////////////////////////////////////////////// + struct MouseMoveEvent + { + int x; ///< X position of the mouse pointer, relative to the left of the owner window + int y; ///< Y position of the mouse pointer, relative to the top of the owner window + }; + + //////////////////////////////////////////////////////////// + /// \brief Mouse buttons events parameters + /// (MouseButtonPressed, MouseButtonReleased) + /// + //////////////////////////////////////////////////////////// + struct MouseButtonEvent + { + Mouse::Button button; ///< Code of the button that has been pressed + int x; ///< X position of the mouse pointer, relative to the left of the owner window + int y; ///< Y position of the mouse pointer, relative to the top of the owner window + }; + + //////////////////////////////////////////////////////////// + /// \brief Mouse wheel events parameters (MouseWheelMoved) + /// + //////////////////////////////////////////////////////////// + struct MouseWheelEvent + { + int delta; ///< Number of ticks the wheel has moved (positive is up, negative is down) + int x; ///< X position of the mouse pointer, relative to the left of the owner window + int y; ///< Y position of the mouse pointer, relative to the top of the owner window + }; + + //////////////////////////////////////////////////////////// + /// \brief Joystick connection events parameters + /// (JoystickConnected, JoystickDisconnected) + /// + //////////////////////////////////////////////////////////// + struct JoystickConnectEvent + { + unsigned int joystickId; ///< Index of the joystick (in range [0 .. Joystick::Count - 1]) + }; + + //////////////////////////////////////////////////////////// + /// \brief Joystick axis move event parameters (JoystickMoved) + /// + //////////////////////////////////////////////////////////// + struct JoystickMoveEvent + { + unsigned int joystickId; ///< Index of the joystick (in range [0 .. Joystick::Count - 1]) + Joystick::Axis axis; ///< Axis on which the joystick moved + float position; ///< New position on the axis (in range [-100 .. 100]) + }; + + //////////////////////////////////////////////////////////// + /// \brief Joystick buttons events parameters + /// (JoystickButtonPressed, JoystickButtonReleased) + /// + //////////////////////////////////////////////////////////// + struct JoystickButtonEvent + { + unsigned int joystickId; ///< Index of the joystick (in range [0 .. Joystick::Count - 1]) + unsigned int button; ///< Index of the button that has been pressed (in range [0 .. Joystick::ButtonCount - 1]) + }; + + //////////////////////////////////////////////////////////// + /// \brief Touch events parameters (TouchBegan, TouchMoved, TouchEnded) + /// + //////////////////////////////////////////////////////////// + struct TouchEvent + { + unsigned int finger; ///< Index of the finger in case of multi-touch events + int x; ///< X position of the touch, relative to the left of the owner window + int y; ///< Y position of the touch, relative to the top of the owner window + }; + + //////////////////////////////////////////////////////////// + /// \brief Sensor event parameters (SensorChanged) + /// + //////////////////////////////////////////////////////////// + struct SensorEvent + { + Sensor::Type type; ///< Type of the sensor + float x; ///< Current value of the sensor on X axis + float y; ///< Current value of the sensor on Y axis + float z; ///< Current value of the sensor on Z axis + }; + + //////////////////////////////////////////////////////////// + /// \brief Enumeration of the different types of events + /// + //////////////////////////////////////////////////////////// + enum EventType + { + Closed, ///< The window requested to be closed (no data) + Resized, ///< The window was resized (data in event.size) + LostFocus, ///< The window lost the focus (no data) + GainedFocus, ///< The window gained the focus (no data) + TextEntered, ///< A character was entered (data in event.text) + KeyPressed, ///< A key was pressed (data in event.key) + KeyReleased, ///< A key was released (data in event.key) + MouseWheelMoved, ///< The mouse wheel was scrolled (data in event.mouseWheel) + MouseButtonPressed, ///< A mouse button was pressed (data in event.mouseButton) + MouseButtonReleased, ///< A mouse button was released (data in event.mouseButton) + MouseMoved, ///< The mouse cursor moved (data in event.mouseMove) + MouseEntered, ///< The mouse cursor entered the area of the window (no data) + MouseLeft, ///< The mouse cursor left the area of the window (no data) + JoystickButtonPressed, ///< A joystick button was pressed (data in event.joystickButton) + JoystickButtonReleased, ///< A joystick button was released (data in event.joystickButton) + JoystickMoved, ///< The joystick moved along an axis (data in event.joystickMove) + JoystickConnected, ///< A joystick was connected (data in event.joystickConnect) + JoystickDisconnected, ///< A joystick was disconnected (data in event.joystickConnect) + TouchBegan, ///< A touch event began (data in event.touch) + TouchMoved, ///< A touch moved (data in event.touch) + TouchEnded, ///< A touch event ended (data in event.touch) + SensorChanged, ///< A sensor value changed (data in event.sensor) + + Count ///< Keep last -- the total number of event types + }; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + EventType type; ///< Type of the event + + union + { + SizeEvent size; ///< Size event parameters (Event::Resized) + KeyEvent key; ///< Key event parameters (Event::KeyPressed, Event::KeyReleased) + TextEvent text; ///< Text event parameters (Event::TextEntered) + MouseMoveEvent mouseMove; ///< Mouse move event parameters (Event::MouseMoved) + MouseButtonEvent mouseButton; ///< Mouse button event parameters (Event::MouseButtonPressed, Event::MouseButtonReleased) + MouseWheelEvent mouseWheel; ///< Mouse wheel event parameters (Event::MouseWheelMoved) + JoystickMoveEvent joystickMove; ///< Joystick move event parameters (Event::JoystickMoved) + JoystickButtonEvent joystickButton; ///< Joystick button event parameters (Event::JoystickButtonPressed, Event::JoystickButtonReleased) + JoystickConnectEvent joystickConnect; ///< Joystick (dis)connect event parameters (Event::JoystickConnected, Event::JoystickDisconnected) + TouchEvent touch; ///< Touch events parameters (Event::TouchBegan, Event::TouchMoved, Event::TouchEnded) + SensorEvent sensor; ///< Sensor event parameters (Event::SensorChanged) + }; +}; + +} // namespace sf + + +#endif // SFML_EVENT_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Event +/// \ingroup window +/// +/// sf::Event holds all the informations about a system event +/// that just happened. Events are retrieved using the +/// sf::Window::pollEvent and sf::Window::waitEvent functions. +/// +/// A sf::Event instance contains the type of the event +/// (mouse moved, key pressed, window closed, ...) as well +/// as the details about this particular event. Please note that +/// the event parameters are defined in a union, which means that +/// only the member matching the type of the event will be properly +/// filled; all other members will have undefined values and must not +/// be read if the type of the event doesn't match. For example, +/// if you received a KeyPressed event, then you must read the +/// event.key member, all other members such as event.MouseMove +/// or event.text will have undefined values. +/// +/// Usage example: +/// \code +/// sf::Event event; +/// while (window.pollEvent(event)) +/// { +/// // Request for closing the window +/// if (event.type == sf::Event::Closed) +/// window.close(); +/// +/// // The escape key was pressed +/// if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) +/// window.close(); +/// +/// // The window was resized +/// if (event.type == sf::Event::Resized) +/// doSomethingWithTheNewSize(event.size.width, event.size.height); +/// +/// // etc ... +/// } +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Window/GlResource.hpp b/include/SFML/Window/GlResource.hpp index 52a67f76..47970fb4 100644 --- a/include/SFML/Window/GlResource.hpp +++ b/include/SFML/Window/GlResource.hpp @@ -1,76 +1,76 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_GLRESOURCE_HPP -#define SFML_GLRESOURCE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Base class for classes that require an OpenGL context -/// -//////////////////////////////////////////////////////////// -class SFML_WINDOW_API GlResource -{ -protected : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - GlResource(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~GlResource(); - - //////////////////////////////////////////////////////////// - /// \brief Make sure that a valid OpenGL context exists in the current thread - /// - //////////////////////////////////////////////////////////// - static void ensureGlContext(); -}; - -} // namespace sf - - -#endif // SFML_GLRESOURCE_HPP - -//////////////////////////////////////////////////////////// -/// \class sf::GlResource -/// \ingroup window -/// -/// This class is for internal use only, it must be the base -/// of every class that requires a valid OpenGL context in -/// order to work. -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GLRESOURCE_HPP +#define SFML_GLRESOURCE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Base class for classes that require an OpenGL context +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API GlResource +{ +protected: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + GlResource(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~GlResource(); + + //////////////////////////////////////////////////////////// + /// \brief Make sure that a valid OpenGL context exists in the current thread + /// + //////////////////////////////////////////////////////////// + static void ensureGlContext(); +}; + +} // namespace sf + + +#endif // SFML_GLRESOURCE_HPP + +//////////////////////////////////////////////////////////// +/// \class sf::GlResource +/// \ingroup window +/// +/// This class is for internal use only, it must be the base +/// of every class that requires a valid OpenGL context in +/// order to work. +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Window/Joystick.hpp b/include/SFML/Window/Joystick.hpp index ccceb15c..85705aa3 100644 --- a/include/SFML/Window/Joystick.hpp +++ b/include/SFML/Window/Joystick.hpp @@ -40,7 +40,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_WINDOW_API Joystick { -public : +public: //////////////////////////////////////////////////////////// /// \brief Constants related to joysticks capabilities diff --git a/include/SFML/Window/Keyboard.hpp b/include/SFML/Window/Keyboard.hpp index 78211169..5dd0d63b 100644 --- a/include/SFML/Window/Keyboard.hpp +++ b/include/SFML/Window/Keyboard.hpp @@ -39,7 +39,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_WINDOW_API Keyboard { -public : +public: //////////////////////////////////////////////////////////// /// \brief Key codes diff --git a/include/SFML/Window/Mouse.hpp b/include/SFML/Window/Mouse.hpp index 8d6b8f3a..022ecc5b 100644 --- a/include/SFML/Window/Mouse.hpp +++ b/include/SFML/Window/Mouse.hpp @@ -42,7 +42,7 @@ class Window; //////////////////////////////////////////////////////////// class SFML_WINDOW_API Mouse { -public : +public: //////////////////////////////////////////////////////////// /// \brief Mouse buttons diff --git a/include/SFML/Window/Sensor.hpp b/include/SFML/Window/Sensor.hpp index 227bb770..3edb8ee5 100644 --- a/include/SFML/Window/Sensor.hpp +++ b/include/SFML/Window/Sensor.hpp @@ -41,7 +41,7 @@ namespace sf //////////////////////////////////////////////////////////// class SFML_WINDOW_API Sensor { -public : +public: //////////////////////////////////////////////////////////// /// \brief Sensor type diff --git a/include/SFML/Window/Touch.hpp b/include/SFML/Window/Touch.hpp index d8c4fcd1..b9e32bc0 100644 --- a/include/SFML/Window/Touch.hpp +++ b/include/SFML/Window/Touch.hpp @@ -42,7 +42,7 @@ class Window; //////////////////////////////////////////////////////////// class SFML_WINDOW_API Touch { -public : +public: //////////////////////////////////////////////////////////// /// \brief Check if a touch event is currently down diff --git a/include/SFML/Window/VideoMode.hpp b/include/SFML/Window/VideoMode.hpp index 0d725a1a..5f7fdb57 100644 --- a/include/SFML/Window/VideoMode.hpp +++ b/include/SFML/Window/VideoMode.hpp @@ -1,228 +1,228 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_VIDEOMODE_HPP -#define SFML_VIDEOMODE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief VideoMode defines a video mode (width, height, bpp) -/// -//////////////////////////////////////////////////////////// -class SFML_WINDOW_API VideoMode -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructors initializes all members to 0. - /// - //////////////////////////////////////////////////////////// - VideoMode(); - - //////////////////////////////////////////////////////////// - /// \brief Construct the video mode with its attributes - /// - /// \param modeWidth Width in pixels - /// \param modeHeight Height in pixels - /// \param modeBitsPerPixel Pixel depths in bits per pixel - /// - //////////////////////////////////////////////////////////// - VideoMode(unsigned int modeWidth, unsigned int modeHeight, unsigned int modeBitsPerPixel = 32); - - //////////////////////////////////////////////////////////// - /// \brief Get the current desktop video mode - /// - /// \return Current desktop video mode - /// - //////////////////////////////////////////////////////////// - static VideoMode getDesktopMode(); - - //////////////////////////////////////////////////////////// - /// \brief Retrieve all the video modes supported in fullscreen mode - /// - /// When creating a fullscreen window, the video mode is restricted - /// to be compatible with what the graphics driver and monitor - /// support. This function returns the complete list of all video - /// modes that can be used in fullscreen mode. - /// The returned array is sorted from best to worst, so that - /// the first element will always give the best mode (higher - /// width, height and bits-per-pixel). - /// - /// \return Array containing all the supported fullscreen modes - /// - //////////////////////////////////////////////////////////// - static const std::vector& getFullscreenModes(); - - //////////////////////////////////////////////////////////// - /// \brief Tell whether or not the video mode is valid - /// - /// The validity of video modes is only relevant when using - /// fullscreen windows; otherwise any video mode can be used - /// with no restriction. - /// - /// \return True if the video mode is valid for fullscreen mode - /// - //////////////////////////////////////////////////////////// - bool isValid() const; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - unsigned int width; ///< Video mode width, in pixels - unsigned int height; ///< Video mode height, in pixels - unsigned int bitsPerPixel; ///< Video mode pixel depth, in bits per pixels -}; - -//////////////////////////////////////////////////////////// -/// \relates VideoMode -/// \brief Overload of == operator to compare two video modes -/// -/// \param left Left operand (a video mode) -/// \param right Right operand (a video mode) -/// -/// \return True if modes are equal -/// -//////////////////////////////////////////////////////////// -SFML_WINDOW_API bool operator ==(const VideoMode& left, const VideoMode& right); - -//////////////////////////////////////////////////////////// -/// \relates VideoMode -/// \brief Overload of != operator to compare two video modes -/// -/// \param left Left operand (a video mode) -/// \param right Right operand (a video mode) -/// -/// \return True if modes are different -/// -//////////////////////////////////////////////////////////// -SFML_WINDOW_API bool operator !=(const VideoMode& left, const VideoMode& right); - -//////////////////////////////////////////////////////////// -/// \relates VideoMode -/// \brief Overload of < operator to compare video modes -/// -/// \param left Left operand (a video mode) -/// \param right Right operand (a video mode) -/// -/// \return True if \a left is lesser than \a right -/// -//////////////////////////////////////////////////////////// -SFML_WINDOW_API bool operator <(const VideoMode& left, const VideoMode& right); - -//////////////////////////////////////////////////////////// -/// \relates VideoMode -/// \brief Overload of > operator to compare video modes -/// -/// \param left Left operand (a video mode) -/// \param right Right operand (a video mode) -/// -/// \return True if \a left is greater than \a right -/// -//////////////////////////////////////////////////////////// -SFML_WINDOW_API bool operator >(const VideoMode& left, const VideoMode& right); - -//////////////////////////////////////////////////////////// -/// \relates VideoMode -/// \brief Overload of <= operator to compare video modes -/// -/// \param left Left operand (a video mode) -/// \param right Right operand (a video mode) -/// -/// \return True if \a left is lesser or equal than \a right -/// -//////////////////////////////////////////////////////////// -SFML_WINDOW_API bool operator <=(const VideoMode& left, const VideoMode& right); - -//////////////////////////////////////////////////////////// -/// \relates VideoMode -/// \brief Overload of >= operator to compare video modes -/// -/// \param left Left operand (a video mode) -/// \param right Right operand (a video mode) -/// -/// \return True if \a left is greater or equal than \a right -/// -//////////////////////////////////////////////////////////// -SFML_WINDOW_API bool operator >=(const VideoMode& left, const VideoMode& right); - -} // namespace sf - - -#endif // SFML_VIDEOMODE_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::VideoMode -/// \ingroup window -/// -/// A video mode is defined by a width and a height (in pixels) -/// and a depth (in bits per pixel). Video modes are used to -/// setup windows (sf::Window) at creation time. -/// -/// The main usage of video modes is for fullscreen mode: -/// indeed you must use one of the valid video modes -/// allowed by the OS (which are defined by what the monitor -/// and the graphics card support), otherwise your window -/// creation will just fail. -/// -/// sf::VideoMode provides a static function for retrieving -/// the list of all the video modes supported by the system: -/// getFullscreenModes(). -/// -/// A custom video mode can also be checked directly for -/// fullscreen compatibility with its isValid() function. -/// -/// Additionnally, sf::VideoMode provides a static function -/// to get the mode currently used by the desktop: getDesktopMode(). -/// This allows to build windows with the same size or pixel -/// depth as the current resolution. -/// -/// Usage example: -/// \code -/// // Display the list of all the video modes available for fullscreen -/// std::vector modes = sf::VideoMode::getFullscreenModes(); -/// for (std::size_t i = 0; i < modes.size(); ++i) -/// { -/// sf::VideoMode mode = modes[i]; -/// std::cout << "Mode #" << i << ": " -/// << mode.width << "x" << mode.height << " - " -/// << mode.bitsPerPixel << " bpp" << std::endl; -/// } -/// -/// // Create a window with the same pixel depth as the desktop -/// sf::VideoMode desktop = sf::VideoMode::getDesktopMode(); -/// window.create(sf::VideoMode(1024, 768, desktop.bitsPerPixel), "SFML window"); -/// \endcode -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VIDEOMODE_HPP +#define SFML_VIDEOMODE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief VideoMode defines a video mode (width, height, bpp) +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API VideoMode +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructors initializes all members to 0. + /// + //////////////////////////////////////////////////////////// + VideoMode(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the video mode with its attributes + /// + /// \param modeWidth Width in pixels + /// \param modeHeight Height in pixels + /// \param modeBitsPerPixel Pixel depths in bits per pixel + /// + //////////////////////////////////////////////////////////// + VideoMode(unsigned int modeWidth, unsigned int modeHeight, unsigned int modeBitsPerPixel = 32); + + //////////////////////////////////////////////////////////// + /// \brief Get the current desktop video mode + /// + /// \return Current desktop video mode + /// + //////////////////////////////////////////////////////////// + static VideoMode getDesktopMode(); + + //////////////////////////////////////////////////////////// + /// \brief Retrieve all the video modes supported in fullscreen mode + /// + /// When creating a fullscreen window, the video mode is restricted + /// to be compatible with what the graphics driver and monitor + /// support. This function returns the complete list of all video + /// modes that can be used in fullscreen mode. + /// The returned array is sorted from best to worst, so that + /// the first element will always give the best mode (higher + /// width, height and bits-per-pixel). + /// + /// \return Array containing all the supported fullscreen modes + /// + //////////////////////////////////////////////////////////// + static const std::vector& getFullscreenModes(); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether or not the video mode is valid + /// + /// The validity of video modes is only relevant when using + /// fullscreen windows; otherwise any video mode can be used + /// with no restriction. + /// + /// \return True if the video mode is valid for fullscreen mode + /// + //////////////////////////////////////////////////////////// + bool isValid() const; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int width; ///< Video mode width, in pixels + unsigned int height; ///< Video mode height, in pixels + unsigned int bitsPerPixel; ///< Video mode pixel depth, in bits per pixels +}; + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of == operator to compare two video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if modes are equal +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator ==(const VideoMode& left, const VideoMode& right); + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of != operator to compare two video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if modes are different +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator !=(const VideoMode& left, const VideoMode& right); + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of < operator to compare video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if \a left is lesser than \a right +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator <(const VideoMode& left, const VideoMode& right); + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of > operator to compare video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if \a left is greater than \a right +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator >(const VideoMode& left, const VideoMode& right); + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of <= operator to compare video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if \a left is lesser or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator <=(const VideoMode& left, const VideoMode& right); + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of >= operator to compare video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if \a left is greater or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator >=(const VideoMode& left, const VideoMode& right); + +} // namespace sf + + +#endif // SFML_VIDEOMODE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::VideoMode +/// \ingroup window +/// +/// A video mode is defined by a width and a height (in pixels) +/// and a depth (in bits per pixel). Video modes are used to +/// setup windows (sf::Window) at creation time. +/// +/// The main usage of video modes is for fullscreen mode: +/// indeed you must use one of the valid video modes +/// allowed by the OS (which are defined by what the monitor +/// and the graphics card support), otherwise your window +/// creation will just fail. +/// +/// sf::VideoMode provides a static function for retrieving +/// the list of all the video modes supported by the system: +/// getFullscreenModes(). +/// +/// A custom video mode can also be checked directly for +/// fullscreen compatibility with its isValid() function. +/// +/// Additionnally, sf::VideoMode provides a static function +/// to get the mode currently used by the desktop: getDesktopMode(). +/// This allows to build windows with the same size or pixel +/// depth as the current resolution. +/// +/// Usage example: +/// \code +/// // Display the list of all the video modes available for fullscreen +/// std::vector modes = sf::VideoMode::getFullscreenModes(); +/// for (std::size_t i = 0; i < modes.size(); ++i) +/// { +/// sf::VideoMode mode = modes[i]; +/// std::cout << "Mode #" << i << ": " +/// << mode.width << "x" << mode.height << " - " +/// << mode.bitsPerPixel << " bpp" << std::endl; +/// } +/// +/// // Create a window with the same pixel depth as the desktop +/// sf::VideoMode desktop = sf::VideoMode::getDesktopMode(); +/// window.create(sf::VideoMode(1024, 768, desktop.bitsPerPixel), "SFML window"); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Window/Window.hpp b/include/SFML/Window/Window.hpp index 4aa191fe..2076f8e0 100644 --- a/include/SFML/Window/Window.hpp +++ b/include/SFML/Window/Window.hpp @@ -1,555 +1,555 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_WINDOW_HPP -#define SFML_WINDOW_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ - class GlContext; - class WindowImpl; -} - -class Event; - -//////////////////////////////////////////////////////////// -/// \brief Window that serves as a target for OpenGL rendering -/// -//////////////////////////////////////////////////////////// -class SFML_WINDOW_API Window : GlResource, NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor doesn't actually create the window, - /// use the other constructors or call create() to do so. - /// - //////////////////////////////////////////////////////////// - Window(); - - //////////////////////////////////////////////////////////// - /// \brief Construct a new window - /// - /// This constructor creates the window with the size and pixel - /// depth defined in \a mode. An optional style can be passed to - /// customize the look and behaviour of the window (borders, - /// title bar, resizable, closable, ...). If \a style contains - /// Style::Fullscreen, then \a mode must be a valid video mode. - /// - /// The fourth parameter is an optional structure specifying - /// advanced OpenGL context settings such as antialiasing, - /// depth-buffer bits, etc. - /// - /// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window) - /// \param title Title of the window - /// \param style %Window style, a bitwise OR combination of sf::Style enumerators - /// \param settings Additional settings for the underlying OpenGL context - /// - //////////////////////////////////////////////////////////// - Window(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings()); - - //////////////////////////////////////////////////////////// - /// \brief Construct the window from an existing control - /// - /// Use this constructor if you want to create an OpenGL - /// rendering area into an already existing control. - /// - /// The second parameter is an optional structure specifying - /// advanced OpenGL context settings such as antialiasing, - /// depth-buffer bits, etc. - /// - /// \param handle Platform-specific handle of the control (\a HWND on - /// Windows, \a %Window on Linux/FreeBSD, \a NSWindow on OS X) - /// \param settings Additional settings for the underlying OpenGL context - /// - //////////////////////////////////////////////////////////// - explicit Window(WindowHandle handle, const ContextSettings& settings = ContextSettings()); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - /// Closes the window and frees all the resources attached to it. - /// - //////////////////////////////////////////////////////////// - virtual ~Window(); - - //////////////////////////////////////////////////////////// - /// \brief Create (or recreate) the window - /// - /// If the window was already created, it closes it first. - /// If \a style contains Style::Fullscreen, then \a mode - /// must be a valid video mode. - /// - /// The fourth parameter is an optional structure specifying - /// advanced OpenGL context settings such as antialiasing, - /// depth-buffer bits, etc. - /// - /// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window) - /// \param title Title of the window - /// \param style %Window style, a bitwise OR combination of sf::Style enumerators - /// \param settings Additional settings for the underlying OpenGL context - /// - //////////////////////////////////////////////////////////// - void create(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings()); - - //////////////////////////////////////////////////////////// - /// \brief Create (or recreate) the window from an existing control - /// - /// Use this function if you want to create an OpenGL - /// rendering area into an already existing control. - /// If the window was already created, it closes it first. - /// - /// The second parameter is an optional structure specifying - /// advanced OpenGL context settings such as antialiasing, - /// depth-buffer bits, etc. - /// - /// \param handle Platform-specific handle of the control (\a HWND on - /// Windows, \a %Window on Linux/FreeBSD, \a NSWindow on OS X) - /// \param settings Additional settings for the underlying OpenGL context - /// - //////////////////////////////////////////////////////////// - void create(WindowHandle handle, const ContextSettings& settings = ContextSettings()); - - //////////////////////////////////////////////////////////// - /// \brief Close the window and destroy all the attached resources - /// - /// After calling this function, the sf::Window instance remains - /// valid and you can call create() to recreate the window. - /// All other functions such as pollEvent() or display() will - /// still work (i.e. you don't have to test isOpen() every time), - /// and will have no effect on closed windows. - /// - //////////////////////////////////////////////////////////// - void close(); - - //////////////////////////////////////////////////////////// - /// \brief Tell whether or not the window is open - /// - /// This function returns whether or not the window exists. - /// Note that a hidden window (setVisible(false)) is open - /// (therefore this function would return true). - /// - /// \return True if the window is open, false if it has been closed - /// - //////////////////////////////////////////////////////////// - bool isOpen() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the settings of the OpenGL context of the window - /// - /// Note that these settings may be different from what was - /// passed to the constructor or the create() function, - /// if one or more settings were not supported. In this case, - /// SFML chose the closest match. - /// - /// \return Structure containing the OpenGL context settings - /// - //////////////////////////////////////////////////////////// - const ContextSettings& getSettings() const; - - //////////////////////////////////////////////////////////// - /// \brief Pop the event on top of the event queue, if any, and return it - /// - /// This function is not blocking: if there's no pending event then - /// it will return false and leave \a event unmodified. - /// Note that more than one event may be present in the event queue, - /// thus you should always call this function in a loop - /// to make sure that you process every pending event. - /// \code - /// sf::Event event; - /// while (window.pollEvent(event)) - /// { - /// // process event... - /// } - /// \endcode - /// - /// \param event Event to be returned - /// - /// \return True if an event was returned, or false if the event queue was empty - /// - /// \see waitEvent - /// - //////////////////////////////////////////////////////////// - bool pollEvent(Event& event); - - //////////////////////////////////////////////////////////// - /// \brief Wait for an event and return it - /// - /// This function is blocking: if there's no pending event then - /// it will wait until an event is received. - /// After this function returns (and no error occured), - /// the \a event object is always valid and filled properly. - /// This function is typically used when you have a thread that - /// is dedicated to events handling: you want to make this thread - /// sleep as long as no new event is received. - /// \code - /// sf::Event event; - /// if (window.waitEvent(event)) - /// { - /// // process event... - /// } - /// \endcode - /// - /// \param event Event to be returned - /// - /// \return False if any error occured - /// - /// \see pollEvent - /// - //////////////////////////////////////////////////////////// - bool waitEvent(Event& event); - - //////////////////////////////////////////////////////////// - /// \brief Get the position of the window - /// - /// \return Position of the window, in pixels - /// - /// \see setPosition - /// - //////////////////////////////////////////////////////////// - Vector2i getPosition() const; - - //////////////////////////////////////////////////////////// - /// \brief Change the position of the window on screen - /// - /// This function only works for top-level windows - /// (i.e. it will be ignored for windows created from - /// the handle of a child window/control). - /// - /// \param position New position, in pixels - /// - /// \see getPosition - /// - //////////////////////////////////////////////////////////// - void setPosition(const Vector2i& position); - - //////////////////////////////////////////////////////////// - /// \brief Get the size of the rendering region of the window - /// - /// The size doesn't include the titlebar and borders - /// of the window. - /// - /// \return Size in pixels - /// - /// \see setSize - /// - //////////////////////////////////////////////////////////// - Vector2u getSize() const; - - //////////////////////////////////////////////////////////// - /// \brief Change the size of the rendering region of the window - /// - /// \param size New size, in pixels - /// - /// \see getSize - /// - //////////////////////////////////////////////////////////// - void setSize(const Vector2u& size); - - //////////////////////////////////////////////////////////// - /// \brief Change the title of the window - /// - /// \param title New title - /// - /// \see setIcon - /// - //////////////////////////////////////////////////////////// - void setTitle(const String& title); - - //////////////////////////////////////////////////////////// - /// \brief Change the window's icon - /// - /// \a pixels must be an array of \a width x \a height pixels - /// in 32-bits RGBA format. - /// - /// The OS default icon is used by default. - /// - /// \param width Icon's width, in pixels - /// \param height Icon's height, in pixels - /// \param pixels Pointer to the array of pixels in memory. The - /// pixels are copied, so you need not keep the - /// source alive after calling this function. - /// - /// \see setTitle - /// - //////////////////////////////////////////////////////////// - void setIcon(unsigned int width, unsigned int height, const Uint8* pixels); - - //////////////////////////////////////////////////////////// - /// \brief Show or hide the window - /// - /// The window is shown by default. - /// - /// \param visible True to show the window, false to hide it - /// - //////////////////////////////////////////////////////////// - void setVisible(bool visible); - - //////////////////////////////////////////////////////////// - /// \brief Enable or disable vertical synchronization - /// - /// Activating vertical synchronization will limit the number - /// of frames displayed to the refresh rate of the monitor. - /// This can avoid some visual artifacts, and limit the framerate - /// to a good value (but not constant across different computers). - /// - /// Vertical synchronization is disabled by default. - /// - /// \param enabled True to enable v-sync, false to deactivate it - /// - //////////////////////////////////////////////////////////// - void setVerticalSyncEnabled(bool enabled); - - //////////////////////////////////////////////////////////// - /// \brief Show or hide the mouse cursor - /// - /// The mouse cursor is visible by default. - /// - /// \param visible True to show the mouse cursor, false to hide it - /// - //////////////////////////////////////////////////////////// - void setMouseCursorVisible(bool visible); - - //////////////////////////////////////////////////////////// - /// \brief Enable or disable automatic key-repeat - /// - /// If key repeat is enabled, you will receive repeated - /// KeyPressed events while keeping a key pressed. If it is disabled, - /// you will only get a single event when the key is pressed. - /// - /// Key repeat is enabled by default. - /// - /// \param enabled True to enable, false to disable - /// - //////////////////////////////////////////////////////////// - void setKeyRepeatEnabled(bool enabled); - - //////////////////////////////////////////////////////////// - /// \brief Limit the framerate to a maximum fixed frequency - /// - /// If a limit is set, the window will use a small delay after - /// each call to display() to ensure that the current frame - /// lasted long enough to match the framerate limit. - /// SFML will try to match the given limit as much as it can, - /// but since it internally uses sf::sleep, whose precision - /// depends on the underlying OS, the results may be a little - /// unprecise as well (for example, you can get 65 FPS when - /// requesting 60). - /// - /// \param limit Framerate limit, in frames per seconds (use 0 to disable limit) - /// - //////////////////////////////////////////////////////////// - void setFramerateLimit(unsigned int limit); - - //////////////////////////////////////////////////////////// - /// \brief Change the joystick threshold - /// - /// The joystick threshold is the value below which - /// no JoystickMoved event will be generated. - /// - /// The threshold value is 0.1 by default. - /// - /// \param threshold New threshold, in the range [0, 100] - /// - //////////////////////////////////////////////////////////// - void setJoystickThreshold(float threshold); - - //////////////////////////////////////////////////////////// - /// \brief Activate or deactivate the window as the current target - /// for OpenGL rendering - /// - /// A window is active only on the current thread, if you want to - /// make it active on another thread you have to deactivate it - /// on the previous thread first if it was active. - /// Only one window can be active on a thread at a time, thus - /// the window previously active (if any) automatically gets deactivated. - /// - /// \param active True to activate, false to deactivate - /// - /// \return True if operation was successful, false otherwise - /// - //////////////////////////////////////////////////////////// - bool setActive(bool active = true) const; - - //////////////////////////////////////////////////////////// - /// \brief Display on screen what has been rendered to the window so far - /// - /// This function is typically called after all OpenGL rendering - /// has been done for the current frame, in order to show - /// it on screen. - /// - //////////////////////////////////////////////////////////// - void display(); - - //////////////////////////////////////////////////////////// - /// \brief Get the OS-specific handle of the window - /// - /// The type of the returned handle is sf::WindowHandle, - /// which is a typedef to the handle type defined by the OS. - /// You shouldn't need to use this function, unless you have - /// very specific stuff to implement that SFML doesn't support, - /// or implement a temporary workaround until a bug is fixed. - /// The type is \a HWND on Windows, \a %Window on Linux/FreeBSD - /// and \a NSWindow on OS X. - /// - /// \return System handle of the window - /// - //////////////////////////////////////////////////////////// - WindowHandle getSystemHandle() const; - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Function called after the window has been created - /// - /// This function is called so that derived classes can - /// perform their own specific initialization as soon as - /// the window is created. - /// - //////////////////////////////////////////////////////////// - virtual void onCreate(); - - //////////////////////////////////////////////////////////// - /// \brief Function called after the window has been resized - /// - /// This function is called so that derived classes can - /// perform custom actions when the size of the window changes. - /// - //////////////////////////////////////////////////////////// - virtual void onResize(); - -private: - - //////////////////////////////////////////////////////////// - /// \brief Processes an event before it is sent to the user - /// - /// This function is called every time an event is received - /// from the internal window (through pollEvent or waitEvent). - /// It filters out unwanted events, and performs whatever internal - /// stuff the window needs before the event is returned to the - /// user. - /// - /// \param event Event to filter - /// - //////////////////////////////////////////////////////////// - bool filterEvent(const Event& event); - - //////////////////////////////////////////////////////////// - /// \brief Perform some common internal initializations - /// - //////////////////////////////////////////////////////////// - void initialize(); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - priv::WindowImpl* m_impl; ///< Platform-specific implementation of the window - priv::GlContext* m_context; ///< Platform-specific implementation of the OpenGL context - Clock m_clock; ///< Clock for measuring the elapsed time between frames - Time m_frameTimeLimit; ///< Current framerate limit - Vector2u m_size; ///< Current size of the window -}; - -} // namespace sf - - -#endif // SFML_WINDOW_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Window -/// \ingroup window -/// -/// sf::Window is the main class of the Window module. It defines -/// an OS window that is able to receive an OpenGL rendering. -/// -/// A sf::Window can create its own new window, or be embedded into -/// an already existing control using the create(handle) function. -/// This can be useful for embedding an OpenGL rendering area into -/// a view which is part of a bigger GUI with existing windows, -/// controls, etc. It can also serve as embedding an OpenGL rendering -/// area into a window created by another (probably richer) GUI library -/// like Qt or wxWidgets. -/// -/// The sf::Window class provides a simple interface for manipulating -/// the window: move, resize, show/hide, control mouse cursor, etc. -/// It also provides event handling through its pollEvent() and waitEvent() -/// functions. -/// -/// Note that OpenGL experts can pass their own parameters (antialiasing -/// level, bits for the depth and stencil buffers, etc.) to the -/// OpenGL context attached to the window, with the sf::ContextSettings -/// structure which is passed as an optional argument when creating the -/// window. -/// -/// Usage example: -/// \code -/// // Declare and create a new window -/// sf::Window window(sf::VideoMode(800, 600), "SFML window"); -/// -/// // Limit the framerate to 60 frames per second (this step is optional) -/// window.setFramerateLimit(60); -/// -/// // The main loop - ends as soon as the window is closed -/// while (window.isOpen()) -/// { -/// // Event processing -/// sf::Event event; -/// while (window.pollEvent(event)) -/// { -/// // Request for closing the window -/// if (event.type == sf::Event::Closed) -/// window.close(); -/// } -/// -/// // Activate the window for OpenGL rendering -/// window.setActive(); -/// -/// // OpenGL drawing commands go here... -/// -/// // End the current frame and display its contents on screen -/// window.display(); -/// } -/// \endcode -/// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WINDOW_HPP +#define SFML_WINDOW_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class GlContext; + class WindowImpl; +} + +class Event; + +//////////////////////////////////////////////////////////// +/// \brief Window that serves as a target for OpenGL rendering +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API Window : GlResource, NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor doesn't actually create the window, + /// use the other constructors or call create() to do so. + /// + //////////////////////////////////////////////////////////// + Window(); + + //////////////////////////////////////////////////////////// + /// \brief Construct a new window + /// + /// This constructor creates the window with the size and pixel + /// depth defined in \a mode. An optional style can be passed to + /// customize the look and behaviour of the window (borders, + /// title bar, resizable, closable, ...). If \a style contains + /// Style::Fullscreen, then \a mode must be a valid video mode. + /// + /// The fourth parameter is an optional structure specifying + /// advanced OpenGL context settings such as antialiasing, + /// depth-buffer bits, etc. + /// + /// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window) + /// \param title Title of the window + /// \param style %Window style, a bitwise OR combination of sf::Style enumerators + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + Window(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Construct the window from an existing control + /// + /// Use this constructor if you want to create an OpenGL + /// rendering area into an already existing control. + /// + /// The second parameter is an optional structure specifying + /// advanced OpenGL context settings such as antialiasing, + /// depth-buffer bits, etc. + /// + /// \param handle Platform-specific handle of the control (\a HWND on + /// Windows, \a %Window on Linux/FreeBSD, \a NSWindow on OS X) + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + explicit Window(WindowHandle handle, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// Closes the window and frees all the resources attached to it. + /// + //////////////////////////////////////////////////////////// + virtual ~Window(); + + //////////////////////////////////////////////////////////// + /// \brief Create (or recreate) the window + /// + /// If the window was already created, it closes it first. + /// If \a style contains Style::Fullscreen, then \a mode + /// must be a valid video mode. + /// + /// The fourth parameter is an optional structure specifying + /// advanced OpenGL context settings such as antialiasing, + /// depth-buffer bits, etc. + /// + /// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window) + /// \param title Title of the window + /// \param style %Window style, a bitwise OR combination of sf::Style enumerators + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + void create(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Create (or recreate) the window from an existing control + /// + /// Use this function if you want to create an OpenGL + /// rendering area into an already existing control. + /// If the window was already created, it closes it first. + /// + /// The second parameter is an optional structure specifying + /// advanced OpenGL context settings such as antialiasing, + /// depth-buffer bits, etc. + /// + /// \param handle Platform-specific handle of the control (\a HWND on + /// Windows, \a %Window on Linux/FreeBSD, \a NSWindow on OS X) + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + void create(WindowHandle handle, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Close the window and destroy all the attached resources + /// + /// After calling this function, the sf::Window instance remains + /// valid and you can call create() to recreate the window. + /// All other functions such as pollEvent() or display() will + /// still work (i.e. you don't have to test isOpen() every time), + /// and will have no effect on closed windows. + /// + //////////////////////////////////////////////////////////// + void close(); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether or not the window is open + /// + /// This function returns whether or not the window exists. + /// Note that a hidden window (setVisible(false)) is open + /// (therefore this function would return true). + /// + /// \return True if the window is open, false if it has been closed + /// + //////////////////////////////////////////////////////////// + bool isOpen() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the settings of the OpenGL context of the window + /// + /// Note that these settings may be different from what was + /// passed to the constructor or the create() function, + /// if one or more settings were not supported. In this case, + /// SFML chose the closest match. + /// + /// \return Structure containing the OpenGL context settings + /// + //////////////////////////////////////////////////////////// + const ContextSettings& getSettings() const; + + //////////////////////////////////////////////////////////// + /// \brief Pop the event on top of the event queue, if any, and return it + /// + /// This function is not blocking: if there's no pending event then + /// it will return false and leave \a event unmodified. + /// Note that more than one event may be present in the event queue, + /// thus you should always call this function in a loop + /// to make sure that you process every pending event. + /// \code + /// sf::Event event; + /// while (window.pollEvent(event)) + /// { + /// // process event... + /// } + /// \endcode + /// + /// \param event Event to be returned + /// + /// \return True if an event was returned, or false if the event queue was empty + /// + /// \see waitEvent + /// + //////////////////////////////////////////////////////////// + bool pollEvent(Event& event); + + //////////////////////////////////////////////////////////// + /// \brief Wait for an event and return it + /// + /// This function is blocking: if there's no pending event then + /// it will wait until an event is received. + /// After this function returns (and no error occured), + /// the \a event object is always valid and filled properly. + /// This function is typically used when you have a thread that + /// is dedicated to events handling: you want to make this thread + /// sleep as long as no new event is received. + /// \code + /// sf::Event event; + /// if (window.waitEvent(event)) + /// { + /// // process event... + /// } + /// \endcode + /// + /// \param event Event to be returned + /// + /// \return False if any error occured + /// + /// \see pollEvent + /// + //////////////////////////////////////////////////////////// + bool waitEvent(Event& event); + + //////////////////////////////////////////////////////////// + /// \brief Get the position of the window + /// + /// \return Position of the window, in pixels + /// + /// \see setPosition + /// + //////////////////////////////////////////////////////////// + Vector2i getPosition() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the position of the window on screen + /// + /// This function only works for top-level windows + /// (i.e. it will be ignored for windows created from + /// the handle of a child window/control). + /// + /// \param position New position, in pixels + /// + /// \see getPosition + /// + //////////////////////////////////////////////////////////// + void setPosition(const Vector2i& position); + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the rendering region of the window + /// + /// The size doesn't include the titlebar and borders + /// of the window. + /// + /// \return Size in pixels + /// + /// \see setSize + /// + //////////////////////////////////////////////////////////// + Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the size of the rendering region of the window + /// + /// \param size New size, in pixels + /// + /// \see getSize + /// + //////////////////////////////////////////////////////////// + void setSize(const Vector2u& size); + + //////////////////////////////////////////////////////////// + /// \brief Change the title of the window + /// + /// \param title New title + /// + /// \see setIcon + /// + //////////////////////////////////////////////////////////// + void setTitle(const String& title); + + //////////////////////////////////////////////////////////// + /// \brief Change the window's icon + /// + /// \a pixels must be an array of \a width x \a height pixels + /// in 32-bits RGBA format. + /// + /// The OS default icon is used by default. + /// + /// \param width Icon's width, in pixels + /// \param height Icon's height, in pixels + /// \param pixels Pointer to the array of pixels in memory. The + /// pixels are copied, so you need not keep the + /// source alive after calling this function. + /// + /// \see setTitle + /// + //////////////////////////////////////////////////////////// + void setIcon(unsigned int width, unsigned int height, const Uint8* pixels); + + //////////////////////////////////////////////////////////// + /// \brief Show or hide the window + /// + /// The window is shown by default. + /// + /// \param visible True to show the window, false to hide it + /// + //////////////////////////////////////////////////////////// + void setVisible(bool visible); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable vertical synchronization + /// + /// Activating vertical synchronization will limit the number + /// of frames displayed to the refresh rate of the monitor. + /// This can avoid some visual artifacts, and limit the framerate + /// to a good value (but not constant across different computers). + /// + /// Vertical synchronization is disabled by default. + /// + /// \param enabled True to enable v-sync, false to deactivate it + /// + //////////////////////////////////////////////////////////// + void setVerticalSyncEnabled(bool enabled); + + //////////////////////////////////////////////////////////// + /// \brief Show or hide the mouse cursor + /// + /// The mouse cursor is visible by default. + /// + /// \param visible True to show the mouse cursor, false to hide it + /// + //////////////////////////////////////////////////////////// + void setMouseCursorVisible(bool visible); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable automatic key-repeat + /// + /// If key repeat is enabled, you will receive repeated + /// KeyPressed events while keeping a key pressed. If it is disabled, + /// you will only get a single event when the key is pressed. + /// + /// Key repeat is enabled by default. + /// + /// \param enabled True to enable, false to disable + /// + //////////////////////////////////////////////////////////// + void setKeyRepeatEnabled(bool enabled); + + //////////////////////////////////////////////////////////// + /// \brief Limit the framerate to a maximum fixed frequency + /// + /// If a limit is set, the window will use a small delay after + /// each call to display() to ensure that the current frame + /// lasted long enough to match the framerate limit. + /// SFML will try to match the given limit as much as it can, + /// but since it internally uses sf::sleep, whose precision + /// depends on the underlying OS, the results may be a little + /// unprecise as well (for example, you can get 65 FPS when + /// requesting 60). + /// + /// \param limit Framerate limit, in frames per seconds (use 0 to disable limit) + /// + //////////////////////////////////////////////////////////// + void setFramerateLimit(unsigned int limit); + + //////////////////////////////////////////////////////////// + /// \brief Change the joystick threshold + /// + /// The joystick threshold is the value below which + /// no JoystickMoved event will be generated. + /// + /// The threshold value is 0.1 by default. + /// + /// \param threshold New threshold, in the range [0, 100] + /// + //////////////////////////////////////////////////////////// + void setJoystickThreshold(float threshold); + + //////////////////////////////////////////////////////////// + /// \brief Activate or deactivate the window as the current target + /// for OpenGL rendering + /// + /// A window is active only on the current thread, if you want to + /// make it active on another thread you have to deactivate it + /// on the previous thread first if it was active. + /// Only one window can be active on a thread at a time, thus + /// the window previously active (if any) automatically gets deactivated. + /// + /// \param active True to activate, false to deactivate + /// + /// \return True if operation was successful, false otherwise + /// + //////////////////////////////////////////////////////////// + bool setActive(bool active = true) const; + + //////////////////////////////////////////////////////////// + /// \brief Display on screen what has been rendered to the window so far + /// + /// This function is typically called after all OpenGL rendering + /// has been done for the current frame, in order to show + /// it on screen. + /// + //////////////////////////////////////////////////////////// + void display(); + + //////////////////////////////////////////////////////////// + /// \brief Get the OS-specific handle of the window + /// + /// The type of the returned handle is sf::WindowHandle, + /// which is a typedef to the handle type defined by the OS. + /// You shouldn't need to use this function, unless you have + /// very specific stuff to implement that SFML doesn't support, + /// or implement a temporary workaround until a bug is fixed. + /// The type is \a HWND on Windows, \a %Window on Linux/FreeBSD + /// and \a NSWindow on OS X. + /// + /// \return System handle of the window + /// + //////////////////////////////////////////////////////////// + WindowHandle getSystemHandle() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Function called after the window has been created + /// + /// This function is called so that derived classes can + /// perform their own specific initialization as soon as + /// the window is created. + /// + //////////////////////////////////////////////////////////// + virtual void onCreate(); + + //////////////////////////////////////////////////////////// + /// \brief Function called after the window has been resized + /// + /// This function is called so that derived classes can + /// perform custom actions when the size of the window changes. + /// + //////////////////////////////////////////////////////////// + virtual void onResize(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Processes an event before it is sent to the user + /// + /// This function is called every time an event is received + /// from the internal window (through pollEvent or waitEvent). + /// It filters out unwanted events, and performs whatever internal + /// stuff the window needs before the event is returned to the + /// user. + /// + /// \param event Event to filter + /// + //////////////////////////////////////////////////////////// + bool filterEvent(const Event& event); + + //////////////////////////////////////////////////////////// + /// \brief Perform some common internal initializations + /// + //////////////////////////////////////////////////////////// + void initialize(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::WindowImpl* m_impl; ///< Platform-specific implementation of the window + priv::GlContext* m_context; ///< Platform-specific implementation of the OpenGL context + Clock m_clock; ///< Clock for measuring the elapsed time between frames + Time m_frameTimeLimit; ///< Current framerate limit + Vector2u m_size; ///< Current size of the window +}; + +} // namespace sf + + +#endif // SFML_WINDOW_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Window +/// \ingroup window +/// +/// sf::Window is the main class of the Window module. It defines +/// an OS window that is able to receive an OpenGL rendering. +/// +/// A sf::Window can create its own new window, or be embedded into +/// an already existing control using the create(handle) function. +/// This can be useful for embedding an OpenGL rendering area into +/// a view which is part of a bigger GUI with existing windows, +/// controls, etc. It can also serve as embedding an OpenGL rendering +/// area into a window created by another (probably richer) GUI library +/// like Qt or wxWidgets. +/// +/// The sf::Window class provides a simple interface for manipulating +/// the window: move, resize, show/hide, control mouse cursor, etc. +/// It also provides event handling through its pollEvent() and waitEvent() +/// functions. +/// +/// Note that OpenGL experts can pass their own parameters (antialiasing +/// level, bits for the depth and stencil buffers, etc.) to the +/// OpenGL context attached to the window, with the sf::ContextSettings +/// structure which is passed as an optional argument when creating the +/// window. +/// +/// Usage example: +/// \code +/// // Declare and create a new window +/// sf::Window window(sf::VideoMode(800, 600), "SFML window"); +/// +/// // Limit the framerate to 60 frames per second (this step is optional) +/// window.setFramerateLimit(60); +/// +/// // The main loop - ends as soon as the window is closed +/// while (window.isOpen()) +/// { +/// // Event processing +/// sf::Event event; +/// while (window.pollEvent(event)) +/// { +/// // Request for closing the window +/// if (event.type == sf::Event::Closed) +/// window.close(); +/// } +/// +/// // Activate the window for OpenGL rendering +/// window.setActive(); +/// +/// // OpenGL drawing commands go here... +/// +/// // End the current frame and display its contents on screen +/// window.display(); +/// } +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Window/WindowStyle.hpp b/include/SFML/Window/WindowStyle.hpp index 41644e1c..cd721b3b 100644 --- a/include/SFML/Window/WindowStyle.hpp +++ b/include/SFML/Window/WindowStyle.hpp @@ -1,53 +1,53 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_WINDOWSTYLE_HPP -#define SFML_WINDOWSTYLE_HPP - - -namespace sf -{ -namespace Style -{ - //////////////////////////////////////////////////////////// - /// \ingroup window - /// \brief Enumeration of the window styles - /// - //////////////////////////////////////////////////////////// - enum - { - None = 0, ///< No border / title bar (this flag and all others are mutually exclusive) - Titlebar = 1 << 0, ///< Title bar + fixed border - Resize = 1 << 1, ///< Title bar + resizable border + maximize button - Close = 1 << 2, ///< Title bar + close button - Fullscreen = 1 << 3, ///< Fullscreen mode (this flag and all others are mutually exclusive) - - Default = Titlebar | Resize | Close ///< Default window style - }; -} - -} // namespace sf - - -#endif // SFML_WINDOWSTYLE_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WINDOWSTYLE_HPP +#define SFML_WINDOWSTYLE_HPP + + +namespace sf +{ +namespace Style +{ + //////////////////////////////////////////////////////////// + /// \ingroup window + /// \brief Enumeration of the window styles + /// + //////////////////////////////////////////////////////////// + enum + { + None = 0, ///< No border / title bar (this flag and all others are mutually exclusive) + Titlebar = 1 << 0, ///< Title bar + fixed border + Resize = 1 << 1, ///< Title bar + resizable border + maximize button + Close = 1 << 2, ///< Title bar + close button + Fullscreen = 1 << 3, ///< Fullscreen mode (this flag and all others are mutually exclusive) + + Default = Titlebar | Resize | Close ///< Default window style + }; +} + +} // namespace sf + + +#endif // SFML_WINDOWSTYLE_HPP diff --git a/license.txt b/license.txt index fc4e4db9..2406368a 100644 --- a/license.txt +++ b/license.txt @@ -1,36 +1,36 @@ -SFML ----- - -SFML - Copyright (C) 2007-2014 Laurent Gomila - laurent.gom@gmail.com - -This software is provided 'as-is', without any express or -implied warranty. In no event will the authors be held -liable for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute -it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; - you must not claim that you wrote the original software. - If you use this software in a product, an acknowledgment - in the product documentation would be appreciated but - is not required. - -2. Altered source versions must be plainly marked as such, - and must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any - source distribution. - - - -External libraries used by SFML -------------------------------- - -* OpenAL-Soft is under the LGPL license -* libsndfile is under the LGPL license -* libjpeg is public domain -* stb_image and stb_image_write are public domain -* freetype is under the FreeType license or the GPL license -* GLEW is under the modified BSD License, the Mesa 3-D License (MIT License), and the Khronos License (MIT License) +SFML +---- + +SFML - Copyright (C) 2007-2014 Laurent Gomila - laurent.gom@gmail.com + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held +liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute +it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but + is not required. + +2. Altered source versions must be plainly marked as such, + and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any + source distribution. + + + +External libraries used by SFML +------------------------------- + +* OpenAL-Soft is under the LGPL license +* libsndfile is under the LGPL license +* libjpeg is public domain +* stb_image and stb_image_write are public domain +* freetype is under the FreeType license or the GPL license +* GLEW is under the modified BSD License, the Mesa 3-D License (MIT License), and the Khronos License (MIT License) diff --git a/src/SFML/Audio/ALCheck.cpp b/src/SFML/Audio/ALCheck.cpp index 4e7c100e..1a7e4bb9 100644 --- a/src/SFML/Audio/ALCheck.cpp +++ b/src/SFML/Audio/ALCheck.cpp @@ -1,109 +1,109 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -void alCheckError(const std::string& file, unsigned int line) -{ - // Get the last error - ALenum errorCode = alGetError(); - - if (errorCode != AL_NO_ERROR) - { - std::string error, description; - - // Decode the error code - switch (errorCode) - { - case AL_INVALID_NAME : - { - error = "AL_INVALID_NAME"; - description = "an unacceptable name has been specified"; - break; - } - - case AL_INVALID_ENUM : - { - error = "AL_INVALID_ENUM"; - description = "an unacceptable value has been specified for an enumerated argument"; - break; - } - - case AL_INVALID_VALUE : - { - error = "AL_INVALID_VALUE"; - description = "a numeric argument is out of range"; - break; - } - - case AL_INVALID_OPERATION : - { - error = "AL_INVALID_OPERATION"; - description = "the specified operation is not allowed in the current state"; - break; - } - - case AL_OUT_OF_MEMORY : - { - error = "AL_OUT_OF_MEMORY"; - description = "there is not enough memory left to execute the command"; - break; - } - } - - // Log the error - err() << "An internal OpenAL call failed in " - << file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : " - << error << ", " << description - << std::endl; - } -} - - -//////////////////////////////////////////////////////////// -/// Make sure that OpenAL is initialized -//////////////////////////////////////////////////////////// -void ensureALInit() -{ - // The audio device is instantiated on demand rather than at global startup, - // which solves a lot of weird crashes and errors. - // It is destroyed at global exit which is fine. - - static AudioDevice globalDevice; -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +void alCheckError(const std::string& file, unsigned int line) +{ + // Get the last error + ALenum errorCode = alGetError(); + + if (errorCode != AL_NO_ERROR) + { + std::string error, description; + + // Decode the error code + switch (errorCode) + { + case AL_INVALID_NAME: + { + error = "AL_INVALID_NAME"; + description = "an unacceptable name has been specified"; + break; + } + + case AL_INVALID_ENUM: + { + error = "AL_INVALID_ENUM"; + description = "an unacceptable value has been specified for an enumerated argument"; + break; + } + + case AL_INVALID_VALUE: + { + error = "AL_INVALID_VALUE"; + description = "a numeric argument is out of range"; + break; + } + + case AL_INVALID_OPERATION: + { + error = "AL_INVALID_OPERATION"; + description = "the specified operation is not allowed in the current state"; + break; + } + + case AL_OUT_OF_MEMORY: + { + error = "AL_OUT_OF_MEMORY"; + description = "there is not enough memory left to execute the command"; + break; + } + } + + // Log the error + err() << "An internal OpenAL call failed in " + << file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : " + << error << ", " << description + << std::endl; + } +} + + +//////////////////////////////////////////////////////////// +/// Make sure that OpenAL is initialized +//////////////////////////////////////////////////////////// +void ensureALInit() +{ + // The audio device is instantiated on demand rather than at global startup, + // which solves a lot of weird crashes and errors. + // It is destroyed at global exit which is fine. + + static AudioDevice globalDevice; +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Audio/ALCheck.hpp b/src/SFML/Audio/ALCheck.hpp index f119c15b..b31a031e 100644 --- a/src/SFML/Audio/ALCheck.hpp +++ b/src/SFML/Audio/ALCheck.hpp @@ -1,78 +1,78 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_ALCHECK_HPP -#define SFML_ALCHECK_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// Let's define a macro to quickly check every OpenAL API calls -//////////////////////////////////////////////////////////// -#ifdef SFML_DEBUG - - // If in debug mode, perform a test on every call - #define alCheck(x) x; sf::priv::alCheckError(__FILE__, __LINE__); - -#else - - // Else, we don't add any overhead - #define alCheck(Func) (Func) - -#endif - - -//////////////////////////////////////////////////////////// -/// Check the last OpenAL error -/// -/// \param file Source file where the call is located -/// \param line Line number of the source file where the call is located -/// -//////////////////////////////////////////////////////////// -void alCheckError(const std::string& file, unsigned int line); - -//////////////////////////////////////////////////////////// -/// Make sure that OpenAL is initialized -/// -//////////////////////////////////////////////////////////// -void ensureALInit(); - -} // namespace priv - -} // namespace sf - - -#endif // SFML_ALCHECK_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_ALCHECK_HPP +#define SFML_ALCHECK_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// Let's define a macro to quickly check every OpenAL API calls +//////////////////////////////////////////////////////////// +#ifdef SFML_DEBUG + + // If in debug mode, perform a test on every call + #define alCheck(x) x; sf::priv::alCheckError(__FILE__, __LINE__); + +#else + + // Else, we don't add any overhead + #define alCheck(Func) (Func) + +#endif + + +//////////////////////////////////////////////////////////// +/// Check the last OpenAL error +/// +/// \param file Source file where the call is located +/// \param line Line number of the source file where the call is located +/// +//////////////////////////////////////////////////////////// +void alCheckError(const std::string& file, unsigned int line); + +//////////////////////////////////////////////////////////// +/// Make sure that OpenAL is initialized +/// +//////////////////////////////////////////////////////////// +void ensureALInit(); + +} // namespace priv + +} // namespace sf + + +#endif // SFML_ALCHECK_HPP diff --git a/src/SFML/Audio/AudioDevice.cpp b/src/SFML/Audio/AudioDevice.cpp index 3b7dcc64..2c9b8337 100644 --- a/src/SFML/Audio/AudioDevice.cpp +++ b/src/SFML/Audio/AudioDevice.cpp @@ -1,125 +1,125 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace -{ - ALCdevice* audioDevice = NULL; - ALCcontext* audioContext = NULL; -} - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -AudioDevice::AudioDevice() -{ - // Create the device - audioDevice = alcOpenDevice(NULL); - - if (audioDevice) - { - // Create the context - audioContext = alcCreateContext(audioDevice, NULL); - - if (audioContext) - { - // Set the context as the current one (we'll only need one) - alcMakeContextCurrent(audioContext); - } - else - { - err() << "Failed to create the audio context" << std::endl; - } - } - else - { - err() << "Failed to open the audio device" << std::endl; - } -} - - -//////////////////////////////////////////////////////////// -AudioDevice::~AudioDevice() -{ - // Destroy the context - alcMakeContextCurrent(NULL); - if (audioContext) - alcDestroyContext(audioContext); - - // Destroy the device - if (audioDevice) - alcCloseDevice(audioDevice); -} - - -//////////////////////////////////////////////////////////// -bool AudioDevice::isExtensionSupported(const std::string& extension) -{ - ensureALInit(); - - if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC")) - return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE; - else - return alIsExtensionPresent(extension.c_str()) != AL_FALSE; -} - - -//////////////////////////////////////////////////////////// -int AudioDevice::getFormatFromChannelCount(unsigned int channelCount) -{ - ensureALInit(); - - // Find the good format according to the number of channels - int format = 0; - switch (channelCount) - { - case 1 : format = AL_FORMAT_MONO16; break; - case 2 : format = AL_FORMAT_STEREO16; break; - case 4 : format = alGetEnumValue("AL_FORMAT_QUAD16"); break; - case 6 : format = alGetEnumValue("AL_FORMAT_51CHN16"); break; - case 7 : format = alGetEnumValue("AL_FORMAT_61CHN16"); break; - case 8 : format = alGetEnumValue("AL_FORMAT_71CHN16"); break; - default : format = 0; break; - } - - // Fixes a bug on OS X - if (format == -1) - format = 0; - - return format; -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace +{ + ALCdevice* audioDevice = NULL; + ALCcontext* audioContext = NULL; +} + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +AudioDevice::AudioDevice() +{ + // Create the device + audioDevice = alcOpenDevice(NULL); + + if (audioDevice) + { + // Create the context + audioContext = alcCreateContext(audioDevice, NULL); + + if (audioContext) + { + // Set the context as the current one (we'll only need one) + alcMakeContextCurrent(audioContext); + } + else + { + err() << "Failed to create the audio context" << std::endl; + } + } + else + { + err() << "Failed to open the audio device" << std::endl; + } +} + + +//////////////////////////////////////////////////////////// +AudioDevice::~AudioDevice() +{ + // Destroy the context + alcMakeContextCurrent(NULL); + if (audioContext) + alcDestroyContext(audioContext); + + // Destroy the device + if (audioDevice) + alcCloseDevice(audioDevice); +} + + +//////////////////////////////////////////////////////////// +bool AudioDevice::isExtensionSupported(const std::string& extension) +{ + ensureALInit(); + + if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC")) + return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE; + else + return alIsExtensionPresent(extension.c_str()) != AL_FALSE; +} + + +//////////////////////////////////////////////////////////// +int AudioDevice::getFormatFromChannelCount(unsigned int channelCount) +{ + ensureALInit(); + + // Find the good format according to the number of channels + int format = 0; + switch (channelCount) + { + case 1: format = AL_FORMAT_MONO16; break; + case 2: format = AL_FORMAT_STEREO16; break; + case 4: format = alGetEnumValue("AL_FORMAT_QUAD16"); break; + case 6: format = alGetEnumValue("AL_FORMAT_51CHN16"); break; + case 7: format = alGetEnumValue("AL_FORMAT_61CHN16"); break; + case 8: format = alGetEnumValue("AL_FORMAT_71CHN16"); break; + default: format = 0; break; + } + + // Fixes a bug on OS X + if (format == -1) + format = 0; + + return format; +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Audio/AudioDevice.hpp b/src/SFML/Audio/AudioDevice.hpp index 674bf4ab..85c121b5 100644 --- a/src/SFML/Audio/AudioDevice.hpp +++ b/src/SFML/Audio/AudioDevice.hpp @@ -1,91 +1,91 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_AUDIODEVICE_HPP -#define SFML_AUDIODEVICE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief High-level wrapper around the audio API, it manages -/// the creation and destruction of the audio device and -/// context and stores the device capabilities -/// -//////////////////////////////////////////////////////////// -class AudioDevice -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - AudioDevice(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~AudioDevice(); - - //////////////////////////////////////////////////////////// - /// \brief Check if an OpenAL extension is supported - /// - /// This functions automatically finds whether it - /// is an AL or ALC extension, and calls the corresponding - /// function. - /// - /// \param extension Name of the extension to test - /// - /// \return True if the extension is supported, false if not - /// - //////////////////////////////////////////////////////////// - static bool isExtensionSupported(const std::string& extension); - - //////////////////////////////////////////////////////////// - /// \brief Get the OpenAL format that matches the given number of channels - /// - /// \param channelCount Number of channels - /// - /// \return Corresponding format - /// - //////////////////////////////////////////////////////////// - static int getFormatFromChannelCount(unsigned int channelCount); -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_AUDIODEVICE_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_AUDIODEVICE_HPP +#define SFML_AUDIODEVICE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief High-level wrapper around the audio API, it manages +/// the creation and destruction of the audio device and +/// context and stores the device capabilities +/// +//////////////////////////////////////////////////////////// +class AudioDevice +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + AudioDevice(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~AudioDevice(); + + //////////////////////////////////////////////////////////// + /// \brief Check if an OpenAL extension is supported + /// + /// This functions automatically finds whether it + /// is an AL or ALC extension, and calls the corresponding + /// function. + /// + /// \param extension Name of the extension to test + /// + /// \return True if the extension is supported, false if not + /// + //////////////////////////////////////////////////////////// + static bool isExtensionSupported(const std::string& extension); + + //////////////////////////////////////////////////////////// + /// \brief Get the OpenAL format that matches the given number of channels + /// + /// \param channelCount Number of channels + /// + /// \return Corresponding format + /// + //////////////////////////////////////////////////////////// + static int getFormatFromChannelCount(unsigned int channelCount); +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_AUDIODEVICE_HPP diff --git a/src/SFML/Audio/CMakeLists.txt b/src/SFML/Audio/CMakeLists.txt index 078d7e17..ee7b7cbb 100644 --- a/src/SFML/Audio/CMakeLists.txt +++ b/src/SFML/Audio/CMakeLists.txt @@ -1,65 +1,65 @@ - -set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Audio) -set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio) - -# all source files -set(SRC - ${SRCROOT}/ALCheck.cpp - ${SRCROOT}/ALCheck.hpp - ${SRCROOT}/AudioDevice.cpp - ${SRCROOT}/AudioDevice.hpp - ${INCROOT}/Export.hpp - ${SRCROOT}/Listener.cpp - ${INCROOT}/Listener.hpp - ${SRCROOT}/Music.cpp - ${INCROOT}/Music.hpp - ${SRCROOT}/Sound.cpp - ${INCROOT}/Sound.hpp - ${SRCROOT}/SoundBuffer.cpp - ${INCROOT}/SoundBuffer.hpp - ${SRCROOT}/SoundBufferRecorder.cpp - ${INCROOT}/SoundBufferRecorder.hpp - ${SRCROOT}/SoundFile.cpp - ${SRCROOT}/SoundFile.hpp - ${SRCROOT}/SoundRecorder.cpp - ${INCROOT}/SoundRecorder.hpp - ${SRCROOT}/SoundSource.cpp - ${INCROOT}/SoundSource.hpp - ${SRCROOT}/SoundStream.cpp - ${INCROOT}/SoundStream.hpp -) -source_group("" FILES ${SRC}) - -# let CMake know about our additional audio libraries paths (on Windows and OSX) -if(SFML_OS_WINDOWS) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL") - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/windows") -elseif(SFML_OS_MACOSX) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/osx") - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks") -elseif(SFML_OS_ANDROID) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL") - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/android") -endif() - -# find external libraries -if(NOT SFML_OS_ANDROID) - find_package(OpenAL REQUIRED) - find_package(Sndfile REQUIRED) -else() - find_host_package(OpenAL REQUIRED) - find_host_package(Sndfile REQUIRED) -endif() -include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR}) - -# build the list of external libraries to link -if(SFML_OS_ANDROID) - list(APPEND AUDIO_EXT_LIBS -landroid -lOpenSLES) -endif() -list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY}) - -# define the sfml-audio target -sfml_add_library(sfml-audio - SOURCES ${SRC} - DEPENDS sfml-system - EXTERNAL_LIBS ${AUDIO_EXT_LIBS}) + +set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Audio) +set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio) + +# all source files +set(SRC + ${SRCROOT}/ALCheck.cpp + ${SRCROOT}/ALCheck.hpp + ${SRCROOT}/AudioDevice.cpp + ${SRCROOT}/AudioDevice.hpp + ${INCROOT}/Export.hpp + ${SRCROOT}/Listener.cpp + ${INCROOT}/Listener.hpp + ${SRCROOT}/Music.cpp + ${INCROOT}/Music.hpp + ${SRCROOT}/Sound.cpp + ${INCROOT}/Sound.hpp + ${SRCROOT}/SoundBuffer.cpp + ${INCROOT}/SoundBuffer.hpp + ${SRCROOT}/SoundBufferRecorder.cpp + ${INCROOT}/SoundBufferRecorder.hpp + ${SRCROOT}/SoundFile.cpp + ${SRCROOT}/SoundFile.hpp + ${SRCROOT}/SoundRecorder.cpp + ${INCROOT}/SoundRecorder.hpp + ${SRCROOT}/SoundSource.cpp + ${INCROOT}/SoundSource.hpp + ${SRCROOT}/SoundStream.cpp + ${INCROOT}/SoundStream.hpp +) +source_group("" FILES ${SRC}) + +# let CMake know about our additional audio libraries paths (on Windows and OSX) +if(SFML_OS_WINDOWS) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL") + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/windows") +elseif(SFML_OS_MACOSX) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/osx") + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks") +elseif(SFML_OS_ANDROID) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL") + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/android") +endif() + +# find external libraries +if(NOT SFML_OS_ANDROID) + find_package(OpenAL REQUIRED) + find_package(Sndfile REQUIRED) +else() + find_host_package(OpenAL REQUIRED) + find_host_package(Sndfile REQUIRED) +endif() +include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR}) + +# build the list of external libraries to link +if(SFML_OS_ANDROID) + list(APPEND AUDIO_EXT_LIBS -landroid -lOpenSLES) +endif() +list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY}) + +# define the sfml-audio target +sfml_add_library(sfml-audio + SOURCES ${SRC} + DEPENDS sfml-system + EXTERNAL_LIBS ${AUDIO_EXT_LIBS}) diff --git a/src/SFML/Audio/Listener.cpp b/src/SFML/Audio/Listener.cpp index 9b008387..ec0a32fd 100644 --- a/src/SFML/Audio/Listener.cpp +++ b/src/SFML/Audio/Listener.cpp @@ -1,145 +1,145 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace -{ - float listenerVolume = 100.f; - sf::Vector3f listenerPosition (0.f, 0.f, 0.f); - sf::Vector3f listenerDirection(0.f, 0.f, -1.f); - sf::Vector3f listenerUpVector (0.f, 1.f, 0.f); -} - - -namespace sf -{ -//////////////////////////////////////////////////////////// -void Listener::setGlobalVolume(float volume) -{ - if (volume != listenerVolume) - { - priv::ensureALInit(); - - alCheck(alListenerf(AL_GAIN, volume * 0.01f)); - listenerVolume = volume; - } -} - - -//////////////////////////////////////////////////////////// -float Listener::getGlobalVolume() -{ - return listenerVolume; -} - - -//////////////////////////////////////////////////////////// -void Listener::setPosition(float x, float y, float z) -{ - setPosition(Vector3f(x, y, z)); -} - - -//////////////////////////////////////////////////////////// -void Listener::setPosition(const Vector3f& position) -{ - if (position != listenerPosition) - { - priv::ensureALInit(); - - alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z)); - listenerPosition = position; - } -} - - -//////////////////////////////////////////////////////////// -Vector3f Listener::getPosition() -{ - return listenerPosition; -} - - -//////////////////////////////////////////////////////////// -void Listener::setDirection(float x, float y, float z) -{ - setDirection(Vector3f(x, y, z)); -} - - -//////////////////////////////////////////////////////////// -void Listener::setDirection(const Vector3f& direction) -{ - if (direction != listenerDirection) - { - priv::ensureALInit(); - - float orientation[] = {direction.x, direction.y, direction.z, listenerUpVector.x, listenerUpVector.y, listenerUpVector.z}; - alCheck(alListenerfv(AL_ORIENTATION, orientation)); - listenerDirection = direction; - } -} - - -//////////////////////////////////////////////////////////// -Vector3f Listener::getDirection() -{ - return listenerDirection; -} - - -//////////////////////////////////////////////////////////// -void Listener::setUpVector(float x, float y, float z) -{ - setUpVector(Vector3f(x, y, z)); -} - - -//////////////////////////////////////////////////////////// -void Listener::setUpVector(const Vector3f& upVector) -{ - if (upVector != listenerUpVector) - { - priv::ensureALInit(); - - float orientation[] = {listenerDirection.x, listenerDirection.y, listenerDirection.z, upVector.x, upVector.y, upVector.z}; - alCheck(alListenerfv(AL_ORIENTATION, orientation)); - listenerUpVector = upVector; - } -} - - -//////////////////////////////////////////////////////////// -Vector3f Listener::getUpVector() -{ - return listenerUpVector; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace +{ + float listenerVolume = 100.f; + sf::Vector3f listenerPosition (0.f, 0.f, 0.f); + sf::Vector3f listenerDirection(0.f, 0.f, -1.f); + sf::Vector3f listenerUpVector (0.f, 1.f, 0.f); +} + + +namespace sf +{ +//////////////////////////////////////////////////////////// +void Listener::setGlobalVolume(float volume) +{ + if (volume != listenerVolume) + { + priv::ensureALInit(); + + alCheck(alListenerf(AL_GAIN, volume * 0.01f)); + listenerVolume = volume; + } +} + + +//////////////////////////////////////////////////////////// +float Listener::getGlobalVolume() +{ + return listenerVolume; +} + + +//////////////////////////////////////////////////////////// +void Listener::setPosition(float x, float y, float z) +{ + setPosition(Vector3f(x, y, z)); +} + + +//////////////////////////////////////////////////////////// +void Listener::setPosition(const Vector3f& position) +{ + if (position != listenerPosition) + { + priv::ensureALInit(); + + alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z)); + listenerPosition = position; + } +} + + +//////////////////////////////////////////////////////////// +Vector3f Listener::getPosition() +{ + return listenerPosition; +} + + +//////////////////////////////////////////////////////////// +void Listener::setDirection(float x, float y, float z) +{ + setDirection(Vector3f(x, y, z)); +} + + +//////////////////////////////////////////////////////////// +void Listener::setDirection(const Vector3f& direction) +{ + if (direction != listenerDirection) + { + priv::ensureALInit(); + + float orientation[] = {direction.x, direction.y, direction.z, listenerUpVector.x, listenerUpVector.y, listenerUpVector.z}; + alCheck(alListenerfv(AL_ORIENTATION, orientation)); + listenerDirection = direction; + } +} + + +//////////////////////////////////////////////////////////// +Vector3f Listener::getDirection() +{ + return listenerDirection; +} + + +//////////////////////////////////////////////////////////// +void Listener::setUpVector(float x, float y, float z) +{ + setUpVector(Vector3f(x, y, z)); +} + + +//////////////////////////////////////////////////////////// +void Listener::setUpVector(const Vector3f& upVector) +{ + if (upVector != listenerUpVector) + { + priv::ensureALInit(); + + float orientation[] = {listenerDirection.x, listenerDirection.y, listenerDirection.z, upVector.x, upVector.y, upVector.z}; + alCheck(alListenerfv(AL_ORIENTATION, orientation)); + listenerUpVector = upVector; + } +} + + +//////////////////////////////////////////////////////////// +Vector3f Listener::getUpVector() +{ + return listenerUpVector; +} + +} // namespace sf diff --git a/src/SFML/Audio/Music.cpp b/src/SFML/Audio/Music.cpp index 8495ebc1..6f3b6db8 100644 --- a/src/SFML/Audio/Music.cpp +++ b/src/SFML/Audio/Music.cpp @@ -1,151 +1,151 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Music::Music() : -m_file (new priv::SoundFile), -m_duration() -{ - -} - - -//////////////////////////////////////////////////////////// -Music::~Music() -{ - // We must stop before destroying the file - stop(); - - delete m_file; -} - - -//////////////////////////////////////////////////////////// -bool Music::openFromFile(const std::string& filename) -{ - // First stop the music if it was already running - stop(); - - // Open the underlying sound file - if (!m_file->openRead(filename)) - return false; - - // Perform common initializations - initialize(); - - return true; -} - - -//////////////////////////////////////////////////////////// -bool Music::openFromMemory(const void* data, std::size_t sizeInBytes) -{ - // First stop the music if it was already running - stop(); - - // Open the underlying sound file - if (!m_file->openRead(data, sizeInBytes)) - return false; - - // Perform common initializations - initialize(); - - return true; -} - - -//////////////////////////////////////////////////////////// -bool Music::openFromStream(InputStream& stream) -{ - // First stop the music if it was already running - stop(); - - // Open the underlying sound file - if (!m_file->openRead(stream)) - return false; - - // Perform common initializations - initialize(); - - return true; -} - - -//////////////////////////////////////////////////////////// -Time Music::getDuration() const -{ - return m_duration; -} - - -//////////////////////////////////////////////////////////// -bool Music::onGetData(SoundStream::Chunk& data) -{ - Lock lock(m_mutex); - - // Fill the chunk parameters - data.samples = &m_samples[0]; - data.sampleCount = m_file->read(&m_samples[0], m_samples.size()); - - // Check if we have reached the end of the audio file - return data.sampleCount == m_samples.size(); -} - - -//////////////////////////////////////////////////////////// -void Music::onSeek(Time timeOffset) -{ - Lock lock(m_mutex); - - m_file->seek(timeOffset); -} - - -//////////////////////////////////////////////////////////// -void Music::initialize() -{ - // Compute the music duration - m_duration = seconds(static_cast(m_file->getSampleCount()) / m_file->getSampleRate() / m_file->getChannelCount()); - - // Resize the internal buffer so that it can contain 1 second of audio samples - m_samples.resize(m_file->getSampleRate() * m_file->getChannelCount()); - - // Initialize the stream - SoundStream::initialize(m_file->getChannelCount(), m_file->getSampleRate()); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Music::Music() : +m_file (new priv::SoundFile), +m_duration() +{ + +} + + +//////////////////////////////////////////////////////////// +Music::~Music() +{ + // We must stop before destroying the file + stop(); + + delete m_file; +} + + +//////////////////////////////////////////////////////////// +bool Music::openFromFile(const std::string& filename) +{ + // First stop the music if it was already running + stop(); + + // Open the underlying sound file + if (!m_file->openRead(filename)) + return false; + + // Perform common initializations + initialize(); + + return true; +} + + +//////////////////////////////////////////////////////////// +bool Music::openFromMemory(const void* data, std::size_t sizeInBytes) +{ + // First stop the music if it was already running + stop(); + + // Open the underlying sound file + if (!m_file->openRead(data, sizeInBytes)) + return false; + + // Perform common initializations + initialize(); + + return true; +} + + +//////////////////////////////////////////////////////////// +bool Music::openFromStream(InputStream& stream) +{ + // First stop the music if it was already running + stop(); + + // Open the underlying sound file + if (!m_file->openRead(stream)) + return false; + + // Perform common initializations + initialize(); + + return true; +} + + +//////////////////////////////////////////////////////////// +Time Music::getDuration() const +{ + return m_duration; +} + + +//////////////////////////////////////////////////////////// +bool Music::onGetData(SoundStream::Chunk& data) +{ + Lock lock(m_mutex); + + // Fill the chunk parameters + data.samples = &m_samples[0]; + data.sampleCount = m_file->read(&m_samples[0], m_samples.size()); + + // Check if we have reached the end of the audio file + return data.sampleCount == m_samples.size(); +} + + +//////////////////////////////////////////////////////////// +void Music::onSeek(Time timeOffset) +{ + Lock lock(m_mutex); + + m_file->seek(timeOffset); +} + + +//////////////////////////////////////////////////////////// +void Music::initialize() +{ + // Compute the music duration + m_duration = seconds(static_cast(m_file->getSampleCount()) / m_file->getSampleRate() / m_file->getChannelCount()); + + // Resize the internal buffer so that it can contain 1 second of audio samples + m_samples.resize(m_file->getSampleRate() * m_file->getChannelCount()); + + // Initialize the stream + SoundStream::initialize(m_file->getChannelCount(), m_file->getSampleRate()); +} + +} // namespace sf diff --git a/src/SFML/Audio/Sound.cpp b/src/SFML/Audio/Sound.cpp index d7228ed1..d138893d 100644 --- a/src/SFML/Audio/Sound.cpp +++ b/src/SFML/Audio/Sound.cpp @@ -1,200 +1,200 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Sound::Sound() : -m_buffer(NULL) -{ -} - - -//////////////////////////////////////////////////////////// -Sound::Sound(const SoundBuffer& buffer) : -m_buffer(NULL) -{ - setBuffer(buffer); -} - - -//////////////////////////////////////////////////////////// -Sound::Sound(const Sound& copy) : -SoundSource(copy), -m_buffer (NULL) -{ - if (copy.m_buffer) - setBuffer(*copy.m_buffer); - setLoop(copy.getLoop()); -} - - -//////////////////////////////////////////////////////////// -Sound::~Sound() -{ - stop(); - if (m_buffer) - m_buffer->detachSound(this); -} - - -//////////////////////////////////////////////////////////// -void Sound::play() -{ - alCheck(alSourcePlay(m_source)); -} - - -//////////////////////////////////////////////////////////// -void Sound::pause() -{ - alCheck(alSourcePause(m_source)); -} - - -//////////////////////////////////////////////////////////// -void Sound::stop() -{ - alCheck(alSourceStop(m_source)); -} - - -//////////////////////////////////////////////////////////// -void Sound::setBuffer(const SoundBuffer& buffer) -{ - // First detach from the previous buffer - if (m_buffer) - { - stop(); - m_buffer->detachSound(this); - } - - // Assign and use the new buffer - m_buffer = &buffer; - m_buffer->attachSound(this); - alCheck(alSourcei(m_source, AL_BUFFER, m_buffer->m_buffer)); -} - - -//////////////////////////////////////////////////////////// -void Sound::setLoop(bool loop) -{ - alCheck(alSourcei(m_source, AL_LOOPING, loop)); -} - - -//////////////////////////////////////////////////////////// -void Sound::setPlayingOffset(Time timeOffset) -{ - alCheck(alSourcef(m_source, AL_SEC_OFFSET, timeOffset.asSeconds())); -} - - -//////////////////////////////////////////////////////////// -const SoundBuffer* Sound::getBuffer() const -{ - return m_buffer; -} - - -//////////////////////////////////////////////////////////// -bool Sound::getLoop() const -{ - ALint loop; - alCheck(alGetSourcei(m_source, AL_LOOPING, &loop)); - - return loop != 0; -} - - -//////////////////////////////////////////////////////////// -Time Sound::getPlayingOffset() const -{ - ALfloat secs = 0.f; - alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs)); - - return seconds(secs); -} - - -//////////////////////////////////////////////////////////// -Sound::Status Sound::getStatus() const -{ - return SoundSource::getStatus(); -} - - -//////////////////////////////////////////////////////////// -Sound& Sound::operator =(const Sound& right) -{ - // Here we don't use the copy-and-swap idiom, because it would mess up - // the list of sound instances contained in the buffers - - // Detach the sound instance from the previous buffer (if any) - if (m_buffer) - { - stop(); - m_buffer->detachSound(this); - m_buffer = NULL; - } - - // Copy the sound attributes - if (right.m_buffer) - setBuffer(*right.m_buffer); - setLoop(right.getLoop()); - setPitch(right.getPitch()); - setVolume(right.getVolume()); - setPosition(right.getPosition()); - setRelativeToListener(right.isRelativeToListener()); - setMinDistance(right.getMinDistance()); - setAttenuation(right.getAttenuation()); - - return *this; -} - - -//////////////////////////////////////////////////////////// -void Sound::resetBuffer() -{ - // First stop the sound in case it is playing - stop(); - - // Detach the buffer - if (m_buffer) - { - alCheck(alSourcei(m_source, AL_BUFFER, 0)); - m_buffer->detachSound(this); - m_buffer = NULL; - } -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Sound::Sound() : +m_buffer(NULL) +{ +} + + +//////////////////////////////////////////////////////////// +Sound::Sound(const SoundBuffer& buffer) : +m_buffer(NULL) +{ + setBuffer(buffer); +} + + +//////////////////////////////////////////////////////////// +Sound::Sound(const Sound& copy) : +SoundSource(copy), +m_buffer (NULL) +{ + if (copy.m_buffer) + setBuffer(*copy.m_buffer); + setLoop(copy.getLoop()); +} + + +//////////////////////////////////////////////////////////// +Sound::~Sound() +{ + stop(); + if (m_buffer) + m_buffer->detachSound(this); +} + + +//////////////////////////////////////////////////////////// +void Sound::play() +{ + alCheck(alSourcePlay(m_source)); +} + + +//////////////////////////////////////////////////////////// +void Sound::pause() +{ + alCheck(alSourcePause(m_source)); +} + + +//////////////////////////////////////////////////////////// +void Sound::stop() +{ + alCheck(alSourceStop(m_source)); +} + + +//////////////////////////////////////////////////////////// +void Sound::setBuffer(const SoundBuffer& buffer) +{ + // First detach from the previous buffer + if (m_buffer) + { + stop(); + m_buffer->detachSound(this); + } + + // Assign and use the new buffer + m_buffer = &buffer; + m_buffer->attachSound(this); + alCheck(alSourcei(m_source, AL_BUFFER, m_buffer->m_buffer)); +} + + +//////////////////////////////////////////////////////////// +void Sound::setLoop(bool loop) +{ + alCheck(alSourcei(m_source, AL_LOOPING, loop)); +} + + +//////////////////////////////////////////////////////////// +void Sound::setPlayingOffset(Time timeOffset) +{ + alCheck(alSourcef(m_source, AL_SEC_OFFSET, timeOffset.asSeconds())); +} + + +//////////////////////////////////////////////////////////// +const SoundBuffer* Sound::getBuffer() const +{ + return m_buffer; +} + + +//////////////////////////////////////////////////////////// +bool Sound::getLoop() const +{ + ALint loop; + alCheck(alGetSourcei(m_source, AL_LOOPING, &loop)); + + return loop != 0; +} + + +//////////////////////////////////////////////////////////// +Time Sound::getPlayingOffset() const +{ + ALfloat secs = 0.f; + alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs)); + + return seconds(secs); +} + + +//////////////////////////////////////////////////////////// +Sound::Status Sound::getStatus() const +{ + return SoundSource::getStatus(); +} + + +//////////////////////////////////////////////////////////// +Sound& Sound::operator =(const Sound& right) +{ + // Here we don't use the copy-and-swap idiom, because it would mess up + // the list of sound instances contained in the buffers + + // Detach the sound instance from the previous buffer (if any) + if (m_buffer) + { + stop(); + m_buffer->detachSound(this); + m_buffer = NULL; + } + + // Copy the sound attributes + if (right.m_buffer) + setBuffer(*right.m_buffer); + setLoop(right.getLoop()); + setPitch(right.getPitch()); + setVolume(right.getVolume()); + setPosition(right.getPosition()); + setRelativeToListener(right.isRelativeToListener()); + setMinDistance(right.getMinDistance()); + setAttenuation(right.getAttenuation()); + + return *this; +} + + +//////////////////////////////////////////////////////////// +void Sound::resetBuffer() +{ + // First stop the sound in case it is playing + stop(); + + // Detach the buffer + if (m_buffer) + { + alCheck(alSourcei(m_source, AL_BUFFER, 0)); + m_buffer->detachSound(this); + m_buffer = NULL; + } +} + +} // namespace sf diff --git a/src/SFML/Audio/SoundBuffer.cpp b/src/SFML/Audio/SoundBuffer.cpp index d17227cb..0d8818c7 100644 --- a/src/SFML/Audio/SoundBuffer.cpp +++ b/src/SFML/Audio/SoundBuffer.cpp @@ -1,286 +1,286 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -SoundBuffer::SoundBuffer() : -m_buffer (0), -m_duration() -{ - priv::ensureALInit(); - - // Create the buffer - alCheck(alGenBuffers(1, &m_buffer)); -} - - -//////////////////////////////////////////////////////////// -SoundBuffer::SoundBuffer(const SoundBuffer& copy) : -m_buffer (0), -m_samples (copy.m_samples), -m_duration(copy.m_duration), -m_sounds () // don't copy the attached sounds -{ - // Create the buffer - alCheck(alGenBuffers(1, &m_buffer)); - - // Update the internal buffer with the new samples - update(copy.getChannelCount(), copy.getSampleRate()); -} - - -//////////////////////////////////////////////////////////// -SoundBuffer::~SoundBuffer() -{ - // First detach the buffer from the sounds that use it (to avoid OpenAL errors) - for (SoundList::const_iterator it = m_sounds.begin(); it != m_sounds.end(); ++it) - (*it)->resetBuffer(); - - // Destroy the buffer - if (m_buffer) - alCheck(alDeleteBuffers(1, &m_buffer)); -} - - -//////////////////////////////////////////////////////////// -bool SoundBuffer::loadFromFile(const std::string& filename) -{ - priv::SoundFile file; - if (file.openRead(filename)) - return initialize(file); - else - return false; -} - - -//////////////////////////////////////////////////////////// -bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes) -{ - priv::SoundFile file; - if (file.openRead(data, sizeInBytes)) - return initialize(file); - else - return false; -} - - -//////////////////////////////////////////////////////////// -bool SoundBuffer::loadFromStream(InputStream& stream) -{ - priv::SoundFile file; - if (file.openRead(stream)) - return initialize(file); - else - return false; -} - - -//////////////////////////////////////////////////////////// -bool SoundBuffer::loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate) -{ - if (samples && sampleCount && channelCount && sampleRate) - { - // Copy the new audio samples - m_samples.assign(samples, samples + sampleCount); - - // Update the internal buffer with the new samples - return update(channelCount, sampleRate); - } - else - { - // Error... - err() << "Failed to load sound buffer from samples (" - << "array: " << samples << ", " - << "count: " << sampleCount << ", " - << "channels: " << channelCount << ", " - << "samplerate: " << sampleRate << ")" - << std::endl; - - return false; - } -} - - -//////////////////////////////////////////////////////////// -bool SoundBuffer::saveToFile(const std::string& filename) const -{ - // Create the sound file in write mode - priv::SoundFile file; - if (file.openWrite(filename, getChannelCount(), getSampleRate())) - { - // Write the samples to the opened file - file.write(&m_samples[0], m_samples.size()); - - return true; - } - else - { - return false; - } -} - - -//////////////////////////////////////////////////////////// -const Int16* SoundBuffer::getSamples() const -{ - return m_samples.empty() ? NULL : &m_samples[0]; -} - - -//////////////////////////////////////////////////////////// -std::size_t SoundBuffer::getSampleCount() const -{ - return m_samples.size(); -} - - -//////////////////////////////////////////////////////////// -unsigned int SoundBuffer::getSampleRate() const -{ - ALint sampleRate; - alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate)); - - return sampleRate; -} - - -//////////////////////////////////////////////////////////// -unsigned int SoundBuffer::getChannelCount() const -{ - ALint channelCount; - alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount)); - - return channelCount; -} - - -//////////////////////////////////////////////////////////// -Time SoundBuffer::getDuration() const -{ - return m_duration; -} - - -//////////////////////////////////////////////////////////// -SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right) -{ - SoundBuffer temp(right); - - std::swap(m_samples, temp.m_samples); - std::swap(m_buffer, temp.m_buffer); - std::swap(m_duration, temp.m_duration); - std::swap(m_sounds, temp.m_sounds); // swap sounds too, so that they are detached when temp is destroyed - - return *this; -} - - -//////////////////////////////////////////////////////////// -bool SoundBuffer::initialize(priv::SoundFile& file) -{ - // Retrieve the sound parameters - std::size_t sampleCount = file.getSampleCount(); - unsigned int channelCount = file.getChannelCount(); - unsigned int sampleRate = file.getSampleRate(); - - // Read the samples from the provided file - m_samples.resize(sampleCount); - if (file.read(&m_samples[0], sampleCount) == sampleCount) - { - // Update the internal buffer with the new samples - return update(channelCount, sampleRate); - } - else - { - return false; - } -} - - -//////////////////////////////////////////////////////////// -bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate) -{ - // Check parameters - if (!channelCount || !sampleRate || m_samples.empty()) - return false; - - // Find the good format according to the number of channels - ALenum format = priv::AudioDevice::getFormatFromChannelCount(channelCount); - - // Check if the format is valid - if (format == 0) - { - err() << "Failed to load sound buffer (unsupported number of channels: " << channelCount << ")" << std::endl; - return false; - } - - // First make a copy of the list of sounds so we can reattach later - SoundList sounds(m_sounds); - - // Detach the buffer from the sounds that use it (to avoid OpenAL errors) - for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it) - (*it)->resetBuffer(); - - // Fill the buffer - ALsizei size = static_cast(m_samples.size()) * sizeof(Int16); - alCheck(alBufferData(m_buffer, format, &m_samples[0], size, sampleRate)); - - // Compute the duration - m_duration = seconds(static_cast(m_samples.size()) / sampleRate / channelCount); - - // Now reattach the buffer to the sounds that use it - for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it) - (*it)->setBuffer(*this); - - return true; -} - - -//////////////////////////////////////////////////////////// -void SoundBuffer::attachSound(Sound* sound) const -{ - m_sounds.insert(sound); -} - - -//////////////////////////////////////////////////////////// -void SoundBuffer::detachSound(Sound* sound) const -{ - m_sounds.erase(sound); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +SoundBuffer::SoundBuffer() : +m_buffer (0), +m_duration() +{ + priv::ensureALInit(); + + // Create the buffer + alCheck(alGenBuffers(1, &m_buffer)); +} + + +//////////////////////////////////////////////////////////// +SoundBuffer::SoundBuffer(const SoundBuffer& copy) : +m_buffer (0), +m_samples (copy.m_samples), +m_duration(copy.m_duration), +m_sounds () // don't copy the attached sounds +{ + // Create the buffer + alCheck(alGenBuffers(1, &m_buffer)); + + // Update the internal buffer with the new samples + update(copy.getChannelCount(), copy.getSampleRate()); +} + + +//////////////////////////////////////////////////////////// +SoundBuffer::~SoundBuffer() +{ + // First detach the buffer from the sounds that use it (to avoid OpenAL errors) + for (SoundList::const_iterator it = m_sounds.begin(); it != m_sounds.end(); ++it) + (*it)->resetBuffer(); + + // Destroy the buffer + if (m_buffer) + alCheck(alDeleteBuffers(1, &m_buffer)); +} + + +//////////////////////////////////////////////////////////// +bool SoundBuffer::loadFromFile(const std::string& filename) +{ + priv::SoundFile file; + if (file.openRead(filename)) + return initialize(file); + else + return false; +} + + +//////////////////////////////////////////////////////////// +bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes) +{ + priv::SoundFile file; + if (file.openRead(data, sizeInBytes)) + return initialize(file); + else + return false; +} + + +//////////////////////////////////////////////////////////// +bool SoundBuffer::loadFromStream(InputStream& stream) +{ + priv::SoundFile file; + if (file.openRead(stream)) + return initialize(file); + else + return false; +} + + +//////////////////////////////////////////////////////////// +bool SoundBuffer::loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate) +{ + if (samples && sampleCount && channelCount && sampleRate) + { + // Copy the new audio samples + m_samples.assign(samples, samples + sampleCount); + + // Update the internal buffer with the new samples + return update(channelCount, sampleRate); + } + else + { + // Error... + err() << "Failed to load sound buffer from samples (" + << "array: " << samples << ", " + << "count: " << sampleCount << ", " + << "channels: " << channelCount << ", " + << "samplerate: " << sampleRate << ")" + << std::endl; + + return false; + } +} + + +//////////////////////////////////////////////////////////// +bool SoundBuffer::saveToFile(const std::string& filename) const +{ + // Create the sound file in write mode + priv::SoundFile file; + if (file.openWrite(filename, getChannelCount(), getSampleRate())) + { + // Write the samples to the opened file + file.write(&m_samples[0], m_samples.size()); + + return true; + } + else + { + return false; + } +} + + +//////////////////////////////////////////////////////////// +const Int16* SoundBuffer::getSamples() const +{ + return m_samples.empty() ? NULL : &m_samples[0]; +} + + +//////////////////////////////////////////////////////////// +std::size_t SoundBuffer::getSampleCount() const +{ + return m_samples.size(); +} + + +//////////////////////////////////////////////////////////// +unsigned int SoundBuffer::getSampleRate() const +{ + ALint sampleRate; + alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate)); + + return sampleRate; +} + + +//////////////////////////////////////////////////////////// +unsigned int SoundBuffer::getChannelCount() const +{ + ALint channelCount; + alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount)); + + return channelCount; +} + + +//////////////////////////////////////////////////////////// +Time SoundBuffer::getDuration() const +{ + return m_duration; +} + + +//////////////////////////////////////////////////////////// +SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right) +{ + SoundBuffer temp(right); + + std::swap(m_samples, temp.m_samples); + std::swap(m_buffer, temp.m_buffer); + std::swap(m_duration, temp.m_duration); + std::swap(m_sounds, temp.m_sounds); // swap sounds too, so that they are detached when temp is destroyed + + return *this; +} + + +//////////////////////////////////////////////////////////// +bool SoundBuffer::initialize(priv::SoundFile& file) +{ + // Retrieve the sound parameters + std::size_t sampleCount = file.getSampleCount(); + unsigned int channelCount = file.getChannelCount(); + unsigned int sampleRate = file.getSampleRate(); + + // Read the samples from the provided file + m_samples.resize(sampleCount); + if (file.read(&m_samples[0], sampleCount) == sampleCount) + { + // Update the internal buffer with the new samples + return update(channelCount, sampleRate); + } + else + { + return false; + } +} + + +//////////////////////////////////////////////////////////// +bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate) +{ + // Check parameters + if (!channelCount || !sampleRate || m_samples.empty()) + return false; + + // Find the good format according to the number of channels + ALenum format = priv::AudioDevice::getFormatFromChannelCount(channelCount); + + // Check if the format is valid + if (format == 0) + { + err() << "Failed to load sound buffer (unsupported number of channels: " << channelCount << ")" << std::endl; + return false; + } + + // First make a copy of the list of sounds so we can reattach later + SoundList sounds(m_sounds); + + // Detach the buffer from the sounds that use it (to avoid OpenAL errors) + for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it) + (*it)->resetBuffer(); + + // Fill the buffer + ALsizei size = static_cast(m_samples.size()) * sizeof(Int16); + alCheck(alBufferData(m_buffer, format, &m_samples[0], size, sampleRate)); + + // Compute the duration + m_duration = seconds(static_cast(m_samples.size()) / sampleRate / channelCount); + + // Now reattach the buffer to the sounds that use it + for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it) + (*it)->setBuffer(*this); + + return true; +} + + +//////////////////////////////////////////////////////////// +void SoundBuffer::attachSound(Sound* sound) const +{ + m_sounds.insert(sound); +} + + +//////////////////////////////////////////////////////////// +void SoundBuffer::detachSound(Sound* sound) const +{ + m_sounds.erase(sound); +} + +} // namespace sf diff --git a/src/SFML/Audio/SoundBufferRecorder.cpp b/src/SFML/Audio/SoundBufferRecorder.cpp index 3d5c7c3d..11724b15 100644 --- a/src/SFML/Audio/SoundBufferRecorder.cpp +++ b/src/SFML/Audio/SoundBufferRecorder.cpp @@ -1,68 +1,68 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -bool SoundBufferRecorder::onStart() -{ - m_samples.clear(); - m_buffer = SoundBuffer(); - - return true; -} - - -//////////////////////////////////////////////////////////// -bool SoundBufferRecorder::onProcessSamples(const Int16* samples, std::size_t sampleCount) -{ - std::copy(samples, samples + sampleCount, std::back_inserter(m_samples)); - - return true; -} - - -//////////////////////////////////////////////////////////// -void SoundBufferRecorder::onStop() -{ - if (!m_samples.empty()) - m_buffer.loadFromSamples(&m_samples[0], m_samples.size(), 1, getSampleRate()); -} - - -//////////////////////////////////////////////////////////// -const SoundBuffer& SoundBufferRecorder::getBuffer() const -{ - return m_buffer; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +bool SoundBufferRecorder::onStart() +{ + m_samples.clear(); + m_buffer = SoundBuffer(); + + return true; +} + + +//////////////////////////////////////////////////////////// +bool SoundBufferRecorder::onProcessSamples(const Int16* samples, std::size_t sampleCount) +{ + std::copy(samples, samples + sampleCount, std::back_inserter(m_samples)); + + return true; +} + + +//////////////////////////////////////////////////////////// +void SoundBufferRecorder::onStop() +{ + if (!m_samples.empty()) + m_buffer.loadFromSamples(&m_samples[0], m_samples.size(), 1, getSampleRate()); +} + + +//////////////////////////////////////////////////////////// +const SoundBuffer& SoundBufferRecorder::getBuffer() const +{ + return m_buffer; +} + +} // namespace sf diff --git a/src/SFML/Audio/SoundFile.cpp b/src/SFML/Audio/SoundFile.cpp index f49515e8..7ca5f82e 100644 --- a/src/SFML/Audio/SoundFile.cpp +++ b/src/SFML/Audio/SoundFile.cpp @@ -1,451 +1,451 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#ifdef SFML_SYSTEM_ANDROID - #include -#endif -#include -#include -#include -#include - - -namespace -{ - // Convert a string to lower case - std::string toLower(std::string str) - { - for (std::string::iterator i = str.begin(); i != str.end(); ++i) - *i = static_cast(std::tolower(*i)); - return str; - } -} - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -SoundFile::SoundFile() : -m_file (NULL), -m_sampleCount (0), -m_channelCount(0), -m_sampleRate (0) -{ - #ifdef SFML_SYSTEM_ANDROID - - m_resourceStream = NULL; - - #endif -} - - -//////////////////////////////////////////////////////////// -SoundFile::~SoundFile() -{ - if (m_file) - sf_close(m_file); - - #ifdef SFML_SYSTEM_ANDROID - - if (m_resourceStream) - delete (priv::ResourceStream*)m_resourceStream; - - #endif -} - - -//////////////////////////////////////////////////////////// -std::size_t SoundFile::getSampleCount() const -{ - return m_sampleCount; -} - - -//////////////////////////////////////////////////////////// -unsigned int SoundFile::getChannelCount() const -{ - return m_channelCount; -} - - -//////////////////////////////////////////////////////////// -unsigned int SoundFile::getSampleRate() const -{ - return m_sampleRate; -} - - -//////////////////////////////////////////////////////////// -bool SoundFile::openRead(const std::string& filename) -{ - #ifndef SFML_SYSTEM_ANDROID - - // If the file is already opened, first close it - if (m_file) - sf_close(m_file); - - // Open the sound file - SF_INFO fileInfo; - fileInfo.format = 0; - m_file = sf_open(filename.c_str(), SFM_READ, &fileInfo); - if (!m_file) - { - err() << "Failed to open sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl; - return false; - } - - // Initialize the internal state from the loaded information - initialize(fileInfo); - - return true; - - #else - - if (m_resourceStream) - delete (priv::ResourceStream*)m_resourceStream; - - m_resourceStream = new priv::ResourceStream(filename); - return openRead(*(priv::ResourceStream*)m_resourceStream); - - #endif -} - - -//////////////////////////////////////////////////////////// -bool SoundFile::openRead(const void* data, std::size_t sizeInBytes) -{ - // If the file is already opened, first close it - if (m_file) - sf_close(m_file); - - // Prepare the memory I/O structure - SF_VIRTUAL_IO io; - io.get_filelen = &Memory::getLength; - io.read = &Memory::read; - io.seek = &Memory::seek; - io.tell = &Memory::tell; - - // Initialize the memory data - m_memory.begin = static_cast(data); - m_memory.current = m_memory.begin; - m_memory.size = sizeInBytes; - - // Open the sound file - SF_INFO fileInfo; - fileInfo.format = 0; - m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_memory); - if (!m_file) - { - err() << "Failed to open sound file from memory (" << sf_strerror(m_file) << ")" << std::endl; - return false; - } - - // Initialize the internal state from the loaded information - initialize(fileInfo); - - return true; -} - - -//////////////////////////////////////////////////////////// -bool SoundFile::openRead(InputStream& stream) -{ - // If the file is already opened, first close it - if (m_file) - sf_close(m_file); - - // Prepare the memory I/O structure - SF_VIRTUAL_IO io; - io.get_filelen = &Stream::getLength; - io.read = &Stream::read; - io.seek = &Stream::seek; - io.tell = &Stream::tell; - - // Initialize the stream data - m_stream.source = &stream; - m_stream.size = stream.getSize(); - - // Make sure that the stream's reading position is at the beginning - stream.seek(0); - - // Open the sound file - SF_INFO fileInfo; - fileInfo.format = 0; - m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream); - if (!m_file) - { - err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl; - return false; - } - - // Initialize the internal state from the loaded information - initialize(fileInfo); - - return true; -} - - -//////////////////////////////////////////////////////////// -bool SoundFile::openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate) -{ - // If the file is already opened, first close it - if (m_file) - sf_close(m_file); - - // Find the right format according to the file extension - int format = getFormatFromFilename(filename); - if (format == -1) - { - // Error : unrecognized extension - err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl; - return false; - } - - // Fill the sound infos with parameters - SF_INFO fileInfos; - fileInfos.channels = channelCount; - fileInfos.samplerate = sampleRate; - fileInfos.format = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16); - - // Open the sound file for writing - m_file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos); - if (!m_file) - { - err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl; - return false; - } - - // Set the sound parameters - m_channelCount = channelCount; - m_sampleRate = sampleRate; - m_sampleCount = 0; - - return true; -} - - -//////////////////////////////////////////////////////////// -std::size_t SoundFile::read(Int16* data, std::size_t sampleCount) -{ - if (m_file && data && sampleCount) - return static_cast(sf_read_short(m_file, data, sampleCount)); - else - return 0; -} - - -//////////////////////////////////////////////////////////// -void SoundFile::write(const Int16* data, std::size_t sampleCount) -{ - if (m_file && data && sampleCount) - { - // Write small chunks instead of everything at once, - // to avoid a stack overflow in libsndfile (happens only with OGG format) - while (sampleCount > 0) - { - std::size_t count = sampleCount > 10000 ? 10000 : sampleCount; - sf_write_short(m_file, data, count); - data += count; - sampleCount -= count; - } - } -} - - -//////////////////////////////////////////////////////////// -void SoundFile::seek(Time timeOffset) -{ - if (m_file) - { - sf_count_t frameOffset = static_cast(timeOffset.asSeconds() * m_sampleRate); - sf_seek(m_file, frameOffset, SEEK_SET); - } -} - - -//////////////////////////////////////////////////////////// -void SoundFile::initialize(SF_INFO fileInfo) -{ - // Save the sound properties - m_channelCount = fileInfo.channels; - m_sampleRate = fileInfo.samplerate; - m_sampleCount = static_cast(fileInfo.frames) * fileInfo.channels; - - // Enable scaling for Vorbis files (float samples) - // @todo enable when it's faster (it currently has to iterate over the *whole* music) - //if (fileInfo.format & SF_FORMAT_VORBIS) - // sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE); -} - - -//////////////////////////////////////////////////////////// -int SoundFile::getFormatFromFilename(const std::string& filename) -{ - // Extract the extension - std::string ext = "wav"; - std::string::size_type pos = filename.find_last_of("."); - if (pos != std::string::npos) - ext = toLower(filename.substr(pos + 1)); - - // Match every supported extension with its format constant - if (ext == "wav" ) return SF_FORMAT_WAV; - if (ext == "aif" ) return SF_FORMAT_AIFF; - if (ext == "aiff" ) return SF_FORMAT_AIFF; - if (ext == "au" ) return SF_FORMAT_AU; - if (ext == "raw" ) return SF_FORMAT_RAW; - if (ext == "paf" ) return SF_FORMAT_PAF; - if (ext == "svx" ) return SF_FORMAT_SVX; - if (ext == "nist" ) return SF_FORMAT_NIST; - if (ext == "voc" ) return SF_FORMAT_VOC; - if (ext == "sf" ) return SF_FORMAT_IRCAM; - if (ext == "w64" ) return SF_FORMAT_W64; - if (ext == "mat4" ) return SF_FORMAT_MAT4; - if (ext == "mat5" ) return SF_FORMAT_MAT5; - if (ext == "pvf" ) return SF_FORMAT_PVF; - if (ext == "xi" ) return SF_FORMAT_XI; - if (ext == "htk" ) return SF_FORMAT_HTK; - if (ext == "sds" ) return SF_FORMAT_SDS; - if (ext == "avr" ) return SF_FORMAT_AVR; - if (ext == "sd2" ) return SF_FORMAT_SD2; - if (ext == "flac" ) return SF_FORMAT_FLAC; - if (ext == "caf" ) return SF_FORMAT_CAF; - if (ext == "wve" ) return SF_FORMAT_WVE; - if (ext == "ogg" ) return SF_FORMAT_OGG; - if (ext == "mpc2k") return SF_FORMAT_MPC2K; - if (ext == "rf64" ) return SF_FORMAT_RF64; - - return -1; -} - - -//////////////////////////////////////////////////////////// -sf_count_t SoundFile::Memory::getLength(void* user) -{ - Memory* memory = static_cast(user); - return memory->size; -} - - -//////////////////////////////////////////////////////////// -sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user) -{ - Memory* memory = static_cast(user); - - sf_count_t position = tell(user); - if (position + count >= memory->size) - count = memory->size - position; - - std::memcpy(ptr, memory->current, static_cast(count)); - memory->current += count; - return count; -} - - -//////////////////////////////////////////////////////////// -sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user) -{ - Memory* memory = static_cast(user); - sf_count_t position = 0; - switch (whence) - { - case SEEK_SET : position = offset; break; - case SEEK_CUR : position = memory->current - memory->begin + offset; break; - case SEEK_END : position = memory->size - offset; break; - default : position = 0; break; - } - - if (position >= memory->size) - position = memory->size - 1; - else if (position < 0) - position = 0; - - memory->current = memory->begin + position; - return position; -} - - -//////////////////////////////////////////////////////////// -sf_count_t SoundFile::Memory::tell(void* user) -{ - Memory* memory = static_cast(user); - return memory->current - memory->begin; -} - - -//////////////////////////////////////////////////////////// -sf_count_t SoundFile::Stream::getLength(void* userData) -{ - Stream* stream = static_cast(userData); - return stream->size; -} - - -//////////////////////////////////////////////////////////// -sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData) -{ - Stream* stream = static_cast(userData); - Int64 position = stream->source->tell(); - if (position != -1) - { - if (count > stream->size - position) - count = stream->size - position; - return stream->source->read(reinterpret_cast(ptr), count); - } - else - { - return -1; - } -} - - -//////////////////////////////////////////////////////////// -sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData) -{ - Stream* stream = static_cast(userData); - switch (whence) - { - case SEEK_SET : return stream->source->seek(offset); - case SEEK_CUR : return stream->source->seek(stream->source->tell() + offset); - case SEEK_END : return stream->source->seek(stream->size - offset); - default : return stream->source->seek(0); - } -} - - -//////////////////////////////////////////////////////////// -sf_count_t SoundFile::Stream::tell(void* userData) -{ - Stream* stream = static_cast(userData); - return stream->source->tell(); -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#ifdef SFML_SYSTEM_ANDROID + #include +#endif +#include +#include +#include +#include + + +namespace +{ + // Convert a string to lower case + std::string toLower(std::string str) + { + for (std::string::iterator i = str.begin(); i != str.end(); ++i) + *i = static_cast(std::tolower(*i)); + return str; + } +} + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +SoundFile::SoundFile() : +m_file (NULL), +m_sampleCount (0), +m_channelCount(0), +m_sampleRate (0) +{ + #ifdef SFML_SYSTEM_ANDROID + + m_resourceStream = NULL; + + #endif +} + + +//////////////////////////////////////////////////////////// +SoundFile::~SoundFile() +{ + if (m_file) + sf_close(m_file); + + #ifdef SFML_SYSTEM_ANDROID + + if (m_resourceStream) + delete (priv::ResourceStream*)m_resourceStream; + + #endif +} + + +//////////////////////////////////////////////////////////// +std::size_t SoundFile::getSampleCount() const +{ + return m_sampleCount; +} + + +//////////////////////////////////////////////////////////// +unsigned int SoundFile::getChannelCount() const +{ + return m_channelCount; +} + + +//////////////////////////////////////////////////////////// +unsigned int SoundFile::getSampleRate() const +{ + return m_sampleRate; +} + + +//////////////////////////////////////////////////////////// +bool SoundFile::openRead(const std::string& filename) +{ + #ifndef SFML_SYSTEM_ANDROID + + // If the file is already opened, first close it + if (m_file) + sf_close(m_file); + + // Open the sound file + SF_INFO fileInfo; + fileInfo.format = 0; + m_file = sf_open(filename.c_str(), SFM_READ, &fileInfo); + if (!m_file) + { + err() << "Failed to open sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl; + return false; + } + + // Initialize the internal state from the loaded information + initialize(fileInfo); + + return true; + + #else + + if (m_resourceStream) + delete (priv::ResourceStream*)m_resourceStream; + + m_resourceStream = new priv::ResourceStream(filename); + return openRead(*(priv::ResourceStream*)m_resourceStream); + + #endif +} + + +//////////////////////////////////////////////////////////// +bool SoundFile::openRead(const void* data, std::size_t sizeInBytes) +{ + // If the file is already opened, first close it + if (m_file) + sf_close(m_file); + + // Prepare the memory I/O structure + SF_VIRTUAL_IO io; + io.get_filelen = &Memory::getLength; + io.read = &Memory::read; + io.seek = &Memory::seek; + io.tell = &Memory::tell; + + // Initialize the memory data + m_memory.begin = static_cast(data); + m_memory.current = m_memory.begin; + m_memory.size = sizeInBytes; + + // Open the sound file + SF_INFO fileInfo; + fileInfo.format = 0; + m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_memory); + if (!m_file) + { + err() << "Failed to open sound file from memory (" << sf_strerror(m_file) << ")" << std::endl; + return false; + } + + // Initialize the internal state from the loaded information + initialize(fileInfo); + + return true; +} + + +//////////////////////////////////////////////////////////// +bool SoundFile::openRead(InputStream& stream) +{ + // If the file is already opened, first close it + if (m_file) + sf_close(m_file); + + // Prepare the memory I/O structure + SF_VIRTUAL_IO io; + io.get_filelen = &Stream::getLength; + io.read = &Stream::read; + io.seek = &Stream::seek; + io.tell = &Stream::tell; + + // Initialize the stream data + m_stream.source = &stream; + m_stream.size = stream.getSize(); + + // Make sure that the stream's reading position is at the beginning + stream.seek(0); + + // Open the sound file + SF_INFO fileInfo; + fileInfo.format = 0; + m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream); + if (!m_file) + { + err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl; + return false; + } + + // Initialize the internal state from the loaded information + initialize(fileInfo); + + return true; +} + + +//////////////////////////////////////////////////////////// +bool SoundFile::openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate) +{ + // If the file is already opened, first close it + if (m_file) + sf_close(m_file); + + // Find the right format according to the file extension + int format = getFormatFromFilename(filename); + if (format == -1) + { + // Error: unrecognized extension + err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl; + return false; + } + + // Fill the sound infos with parameters + SF_INFO fileInfos; + fileInfos.channels = channelCount; + fileInfos.samplerate = sampleRate; + fileInfos.format = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16); + + // Open the sound file for writing + m_file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos); + if (!m_file) + { + err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl; + return false; + } + + // Set the sound parameters + m_channelCount = channelCount; + m_sampleRate = sampleRate; + m_sampleCount = 0; + + return true; +} + + +//////////////////////////////////////////////////////////// +std::size_t SoundFile::read(Int16* data, std::size_t sampleCount) +{ + if (m_file && data && sampleCount) + return static_cast(sf_read_short(m_file, data, sampleCount)); + else + return 0; +} + + +//////////////////////////////////////////////////////////// +void SoundFile::write(const Int16* data, std::size_t sampleCount) +{ + if (m_file && data && sampleCount) + { + // Write small chunks instead of everything at once, + // to avoid a stack overflow in libsndfile (happens only with OGG format) + while (sampleCount > 0) + { + std::size_t count = sampleCount > 10000 ? 10000 : sampleCount; + sf_write_short(m_file, data, count); + data += count; + sampleCount -= count; + } + } +} + + +//////////////////////////////////////////////////////////// +void SoundFile::seek(Time timeOffset) +{ + if (m_file) + { + sf_count_t frameOffset = static_cast(timeOffset.asSeconds() * m_sampleRate); + sf_seek(m_file, frameOffset, SEEK_SET); + } +} + + +//////////////////////////////////////////////////////////// +void SoundFile::initialize(SF_INFO fileInfo) +{ + // Save the sound properties + m_channelCount = fileInfo.channels; + m_sampleRate = fileInfo.samplerate; + m_sampleCount = static_cast(fileInfo.frames) * fileInfo.channels; + + // Enable scaling for Vorbis files (float samples) + // @todo enable when it's faster (it currently has to iterate over the *whole* music) + //if (fileInfo.format & SF_FORMAT_VORBIS) + // sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE); +} + + +//////////////////////////////////////////////////////////// +int SoundFile::getFormatFromFilename(const std::string& filename) +{ + // Extract the extension + std::string ext = "wav"; + std::string::size_type pos = filename.find_last_of("."); + if (pos != std::string::npos) + ext = toLower(filename.substr(pos + 1)); + + // Match every supported extension with its format constant + if (ext == "wav" ) return SF_FORMAT_WAV; + if (ext == "aif" ) return SF_FORMAT_AIFF; + if (ext == "aiff" ) return SF_FORMAT_AIFF; + if (ext == "au" ) return SF_FORMAT_AU; + if (ext == "raw" ) return SF_FORMAT_RAW; + if (ext == "paf" ) return SF_FORMAT_PAF; + if (ext == "svx" ) return SF_FORMAT_SVX; + if (ext == "nist" ) return SF_FORMAT_NIST; + if (ext == "voc" ) return SF_FORMAT_VOC; + if (ext == "sf" ) return SF_FORMAT_IRCAM; + if (ext == "w64" ) return SF_FORMAT_W64; + if (ext == "mat4" ) return SF_FORMAT_MAT4; + if (ext == "mat5" ) return SF_FORMAT_MAT5; + if (ext == "pvf" ) return SF_FORMAT_PVF; + if (ext == "xi" ) return SF_FORMAT_XI; + if (ext == "htk" ) return SF_FORMAT_HTK; + if (ext == "sds" ) return SF_FORMAT_SDS; + if (ext == "avr" ) return SF_FORMAT_AVR; + if (ext == "sd2" ) return SF_FORMAT_SD2; + if (ext == "flac" ) return SF_FORMAT_FLAC; + if (ext == "caf" ) return SF_FORMAT_CAF; + if (ext == "wve" ) return SF_FORMAT_WVE; + if (ext == "ogg" ) return SF_FORMAT_OGG; + if (ext == "mpc2k") return SF_FORMAT_MPC2K; + if (ext == "rf64" ) return SF_FORMAT_RF64; + + return -1; +} + + +//////////////////////////////////////////////////////////// +sf_count_t SoundFile::Memory::getLength(void* user) +{ + Memory* memory = static_cast(user); + return memory->size; +} + + +//////////////////////////////////////////////////////////// +sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user) +{ + Memory* memory = static_cast(user); + + sf_count_t position = tell(user); + if (position + count >= memory->size) + count = memory->size - position; + + std::memcpy(ptr, memory->current, static_cast(count)); + memory->current += count; + return count; +} + + +//////////////////////////////////////////////////////////// +sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user) +{ + Memory* memory = static_cast(user); + sf_count_t position = 0; + switch (whence) + { + case SEEK_SET: position = offset; break; + case SEEK_CUR: position = memory->current - memory->begin + offset; break; + case SEEK_END: position = memory->size - offset; break; + default: position = 0; break; + } + + if (position >= memory->size) + position = memory->size - 1; + else if (position < 0) + position = 0; + + memory->current = memory->begin + position; + return position; +} + + +//////////////////////////////////////////////////////////// +sf_count_t SoundFile::Memory::tell(void* user) +{ + Memory* memory = static_cast(user); + return memory->current - memory->begin; +} + + +//////////////////////////////////////////////////////////// +sf_count_t SoundFile::Stream::getLength(void* userData) +{ + Stream* stream = static_cast(userData); + return stream->size; +} + + +//////////////////////////////////////////////////////////// +sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData) +{ + Stream* stream = static_cast(userData); + Int64 position = stream->source->tell(); + if (position != -1) + { + if (count > stream->size - position) + count = stream->size - position; + return stream->source->read(reinterpret_cast(ptr), count); + } + else + { + return -1; + } +} + + +//////////////////////////////////////////////////////////// +sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData) +{ + Stream* stream = static_cast(userData); + switch (whence) + { + case SEEK_SET: return stream->source->seek(offset); + case SEEK_CUR: return stream->source->seek(stream->source->tell() + offset); + case SEEK_END: return stream->source->seek(stream->size - offset); + default: return stream->source->seek(0); + } +} + + +//////////////////////////////////////////////////////////// +sf_count_t SoundFile::Stream::tell(void* userData) +{ + Stream* stream = static_cast(userData); + return stream->source->tell(); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Audio/SoundFile.hpp b/src/SFML/Audio/SoundFile.hpp index 16bfe6f0..a04a0ff8 100644 --- a/src/SFML/Audio/SoundFile.hpp +++ b/src/SFML/Audio/SoundFile.hpp @@ -1,231 +1,231 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOUNDFILE_HPP -#define SFML_SOUNDFILE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -class InputStream; - -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Provide read and write access to sound files -/// -//////////////////////////////////////////////////////////// -class SoundFile : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - SoundFile(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~SoundFile(); - - //////////////////////////////////////////////////////////// - /// \brief Get the total number of audio samples in the file - /// - /// \return Number of samples - /// - //////////////////////////////////////////////////////////// - std::size_t getSampleCount() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the number of channels used by the sound - /// - /// \return Number of channels (1 = mono, 2 = stereo) - /// - //////////////////////////////////////////////////////////// - unsigned int getChannelCount() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the sample rate of the sound - /// - /// \return Sample rate, in samples per second - /// - //////////////////////////////////////////////////////////// - unsigned int getSampleRate() const; - - //////////////////////////////////////////////////////////// - /// \brief Open a sound file for reading - /// - /// \param filename Path of the sound file to load - /// - /// \return True if the file was successfully opened - /// - //////////////////////////////////////////////////////////// - bool openRead(const std::string& filename); - - //////////////////////////////////////////////////////////// - /// \brief Open a sound file in memory for reading - /// - /// \param data Pointer to the file data in memory - /// \param sizeInBytes Size of the data to load, in bytes - /// - /// \return True if the file was successfully opened - /// - //////////////////////////////////////////////////////////// - bool openRead(const void* data, std::size_t sizeInBytes); - - //////////////////////////////////////////////////////////// - /// \brief Open a sound file from a custom stream for reading - /// - /// \param stream Source stream to read from - /// - /// \return True if the file was successfully opened - /// - //////////////////////////////////////////////////////////// - bool openRead(InputStream& stream); - - //////////////////////////////////////////////////////////// - /// \brief a the sound file for writing - /// - /// \param filename Path of the sound file to write - /// \param channelCount Number of channels in the sound - /// \param sampleRate Sample rate of the sound - /// - /// \return True if the file was successfully opened - /// - //////////////////////////////////////////////////////////// - bool openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate); - - //////////////////////////////////////////////////////////// - /// \brief Read audio samples from the loaded sound - /// - /// \param data Pointer to the sample array to fill - /// \param sampleCount Number of samples to read - /// - /// \return Number of samples actually read (may be less than \a sampleCount) - /// - //////////////////////////////////////////////////////////// - std::size_t read(Int16* data, std::size_t sampleCount); - - //////////////////////////////////////////////////////////// - /// \brief Write audio samples to the file - /// - /// \param data Pointer to the sample array to write - /// \param sampleCount Number of samples to write - /// - //////////////////////////////////////////////////////////// - void write(const Int16* data, std::size_t sampleCount); - - //////////////////////////////////////////////////////////// - /// \brief Change the current read position in the file - /// - /// \param timeOffset New playing position, from the beginning of the file - /// - //////////////////////////////////////////////////////////// - void seek(Time timeOffset); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Initialize the internal state of the sound file - /// - /// This function is called by all the openRead functions. - /// - /// \param fileInfo Information about the loaded sound file - /// - //////////////////////////////////////////////////////////// - void initialize(SF_INFO fileInfo); - - //////////////////////////////////////////////////////////// - /// \brief Get the internal format of an audio file according to - /// its filename extension - /// - /// \param filename Filename to check - /// - /// \return Internal format matching the filename (-1 if no match) - /// - //////////////////////////////////////////////////////////// - static int getFormatFromFilename(const std::string& filename); - - //////////////////////////////////////////////////////////// - /// \brief Data and callbacks for opening from memory - /// - //////////////////////////////////////////////////////////// - struct Memory - { - const char* begin; - const char* current; - sf_count_t size; - - static sf_count_t getLength(void* user); - static sf_count_t read(void* ptr, sf_count_t count, void* user); - static sf_count_t seek(sf_count_t offset, int whence, void* user); - static sf_count_t tell(void* user); - }; - - //////////////////////////////////////////////////////////// - /// \brief Data and callbacks for opening from stream - /// - //////////////////////////////////////////////////////////// - struct Stream - { - InputStream* source; - Int64 size; - - static sf_count_t getLength(void* user); - static sf_count_t read(void* ptr, sf_count_t count, void* user); - static sf_count_t seek(sf_count_t offset, int whence, void* user); - static sf_count_t tell(void* user); - }; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - SNDFILE* m_file; ///< File descriptor - Memory m_memory; ///< Memory reading info - Stream m_stream; ///< Stream reading info - std::size_t m_sampleCount; ///< Total number of samples in the file - unsigned int m_channelCount; ///< Number of channels used by the sound - unsigned int m_sampleRate; ///< Number of samples per second - #ifdef SFML_SYSTEM_ANDROID - void* m_resourceStream; ///< Asset file streamer (if loaded from file) - #endif -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_SOUNDFILE_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDFILE_HPP +#define SFML_SOUNDFILE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +class InputStream; + +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Provide read and write access to sound files +/// +//////////////////////////////////////////////////////////// +class SoundFile : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + SoundFile(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~SoundFile(); + + //////////////////////////////////////////////////////////// + /// \brief Get the total number of audio samples in the file + /// + /// \return Number of samples + /// + //////////////////////////////////////////////////////////// + std::size_t getSampleCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the number of channels used by the sound + /// + /// \return Number of channels (1 = mono, 2 = stereo) + /// + //////////////////////////////////////////////////////////// + unsigned int getChannelCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the sample rate of the sound + /// + /// \return Sample rate, in samples per second + /// + //////////////////////////////////////////////////////////// + unsigned int getSampleRate() const; + + //////////////////////////////////////////////////////////// + /// \brief Open a sound file for reading + /// + /// \param filename Path of the sound file to load + /// + /// \return True if the file was successfully opened + /// + //////////////////////////////////////////////////////////// + bool openRead(const std::string& filename); + + //////////////////////////////////////////////////////////// + /// \brief Open a sound file in memory for reading + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \return True if the file was successfully opened + /// + //////////////////////////////////////////////////////////// + bool openRead(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Open a sound file from a custom stream for reading + /// + /// \param stream Source stream to read from + /// + /// \return True if the file was successfully opened + /// + //////////////////////////////////////////////////////////// + bool openRead(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief a the sound file for writing + /// + /// \param filename Path of the sound file to write + /// \param channelCount Number of channels in the sound + /// \param sampleRate Sample rate of the sound + /// + /// \return True if the file was successfully opened + /// + //////////////////////////////////////////////////////////// + bool openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate); + + //////////////////////////////////////////////////////////// + /// \brief Read audio samples from the loaded sound + /// + /// \param data Pointer to the sample array to fill + /// \param sampleCount Number of samples to read + /// + /// \return Number of samples actually read (may be less than \a sampleCount) + /// + //////////////////////////////////////////////////////////// + std::size_t read(Int16* data, std::size_t sampleCount); + + //////////////////////////////////////////////////////////// + /// \brief Write audio samples to the file + /// + /// \param data Pointer to the sample array to write + /// \param sampleCount Number of samples to write + /// + //////////////////////////////////////////////////////////// + void write(const Int16* data, std::size_t sampleCount); + + //////////////////////////////////////////////////////////// + /// \brief Change the current read position in the file + /// + /// \param timeOffset New playing position, from the beginning of the file + /// + //////////////////////////////////////////////////////////// + void seek(Time timeOffset); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Initialize the internal state of the sound file + /// + /// This function is called by all the openRead functions. + /// + /// \param fileInfo Information about the loaded sound file + /// + //////////////////////////////////////////////////////////// + void initialize(SF_INFO fileInfo); + + //////////////////////////////////////////////////////////// + /// \brief Get the internal format of an audio file according to + /// its filename extension + /// + /// \param filename Filename to check + /// + /// \return Internal format matching the filename (-1 if no match) + /// + //////////////////////////////////////////////////////////// + static int getFormatFromFilename(const std::string& filename); + + //////////////////////////////////////////////////////////// + /// \brief Data and callbacks for opening from memory + /// + //////////////////////////////////////////////////////////// + struct Memory + { + const char* begin; + const char* current; + sf_count_t size; + + static sf_count_t getLength(void* user); + static sf_count_t read(void* ptr, sf_count_t count, void* user); + static sf_count_t seek(sf_count_t offset, int whence, void* user); + static sf_count_t tell(void* user); + }; + + //////////////////////////////////////////////////////////// + /// \brief Data and callbacks for opening from stream + /// + //////////////////////////////////////////////////////////// + struct Stream + { + InputStream* source; + Int64 size; + + static sf_count_t getLength(void* user); + static sf_count_t read(void* ptr, sf_count_t count, void* user); + static sf_count_t seek(sf_count_t offset, int whence, void* user); + static sf_count_t tell(void* user); + }; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + SNDFILE* m_file; ///< File descriptor + Memory m_memory; ///< Memory reading info + Stream m_stream; ///< Stream reading info + std::size_t m_sampleCount; ///< Total number of samples in the file + unsigned int m_channelCount; ///< Number of channels used by the sound + unsigned int m_sampleRate; ///< Number of samples per second + #ifdef SFML_SYSTEM_ANDROID + void* m_resourceStream; ///< Asset file streamer (if loaded from file) + #endif +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_SOUNDFILE_HPP diff --git a/src/SFML/Audio/SoundRecorder.cpp b/src/SFML/Audio/SoundRecorder.cpp index ac0d7881..51e7ef97 100644 --- a/src/SFML/Audio/SoundRecorder.cpp +++ b/src/SFML/Audio/SoundRecorder.cpp @@ -1,290 +1,290 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER - #pragma warning(disable : 4355) // 'this' used in base member initializer list -#endif - - -namespace -{ - ALCdevice* captureDevice = NULL; -} - -namespace sf -{ -//////////////////////////////////////////////////////////// -SoundRecorder::SoundRecorder() : -m_thread (&SoundRecorder::record, this), -m_sampleRate (0), -m_processingInterval(milliseconds(100)), -m_isCapturing (false) -{ - priv::ensureALInit(); - - // Set the device name to the default device - m_deviceName = getDefaultDevice(); -} - - -//////////////////////////////////////////////////////////// -SoundRecorder::~SoundRecorder() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -bool SoundRecorder::start(unsigned int sampleRate) -{ - // Check if the device can do audio capture - if (!isAvailable()) - { - err() << "Failed to start capture : your system cannot capture audio data (call SoundRecorder::isAvailable to check it)" << std::endl; - return false; - } - - // Check that another capture is not already running - if (captureDevice) - { - err() << "Trying to start audio capture, but another capture is already running" << std::endl; - return false; - } - - // Open the capture device for capturing 16 bits mono samples - captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), sampleRate, AL_FORMAT_MONO16, sampleRate); - if (!captureDevice) - { - err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl; - return false; - } - - // Clear the array of samples - m_samples.clear(); - - // Store the sample rate - m_sampleRate = sampleRate; - - // Notify derived class - if (onStart()) - { - // Start the capture - alcCaptureStart(captureDevice); - - // Start the capture in a new thread, to avoid blocking the main thread - m_isCapturing = true; - m_thread.launch(); - - return true; - } - - return false; -} - - -//////////////////////////////////////////////////////////// -void SoundRecorder::stop() -{ - // Stop the capturing thread - m_isCapturing = false; - m_thread.wait(); - - // Notify derived class - onStop(); -} - - -//////////////////////////////////////////////////////////// -unsigned int SoundRecorder::getSampleRate() const -{ - return m_sampleRate; -} - - -//////////////////////////////////////////////////////////// -std::vector SoundRecorder::getAvailableDevices() -{ - std::vector deviceNameList; - - const ALchar *deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); - if (deviceList) - { - while (*deviceList) - { - deviceNameList.push_back(deviceList); - deviceList += std::strlen(deviceList) + 1; - } - } - - return deviceNameList; -} - - -//////////////////////////////////////////////////////////// -std::string SoundRecorder::getDefaultDevice() -{ - return alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); -} - - -//////////////////////////////////////////////////////////// -bool SoundRecorder::setDevice(const std::string& name) -{ - // Store the device name - if (name.empty()) - m_deviceName = getDefaultDevice(); - else - m_deviceName = name; - - if (m_isCapturing) - { - // Stop the capturing thread - m_isCapturing = false; - m_thread.wait(); - - // Open the requested capture device for capturing 16 bits mono samples - captureDevice = alcCaptureOpenDevice(name.c_str(), m_sampleRate, AL_FORMAT_MONO16, m_sampleRate); - if (!captureDevice) - { - // Notify derived class - onStop(); - - err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl; - return false; - } - - // Start the capture - alcCaptureStart(captureDevice); - - // Start the capture in a new thread, to avoid blocking the main thread - m_isCapturing = true; - m_thread.launch(); - } - - return true; -} - - -//////////////////////////////////////////////////////////// -const std::string& SoundRecorder::getDevice() const -{ - return m_deviceName; -} - - -//////////////////////////////////////////////////////////// -bool SoundRecorder::isAvailable() -{ - return (priv::AudioDevice::isExtensionSupported("ALC_EXT_CAPTURE") != AL_FALSE) || - (priv::AudioDevice::isExtensionSupported("ALC_EXT_capture") != AL_FALSE); // "bug" in Mac OS X 10.5 and 10.6 -} - - -//////////////////////////////////////////////////////////// -void SoundRecorder::setProcessingInterval(sf::Time interval) -{ - m_processingInterval = interval; -} - - -//////////////////////////////////////////////////////////// -bool SoundRecorder::onStart() -{ - // Nothing to do - return true; -} - - -//////////////////////////////////////////////////////////// -void SoundRecorder::onStop() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -void SoundRecorder::record() -{ - while (m_isCapturing) - { - // Process available samples - processCapturedSamples(); - - // Don't bother the CPU while waiting for more captured data - sleep(m_processingInterval); - } - - // Capture is finished : clean up everything - cleanup(); -} - - -//////////////////////////////////////////////////////////// -void SoundRecorder::processCapturedSamples() -{ - // Get the number of samples available - ALCint samplesAvailable; - alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable); - - if (samplesAvailable > 0) - { - // Get the recorded samples - m_samples.resize(samplesAvailable); - alcCaptureSamples(captureDevice, &m_samples[0], samplesAvailable); - - // Forward them to the derived class - if (!onProcessSamples(&m_samples[0], m_samples.size())) - { - // The user wants to stop the capture - m_isCapturing = false; - } - } -} - - -//////////////////////////////////////////////////////////// -void SoundRecorder::cleanup() -{ - // Stop the capture - alcCaptureStop(captureDevice); - - // Get the samples left in the buffer - processCapturedSamples(); - - // Close the device - alcCaptureCloseDevice(captureDevice); - captureDevice = NULL; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER + #pragma warning(disable: 4355) // 'this' used in base member initializer list +#endif + + +namespace +{ + ALCdevice* captureDevice = NULL; +} + +namespace sf +{ +//////////////////////////////////////////////////////////// +SoundRecorder::SoundRecorder() : +m_thread (&SoundRecorder::record, this), +m_sampleRate (0), +m_processingInterval(milliseconds(100)), +m_isCapturing (false) +{ + priv::ensureALInit(); + + // Set the device name to the default device + m_deviceName = getDefaultDevice(); +} + + +//////////////////////////////////////////////////////////// +SoundRecorder::~SoundRecorder() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +bool SoundRecorder::start(unsigned int sampleRate) +{ + // Check if the device can do audio capture + if (!isAvailable()) + { + err() << "Failed to start capture: your system cannot capture audio data (call SoundRecorder::isAvailable to check it)" << std::endl; + return false; + } + + // Check that another capture is not already running + if (captureDevice) + { + err() << "Trying to start audio capture, but another capture is already running" << std::endl; + return false; + } + + // Open the capture device for capturing 16 bits mono samples + captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), sampleRate, AL_FORMAT_MONO16, sampleRate); + if (!captureDevice) + { + err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl; + return false; + } + + // Clear the array of samples + m_samples.clear(); + + // Store the sample rate + m_sampleRate = sampleRate; + + // Notify derived class + if (onStart()) + { + // Start the capture + alcCaptureStart(captureDevice); + + // Start the capture in a new thread, to avoid blocking the main thread + m_isCapturing = true; + m_thread.launch(); + + return true; + } + + return false; +} + + +//////////////////////////////////////////////////////////// +void SoundRecorder::stop() +{ + // Stop the capturing thread + m_isCapturing = false; + m_thread.wait(); + + // Notify derived class + onStop(); +} + + +//////////////////////////////////////////////////////////// +unsigned int SoundRecorder::getSampleRate() const +{ + return m_sampleRate; +} + + +//////////////////////////////////////////////////////////// +std::vector SoundRecorder::getAvailableDevices() +{ + std::vector deviceNameList; + + const ALchar *deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); + if (deviceList) + { + while (*deviceList) + { + deviceNameList.push_back(deviceList); + deviceList += std::strlen(deviceList) + 1; + } + } + + return deviceNameList; +} + + +//////////////////////////////////////////////////////////// +std::string SoundRecorder::getDefaultDevice() +{ + return alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); +} + + +//////////////////////////////////////////////////////////// +bool SoundRecorder::setDevice(const std::string& name) +{ + // Store the device name + if (name.empty()) + m_deviceName = getDefaultDevice(); + else + m_deviceName = name; + + if (m_isCapturing) + { + // Stop the capturing thread + m_isCapturing = false; + m_thread.wait(); + + // Open the requested capture device for capturing 16 bits mono samples + captureDevice = alcCaptureOpenDevice(name.c_str(), m_sampleRate, AL_FORMAT_MONO16, m_sampleRate); + if (!captureDevice) + { + // Notify derived class + onStop(); + + err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl; + return false; + } + + // Start the capture + alcCaptureStart(captureDevice); + + // Start the capture in a new thread, to avoid blocking the main thread + m_isCapturing = true; + m_thread.launch(); + } + + return true; +} + + +//////////////////////////////////////////////////////////// +const std::string& SoundRecorder::getDevice() const +{ + return m_deviceName; +} + + +//////////////////////////////////////////////////////////// +bool SoundRecorder::isAvailable() +{ + return (priv::AudioDevice::isExtensionSupported("ALC_EXT_CAPTURE") != AL_FALSE) || + (priv::AudioDevice::isExtensionSupported("ALC_EXT_capture") != AL_FALSE); // "bug" in Mac OS X 10.5 and 10.6 +} + + +//////////////////////////////////////////////////////////// +void SoundRecorder::setProcessingInterval(sf::Time interval) +{ + m_processingInterval = interval; +} + + +//////////////////////////////////////////////////////////// +bool SoundRecorder::onStart() +{ + // Nothing to do + return true; +} + + +//////////////////////////////////////////////////////////// +void SoundRecorder::onStop() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +void SoundRecorder::record() +{ + while (m_isCapturing) + { + // Process available samples + processCapturedSamples(); + + // Don't bother the CPU while waiting for more captured data + sleep(m_processingInterval); + } + + // Capture is finished: clean up everything + cleanup(); +} + + +//////////////////////////////////////////////////////////// +void SoundRecorder::processCapturedSamples() +{ + // Get the number of samples available + ALCint samplesAvailable; + alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable); + + if (samplesAvailable > 0) + { + // Get the recorded samples + m_samples.resize(samplesAvailable); + alcCaptureSamples(captureDevice, &m_samples[0], samplesAvailable); + + // Forward them to the derived class + if (!onProcessSamples(&m_samples[0], m_samples.size())) + { + // The user wants to stop the capture + m_isCapturing = false; + } + } +} + + +//////////////////////////////////////////////////////////// +void SoundRecorder::cleanup() +{ + // Stop the capture + alcCaptureStop(captureDevice); + + // Get the samples left in the buffer + processCapturedSamples(); + + // Close the device + alcCaptureCloseDevice(captureDevice); + captureDevice = NULL; +} + +} // namespace sf diff --git a/src/SFML/Audio/SoundSource.cpp b/src/SFML/Audio/SoundSource.cpp index 2a4afef6..3129b2e9 100644 --- a/src/SFML/Audio/SoundSource.cpp +++ b/src/SFML/Audio/SoundSource.cpp @@ -1,194 +1,194 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -SoundSource::SoundSource() -{ - priv::ensureALInit(); - - alCheck(alGenSources(1, &m_source)); - alCheck(alSourcei(m_source, AL_BUFFER, 0)); -} - - -//////////////////////////////////////////////////////////// -SoundSource::SoundSource(const SoundSource& copy) -{ - priv::ensureALInit(); - - alCheck(alGenSources(1, &m_source)); - alCheck(alSourcei(m_source, AL_BUFFER, 0)); - - setPitch(copy.getPitch()); - setVolume(copy.getVolume()); - setPosition(copy.getPosition()); - setRelativeToListener(copy.isRelativeToListener()); - setMinDistance(copy.getMinDistance()); - setAttenuation(copy.getAttenuation()); -} - - -//////////////////////////////////////////////////////////// -SoundSource::~SoundSource() -{ - alCheck(alSourcei(m_source, AL_BUFFER, 0)); - alCheck(alDeleteSources(1, &m_source)); -} - - -//////////////////////////////////////////////////////////// -void SoundSource::setPitch(float pitch) -{ - alCheck(alSourcef(m_source, AL_PITCH, pitch)); -} - - -//////////////////////////////////////////////////////////// -void SoundSource::setVolume(float volume) -{ - alCheck(alSourcef(m_source, AL_GAIN, volume * 0.01f)); -} - -//////////////////////////////////////////////////////////// -void SoundSource::setPosition(float x, float y, float z) -{ - alCheck(alSource3f(m_source, AL_POSITION, x, y, z)); -} - - -//////////////////////////////////////////////////////////// -void SoundSource::setPosition(const Vector3f& position) -{ - setPosition(position.x, position.y, position.z); -} - - -//////////////////////////////////////////////////////////// -void SoundSource::setRelativeToListener(bool relative) -{ - alCheck(alSourcei(m_source, AL_SOURCE_RELATIVE, relative)); -} - - -//////////////////////////////////////////////////////////// -void SoundSource::setMinDistance(float distance) -{ - alCheck(alSourcef(m_source, AL_REFERENCE_DISTANCE, distance)); -} - - -//////////////////////////////////////////////////////////// -void SoundSource::setAttenuation(float attenuation) -{ - alCheck(alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation)); -} - - -//////////////////////////////////////////////////////////// -float SoundSource::getPitch() const -{ - ALfloat pitch; - alCheck(alGetSourcef(m_source, AL_PITCH, &pitch)); - - return pitch; -} - - -//////////////////////////////////////////////////////////// -float SoundSource::getVolume() const -{ - ALfloat gain; - alCheck(alGetSourcef(m_source, AL_GAIN, &gain)); - - return gain * 100.f; -} - - -//////////////////////////////////////////////////////////// -Vector3f SoundSource::getPosition() const -{ - Vector3f position; - alCheck(alGetSource3f(m_source, AL_POSITION, &position.x, &position.y, &position.z)); - - return position; -} - - -//////////////////////////////////////////////////////////// -bool SoundSource::isRelativeToListener() const -{ - ALint relative; - alCheck(alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative)); - - return relative != 0; -} - - -//////////////////////////////////////////////////////////// -float SoundSource::getMinDistance() const -{ - ALfloat distance; - alCheck(alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance)); - - return distance; -} - - -//////////////////////////////////////////////////////////// -float SoundSource::getAttenuation() const -{ - ALfloat attenuation; - alCheck(alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation)); - - return attenuation; -} - - -//////////////////////////////////////////////////////////// -SoundSource::Status SoundSource::getStatus() const -{ - ALint status; - alCheck(alGetSourcei(m_source, AL_SOURCE_STATE, &status)); - - switch (status) - { - case AL_INITIAL : - case AL_STOPPED : return Stopped; - case AL_PAUSED : return Paused; - case AL_PLAYING : return Playing; - } - - return Stopped; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +SoundSource::SoundSource() +{ + priv::ensureALInit(); + + alCheck(alGenSources(1, &m_source)); + alCheck(alSourcei(m_source, AL_BUFFER, 0)); +} + + +//////////////////////////////////////////////////////////// +SoundSource::SoundSource(const SoundSource& copy) +{ + priv::ensureALInit(); + + alCheck(alGenSources(1, &m_source)); + alCheck(alSourcei(m_source, AL_BUFFER, 0)); + + setPitch(copy.getPitch()); + setVolume(copy.getVolume()); + setPosition(copy.getPosition()); + setRelativeToListener(copy.isRelativeToListener()); + setMinDistance(copy.getMinDistance()); + setAttenuation(copy.getAttenuation()); +} + + +//////////////////////////////////////////////////////////// +SoundSource::~SoundSource() +{ + alCheck(alSourcei(m_source, AL_BUFFER, 0)); + alCheck(alDeleteSources(1, &m_source)); +} + + +//////////////////////////////////////////////////////////// +void SoundSource::setPitch(float pitch) +{ + alCheck(alSourcef(m_source, AL_PITCH, pitch)); +} + + +//////////////////////////////////////////////////////////// +void SoundSource::setVolume(float volume) +{ + alCheck(alSourcef(m_source, AL_GAIN, volume * 0.01f)); +} + +//////////////////////////////////////////////////////////// +void SoundSource::setPosition(float x, float y, float z) +{ + alCheck(alSource3f(m_source, AL_POSITION, x, y, z)); +} + + +//////////////////////////////////////////////////////////// +void SoundSource::setPosition(const Vector3f& position) +{ + setPosition(position.x, position.y, position.z); +} + + +//////////////////////////////////////////////////////////// +void SoundSource::setRelativeToListener(bool relative) +{ + alCheck(alSourcei(m_source, AL_SOURCE_RELATIVE, relative)); +} + + +//////////////////////////////////////////////////////////// +void SoundSource::setMinDistance(float distance) +{ + alCheck(alSourcef(m_source, AL_REFERENCE_DISTANCE, distance)); +} + + +//////////////////////////////////////////////////////////// +void SoundSource::setAttenuation(float attenuation) +{ + alCheck(alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation)); +} + + +//////////////////////////////////////////////////////////// +float SoundSource::getPitch() const +{ + ALfloat pitch; + alCheck(alGetSourcef(m_source, AL_PITCH, &pitch)); + + return pitch; +} + + +//////////////////////////////////////////////////////////// +float SoundSource::getVolume() const +{ + ALfloat gain; + alCheck(alGetSourcef(m_source, AL_GAIN, &gain)); + + return gain * 100.f; +} + + +//////////////////////////////////////////////////////////// +Vector3f SoundSource::getPosition() const +{ + Vector3f position; + alCheck(alGetSource3f(m_source, AL_POSITION, &position.x, &position.y, &position.z)); + + return position; +} + + +//////////////////////////////////////////////////////////// +bool SoundSource::isRelativeToListener() const +{ + ALint relative; + alCheck(alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative)); + + return relative != 0; +} + + +//////////////////////////////////////////////////////////// +float SoundSource::getMinDistance() const +{ + ALfloat distance; + alCheck(alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance)); + + return distance; +} + + +//////////////////////////////////////////////////////////// +float SoundSource::getAttenuation() const +{ + ALfloat attenuation; + alCheck(alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation)); + + return attenuation; +} + + +//////////////////////////////////////////////////////////// +SoundSource::Status SoundSource::getStatus() const +{ + ALint status; + alCheck(alGetSourcei(m_source, AL_SOURCE_STATE, &status)); + + switch (status) + { + case AL_INITIAL: + case AL_STOPPED: return Stopped; + case AL_PAUSED: return Paused; + case AL_PLAYING: return Playing; + } + + return Stopped; +} + +} // namespace sf diff --git a/src/SFML/Audio/SoundStream.cpp b/src/SFML/Audio/SoundStream.cpp index eb84f25f..f3ac6a40 100644 --- a/src/SFML/Audio/SoundStream.cpp +++ b/src/SFML/Audio/SoundStream.cpp @@ -1,469 +1,469 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER - #pragma warning(disable : 4355) // 'this' used in base member initializer list -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -SoundStream::SoundStream() : -m_thread (&SoundStream::streamData, this), -m_threadMutex (), -m_threadStartState(Stopped), -m_isStreaming (false), -m_channelCount (0), -m_sampleRate (0), -m_format (0), -m_loop (false), -m_samplesProcessed(0) -{ - -} - - -//////////////////////////////////////////////////////////// -SoundStream::~SoundStream() -{ - // Stop the sound if it was playing - - // Request the thread to terminate - { - Lock lock(m_threadMutex); - m_isStreaming = false; - } - - // Wait for the thread to terminate - m_thread.wait(); -} - - -//////////////////////////////////////////////////////////// -void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate) -{ - m_channelCount = channelCount; - m_sampleRate = sampleRate; - - // Deduce the format from the number of channels - m_format = priv::AudioDevice::getFormatFromChannelCount(channelCount); - - // Check if the format is valid - if (m_format == 0) - { - m_channelCount = 0; - m_sampleRate = 0; - err() << "Unsupported number of channels (" << m_channelCount << ")" << std::endl; - } -} - - -//////////////////////////////////////////////////////////// -void SoundStream::play() -{ - // Check if the sound parameters have been set - if (m_format == 0) - { - err() << "Failed to play audio stream: sound parameters have not been initialized (call initialize() first)" << std::endl; - return; - } - - bool isStreaming = false; - Status threadStartState = Stopped; - - { - Lock lock(m_threadMutex); - - isStreaming = m_isStreaming; - threadStartState = m_threadStartState; - } - - - if (isStreaming && (threadStartState == Paused)) - { - // If the sound is paused, resume it - Lock lock(m_threadMutex); - m_threadStartState = Playing; - alCheck(alSourcePlay(m_source)); - return; - } - else if (isStreaming && (threadStartState == Playing)) - { - // If the sound is playing, stop it and continue as if it was stopped - stop(); - } - - // Move to the beginning - onSeek(Time::Zero); - - // Start updating the stream in a separate thread to avoid blocking the application - m_samplesProcessed = 0; - m_isStreaming = true; - m_threadStartState = Playing; - m_thread.launch(); -} - - -//////////////////////////////////////////////////////////// -void SoundStream::pause() -{ - // Handle pause() being called before the thread has started - { - Lock lock(m_threadMutex); - - if (!m_isStreaming) - return; - - m_threadStartState = Paused; - } - - alCheck(alSourcePause(m_source)); -} - - -//////////////////////////////////////////////////////////// -void SoundStream::stop() -{ - // Request the thread to terminate - { - Lock lock(m_threadMutex); - m_isStreaming = false; - } - - // Wait for the thread to terminate - m_thread.wait(); - - // Move to the beginning - onSeek(Time::Zero); - - // Reset the playing position - m_samplesProcessed = 0; -} - - -//////////////////////////////////////////////////////////// -unsigned int SoundStream::getChannelCount() const -{ - return m_channelCount; -} - - -//////////////////////////////////////////////////////////// -unsigned int SoundStream::getSampleRate() const -{ - return m_sampleRate; -} - - -//////////////////////////////////////////////////////////// -SoundStream::Status SoundStream::getStatus() const -{ - Status status = SoundSource::getStatus(); - - // To compensate for the lag between play() and alSourceplay() - if (status == Stopped) - { - Lock lock(m_threadMutex); - - if (m_isStreaming) - status = m_threadStartState; - } - - return status; -} - - -//////////////////////////////////////////////////////////// -void SoundStream::setPlayingOffset(Time timeOffset) -{ - // Get old playing status - Status oldStatus = getStatus(); - - // Stop the stream - stop(); - - // Let the derived class update the current position - onSeek(timeOffset); - - // Restart streaming - m_samplesProcessed = static_cast(timeOffset.asSeconds() * m_sampleRate * m_channelCount); - - if (oldStatus == Stopped) - return; - - m_isStreaming = true; - m_threadStartState = oldStatus; - m_thread.launch(); -} - - -//////////////////////////////////////////////////////////// -Time SoundStream::getPlayingOffset() const -{ - if (m_sampleRate && m_channelCount) - { - ALfloat secs = 0.f; - alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs)); - - return seconds(secs + static_cast(m_samplesProcessed) / m_sampleRate / m_channelCount); - } - else - { - return Time::Zero; - } -} - - -//////////////////////////////////////////////////////////// -void SoundStream::setLoop(bool loop) -{ - m_loop = loop; -} - - -//////////////////////////////////////////////////////////// -bool SoundStream::getLoop() const -{ - return m_loop; -} - - -//////////////////////////////////////////////////////////// -void SoundStream::streamData() -{ - bool requestStop = false; - - { - Lock lock(m_threadMutex); - - // Check if the thread was launched Stopped - if (m_threadStartState == Stopped) - { - m_isStreaming = false; - return; - } - - // Create the buffers - alCheck(alGenBuffers(BufferCount, m_buffers)); - for (int i = 0; i < BufferCount; ++i) - m_endBuffers[i] = false; - - // Fill the queue - requestStop = fillQueue(); - - // Play the sound - alCheck(alSourcePlay(m_source)); - - // Check if the thread was launched Paused - if (m_threadStartState == Paused) - alCheck(alSourcePause(m_source)); - } - - for (;;) - { - { - Lock lock(m_threadMutex); - if (!m_isStreaming) - break; - } - - // The stream has been interrupted! - if (SoundSource::getStatus() == Stopped) - { - if (!requestStop) - { - // Just continue - alCheck(alSourcePlay(m_source)); - } - else - { - // End streaming - Lock lock(m_threadMutex); - m_isStreaming = false; - } - } - - // Get the number of buffers that have been processed (ie. ready for reuse) - ALint nbProcessed = 0; - alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed)); - - while (nbProcessed--) - { - // Pop the first unused buffer from the queue - ALuint buffer; - alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer)); - - // Find its number - unsigned int bufferNum = 0; - for (int i = 0; i < BufferCount; ++i) - if (m_buffers[i] == buffer) - { - bufferNum = i; - break; - } - - // Retrieve its size and add it to the samples count - if (m_endBuffers[bufferNum]) - { - // This was the last buffer: reset the sample count - m_samplesProcessed = 0; - m_endBuffers[bufferNum] = false; - } - else - { - ALint size, bits; - alCheck(alGetBufferi(buffer, AL_SIZE, &size)); - alCheck(alGetBufferi(buffer, AL_BITS, &bits)); - - // Bits can be 0 if the format or parameters are corrupt, avoid division by zero - if (bits == 0) - { - err() << "Bits in sound stream are 0: make sure that the audio format is not corrupt " - << "and initialize() has been called correctly" << std::endl; - - // Abort streaming (exit main loop) - Lock lock(m_threadMutex); - m_isStreaming = false; - requestStop = true; - break; - } - else - { - m_samplesProcessed += size / (bits / 8); - } - } - - // Fill it and push it back into the playing queue - if (!requestStop) - { - if (fillAndPushBuffer(bufferNum)) - requestStop = true; - } - } - - // Leave some time for the other threads if the stream is still playing - if (SoundSource::getStatus() != Stopped) - sleep(milliseconds(10)); - } - - // Stop the playback - alCheck(alSourceStop(m_source)); - - // Unqueue any buffer left in the queue - clearQueue(); - - // Delete the buffers - alCheck(alSourcei(m_source, AL_BUFFER, 0)); - alCheck(alDeleteBuffers(BufferCount, m_buffers)); -} - - -//////////////////////////////////////////////////////////// -bool SoundStream::fillAndPushBuffer(unsigned int bufferNum) -{ - bool requestStop = false; - - // Acquire audio data - Chunk data = {NULL, 0}; - if (!onGetData(data)) - { - // Mark the buffer as the last one (so that we know when to reset the playing position) - m_endBuffers[bufferNum] = true; - - // Check if the stream must loop or stop - if (m_loop) - { - // Return to the beginning of the stream source - onSeek(Time::Zero); - - // If we previously had no data, try to fill the buffer once again - if (!data.samples || (data.sampleCount == 0)) - { - return fillAndPushBuffer(bufferNum); - } - } - else - { - // Not looping: request stop - requestStop = true; - } - } - - // Fill the buffer if some data was returned - if (data.samples && data.sampleCount) - { - unsigned int buffer = m_buffers[bufferNum]; - - // Fill the buffer - ALsizei size = static_cast(data.sampleCount) * sizeof(Int16); - alCheck(alBufferData(buffer, m_format, data.samples, size, m_sampleRate)); - - // Push it into the sound queue - alCheck(alSourceQueueBuffers(m_source, 1, &buffer)); - } - - return requestStop; -} - - -//////////////////////////////////////////////////////////// -bool SoundStream::fillQueue() -{ - // Fill and enqueue all the available buffers - bool requestStop = false; - for (int i = 0; (i < BufferCount) && !requestStop; ++i) - { - if (fillAndPushBuffer(i)) - requestStop = true; - } - - return requestStop; -} - - -//////////////////////////////////////////////////////////// -void SoundStream::clearQueue() -{ - // Get the number of buffers still in the queue - ALint nbQueued; - alCheck(alGetSourcei(m_source, AL_BUFFERS_QUEUED, &nbQueued)); - - // Unqueue them all - ALuint buffer; - for (ALint i = 0; i < nbQueued; ++i) - alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer)); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER + #pragma warning(disable: 4355) // 'this' used in base member initializer list +#endif + + +namespace sf +{ +//////////////////////////////////////////////////////////// +SoundStream::SoundStream() : +m_thread (&SoundStream::streamData, this), +m_threadMutex (), +m_threadStartState(Stopped), +m_isStreaming (false), +m_channelCount (0), +m_sampleRate (0), +m_format (0), +m_loop (false), +m_samplesProcessed(0) +{ + +} + + +//////////////////////////////////////////////////////////// +SoundStream::~SoundStream() +{ + // Stop the sound if it was playing + + // Request the thread to terminate + { + Lock lock(m_threadMutex); + m_isStreaming = false; + } + + // Wait for the thread to terminate + m_thread.wait(); +} + + +//////////////////////////////////////////////////////////// +void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate) +{ + m_channelCount = channelCount; + m_sampleRate = sampleRate; + + // Deduce the format from the number of channels + m_format = priv::AudioDevice::getFormatFromChannelCount(channelCount); + + // Check if the format is valid + if (m_format == 0) + { + m_channelCount = 0; + m_sampleRate = 0; + err() << "Unsupported number of channels (" << m_channelCount << ")" << std::endl; + } +} + + +//////////////////////////////////////////////////////////// +void SoundStream::play() +{ + // Check if the sound parameters have been set + if (m_format == 0) + { + err() << "Failed to play audio stream: sound parameters have not been initialized (call initialize() first)" << std::endl; + return; + } + + bool isStreaming = false; + Status threadStartState = Stopped; + + { + Lock lock(m_threadMutex); + + isStreaming = m_isStreaming; + threadStartState = m_threadStartState; + } + + + if (isStreaming && (threadStartState == Paused)) + { + // If the sound is paused, resume it + Lock lock(m_threadMutex); + m_threadStartState = Playing; + alCheck(alSourcePlay(m_source)); + return; + } + else if (isStreaming && (threadStartState == Playing)) + { + // If the sound is playing, stop it and continue as if it was stopped + stop(); + } + + // Move to the beginning + onSeek(Time::Zero); + + // Start updating the stream in a separate thread to avoid blocking the application + m_samplesProcessed = 0; + m_isStreaming = true; + m_threadStartState = Playing; + m_thread.launch(); +} + + +//////////////////////////////////////////////////////////// +void SoundStream::pause() +{ + // Handle pause() being called before the thread has started + { + Lock lock(m_threadMutex); + + if (!m_isStreaming) + return; + + m_threadStartState = Paused; + } + + alCheck(alSourcePause(m_source)); +} + + +//////////////////////////////////////////////////////////// +void SoundStream::stop() +{ + // Request the thread to terminate + { + Lock lock(m_threadMutex); + m_isStreaming = false; + } + + // Wait for the thread to terminate + m_thread.wait(); + + // Move to the beginning + onSeek(Time::Zero); + + // Reset the playing position + m_samplesProcessed = 0; +} + + +//////////////////////////////////////////////////////////// +unsigned int SoundStream::getChannelCount() const +{ + return m_channelCount; +} + + +//////////////////////////////////////////////////////////// +unsigned int SoundStream::getSampleRate() const +{ + return m_sampleRate; +} + + +//////////////////////////////////////////////////////////// +SoundStream::Status SoundStream::getStatus() const +{ + Status status = SoundSource::getStatus(); + + // To compensate for the lag between play() and alSourceplay() + if (status == Stopped) + { + Lock lock(m_threadMutex); + + if (m_isStreaming) + status = m_threadStartState; + } + + return status; +} + + +//////////////////////////////////////////////////////////// +void SoundStream::setPlayingOffset(Time timeOffset) +{ + // Get old playing status + Status oldStatus = getStatus(); + + // Stop the stream + stop(); + + // Let the derived class update the current position + onSeek(timeOffset); + + // Restart streaming + m_samplesProcessed = static_cast(timeOffset.asSeconds() * m_sampleRate * m_channelCount); + + if (oldStatus == Stopped) + return; + + m_isStreaming = true; + m_threadStartState = oldStatus; + m_thread.launch(); +} + + +//////////////////////////////////////////////////////////// +Time SoundStream::getPlayingOffset() const +{ + if (m_sampleRate && m_channelCount) + { + ALfloat secs = 0.f; + alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs)); + + return seconds(secs + static_cast(m_samplesProcessed) / m_sampleRate / m_channelCount); + } + else + { + return Time::Zero; + } +} + + +//////////////////////////////////////////////////////////// +void SoundStream::setLoop(bool loop) +{ + m_loop = loop; +} + + +//////////////////////////////////////////////////////////// +bool SoundStream::getLoop() const +{ + return m_loop; +} + + +//////////////////////////////////////////////////////////// +void SoundStream::streamData() +{ + bool requestStop = false; + + { + Lock lock(m_threadMutex); + + // Check if the thread was launched Stopped + if (m_threadStartState == Stopped) + { + m_isStreaming = false; + return; + } + + // Create the buffers + alCheck(alGenBuffers(BufferCount, m_buffers)); + for (int i = 0; i < BufferCount; ++i) + m_endBuffers[i] = false; + + // Fill the queue + requestStop = fillQueue(); + + // Play the sound + alCheck(alSourcePlay(m_source)); + + // Check if the thread was launched Paused + if (m_threadStartState == Paused) + alCheck(alSourcePause(m_source)); + } + + for (;;) + { + { + Lock lock(m_threadMutex); + if (!m_isStreaming) + break; + } + + // The stream has been interrupted! + if (SoundSource::getStatus() == Stopped) + { + if (!requestStop) + { + // Just continue + alCheck(alSourcePlay(m_source)); + } + else + { + // End streaming + Lock lock(m_threadMutex); + m_isStreaming = false; + } + } + + // Get the number of buffers that have been processed (ie. ready for reuse) + ALint nbProcessed = 0; + alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed)); + + while (nbProcessed--) + { + // Pop the first unused buffer from the queue + ALuint buffer; + alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer)); + + // Find its number + unsigned int bufferNum = 0; + for (int i = 0; i < BufferCount; ++i) + if (m_buffers[i] == buffer) + { + bufferNum = i; + break; + } + + // Retrieve its size and add it to the samples count + if (m_endBuffers[bufferNum]) + { + // This was the last buffer: reset the sample count + m_samplesProcessed = 0; + m_endBuffers[bufferNum] = false; + } + else + { + ALint size, bits; + alCheck(alGetBufferi(buffer, AL_SIZE, &size)); + alCheck(alGetBufferi(buffer, AL_BITS, &bits)); + + // Bits can be 0 if the format or parameters are corrupt, avoid division by zero + if (bits == 0) + { + err() << "Bits in sound stream are 0: make sure that the audio format is not corrupt " + << "and initialize() has been called correctly" << std::endl; + + // Abort streaming (exit main loop) + Lock lock(m_threadMutex); + m_isStreaming = false; + requestStop = true; + break; + } + else + { + m_samplesProcessed += size / (bits / 8); + } + } + + // Fill it and push it back into the playing queue + if (!requestStop) + { + if (fillAndPushBuffer(bufferNum)) + requestStop = true; + } + } + + // Leave some time for the other threads if the stream is still playing + if (SoundSource::getStatus() != Stopped) + sleep(milliseconds(10)); + } + + // Stop the playback + alCheck(alSourceStop(m_source)); + + // Unqueue any buffer left in the queue + clearQueue(); + + // Delete the buffers + alCheck(alSourcei(m_source, AL_BUFFER, 0)); + alCheck(alDeleteBuffers(BufferCount, m_buffers)); +} + + +//////////////////////////////////////////////////////////// +bool SoundStream::fillAndPushBuffer(unsigned int bufferNum) +{ + bool requestStop = false; + + // Acquire audio data + Chunk data = {NULL, 0}; + if (!onGetData(data)) + { + // Mark the buffer as the last one (so that we know when to reset the playing position) + m_endBuffers[bufferNum] = true; + + // Check if the stream must loop or stop + if (m_loop) + { + // Return to the beginning of the stream source + onSeek(Time::Zero); + + // If we previously had no data, try to fill the buffer once again + if (!data.samples || (data.sampleCount == 0)) + { + return fillAndPushBuffer(bufferNum); + } + } + else + { + // Not looping: request stop + requestStop = true; + } + } + + // Fill the buffer if some data was returned + if (data.samples && data.sampleCount) + { + unsigned int buffer = m_buffers[bufferNum]; + + // Fill the buffer + ALsizei size = static_cast(data.sampleCount) * sizeof(Int16); + alCheck(alBufferData(buffer, m_format, data.samples, size, m_sampleRate)); + + // Push it into the sound queue + alCheck(alSourceQueueBuffers(m_source, 1, &buffer)); + } + + return requestStop; +} + + +//////////////////////////////////////////////////////////// +bool SoundStream::fillQueue() +{ + // Fill and enqueue all the available buffers + bool requestStop = false; + for (int i = 0; (i < BufferCount) && !requestStop; ++i) + { + if (fillAndPushBuffer(i)) + requestStop = true; + } + + return requestStop; +} + + +//////////////////////////////////////////////////////////// +void SoundStream::clearQueue() +{ + // Get the number of buffers still in the queue + ALint nbQueued; + alCheck(alGetSourcei(m_source, AL_BUFFERS_QUEUED, &nbQueued)); + + // Unqueue them all + ALuint buffer; + for (ALint i = 0; i < nbQueued; ++i) + alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer)); +} + +} // namespace sf diff --git a/src/SFML/CMakeLists.txt b/src/SFML/CMakeLists.txt index ed1d1b45..1bbfc7fb 100644 --- a/src/SFML/CMakeLists.txt +++ b/src/SFML/CMakeLists.txt @@ -1,53 +1,53 @@ - -# include the SFML specific macros -include(${PROJECT_SOURCE_DIR}/cmake/Macros.cmake) -# let CMake know about our additional libraries paths +# include the SFML specific macros +include(${PROJECT_SOURCE_DIR}/cmake/Macros.cmake) + +# let CMake know about our additional libraries paths if (SFML_OS_WINDOWS) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers") - if(SFML_COMPILER_GCC) - if(ARCH_32BITS) - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x86") - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x86") - elseif(ARCH_64BITS) - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x64") - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x64") - endif() - elseif(SFML_COMPILER_MSVC) - if(ARCH_32BITS) - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x86") - elseif(ARCH_64BITS) - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x64") - endif() - endif() -elseif(SFML_OS_MACOSX) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers") - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/lib/") -elseif(SFML_OS_IOS) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers") - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-ios/") -elseif(SFML_OS_ANDROID) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers") - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-android/${ANDROID_ABI}") -endif() - -# add the SFML sources path -include_directories(${PROJECT_SOURCE_DIR}/src) - -# define the path of our additional CMake modules -set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules/") - -# set the output directory for SFML libraries -set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib") - -# add the modules subdirectories + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers") + if(SFML_COMPILER_GCC) + if(ARCH_32BITS) + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x86") + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x86") + elseif(ARCH_64BITS) + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x64") + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x64") + endif() + elseif(SFML_COMPILER_MSVC) + if(ARCH_32BITS) + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x86") + elseif(ARCH_64BITS) + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x64") + endif() + endif() +elseif(SFML_OS_MACOSX) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers") + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/lib/") +elseif(SFML_OS_IOS) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers") + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-ios/") +elseif(SFML_OS_ANDROID) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers") + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-android/${ANDROID_ABI}") +endif() + +# add the SFML sources path +include_directories(${PROJECT_SOURCE_DIR}/src) + +# define the path of our additional CMake modules +set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules/") + +# set the output directory for SFML libraries +set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib") + +# add the modules subdirectories add_subdirectory(System) -if(SFML_OS_WINDOWS OR SFML_OS_ANDROID OR SFML_OS_IOS) - add_subdirectory(Main) -endif() -add_subdirectory(Window) +if(SFML_OS_WINDOWS OR SFML_OS_ANDROID OR SFML_OS_IOS) + add_subdirectory(Main) +endif() +add_subdirectory(Window) add_subdirectory(Network) add_subdirectory(Graphics) if(NOT SFML_OS_IOS) - add_subdirectory(Audio) -endif() + add_subdirectory(Audio) +endif() diff --git a/src/SFML/Graphics/CMakeLists.txt b/src/SFML/Graphics/CMakeLists.txt index 214bcd85..81a730e3 100644 --- a/src/SFML/Graphics/CMakeLists.txt +++ b/src/SFML/Graphics/CMakeLists.txt @@ -1,168 +1,168 @@ - -set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Graphics) -set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Graphics) - -# all source files -set(SRC - ${SRCROOT}/BlendMode.cpp - ${INCROOT}/BlendMode.hpp - ${SRCROOT}/Color.cpp - ${INCROOT}/Color.hpp - ${INCROOT}/Export.hpp - ${SRCROOT}/Font.cpp - ${INCROOT}/Font.hpp - ${INCROOT}/Glyph.hpp - ${SRCROOT}/GLCheck.cpp - ${SRCROOT}/GLCheck.hpp - ${SRCROOT}/GLExtensions.hpp - ${SRCROOT}/GLExtensions.cpp - ${SRCROOT}/Image.cpp - ${INCROOT}/Image.hpp - ${SRCROOT}/ImageLoader.cpp - ${SRCROOT}/ImageLoader.hpp - ${INCROOT}/PrimitiveType.hpp - ${INCROOT}/Rect.hpp - ${INCROOT}/Rect.inl - ${SRCROOT}/RenderStates.cpp - ${INCROOT}/RenderStates.hpp - ${SRCROOT}/RenderTexture.cpp - ${INCROOT}/RenderTexture.hpp - ${SRCROOT}/RenderTarget.cpp - ${INCROOT}/RenderTarget.hpp - ${SRCROOT}/RenderWindow.cpp - ${INCROOT}/RenderWindow.hpp - ${SRCROOT}/Shader.cpp - ${INCROOT}/Shader.hpp - ${SRCROOT}/Texture.cpp - ${INCROOT}/Texture.hpp - ${SRCROOT}/TextureSaver.cpp - ${SRCROOT}/TextureSaver.hpp - ${SRCROOT}/Transform.cpp - ${INCROOT}/Transform.hpp - ${SRCROOT}/Transformable.cpp - ${INCROOT}/Transformable.hpp - ${SRCROOT}/View.cpp - ${INCROOT}/View.hpp - ${SRCROOT}/Vertex.cpp - ${INCROOT}/Vertex.hpp -) -source_group("" FILES ${SRC}) - -# drawables sources -set(DRAWABLES_SRC - ${INCROOT}/Drawable.hpp - ${SRCROOT}/Shape.cpp - ${INCROOT}/Shape.hpp - ${SRCROOT}/CircleShape.cpp - ${INCROOT}/CircleShape.hpp - ${SRCROOT}/RectangleShape.cpp - ${INCROOT}/RectangleShape.hpp - ${SRCROOT}/ConvexShape.cpp - ${INCROOT}/ConvexShape.hpp - ${SRCROOT}/Sprite.cpp - ${INCROOT}/Sprite.hpp - ${SRCROOT}/Text.cpp - ${INCROOT}/Text.hpp - ${SRCROOT}/VertexArray.cpp - ${INCROOT}/VertexArray.hpp -) -source_group("drawables" FILES ${DRAWABLES_SRC}) - -# render-texture sources -set(RENDER_TEXTURE_SRC - ${SRCROOT}/RenderTextureImpl.cpp - ${SRCROOT}/RenderTextureImpl.hpp - ${SRCROOT}/RenderTextureImplFBO.cpp - ${SRCROOT}/RenderTextureImplFBO.hpp - ${SRCROOT}/RenderTextureImplDefault.cpp - ${SRCROOT}/RenderTextureImplDefault.hpp -) -source_group("render texture" FILES ${RENDER_TEXTURE_SRC}) - -# stb_image sources -set(STB_SRC - ${SRCROOT}/stb_image/stb_image.h - ${SRCROOT}/stb_image/stb_image_write.h -) -source_group("stb_image" FILES ${STB_SRC}) -# let CMake know about our additional graphics libraries paths (on Windows and OSX) -if(SFML_OS_WINDOWS OR SFML_OS_MACOSX) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg") +set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Graphics) +set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Graphics) + +# all source files +set(SRC + ${SRCROOT}/BlendMode.cpp + ${INCROOT}/BlendMode.hpp + ${SRCROOT}/Color.cpp + ${INCROOT}/Color.hpp + ${INCROOT}/Export.hpp + ${SRCROOT}/Font.cpp + ${INCROOT}/Font.hpp + ${INCROOT}/Glyph.hpp + ${SRCROOT}/GLCheck.cpp + ${SRCROOT}/GLCheck.hpp + ${SRCROOT}/GLExtensions.hpp + ${SRCROOT}/GLExtensions.cpp + ${SRCROOT}/Image.cpp + ${INCROOT}/Image.hpp + ${SRCROOT}/ImageLoader.cpp + ${SRCROOT}/ImageLoader.hpp + ${INCROOT}/PrimitiveType.hpp + ${INCROOT}/Rect.hpp + ${INCROOT}/Rect.inl + ${SRCROOT}/RenderStates.cpp + ${INCROOT}/RenderStates.hpp + ${SRCROOT}/RenderTexture.cpp + ${INCROOT}/RenderTexture.hpp + ${SRCROOT}/RenderTarget.cpp + ${INCROOT}/RenderTarget.hpp + ${SRCROOT}/RenderWindow.cpp + ${INCROOT}/RenderWindow.hpp + ${SRCROOT}/Shader.cpp + ${INCROOT}/Shader.hpp + ${SRCROOT}/Texture.cpp + ${INCROOT}/Texture.hpp + ${SRCROOT}/TextureSaver.cpp + ${SRCROOT}/TextureSaver.hpp + ${SRCROOT}/Transform.cpp + ${INCROOT}/Transform.hpp + ${SRCROOT}/Transformable.cpp + ${INCROOT}/Transformable.hpp + ${SRCROOT}/View.cpp + ${INCROOT}/View.hpp + ${SRCROOT}/Vertex.cpp + ${INCROOT}/Vertex.hpp +) +source_group("" FILES ${SRC}) + +# drawables sources +set(DRAWABLES_SRC + ${INCROOT}/Drawable.hpp + ${SRCROOT}/Shape.cpp + ${INCROOT}/Shape.hpp + ${SRCROOT}/CircleShape.cpp + ${INCROOT}/CircleShape.hpp + ${SRCROOT}/RectangleShape.cpp + ${INCROOT}/RectangleShape.hpp + ${SRCROOT}/ConvexShape.cpp + ${INCROOT}/ConvexShape.hpp + ${SRCROOT}/Sprite.cpp + ${INCROOT}/Sprite.hpp + ${SRCROOT}/Text.cpp + ${INCROOT}/Text.hpp + ${SRCROOT}/VertexArray.cpp + ${INCROOT}/VertexArray.hpp +) +source_group("drawables" FILES ${DRAWABLES_SRC}) + +# render-texture sources +set(RENDER_TEXTURE_SRC + ${SRCROOT}/RenderTextureImpl.cpp + ${SRCROOT}/RenderTextureImpl.hpp + ${SRCROOT}/RenderTextureImplFBO.cpp + ${SRCROOT}/RenderTextureImplFBO.hpp + ${SRCROOT}/RenderTextureImplDefault.cpp + ${SRCROOT}/RenderTextureImplDefault.hpp +) +source_group("render texture" FILES ${RENDER_TEXTURE_SRC}) + +# stb_image sources +set(STB_SRC + ${SRCROOT}/stb_image/stb_image.h + ${SRCROOT}/stb_image/stb_image_write.h +) +source_group("stb_image" FILES ${STB_SRC}) + +# let CMake know about our additional graphics libraries paths (on Windows and OSX) +if(SFML_OS_WINDOWS OR SFML_OS_MACOSX) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg") endif() -# let CMake know about our additional graphics libraries paths -if(SFML_OS_WINDOWS) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows") - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows/freetype") +# let CMake know about our additional graphics libraries paths +if(SFML_OS_WINDOWS) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows") + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows/freetype") elseif(SFML_OS_MACOSX) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx") - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx/freetype2") - set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks") -elseif(SFML_OS_IOS) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg") - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios") - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios/freetype2") -elseif(SFML_OS_ANDROID) - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg") - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android") - set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android/freetype") -endif() + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx") + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx/freetype2") + set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks") +elseif(SFML_OS_IOS) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg") + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios") + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios/freetype2") +elseif(SFML_OS_ANDROID) + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg") + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android") + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android/freetype") +endif() -# find external libraries -if(NOT SFML_OPENGL_ES) - find_package(OpenGL REQUIRED) - find_package(GLEW REQUIRED) - if(SFML_OS_LINUX) - find_package(X11 REQUIRED) - endif() - include_directories(${FREETYPE_INCLUDE_DIRS} ${GLEW_INCLUDE_PATH} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR}) -endif() -if(SFML_OPENGL_ES AND SFML_OS_LINUX) - find_package(EGL REQUIRED) - find_package(GLES REQUIRED) - include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR}) -endif() -if(SFML_OS_ANDROID) - find_host_package(JPEG REQUIRED) - find_host_package(Freetype REQUIRED) -else() - find_package(JPEG REQUIRED) - find_package(Freetype REQUIRED) -endif() -include_directories(${FREETYPE_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR}) - -# build the list of external libraries to link -if(NOT SFML_OPENGL_ES) - list(APPEND GRAPHICS_EXT_LIBS ${GLEW_LIBRARY} ${OPENGL_gl_LIBRARY}) - if(SFML_OS_LINUX) - list(APPEND GRAPHICS_EXT_LIBS ${X11_LIBRARIES}) - endif() -endif() -if(SFML_OPENGL_ES AND SFML_OS_LINUX) - list(APPEND GRAPHICS_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY}) -endif() +# find external libraries +if(NOT SFML_OPENGL_ES) + find_package(OpenGL REQUIRED) + find_package(GLEW REQUIRED) + if(SFML_OS_LINUX) + find_package(X11 REQUIRED) + endif() + include_directories(${FREETYPE_INCLUDE_DIRS} ${GLEW_INCLUDE_PATH} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR}) +endif() +if(SFML_OPENGL_ES AND SFML_OS_LINUX) + find_package(EGL REQUIRED) + find_package(GLES REQUIRED) + include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR}) +endif() +if(SFML_OS_ANDROID) + find_host_package(JPEG REQUIRED) + find_host_package(Freetype REQUIRED) +else() + find_package(JPEG REQUIRED) + find_package(Freetype REQUIRED) +endif() +include_directories(${FREETYPE_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR}) + +# build the list of external libraries to link +if(NOT SFML_OPENGL_ES) + list(APPEND GRAPHICS_EXT_LIBS ${GLEW_LIBRARY} ${OPENGL_gl_LIBRARY}) + if(SFML_OS_LINUX) + list(APPEND GRAPHICS_EXT_LIBS ${X11_LIBRARIES}) + endif() +endif() +if(SFML_OPENGL_ES AND SFML_OS_LINUX) + list(APPEND GRAPHICS_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY}) +endif() if(SFML_OS_IOS) - list(APPEND GRAPHICS_EXT_LIBS "-framework OpenGLES") -elseif(SFML_OS_ANDROID) + list(APPEND GRAPHICS_EXT_LIBS "-framework OpenGLES") +elseif(SFML_OS_ANDROID) list(APPEND GRAPHICS_EXT_LIBS -lz) -endif() -list(APPEND GRAPHICS_EXT_LIBS ${FREETYPE_LIBRARY} ${JPEG_LIBRARY}) - -# add preprocessor symbols -if(NOT SFML_OPENGL_ES) - add_definitions(-DGLEW_STATIC) -endif() -add_definitions(-DSTBI_FAILURE_USERMSG) - -# ImageLoader.cpp must be compiled with the -fno-strict-aliasing -# when gcc is used; otherwise saving PNGs may crash in stb_image_write -if(SFML_COMPILER_GCC) - set_source_files_properties(${SRCROOT}/ImageLoader.cpp PROPERTIES COMPILE_FLAGS -fno-strict-aliasing) -endif() - -# define the sfml-graphics target -sfml_add_library(sfml-graphics - SOURCES ${SRC} ${DRAWABLES_SRC} ${RENDER_TEXTURE_SRC} ${STB_SRC} - DEPENDS sfml-window sfml-system - EXTERNAL_LIBS ${GRAPHICS_EXT_LIBS}) +endif() +list(APPEND GRAPHICS_EXT_LIBS ${FREETYPE_LIBRARY} ${JPEG_LIBRARY}) + +# add preprocessor symbols +if(NOT SFML_OPENGL_ES) + add_definitions(-DGLEW_STATIC) +endif() +add_definitions(-DSTBI_FAILURE_USERMSG) + +# ImageLoader.cpp must be compiled with the -fno-strict-aliasing +# when gcc is used; otherwise saving PNGs may crash in stb_image_write +if(SFML_COMPILER_GCC) + set_source_files_properties(${SRCROOT}/ImageLoader.cpp PROPERTIES COMPILE_FLAGS -fno-strict-aliasing) +endif() + +# define the sfml-graphics target +sfml_add_library(sfml-graphics + SOURCES ${SRC} ${DRAWABLES_SRC} ${RENDER_TEXTURE_SRC} ${STB_SRC} + DEPENDS sfml-window sfml-system + EXTERNAL_LIBS ${GRAPHICS_EXT_LIBS}) diff --git a/src/SFML/Graphics/Color.cpp b/src/SFML/Graphics/Color.cpp index 5cea1ee4..00d215a9 100644 --- a/src/SFML/Graphics/Color.cpp +++ b/src/SFML/Graphics/Color.cpp @@ -1,137 +1,137 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -// Static member data -//////////////////////////////////////////////////////////// -const Color Color::Black(0, 0, 0); -const Color Color::White(255, 255, 255); -const Color Color::Red(255, 0, 0); -const Color Color::Green(0, 255, 0); -const Color Color::Blue(0, 0, 255); -const Color Color::Yellow(255, 255, 0); -const Color Color::Magenta(255, 0, 255); -const Color Color::Cyan(0, 255, 255); -const Color Color::Transparent(0, 0, 0, 0); - - -//////////////////////////////////////////////////////////// -Color::Color() : -r(0), -g(0), -b(0), -a(255) -{ - -} - - -//////////////////////////////////////////////////////////// -Color::Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha) : -r(red), -g(green), -b(blue), -a(alpha) -{ - -} - - -//////////////////////////////////////////////////////////// -bool operator ==(const Color& left, const Color& right) -{ - return (left.r == right.r) && - (left.g == right.g) && - (left.b == right.b) && - (left.a == right.a); -} - - -//////////////////////////////////////////////////////////// -bool operator !=(const Color& left, const Color& right) -{ - return !(left == right); -} - - -//////////////////////////////////////////////////////////// -Color operator +(const Color& left, const Color& right) -{ - return Color(Uint8(std::min(int(left.r) + right.r, 255)), - Uint8(std::min(int(left.g) + right.g, 255)), - Uint8(std::min(int(left.b) + right.b, 255)), - Uint8(std::min(int(left.a) + right.a, 255))); -} - - -//////////////////////////////////////////////////////////// -Color operator -(const Color& left, const Color& right) -{ - return Color(Uint8(std::max(int(left.r) - right.r, 0)), - Uint8(std::max(int(left.g) - right.g, 0)), - Uint8(std::max(int(left.b) - right.b, 0)), - Uint8(std::max(int(left.a) - right.a, 0))); -} - - -//////////////////////////////////////////////////////////// -Color operator *(const Color& left, const Color& right) -{ - return Color(Uint8(int(left.r) * right.r / 255), - Uint8(int(left.g) * right.g / 255), - Uint8(int(left.b) * right.b / 255), - Uint8(int(left.a) * right.a / 255)); -} - - -//////////////////////////////////////////////////////////// -Color& operator +=(Color& left, const Color& right) -{ - return left = left + right; -} - - -//////////////////////////////////////////////////////////// -Color& operator -=(Color& left, const Color& right) -{ - return left = left - right; -} - - -//////////////////////////////////////////////////////////// -Color& operator *=(Color& left, const Color& right) -{ - return left = left * right; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +// Static member data +//////////////////////////////////////////////////////////// +const Color Color::Black(0, 0, 0); +const Color Color::White(255, 255, 255); +const Color Color::Red(255, 0, 0); +const Color Color::Green(0, 255, 0); +const Color Color::Blue(0, 0, 255); +const Color Color::Yellow(255, 255, 0); +const Color Color::Magenta(255, 0, 255); +const Color Color::Cyan(0, 255, 255); +const Color Color::Transparent(0, 0, 0, 0); + + +//////////////////////////////////////////////////////////// +Color::Color() : +r(0), +g(0), +b(0), +a(255) +{ + +} + + +//////////////////////////////////////////////////////////// +Color::Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha) : +r(red), +g(green), +b(blue), +a(alpha) +{ + +} + + +//////////////////////////////////////////////////////////// +bool operator ==(const Color& left, const Color& right) +{ + return (left.r == right.r) && + (left.g == right.g) && + (left.b == right.b) && + (left.a == right.a); +} + + +//////////////////////////////////////////////////////////// +bool operator !=(const Color& left, const Color& right) +{ + return !(left == right); +} + + +//////////////////////////////////////////////////////////// +Color operator +(const Color& left, const Color& right) +{ + return Color(Uint8(std::min(int(left.r) + right.r, 255)), + Uint8(std::min(int(left.g) + right.g, 255)), + Uint8(std::min(int(left.b) + right.b, 255)), + Uint8(std::min(int(left.a) + right.a, 255))); +} + + +//////////////////////////////////////////////////////////// +Color operator -(const Color& left, const Color& right) +{ + return Color(Uint8(std::max(int(left.r) - right.r, 0)), + Uint8(std::max(int(left.g) - right.g, 0)), + Uint8(std::max(int(left.b) - right.b, 0)), + Uint8(std::max(int(left.a) - right.a, 0))); +} + + +//////////////////////////////////////////////////////////// +Color operator *(const Color& left, const Color& right) +{ + return Color(Uint8(int(left.r) * right.r / 255), + Uint8(int(left.g) * right.g / 255), + Uint8(int(left.b) * right.b / 255), + Uint8(int(left.a) * right.a / 255)); +} + + +//////////////////////////////////////////////////////////// +Color& operator +=(Color& left, const Color& right) +{ + return left = left + right; +} + + +//////////////////////////////////////////////////////////// +Color& operator -=(Color& left, const Color& right) +{ + return left = left - right; +} + + +//////////////////////////////////////////////////////////// +Color& operator *=(Color& left, const Color& right) +{ + return left = left * right; +} + +} // namespace sf diff --git a/src/SFML/Graphics/Font.cpp b/src/SFML/Graphics/Font.cpp index a0510ae8..68083b9d 100644 --- a/src/SFML/Graphics/Font.cpp +++ b/src/SFML/Graphics/Font.cpp @@ -1,719 +1,719 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#ifdef SFML_SYSTEM_ANDROID - #include -#endif -#include -#include -#include -#include FT_FREETYPE_H -#include FT_GLYPH_H -#include FT_OUTLINE_H -#include FT_BITMAP_H -#include -#include - - -namespace -{ - // FreeType callbacks that operate on a sf::InputStream - unsigned long read(FT_Stream rec, unsigned long offset, unsigned char* buffer, unsigned long count) - { - sf::InputStream* stream = static_cast(rec->descriptor.pointer); - if (static_cast(stream->seek(offset)) == offset) - { - if (count > 0) - return static_cast(stream->read(reinterpret_cast(buffer), count)); - else - return 0; - } - else - return count > 0 ? 0 : 1; // error code is 0 if we're reading, or nonzero if we're seeking - } - void close(FT_Stream) - { - } -} - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Font::Font() : -m_library (NULL), -m_face (NULL), -m_streamRec(NULL), -m_refCount (NULL), -m_info () -{ - #ifdef SFML_SYSTEM_ANDROID - m_stream = NULL; - #endif -} - - -//////////////////////////////////////////////////////////// -Font::Font(const Font& copy) : -m_library (copy.m_library), -m_face (copy.m_face), -m_streamRec (copy.m_streamRec), -m_refCount (copy.m_refCount), -m_info (copy.m_info), -m_pages (copy.m_pages), -m_pixelBuffer(copy.m_pixelBuffer) -{ - #ifdef SFML_SYSTEM_ANDROID - m_stream = NULL; - #endif - - // Note: as FreeType doesn't provide functions for copying/cloning, - // we must share all the FreeType pointers - - if (m_refCount) - (*m_refCount)++; -} - - -//////////////////////////////////////////////////////////// -Font::~Font() -{ - cleanup(); - - #ifdef SFML_SYSTEM_ANDROID - - if (m_stream) - delete (priv::ResourceStream*)m_stream; - - #endif -} - - -//////////////////////////////////////////////////////////// -bool Font::loadFromFile(const std::string& filename) -{ - #ifndef SFML_SYSTEM_ANDROID - - // Cleanup the previous resources - cleanup(); - m_refCount = new int(1); - - // Initialize FreeType - // Note: we initialize FreeType for every font instance in order to avoid having a single - // global manager that would create a lot of issues regarding creation and destruction order. - FT_Library library; - if (FT_Init_FreeType(&library) != 0) - { - err() << "Failed to load font \"" << filename << "\" (failed to initialize FreeType)" << std::endl; - return false; - } - m_library = library; - - // Load the new font face from the specified file - FT_Face face; - if (FT_New_Face(static_cast(m_library), filename.c_str(), 0, &face) != 0) - { - err() << "Failed to load font \"" << filename << "\" (failed to create the font face)" << std::endl; - return false; - } - - // Select the unicode character map - if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) - { - err() << "Failed to load font \"" << filename << "\" (failed to set the Unicode character set)" << std::endl; - FT_Done_Face(face); - return false; - } - - // Store the loaded font in our ugly void* :) - m_face = face; - - // Store the font information - m_info.family = face->family_name ? face->family_name : std::string(); - - return true; - - #else - - if (m_stream) - delete (priv::ResourceStream*)m_stream; - - m_stream = new priv::ResourceStream(filename); - return loadFromStream(*(priv::ResourceStream*)m_stream); - - #endif -} - - -//////////////////////////////////////////////////////////// -bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes) -{ - // Cleanup the previous resources - cleanup(); - m_refCount = new int(1); - - // Initialize FreeType - // Note: we initialize FreeType for every font instance in order to avoid having a single - // global manager that would create a lot of issues regarding creation and destruction order. - FT_Library library; - if (FT_Init_FreeType(&library) != 0) - { - err() << "Failed to load font from memory (failed to initialize FreeType)" << std::endl; - return false; - } - m_library = library; - - // Load the new font face from the specified file - FT_Face face; - if (FT_New_Memory_Face(static_cast(m_library), reinterpret_cast(data), static_cast(sizeInBytes), 0, &face) != 0) - { - err() << "Failed to load font from memory (failed to create the font face)" << std::endl; - return false; - } - - // Select the unicode character map - if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) - { - err() << "Failed to load font from memory (failed to set the Unicode character set)" << std::endl; - FT_Done_Face(face); - return false; - } - - // Store the loaded font in our ugly void* :) - m_face = face; - - // Store the font information - m_info.family = face->family_name ? face->family_name : std::string(); - - return true; -} - - -//////////////////////////////////////////////////////////// -bool Font::loadFromStream(InputStream& stream) -{ - // Cleanup the previous resources - cleanup(); - m_refCount = new int(1); - - // Initialize FreeType - // Note: we initialize FreeType for every font instance in order to avoid having a single - // global manager that would create a lot of issues regarding creation and destruction order. - FT_Library library; - if (FT_Init_FreeType(&library) != 0) - { - err() << "Failed to load font from stream (failed to initialize FreeType)" << std::endl; - return false; - } - m_library = library; - - // Make sure that the stream's reading position is at the beginning - stream.seek(0); - - // Prepare a wrapper for our stream, that we'll pass to FreeType callbacks - FT_StreamRec* rec = new FT_StreamRec; - std::memset(rec, 0, sizeof(*rec)); - rec->base = NULL; - rec->size = static_cast(stream.getSize()); - rec->pos = 0; - rec->descriptor.pointer = &stream; - rec->read = &read; - rec->close = &close; - - // Setup the FreeType callbacks that will read our stream - FT_Open_Args args; - args.flags = FT_OPEN_STREAM; - args.stream = rec; - args.driver = 0; - - // Load the new font face from the specified stream - FT_Face face; - if (FT_Open_Face(static_cast(m_library), &args, 0, &face) != 0) - { - err() << "Failed to load font from stream (failed to create the font face)" << std::endl; - delete rec; - return false; - } - - // Select the unicode character map - if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) - { - err() << "Failed to load font from stream (failed to set the Unicode character set)" << std::endl; - FT_Done_Face(face); - delete rec; - return false; - } - - // Store the loaded font in our ugly void* :) - m_face = face; - m_streamRec = rec; - - // Store the font information - m_info.family = face->family_name ? face->family_name : std::string(); - - return true; -} - - -//////////////////////////////////////////////////////////// -const Font::Info& Font::getInfo() const -{ - return m_info; -} - - -//////////////////////////////////////////////////////////// -const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const -{ - // Get the page corresponding to the character size - GlyphTable& glyphs = m_pages[characterSize].glyphs; - - // Build the key by combining the code point and the bold flag - Uint32 key = ((bold ? 1 : 0) << 31) | codePoint; - - // Search the glyph into the cache - GlyphTable::const_iterator it = glyphs.find(key); - if (it != glyphs.end()) - { - // Found: just return it - return it->second; - } - else - { - // Not found: we have to load it - Glyph glyph = loadGlyph(codePoint, characterSize, bold); - return glyphs.insert(std::make_pair(key, glyph)).first->second; - } -} - - -//////////////////////////////////////////////////////////// -float Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const -{ - // Special case where first or second is 0 (null character) - if (first == 0 || second == 0) - return 0.f; - - FT_Face face = static_cast(m_face); - - if (face && FT_HAS_KERNING(face) && setCurrentSize(characterSize)) - { - // Convert the characters to indices - FT_UInt index1 = FT_Get_Char_Index(face, first); - FT_UInt index2 = FT_Get_Char_Index(face, second); - - // Get the kerning vector - FT_Vector kerning; - FT_Get_Kerning(face, index1, index2, FT_KERNING_DEFAULT, &kerning); - - // X advance is already in pixels for bitmap fonts - if (!FT_IS_SCALABLE(face)) - return static_cast(kerning.x); - - // Return the X advance - return static_cast(kerning.x) / static_cast(1 << 6); - } - else - { - // Invalid font, or no kerning - return 0.f; - } -} - - -//////////////////////////////////////////////////////////// -float Font::getLineSpacing(unsigned int characterSize) const -{ - FT_Face face = static_cast(m_face); - - if (face && setCurrentSize(characterSize)) - { - return static_cast(face->size->metrics.height) / static_cast(1 << 6); - } - else - { - return 0.f; - } -} - - -//////////////////////////////////////////////////////////// -float Font::getUnderlinePosition(unsigned int characterSize) const -{ - FT_Face face = static_cast(m_face); - - if (face && setCurrentSize(characterSize)) - { - // Return a fixed position if font is a bitmap font - if (!FT_IS_SCALABLE(face)) - return characterSize / 10.f; - - return -static_cast(FT_MulFix(face->underline_position, face->size->metrics.y_scale)) / static_cast(1 << 6); - } - else - { - return 0.f; - } -} - - -//////////////////////////////////////////////////////////// -float Font::getUnderlineThickness(unsigned int characterSize) const -{ - FT_Face face = static_cast(m_face); - - if (face && setCurrentSize(characterSize)) - { - // Return a fixed thickness if font is a bitmap font - if (!FT_IS_SCALABLE(face)) - return characterSize / 14.f; - - return static_cast(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)) / static_cast(1 << 6); - } - else - { - return 0.f; - } -} - - -//////////////////////////////////////////////////////////// -const Texture& Font::getTexture(unsigned int characterSize) const -{ - return m_pages[characterSize].texture; -} - - -//////////////////////////////////////////////////////////// -Font& Font::operator =(const Font& right) -{ - Font temp(right); - - std::swap(m_library, temp.m_library); - std::swap(m_face, temp.m_face); - std::swap(m_streamRec, temp.m_streamRec); - std::swap(m_refCount, temp.m_refCount); - std::swap(m_info, temp.m_info); - std::swap(m_pages, temp.m_pages); - std::swap(m_pixelBuffer, temp.m_pixelBuffer); - - return *this; -} - - -//////////////////////////////////////////////////////////// -void Font::cleanup() -{ - // Check if we must destroy the FreeType pointers - if (m_refCount) - { - // Decrease the reference counter - (*m_refCount)--; - - // Free the resources only if we are the last owner - if (*m_refCount == 0) - { - // Delete the reference counter - delete m_refCount; - - // Destroy the font face - if (m_face) - FT_Done_Face(static_cast(m_face)); - - // Destroy the stream rec instance, if any (must be done after FT_Done_Face!) - if (m_streamRec) - delete static_cast(m_streamRec); - - // Close the library - if (m_library) - FT_Done_FreeType(static_cast(m_library)); - } - } - - // Reset members - m_library = NULL; - m_face = NULL; - m_streamRec = NULL; - m_refCount = NULL; - m_pages.clear(); - m_pixelBuffer.clear(); -} - - -//////////////////////////////////////////////////////////// -Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const -{ - // The glyph to return - Glyph glyph; - - // First, transform our ugly void* to a FT_Face - FT_Face face = static_cast(m_face); - if (!face) - return glyph; - - // Set the character size - if (!setCurrentSize(characterSize)) - return glyph; - - // Load the glyph corresponding to the code point - if (FT_Load_Char(face, codePoint, FT_LOAD_TARGET_NORMAL | FT_LOAD_FORCE_AUTOHINT) != 0) - return glyph; - - // Retrieve the glyph - FT_Glyph glyphDesc; - if (FT_Get_Glyph(face->glyph, &glyphDesc) != 0) - return glyph; - - // Apply bold if necessary -- first technique using outline (highest quality) - FT_Pos weight = 1 << 6; - bool outline = (glyphDesc->format == FT_GLYPH_FORMAT_OUTLINE); - if (bold && outline) - { - FT_OutlineGlyph outlineGlyph = (FT_OutlineGlyph)glyphDesc; - FT_Outline_Embolden(&outlineGlyph->outline, weight); - } - - // Convert the glyph to a bitmap (i.e. rasterize it) - FT_Glyph_To_Bitmap(&glyphDesc, FT_RENDER_MODE_NORMAL, 0, 1); - FT_Bitmap& bitmap = reinterpret_cast(glyphDesc)->bitmap; - - // Apply bold if necessary -- fallback technique using bitmap (lower quality) - if (bold && !outline) - { - FT_Bitmap_Embolden(static_cast(m_library), &bitmap, weight, weight); - } - - // Compute the glyph's advance offset - glyph.advance = static_cast(face->glyph->metrics.horiAdvance) / static_cast(1 << 6); - if (bold) - glyph.advance += static_cast(weight) / static_cast(1 << 6); - - int width = bitmap.width; - int height = bitmap.rows; - - if ((width > 0) && (height > 0)) - { - // Leave a small padding around characters, so that filtering doesn't - // pollute them with pixels from neighbours - const unsigned int padding = 1; - - // Get the glyphs page corresponding to the character size - Page& page = m_pages[characterSize]; - - // Find a good position for the new glyph into the texture - glyph.textureRect = findGlyphRect(page, width + 2 * padding, height + 2 * padding); - - // Make sure the texture data is positioned in the centre - // of the allocated texture rectangle - glyph.textureRect.left += padding; - glyph.textureRect.top += padding; - glyph.textureRect.width -= 2 * padding; - glyph.textureRect.height -= 2 * padding; - - // Compute the glyph's bounding box - glyph.bounds.left = static_cast(face->glyph->metrics.horiBearingX) / static_cast(1 << 6); - glyph.bounds.top = -static_cast(face->glyph->metrics.horiBearingY) / static_cast(1 << 6); - glyph.bounds.width = static_cast(face->glyph->metrics.width) / static_cast(1 << 6); - glyph.bounds.height = static_cast(face->glyph->metrics.height) / static_cast(1 << 6); - - // Extract the glyph's pixels from the bitmap - m_pixelBuffer.resize(width * height * 4, 255); - const Uint8* pixels = bitmap.buffer; - if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO) - { - // Pixels are 1 bit monochrome values - for (int y = 0; y < height; ++y) - { - for (int x = 0; x < width; ++x) - { - // The color channels remain white, just fill the alpha channel - std::size_t index = (x + y * width) * 4 + 3; - m_pixelBuffer[index] = ((pixels[x / 8]) & (1 << (7 - (x % 8)))) ? 255 : 0; - } - pixels += bitmap.pitch; - } - } - else - { - // Pixels are 8 bits gray levels - for (int y = 0; y < height; ++y) - { - for (int x = 0; x < width; ++x) - { - // The color channels remain white, just fill the alpha channel - std::size_t index = (x + y * width) * 4 + 3; - m_pixelBuffer[index] = pixels[x]; - } - pixels += bitmap.pitch; - } - } - - // Write the pixels to the texture - unsigned int x = glyph.textureRect.left; - unsigned int y = glyph.textureRect.top; - unsigned int w = glyph.textureRect.width; - unsigned int h = glyph.textureRect.height; - page.texture.update(&m_pixelBuffer[0], w, h, x, y); - } - - // Delete the FT glyph - FT_Done_Glyph(glyphDesc); - - // Force an OpenGL flush, so that the font's texture will appear updated - // in all contexts immediately (solves problems in multi-threaded apps) - glCheck(glFlush()); - - // Done :) - return glyph; -} - - -//////////////////////////////////////////////////////////// -IntRect Font::findGlyphRect(Page& page, unsigned int width, unsigned int height) const -{ - // Find the line that fits well the glyph - Row* row = NULL; - float bestRatio = 0; - for (std::vector::iterator it = page.rows.begin(); it != page.rows.end() && !row; ++it) - { - float ratio = static_cast(height) / it->height; - - // Ignore rows that are either too small or too high - if ((ratio < 0.7f) || (ratio > 1.f)) - continue; - - // Check if there's enough horizontal space left in the row - if (width > page.texture.getSize().x - it->width) - continue; - - // Make sure that this new row is the best found so far - if (ratio < bestRatio) - continue; - - // The current row passed all the tests: we can select it - row = &*it; - bestRatio = ratio; - } - - // If we didn't find a matching row, create a new one (10% taller than the glyph) - if (!row) - { - int rowHeight = height + height / 10; - while ((page.nextRow + rowHeight >= page.texture.getSize().y) || (width >= page.texture.getSize().x)) - { - // Not enough space: resize the texture if possible - unsigned int textureWidth = page.texture.getSize().x; - unsigned int textureHeight = page.texture.getSize().y; - if ((textureWidth * 2 <= Texture::getMaximumSize()) && (textureHeight * 2 <= Texture::getMaximumSize())) - { - // Make the texture 2 times bigger - Image newImage; - newImage.create(textureWidth * 2, textureHeight * 2, Color(255, 255, 255, 0)); - newImage.copy(page.texture.copyToImage(), 0, 0); - page.texture.loadFromImage(newImage); - } - else - { - // Oops, we've reached the maximum texture size... - err() << "Failed to add a new character to the font: the maximum texture size has been reached" << std::endl; - return IntRect(0, 0, 2, 2); - } - } - - // We can now create the new row - page.rows.push_back(Row(page.nextRow, rowHeight)); - page.nextRow += rowHeight; - row = &page.rows.back(); - } - - // Find the glyph's rectangle on the selected row - IntRect rect(row->width, row->top, width, height); - - // Update the row informations - row->width += width; - - return rect; -} - - -//////////////////////////////////////////////////////////// -bool Font::setCurrentSize(unsigned int characterSize) const -{ - // FT_Set_Pixel_Sizes is an expensive function, so we must call it - // only when necessary to avoid killing performances - - FT_Face face = static_cast(m_face); - FT_UShort currentSize = face->size->metrics.x_ppem; - - if (currentSize != characterSize) - { - FT_Error result = FT_Set_Pixel_Sizes(face, 0, characterSize); - - if (result == FT_Err_Invalid_Pixel_Size) - { - // In the case of bitmap fonts, resizing can - // fail if the requested size is not available - if (!FT_IS_SCALABLE(face)) - { - err() << "Failed to set bitmap font size to " << characterSize << std::endl; - err() << "Available sizes are: "; - for (int i = 0; i < face->num_fixed_sizes; ++i) - err() << face->available_sizes[i].height << " "; - err() << std::endl; - } - } - - return result == FT_Err_Ok; - } - else - { - return true; - } -} - - -//////////////////////////////////////////////////////////// -Font::Page::Page() : -nextRow(3) -{ - // Make sure that the texture is initialized by default - sf::Image image; - image.create(128, 128, Color(255, 255, 255, 0)); - - // Reserve a 2x2 white square for texturing underlines - for (int x = 0; x < 2; ++x) - for (int y = 0; y < 2; ++y) - image.setPixel(x, y, Color(255, 255, 255, 255)); - - // Create the texture - texture.loadFromImage(image); - texture.setSmooth(true); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#ifdef SFML_SYSTEM_ANDROID + #include +#endif +#include +#include +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include FT_OUTLINE_H +#include FT_BITMAP_H +#include +#include + + +namespace +{ + // FreeType callbacks that operate on a sf::InputStream + unsigned long read(FT_Stream rec, unsigned long offset, unsigned char* buffer, unsigned long count) + { + sf::InputStream* stream = static_cast(rec->descriptor.pointer); + if (static_cast(stream->seek(offset)) == offset) + { + if (count > 0) + return static_cast(stream->read(reinterpret_cast(buffer), count)); + else + return 0; + } + else + return count > 0 ? 0 : 1; // error code is 0 if we're reading, or nonzero if we're seeking + } + void close(FT_Stream) + { + } +} + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Font::Font() : +m_library (NULL), +m_face (NULL), +m_streamRec(NULL), +m_refCount (NULL), +m_info () +{ + #ifdef SFML_SYSTEM_ANDROID + m_stream = NULL; + #endif +} + + +//////////////////////////////////////////////////////////// +Font::Font(const Font& copy) : +m_library (copy.m_library), +m_face (copy.m_face), +m_streamRec (copy.m_streamRec), +m_refCount (copy.m_refCount), +m_info (copy.m_info), +m_pages (copy.m_pages), +m_pixelBuffer(copy.m_pixelBuffer) +{ + #ifdef SFML_SYSTEM_ANDROID + m_stream = NULL; + #endif + + // Note: as FreeType doesn't provide functions for copying/cloning, + // we must share all the FreeType pointers + + if (m_refCount) + (*m_refCount)++; +} + + +//////////////////////////////////////////////////////////// +Font::~Font() +{ + cleanup(); + + #ifdef SFML_SYSTEM_ANDROID + + if (m_stream) + delete (priv::ResourceStream*)m_stream; + + #endif +} + + +//////////////////////////////////////////////////////////// +bool Font::loadFromFile(const std::string& filename) +{ + #ifndef SFML_SYSTEM_ANDROID + + // Cleanup the previous resources + cleanup(); + m_refCount = new int(1); + + // Initialize FreeType + // Note: we initialize FreeType for every font instance in order to avoid having a single + // global manager that would create a lot of issues regarding creation and destruction order. + FT_Library library; + if (FT_Init_FreeType(&library) != 0) + { + err() << "Failed to load font \"" << filename << "\" (failed to initialize FreeType)" << std::endl; + return false; + } + m_library = library; + + // Load the new font face from the specified file + FT_Face face; + if (FT_New_Face(static_cast(m_library), filename.c_str(), 0, &face) != 0) + { + err() << "Failed to load font \"" << filename << "\" (failed to create the font face)" << std::endl; + return false; + } + + // Select the unicode character map + if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) + { + err() << "Failed to load font \"" << filename << "\" (failed to set the Unicode character set)" << std::endl; + FT_Done_Face(face); + return false; + } + + // Store the loaded font in our ugly void* :) + m_face = face; + + // Store the font information + m_info.family = face->family_name ? face->family_name : std::string(); + + return true; + + #else + + if (m_stream) + delete (priv::ResourceStream*)m_stream; + + m_stream = new priv::ResourceStream(filename); + return loadFromStream(*(priv::ResourceStream*)m_stream); + + #endif +} + + +//////////////////////////////////////////////////////////// +bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes) +{ + // Cleanup the previous resources + cleanup(); + m_refCount = new int(1); + + // Initialize FreeType + // Note: we initialize FreeType for every font instance in order to avoid having a single + // global manager that would create a lot of issues regarding creation and destruction order. + FT_Library library; + if (FT_Init_FreeType(&library) != 0) + { + err() << "Failed to load font from memory (failed to initialize FreeType)" << std::endl; + return false; + } + m_library = library; + + // Load the new font face from the specified file + FT_Face face; + if (FT_New_Memory_Face(static_cast(m_library), reinterpret_cast(data), static_cast(sizeInBytes), 0, &face) != 0) + { + err() << "Failed to load font from memory (failed to create the font face)" << std::endl; + return false; + } + + // Select the unicode character map + if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) + { + err() << "Failed to load font from memory (failed to set the Unicode character set)" << std::endl; + FT_Done_Face(face); + return false; + } + + // Store the loaded font in our ugly void* :) + m_face = face; + + // Store the font information + m_info.family = face->family_name ? face->family_name : std::string(); + + return true; +} + + +//////////////////////////////////////////////////////////// +bool Font::loadFromStream(InputStream& stream) +{ + // Cleanup the previous resources + cleanup(); + m_refCount = new int(1); + + // Initialize FreeType + // Note: we initialize FreeType for every font instance in order to avoid having a single + // global manager that would create a lot of issues regarding creation and destruction order. + FT_Library library; + if (FT_Init_FreeType(&library) != 0) + { + err() << "Failed to load font from stream (failed to initialize FreeType)" << std::endl; + return false; + } + m_library = library; + + // Make sure that the stream's reading position is at the beginning + stream.seek(0); + + // Prepare a wrapper for our stream, that we'll pass to FreeType callbacks + FT_StreamRec* rec = new FT_StreamRec; + std::memset(rec, 0, sizeof(*rec)); + rec->base = NULL; + rec->size = static_cast(stream.getSize()); + rec->pos = 0; + rec->descriptor.pointer = &stream; + rec->read = &read; + rec->close = &close; + + // Setup the FreeType callbacks that will read our stream + FT_Open_Args args; + args.flags = FT_OPEN_STREAM; + args.stream = rec; + args.driver = 0; + + // Load the new font face from the specified stream + FT_Face face; + if (FT_Open_Face(static_cast(m_library), &args, 0, &face) != 0) + { + err() << "Failed to load font from stream (failed to create the font face)" << std::endl; + delete rec; + return false; + } + + // Select the unicode character map + if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) + { + err() << "Failed to load font from stream (failed to set the Unicode character set)" << std::endl; + FT_Done_Face(face); + delete rec; + return false; + } + + // Store the loaded font in our ugly void* :) + m_face = face; + m_streamRec = rec; + + // Store the font information + m_info.family = face->family_name ? face->family_name : std::string(); + + return true; +} + + +//////////////////////////////////////////////////////////// +const Font::Info& Font::getInfo() const +{ + return m_info; +} + + +//////////////////////////////////////////////////////////// +const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const +{ + // Get the page corresponding to the character size + GlyphTable& glyphs = m_pages[characterSize].glyphs; + + // Build the key by combining the code point and the bold flag + Uint32 key = ((bold ? 1 : 0) << 31) | codePoint; + + // Search the glyph into the cache + GlyphTable::const_iterator it = glyphs.find(key); + if (it != glyphs.end()) + { + // Found: just return it + return it->second; + } + else + { + // Not found: we have to load it + Glyph glyph = loadGlyph(codePoint, characterSize, bold); + return glyphs.insert(std::make_pair(key, glyph)).first->second; + } +} + + +//////////////////////////////////////////////////////////// +float Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const +{ + // Special case where first or second is 0 (null character) + if (first == 0 || second == 0) + return 0.f; + + FT_Face face = static_cast(m_face); + + if (face && FT_HAS_KERNING(face) && setCurrentSize(characterSize)) + { + // Convert the characters to indices + FT_UInt index1 = FT_Get_Char_Index(face, first); + FT_UInt index2 = FT_Get_Char_Index(face, second); + + // Get the kerning vector + FT_Vector kerning; + FT_Get_Kerning(face, index1, index2, FT_KERNING_DEFAULT, &kerning); + + // X advance is already in pixels for bitmap fonts + if (!FT_IS_SCALABLE(face)) + return static_cast(kerning.x); + + // Return the X advance + return static_cast(kerning.x) / static_cast(1 << 6); + } + else + { + // Invalid font, or no kerning + return 0.f; + } +} + + +//////////////////////////////////////////////////////////// +float Font::getLineSpacing(unsigned int characterSize) const +{ + FT_Face face = static_cast(m_face); + + if (face && setCurrentSize(characterSize)) + { + return static_cast(face->size->metrics.height) / static_cast(1 << 6); + } + else + { + return 0.f; + } +} + + +//////////////////////////////////////////////////////////// +float Font::getUnderlinePosition(unsigned int characterSize) const +{ + FT_Face face = static_cast(m_face); + + if (face && setCurrentSize(characterSize)) + { + // Return a fixed position if font is a bitmap font + if (!FT_IS_SCALABLE(face)) + return characterSize / 10.f; + + return -static_cast(FT_MulFix(face->underline_position, face->size->metrics.y_scale)) / static_cast(1 << 6); + } + else + { + return 0.f; + } +} + + +//////////////////////////////////////////////////////////// +float Font::getUnderlineThickness(unsigned int characterSize) const +{ + FT_Face face = static_cast(m_face); + + if (face && setCurrentSize(characterSize)) + { + // Return a fixed thickness if font is a bitmap font + if (!FT_IS_SCALABLE(face)) + return characterSize / 14.f; + + return static_cast(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)) / static_cast(1 << 6); + } + else + { + return 0.f; + } +} + + +//////////////////////////////////////////////////////////// +const Texture& Font::getTexture(unsigned int characterSize) const +{ + return m_pages[characterSize].texture; +} + + +//////////////////////////////////////////////////////////// +Font& Font::operator =(const Font& right) +{ + Font temp(right); + + std::swap(m_library, temp.m_library); + std::swap(m_face, temp.m_face); + std::swap(m_streamRec, temp.m_streamRec); + std::swap(m_refCount, temp.m_refCount); + std::swap(m_info, temp.m_info); + std::swap(m_pages, temp.m_pages); + std::swap(m_pixelBuffer, temp.m_pixelBuffer); + + return *this; +} + + +//////////////////////////////////////////////////////////// +void Font::cleanup() +{ + // Check if we must destroy the FreeType pointers + if (m_refCount) + { + // Decrease the reference counter + (*m_refCount)--; + + // Free the resources only if we are the last owner + if (*m_refCount == 0) + { + // Delete the reference counter + delete m_refCount; + + // Destroy the font face + if (m_face) + FT_Done_Face(static_cast(m_face)); + + // Destroy the stream rec instance, if any (must be done after FT_Done_Face!) + if (m_streamRec) + delete static_cast(m_streamRec); + + // Close the library + if (m_library) + FT_Done_FreeType(static_cast(m_library)); + } + } + + // Reset members + m_library = NULL; + m_face = NULL; + m_streamRec = NULL; + m_refCount = NULL; + m_pages.clear(); + m_pixelBuffer.clear(); +} + + +//////////////////////////////////////////////////////////// +Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const +{ + // The glyph to return + Glyph glyph; + + // First, transform our ugly void* to a FT_Face + FT_Face face = static_cast(m_face); + if (!face) + return glyph; + + // Set the character size + if (!setCurrentSize(characterSize)) + return glyph; + + // Load the glyph corresponding to the code point + if (FT_Load_Char(face, codePoint, FT_LOAD_TARGET_NORMAL | FT_LOAD_FORCE_AUTOHINT) != 0) + return glyph; + + // Retrieve the glyph + FT_Glyph glyphDesc; + if (FT_Get_Glyph(face->glyph, &glyphDesc) != 0) + return glyph; + + // Apply bold if necessary -- first technique using outline (highest quality) + FT_Pos weight = 1 << 6; + bool outline = (glyphDesc->format == FT_GLYPH_FORMAT_OUTLINE); + if (bold && outline) + { + FT_OutlineGlyph outlineGlyph = (FT_OutlineGlyph)glyphDesc; + FT_Outline_Embolden(&outlineGlyph->outline, weight); + } + + // Convert the glyph to a bitmap (i.e. rasterize it) + FT_Glyph_To_Bitmap(&glyphDesc, FT_RENDER_MODE_NORMAL, 0, 1); + FT_Bitmap& bitmap = reinterpret_cast(glyphDesc)->bitmap; + + // Apply bold if necessary -- fallback technique using bitmap (lower quality) + if (bold && !outline) + { + FT_Bitmap_Embolden(static_cast(m_library), &bitmap, weight, weight); + } + + // Compute the glyph's advance offset + glyph.advance = static_cast(face->glyph->metrics.horiAdvance) / static_cast(1 << 6); + if (bold) + glyph.advance += static_cast(weight) / static_cast(1 << 6); + + int width = bitmap.width; + int height = bitmap.rows; + + if ((width > 0) && (height > 0)) + { + // Leave a small padding around characters, so that filtering doesn't + // pollute them with pixels from neighbours + const unsigned int padding = 1; + + // Get the glyphs page corresponding to the character size + Page& page = m_pages[characterSize]; + + // Find a good position for the new glyph into the texture + glyph.textureRect = findGlyphRect(page, width + 2 * padding, height + 2 * padding); + + // Make sure the texture data is positioned in the centre + // of the allocated texture rectangle + glyph.textureRect.left += padding; + glyph.textureRect.top += padding; + glyph.textureRect.width -= 2 * padding; + glyph.textureRect.height -= 2 * padding; + + // Compute the glyph's bounding box + glyph.bounds.left = static_cast(face->glyph->metrics.horiBearingX) / static_cast(1 << 6); + glyph.bounds.top = -static_cast(face->glyph->metrics.horiBearingY) / static_cast(1 << 6); + glyph.bounds.width = static_cast(face->glyph->metrics.width) / static_cast(1 << 6); + glyph.bounds.height = static_cast(face->glyph->metrics.height) / static_cast(1 << 6); + + // Extract the glyph's pixels from the bitmap + m_pixelBuffer.resize(width * height * 4, 255); + const Uint8* pixels = bitmap.buffer; + if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO) + { + // Pixels are 1 bit monochrome values + for (int y = 0; y < height; ++y) + { + for (int x = 0; x < width; ++x) + { + // The color channels remain white, just fill the alpha channel + std::size_t index = (x + y * width) * 4 + 3; + m_pixelBuffer[index] = ((pixels[x / 8]) & (1 << (7 - (x % 8)))) ? 255 : 0; + } + pixels += bitmap.pitch; + } + } + else + { + // Pixels are 8 bits gray levels + for (int y = 0; y < height; ++y) + { + for (int x = 0; x < width; ++x) + { + // The color channels remain white, just fill the alpha channel + std::size_t index = (x + y * width) * 4 + 3; + m_pixelBuffer[index] = pixels[x]; + } + pixels += bitmap.pitch; + } + } + + // Write the pixels to the texture + unsigned int x = glyph.textureRect.left; + unsigned int y = glyph.textureRect.top; + unsigned int w = glyph.textureRect.width; + unsigned int h = glyph.textureRect.height; + page.texture.update(&m_pixelBuffer[0], w, h, x, y); + } + + // Delete the FT glyph + FT_Done_Glyph(glyphDesc); + + // Force an OpenGL flush, so that the font's texture will appear updated + // in all contexts immediately (solves problems in multi-threaded apps) + glCheck(glFlush()); + + // Done :) + return glyph; +} + + +//////////////////////////////////////////////////////////// +IntRect Font::findGlyphRect(Page& page, unsigned int width, unsigned int height) const +{ + // Find the line that fits well the glyph + Row* row = NULL; + float bestRatio = 0; + for (std::vector::iterator it = page.rows.begin(); it != page.rows.end() && !row; ++it) + { + float ratio = static_cast(height) / it->height; + + // Ignore rows that are either too small or too high + if ((ratio < 0.7f) || (ratio > 1.f)) + continue; + + // Check if there's enough horizontal space left in the row + if (width > page.texture.getSize().x - it->width) + continue; + + // Make sure that this new row is the best found so far + if (ratio < bestRatio) + continue; + + // The current row passed all the tests: we can select it + row = &*it; + bestRatio = ratio; + } + + // If we didn't find a matching row, create a new one (10% taller than the glyph) + if (!row) + { + int rowHeight = height + height / 10; + while ((page.nextRow + rowHeight >= page.texture.getSize().y) || (width >= page.texture.getSize().x)) + { + // Not enough space: resize the texture if possible + unsigned int textureWidth = page.texture.getSize().x; + unsigned int textureHeight = page.texture.getSize().y; + if ((textureWidth * 2 <= Texture::getMaximumSize()) && (textureHeight * 2 <= Texture::getMaximumSize())) + { + // Make the texture 2 times bigger + Image newImage; + newImage.create(textureWidth * 2, textureHeight * 2, Color(255, 255, 255, 0)); + newImage.copy(page.texture.copyToImage(), 0, 0); + page.texture.loadFromImage(newImage); + } + else + { + // Oops, we've reached the maximum texture size... + err() << "Failed to add a new character to the font: the maximum texture size has been reached" << std::endl; + return IntRect(0, 0, 2, 2); + } + } + + // We can now create the new row + page.rows.push_back(Row(page.nextRow, rowHeight)); + page.nextRow += rowHeight; + row = &page.rows.back(); + } + + // Find the glyph's rectangle on the selected row + IntRect rect(row->width, row->top, width, height); + + // Update the row informations + row->width += width; + + return rect; +} + + +//////////////////////////////////////////////////////////// +bool Font::setCurrentSize(unsigned int characterSize) const +{ + // FT_Set_Pixel_Sizes is an expensive function, so we must call it + // only when necessary to avoid killing performances + + FT_Face face = static_cast(m_face); + FT_UShort currentSize = face->size->metrics.x_ppem; + + if (currentSize != characterSize) + { + FT_Error result = FT_Set_Pixel_Sizes(face, 0, characterSize); + + if (result == FT_Err_Invalid_Pixel_Size) + { + // In the case of bitmap fonts, resizing can + // fail if the requested size is not available + if (!FT_IS_SCALABLE(face)) + { + err() << "Failed to set bitmap font size to " << characterSize << std::endl; + err() << "Available sizes are: "; + for (int i = 0; i < face->num_fixed_sizes; ++i) + err() << face->available_sizes[i].height << " "; + err() << std::endl; + } + } + + return result == FT_Err_Ok; + } + else + { + return true; + } +} + + +//////////////////////////////////////////////////////////// +Font::Page::Page() : +nextRow(3) +{ + // Make sure that the texture is initialized by default + sf::Image image; + image.create(128, 128, Color(255, 255, 255, 0)); + + // Reserve a 2x2 white square for texturing underlines + for (int x = 0; x < 2; ++x) + for (int y = 0; y < 2; ++y) + image.setPixel(x, y, Color(255, 255, 255, 255)); + + // Create the texture + texture.loadFromImage(image); + texture.setSmooth(true); +} + +} // namespace sf diff --git a/src/SFML/Graphics/GLCheck.cpp b/src/SFML/Graphics/GLCheck.cpp index 559c5f69..0e8f6de5 100644 --- a/src/SFML/Graphics/GLCheck.cpp +++ b/src/SFML/Graphics/GLCheck.cpp @@ -1,112 +1,112 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -void glCheckError(const char* file, unsigned int line) -{ - // Get the last error - GLenum errorCode = glGetError(); - - if (errorCode != GL_NO_ERROR) - { - std::string fileString(file); - std::string error = "unknown error"; - std::string description = "no description"; - - // Decode the error code - switch (errorCode) - { - case GL_INVALID_ENUM : - { - error = "GL_INVALID_ENUM"; - description = "an unacceptable value has been specified for an enumerated argument"; - break; - } - - case GL_INVALID_VALUE : - { - error = "GL_INVALID_VALUE"; - description = "a numeric argument is out of range"; - break; - } - - case GL_INVALID_OPERATION : - { - error = "GL_INVALID_OPERATION"; - description = "the specified operation is not allowed in the current state"; - break; - } - - case GL_STACK_OVERFLOW : - { - error = "GL_STACK_OVERFLOW"; - description = "this command would cause a stack overflow"; - break; - } - - case GL_STACK_UNDERFLOW : - { - error = "GL_STACK_UNDERFLOW"; - description = "this command would cause a stack underflow"; - break; - } - - case GL_OUT_OF_MEMORY : - { - error = "GL_OUT_OF_MEMORY"; - description = "there is not enough memory left to execute the command"; - break; - } - - case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION : - { - error = "GL_INVALID_FRAMEBUFFER_OPERATION"; - description = "the object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\""; - break; - } - } - - // Log the error - err() << "An internal OpenGL call failed in " - << fileString.substr(fileString.find_last_of("\\/") + 1) << " (" << line << ") : " - << error << ", " << description - << std::endl; - } -} - - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +void glCheckError(const char* file, unsigned int line) +{ + // Get the last error + GLenum errorCode = glGetError(); + + if (errorCode != GL_NO_ERROR) + { + std::string fileString(file); + std::string error = "unknown error"; + std::string description = "no description"; + + // Decode the error code + switch (errorCode) + { + case GL_INVALID_ENUM: + { + error = "GL_INVALID_ENUM"; + description = "an unacceptable value has been specified for an enumerated argument"; + break; + } + + case GL_INVALID_VALUE: + { + error = "GL_INVALID_VALUE"; + description = "a numeric argument is out of range"; + break; + } + + case GL_INVALID_OPERATION: + { + error = "GL_INVALID_OPERATION"; + description = "the specified operation is not allowed in the current state"; + break; + } + + case GL_STACK_OVERFLOW: + { + error = "GL_STACK_OVERFLOW"; + description = "this command would cause a stack overflow"; + break; + } + + case GL_STACK_UNDERFLOW: + { + error = "GL_STACK_UNDERFLOW"; + description = "this command would cause a stack underflow"; + break; + } + + case GL_OUT_OF_MEMORY: + { + error = "GL_OUT_OF_MEMORY"; + description = "there is not enough memory left to execute the command"; + break; + } + + case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION: + { + error = "GL_INVALID_FRAMEBUFFER_OPERATION"; + description = "the object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\""; + break; + } + } + + // Log the error + err() << "An internal OpenGL call failed in " + << fileString.substr(fileString.find_last_of("\\/") + 1) << " (" << line << ") : " + << error << ", " << description + << std::endl; + } +} + + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/GLCheck.hpp b/src/SFML/Graphics/GLCheck.hpp index f96289e8..23ee4d07 100644 --- a/src/SFML/Graphics/GLCheck.hpp +++ b/src/SFML/Graphics/GLCheck.hpp @@ -1,69 +1,69 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_GLCHECK_HPP -#define SFML_GLCHECK_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// Let's define a macro to quickly check every OpenGL API calls -//////////////////////////////////////////////////////////// -#ifdef SFML_DEBUG - - // In debug mode, perform a test on every OpenGL call - #define glCheck(x) x; sf::priv::glCheckError(__FILE__, __LINE__); - -#else - - // Else, we don't add any overhead - #define glCheck(call) (call) - -#endif - -//////////////////////////////////////////////////////////// -/// \brief Check the last OpenGL error -/// -/// \param file Source file where the call is located -/// \param line Line number of the source file where the call is located -/// -//////////////////////////////////////////////////////////// -void glCheckError(const char* file, unsigned int line); - -} // namespace priv - -} // namespace sf - - -#endif // SFML_GLCHECK_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GLCHECK_HPP +#define SFML_GLCHECK_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// Let's define a macro to quickly check every OpenGL API calls +//////////////////////////////////////////////////////////// +#ifdef SFML_DEBUG + + // In debug mode, perform a test on every OpenGL call + #define glCheck(x) x; sf::priv::glCheckError(__FILE__, __LINE__); + +#else + + // Else, we don't add any overhead + #define glCheck(call) (call) + +#endif + +//////////////////////////////////////////////////////////// +/// \brief Check the last OpenGL error +/// +/// \param file Source file where the call is located +/// \param line Line number of the source file where the call is located +/// +//////////////////////////////////////////////////////////// +void glCheckError(const char* file, unsigned int line); + +} // namespace priv + +} // namespace sf + + +#endif // SFML_GLCHECK_HPP diff --git a/src/SFML/Graphics/GLExtensions.cpp b/src/SFML/Graphics/GLExtensions.cpp index ed0c7d54..d3caf6cd 100644 --- a/src/SFML/Graphics/GLExtensions.cpp +++ b/src/SFML/Graphics/GLExtensions.cpp @@ -1,58 +1,58 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -void ensureExtensionsInit() -{ -#if !defined(SFML_OPENGL_ES) - static bool initialized = false; - if (!initialized) - { - GLenum status = glewInit(); - if (status == GLEW_OK) - { - initialized = true; - } - else - { - err() << "Failed to initialize GLEW, " << glewGetErrorString(status) << std::endl; - } - } -#endif -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +void ensureExtensionsInit() +{ +#if !defined(SFML_OPENGL_ES) + static bool initialized = false; + if (!initialized) + { + GLenum status = glewInit(); + if (status == GLEW_OK) + { + initialized = true; + } + else + { + err() << "Failed to initialize GLEW, " << glewGetErrorString(status) << std::endl; + } + } +#endif +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/GLExtensions.hpp b/src/SFML/Graphics/GLExtensions.hpp index 6266c377..ae97741d 100644 --- a/src/SFML/Graphics/GLExtensions.hpp +++ b/src/SFML/Graphics/GLExtensions.hpp @@ -1,130 +1,130 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_GLEXTENSIONS_HPP -#define SFML_GLEXTENSIONS_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#ifdef SFML_OPENGL_ES - - #include - -#ifdef SFML_SYSTEM_ANDROID - // Hack to make transparency working on some Android devices - #define GLEXT_blend_func_separate false - #define GLEXT_blend_equation_separate false -#else - #define GLEXT_blend_func_separate GL_OES_blend_func_separate - #define GLEXT_blend_equation_separate GL_OES_blend_equation_separate -#endif - #define GLEXT_glBlendFuncSeparate glBlendFuncSeparateOES - #define GLEXT_glBlendEquationSeparate glBlendEquationSeparateOES - #define GLEXT_framebuffer_object GL_OES_framebuffer_object - #define GLEXT_glGenFramebuffers glGenFramebuffersOES - #define GLEXT_glGenRenderbuffers glGenRenderbuffersOES - #define GLEXT_glBindFramebuffer glBindFramebufferOES - #define GLEXT_glBindRenderbuffer glBindRenderbufferOES - #define GLEXT_glDeleteFramebuffers glDeleteFramebuffersOES - #define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersOES - #define GLEXT_glRenderbufferStorage glRenderbufferStorageOES - #define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferOES - #define GLEXT_glFramebufferTexture2D glFramebufferTexture2DOES - #define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusOES - #define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES - #define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES - #define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_OES - #define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES - #define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES - #define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES - #define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT16_OES - #define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_OES - #define GLEXT_texture_non_power_of_two false - #define GLEXT_multitexture true - #define GLEXT_glClientActiveTexture glClientActiveTexture - #define GLEXT_glActiveTexture glActiveTexture - #define GLEXT_GL_TEXTURE0 GL_TEXTURE0 - #define GLEXT_glBlendEquation glBlendEquationOES - #define GLEXT_GL_FUNC_ADD GL_FUNC_ADD_OES - #define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT_OES - -#else - - #include - #include - - #define GLEXT_blend_func_separate GLEW_EXT_blend_func_separate - #define GLEXT_blend_equation_separate GLEW_EXT_blend_equation_separate - #define GLEXT_glBlendFuncSeparate glBlendFuncSeparateEXT - #define GLEXT_glBlendEquationSeparate glBlendEquationSeparateEXT - #define GLEXT_framebuffer_object GLEW_EXT_framebuffer_object - #define GLEXT_glGenFramebuffers glGenFramebuffersEXT - #define GLEXT_glGenRenderbuffers glGenRenderbuffersEXT - #define GLEXT_glBindFramebuffer glBindFramebufferEXT - #define GLEXT_glBindRenderbuffer glBindRenderbufferEXT - #define GLEXT_glDeleteFramebuffers glDeleteFramebuffersEXT - #define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersEXT - #define GLEXT_glRenderbufferStorage glRenderbufferStorageEXT - #define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferEXT - #define GLEXT_glFramebufferTexture2D glFramebufferTexture2DEXT - #define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusEXT - #define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT - #define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT - #define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_EXT - #define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT - #define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT - #define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT - #define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT - #define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT - #define GLEXT_texture_non_power_of_two GLEW_ARB_texture_non_power_of_two - #define GLEXT_multitexture GLEW_ARB_multitexture - #define GLEXT_glClientActiveTexture glClientActiveTextureARB - #define GLEXT_glActiveTexture glActiveTextureARB - #define GLEXT_GL_TEXTURE0 GL_TEXTURE0_ARB - #define GLEXT_glBlendEquation glBlendEquation - #define GLEXT_GL_FUNC_ADD GL_FUNC_ADD - #define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT - -#endif - -namespace sf -{ -namespace priv -{ - -//////////////////////////////////////////////////////////// -/// \brief Make sure that extensions are initialized -/// -//////////////////////////////////////////////////////////// -void ensureExtensionsInit(); - -} // namespace priv - -} // namespace sf - - -#endif // SFML_GLEXTENSIONS_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GLEXTENSIONS_HPP +#define SFML_GLEXTENSIONS_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#ifdef SFML_OPENGL_ES + + #include + +#ifdef SFML_SYSTEM_ANDROID + // Hack to make transparency working on some Android devices + #define GLEXT_blend_func_separate false + #define GLEXT_blend_equation_separate false +#else + #define GLEXT_blend_func_separate GL_OES_blend_func_separate + #define GLEXT_blend_equation_separate GL_OES_blend_equation_separate +#endif + #define GLEXT_glBlendFuncSeparate glBlendFuncSeparateOES + #define GLEXT_glBlendEquationSeparate glBlendEquationSeparateOES + #define GLEXT_framebuffer_object GL_OES_framebuffer_object + #define GLEXT_glGenFramebuffers glGenFramebuffersOES + #define GLEXT_glGenRenderbuffers glGenRenderbuffersOES + #define GLEXT_glBindFramebuffer glBindFramebufferOES + #define GLEXT_glBindRenderbuffer glBindRenderbufferOES + #define GLEXT_glDeleteFramebuffers glDeleteFramebuffersOES + #define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersOES + #define GLEXT_glRenderbufferStorage glRenderbufferStorageOES + #define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferOES + #define GLEXT_glFramebufferTexture2D glFramebufferTexture2DOES + #define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusOES + #define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES + #define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES + #define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_OES + #define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES + #define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES + #define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES + #define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT16_OES + #define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_OES + #define GLEXT_texture_non_power_of_two false + #define GLEXT_multitexture true + #define GLEXT_glClientActiveTexture glClientActiveTexture + #define GLEXT_glActiveTexture glActiveTexture + #define GLEXT_GL_TEXTURE0 GL_TEXTURE0 + #define GLEXT_glBlendEquation glBlendEquationOES + #define GLEXT_GL_FUNC_ADD GL_FUNC_ADD_OES + #define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT_OES + +#else + + #include + #include + + #define GLEXT_blend_func_separate GLEW_EXT_blend_func_separate + #define GLEXT_blend_equation_separate GLEW_EXT_blend_equation_separate + #define GLEXT_glBlendFuncSeparate glBlendFuncSeparateEXT + #define GLEXT_glBlendEquationSeparate glBlendEquationSeparateEXT + #define GLEXT_framebuffer_object GLEW_EXT_framebuffer_object + #define GLEXT_glGenFramebuffers glGenFramebuffersEXT + #define GLEXT_glGenRenderbuffers glGenRenderbuffersEXT + #define GLEXT_glBindFramebuffer glBindFramebufferEXT + #define GLEXT_glBindRenderbuffer glBindRenderbufferEXT + #define GLEXT_glDeleteFramebuffers glDeleteFramebuffersEXT + #define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersEXT + #define GLEXT_glRenderbufferStorage glRenderbufferStorageEXT + #define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferEXT + #define GLEXT_glFramebufferTexture2D glFramebufferTexture2DEXT + #define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusEXT + #define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT + #define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT + #define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_EXT + #define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT + #define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT + #define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT + #define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT + #define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT + #define GLEXT_texture_non_power_of_two GLEW_ARB_texture_non_power_of_two + #define GLEXT_multitexture GLEW_ARB_multitexture + #define GLEXT_glClientActiveTexture glClientActiveTextureARB + #define GLEXT_glActiveTexture glActiveTextureARB + #define GLEXT_GL_TEXTURE0 GL_TEXTURE0_ARB + #define GLEXT_glBlendEquation glBlendEquation + #define GLEXT_GL_FUNC_ADD GL_FUNC_ADD + #define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT + +#endif + +namespace sf +{ +namespace priv +{ + +//////////////////////////////////////////////////////////// +/// \brief Make sure that extensions are initialized +/// +//////////////////////////////////////////////////////////// +void ensureExtensionsInit(); + +} // namespace priv + +} // namespace sf + + +#endif // SFML_GLEXTENSIONS_HPP diff --git a/src/SFML/Graphics/Image.cpp b/src/SFML/Graphics/Image.cpp index a27ab92d..7cc45e06 100644 --- a/src/SFML/Graphics/Image.cpp +++ b/src/SFML/Graphics/Image.cpp @@ -1,344 +1,344 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#ifdef SFML_SYSTEM_ANDROID - #include -#endif -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Image::Image() : -m_size(0, 0) -{ - #ifdef SFML_SYSTEM_ANDROID - - m_stream = NULL; - - #endif -} - - -//////////////////////////////////////////////////////////// -Image::~Image() -{ - #ifdef SFML_SYSTEM_ANDROID - - if (m_stream) - delete (priv::ResourceStream*)m_stream; - - #endif -} - - -//////////////////////////////////////////////////////////// -void Image::create(unsigned int width, unsigned int height, const Color& color) -{ - if (width && height) - { - // Assign the new size - m_size.x = width; - m_size.y = height; - - // Resize the pixel buffer - m_pixels.resize(width * height * 4); - - // Fill it with the specified color - Uint8* ptr = &m_pixels[0]; - Uint8* end = ptr + m_pixels.size(); - while (ptr < end) - { - *ptr++ = color.r; - *ptr++ = color.g; - *ptr++ = color.b; - *ptr++ = color.a; - } - } - else - { - // Create an empty image - m_size.x = 0; - m_size.y = 0; - m_pixels.clear(); - } -} - - -//////////////////////////////////////////////////////////// -void Image::create(unsigned int width, unsigned int height, const Uint8* pixels) -{ - if (pixels && width && height) - { - // Assign the new size - m_size.x = width; - m_size.y = height; - - // Copy the pixels - std::size_t size = width * height * 4; - m_pixels.resize(size); - std::memcpy(&m_pixels[0], pixels, size); // faster than vector::assign - } - else - { - // Create an empty image - m_size.x = 0; - m_size.y = 0; - m_pixels.clear(); - } -} - - -//////////////////////////////////////////////////////////// -bool Image::loadFromFile(const std::string& filename) -{ - #ifndef SFML_SYSTEM_ANDROID - - return priv::ImageLoader::getInstance().loadImageFromFile(filename, m_pixels, m_size); - - #else - - if (m_stream) - delete (priv::ResourceStream*)m_stream; - - m_stream = new priv::ResourceStream(filename); - return loadFromStream(*(priv::ResourceStream*)m_stream); - - #endif -} - - -//////////////////////////////////////////////////////////// -bool Image::loadFromMemory(const void* data, std::size_t size) -{ - return priv::ImageLoader::getInstance().loadImageFromMemory(data, size, m_pixels, m_size); -} - - -//////////////////////////////////////////////////////////// -bool Image::loadFromStream(InputStream& stream) -{ - return priv::ImageLoader::getInstance().loadImageFromStream(stream, m_pixels, m_size); -} - - -//////////////////////////////////////////////////////////// -bool Image::saveToFile(const std::string& filename) const -{ - return priv::ImageLoader::getInstance().saveImageToFile(filename, m_pixels, m_size); -} - - -//////////////////////////////////////////////////////////// -Vector2u Image::getSize() const -{ - return m_size; -} - - -//////////////////////////////////////////////////////////// -void Image::createMaskFromColor(const Color& color, Uint8 alpha) -{ - // Make sure that the image is not empty - if (!m_pixels.empty()) - { - // Replace the alpha of the pixels that match the transparent color - Uint8* ptr = &m_pixels[0]; - Uint8* end = ptr + m_pixels.size(); - while (ptr < end) - { - if ((ptr[0] == color.r) && (ptr[1] == color.g) && (ptr[2] == color.b) && (ptr[3] == color.a)) - ptr[3] = alpha; - ptr += 4; - } - } -} - - -//////////////////////////////////////////////////////////// -void Image::copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect, bool applyAlpha) -{ - // Make sure that both images are valid - if ((source.m_size.x == 0) || (source.m_size.y == 0) || (m_size.x == 0) || (m_size.y == 0)) - return; - - // Adjust the source rectangle - IntRect srcRect = sourceRect; - if (srcRect.width == 0 || (srcRect.height == 0)) - { - srcRect.left = 0; - srcRect.top = 0; - srcRect.width = source.m_size.x; - srcRect.height = source.m_size.y; - } - else - { - if (srcRect.left < 0) srcRect.left = 0; - if (srcRect.top < 0) srcRect.top = 0; - if (srcRect.width > static_cast(source.m_size.x)) srcRect.width = source.m_size.x; - if (srcRect.height > static_cast(source.m_size.y)) srcRect.height = source.m_size.y; - } - - // Then find the valid bounds of the destination rectangle - int width = srcRect.width; - int height = srcRect.height; - if (destX + width > m_size.x) width = m_size.x - destX; - if (destY + height > m_size.y) height = m_size.y - destY; - - // Make sure the destination area is valid - if ((width <= 0) || (height <= 0)) - return; - - // Precompute as much as possible - int pitch = width * 4; - int rows = height; - int srcStride = source.m_size.x * 4; - int dstStride = m_size.x * 4; - const Uint8* srcPixels = &source.m_pixels[0] + (srcRect.left + srcRect.top * source.m_size.x) * 4; - Uint8* dstPixels = &m_pixels[0] + (destX + destY * m_size.x) * 4; - - // Copy the pixels - if (applyAlpha) - { - // Interpolation using alpha values, pixel by pixel (slower) - for (int i = 0; i < rows; ++i) - { - for (int j = 0; j < width; ++j) - { - // Get a direct pointer to the components of the current pixel - const Uint8* src = srcPixels + j * 4; - Uint8* dst = dstPixels + j * 4; - - // Interpolate RGBA components using the alpha value of the source pixel - Uint8 alpha = src[3]; - dst[0] = (src[0] * alpha + dst[0] * (255 - alpha)) / 255; - dst[1] = (src[1] * alpha + dst[1] * (255 - alpha)) / 255; - dst[2] = (src[2] * alpha + dst[2] * (255 - alpha)) / 255; - dst[3] = alpha + dst[3] * (255 - alpha) / 255; - } - - srcPixels += srcStride; - dstPixels += dstStride; - } - } - else - { - // Optimized copy ignoring alpha values, row by row (faster) - for (int i = 0; i < rows; ++i) - { - std::memcpy(dstPixels, srcPixels, pitch); - srcPixels += srcStride; - dstPixels += dstStride; - } - } -} - - -//////////////////////////////////////////////////////////// -void Image::setPixel(unsigned int x, unsigned int y, const Color& color) -{ - Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4]; - *pixel++ = color.r; - *pixel++ = color.g; - *pixel++ = color.b; - *pixel++ = color.a; -} - - -//////////////////////////////////////////////////////////// -Color Image::getPixel(unsigned int x, unsigned int y) const -{ - const Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4]; - return Color(pixel[0], pixel[1], pixel[2], pixel[3]); -} - - -//////////////////////////////////////////////////////////// -const Uint8* Image::getPixelsPtr() const -{ - if (!m_pixels.empty()) - { - return &m_pixels[0]; - } - else - { - err() << "Trying to access the pixels of an empty image" << std::endl; - return NULL; - } -} - - -//////////////////////////////////////////////////////////// -void Image::flipHorizontally() -{ - if (!m_pixels.empty()) - { - std::size_t rowSize = m_size.x * 4; - - for (std::size_t y = 0; y < m_size.y; ++y) - { - std::vector::iterator left = m_pixels.begin() + y * rowSize; - std::vector::iterator right = m_pixels.begin() + (y + 1) * rowSize - 4; - - for (std::size_t x = 0; x < m_size.x / 2; ++x) - { - std::swap_ranges(left, left + 4, right); - - left += 4; - right -= 4; - } - } - } -} - - -//////////////////////////////////////////////////////////// -void Image::flipVertically() -{ - if (!m_pixels.empty()) - { - std::size_t rowSize = m_size.x * 4; - - std::vector::iterator top = m_pixels.begin(); - std::vector::iterator bottom = m_pixels.end() - rowSize; - - for (std::size_t y = 0; y < m_size.y / 2; ++y) - { - std::swap_ranges(top, top + rowSize, bottom); - - top += rowSize; - bottom -= rowSize; - } - } -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#ifdef SFML_SYSTEM_ANDROID + #include +#endif +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Image::Image() : +m_size(0, 0) +{ + #ifdef SFML_SYSTEM_ANDROID + + m_stream = NULL; + + #endif +} + + +//////////////////////////////////////////////////////////// +Image::~Image() +{ + #ifdef SFML_SYSTEM_ANDROID + + if (m_stream) + delete (priv::ResourceStream*)m_stream; + + #endif +} + + +//////////////////////////////////////////////////////////// +void Image::create(unsigned int width, unsigned int height, const Color& color) +{ + if (width && height) + { + // Assign the new size + m_size.x = width; + m_size.y = height; + + // Resize the pixel buffer + m_pixels.resize(width * height * 4); + + // Fill it with the specified color + Uint8* ptr = &m_pixels[0]; + Uint8* end = ptr + m_pixels.size(); + while (ptr < end) + { + *ptr++ = color.r; + *ptr++ = color.g; + *ptr++ = color.b; + *ptr++ = color.a; + } + } + else + { + // Create an empty image + m_size.x = 0; + m_size.y = 0; + m_pixels.clear(); + } +} + + +//////////////////////////////////////////////////////////// +void Image::create(unsigned int width, unsigned int height, const Uint8* pixels) +{ + if (pixels && width && height) + { + // Assign the new size + m_size.x = width; + m_size.y = height; + + // Copy the pixels + std::size_t size = width * height * 4; + m_pixels.resize(size); + std::memcpy(&m_pixels[0], pixels, size); // faster than vector::assign + } + else + { + // Create an empty image + m_size.x = 0; + m_size.y = 0; + m_pixels.clear(); + } +} + + +//////////////////////////////////////////////////////////// +bool Image::loadFromFile(const std::string& filename) +{ + #ifndef SFML_SYSTEM_ANDROID + + return priv::ImageLoader::getInstance().loadImageFromFile(filename, m_pixels, m_size); + + #else + + if (m_stream) + delete (priv::ResourceStream*)m_stream; + + m_stream = new priv::ResourceStream(filename); + return loadFromStream(*(priv::ResourceStream*)m_stream); + + #endif +} + + +//////////////////////////////////////////////////////////// +bool Image::loadFromMemory(const void* data, std::size_t size) +{ + return priv::ImageLoader::getInstance().loadImageFromMemory(data, size, m_pixels, m_size); +} + + +//////////////////////////////////////////////////////////// +bool Image::loadFromStream(InputStream& stream) +{ + return priv::ImageLoader::getInstance().loadImageFromStream(stream, m_pixels, m_size); +} + + +//////////////////////////////////////////////////////////// +bool Image::saveToFile(const std::string& filename) const +{ + return priv::ImageLoader::getInstance().saveImageToFile(filename, m_pixels, m_size); +} + + +//////////////////////////////////////////////////////////// +Vector2u Image::getSize() const +{ + return m_size; +} + + +//////////////////////////////////////////////////////////// +void Image::createMaskFromColor(const Color& color, Uint8 alpha) +{ + // Make sure that the image is not empty + if (!m_pixels.empty()) + { + // Replace the alpha of the pixels that match the transparent color + Uint8* ptr = &m_pixels[0]; + Uint8* end = ptr + m_pixels.size(); + while (ptr < end) + { + if ((ptr[0] == color.r) && (ptr[1] == color.g) && (ptr[2] == color.b) && (ptr[3] == color.a)) + ptr[3] = alpha; + ptr += 4; + } + } +} + + +//////////////////////////////////////////////////////////// +void Image::copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect, bool applyAlpha) +{ + // Make sure that both images are valid + if ((source.m_size.x == 0) || (source.m_size.y == 0) || (m_size.x == 0) || (m_size.y == 0)) + return; + + // Adjust the source rectangle + IntRect srcRect = sourceRect; + if (srcRect.width == 0 || (srcRect.height == 0)) + { + srcRect.left = 0; + srcRect.top = 0; + srcRect.width = source.m_size.x; + srcRect.height = source.m_size.y; + } + else + { + if (srcRect.left < 0) srcRect.left = 0; + if (srcRect.top < 0) srcRect.top = 0; + if (srcRect.width > static_cast(source.m_size.x)) srcRect.width = source.m_size.x; + if (srcRect.height > static_cast(source.m_size.y)) srcRect.height = source.m_size.y; + } + + // Then find the valid bounds of the destination rectangle + int width = srcRect.width; + int height = srcRect.height; + if (destX + width > m_size.x) width = m_size.x - destX; + if (destY + height > m_size.y) height = m_size.y - destY; + + // Make sure the destination area is valid + if ((width <= 0) || (height <= 0)) + return; + + // Precompute as much as possible + int pitch = width * 4; + int rows = height; + int srcStride = source.m_size.x * 4; + int dstStride = m_size.x * 4; + const Uint8* srcPixels = &source.m_pixels[0] + (srcRect.left + srcRect.top * source.m_size.x) * 4; + Uint8* dstPixels = &m_pixels[0] + (destX + destY * m_size.x) * 4; + + // Copy the pixels + if (applyAlpha) + { + // Interpolation using alpha values, pixel by pixel (slower) + for (int i = 0; i < rows; ++i) + { + for (int j = 0; j < width; ++j) + { + // Get a direct pointer to the components of the current pixel + const Uint8* src = srcPixels + j * 4; + Uint8* dst = dstPixels + j * 4; + + // Interpolate RGBA components using the alpha value of the source pixel + Uint8 alpha = src[3]; + dst[0] = (src[0] * alpha + dst[0] * (255 - alpha)) / 255; + dst[1] = (src[1] * alpha + dst[1] * (255 - alpha)) / 255; + dst[2] = (src[2] * alpha + dst[2] * (255 - alpha)) / 255; + dst[3] = alpha + dst[3] * (255 - alpha) / 255; + } + + srcPixels += srcStride; + dstPixels += dstStride; + } + } + else + { + // Optimized copy ignoring alpha values, row by row (faster) + for (int i = 0; i < rows; ++i) + { + std::memcpy(dstPixels, srcPixels, pitch); + srcPixels += srcStride; + dstPixels += dstStride; + } + } +} + + +//////////////////////////////////////////////////////////// +void Image::setPixel(unsigned int x, unsigned int y, const Color& color) +{ + Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4]; + *pixel++ = color.r; + *pixel++ = color.g; + *pixel++ = color.b; + *pixel++ = color.a; +} + + +//////////////////////////////////////////////////////////// +Color Image::getPixel(unsigned int x, unsigned int y) const +{ + const Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4]; + return Color(pixel[0], pixel[1], pixel[2], pixel[3]); +} + + +//////////////////////////////////////////////////////////// +const Uint8* Image::getPixelsPtr() const +{ + if (!m_pixels.empty()) + { + return &m_pixels[0]; + } + else + { + err() << "Trying to access the pixels of an empty image" << std::endl; + return NULL; + } +} + + +//////////////////////////////////////////////////////////// +void Image::flipHorizontally() +{ + if (!m_pixels.empty()) + { + std::size_t rowSize = m_size.x * 4; + + for (std::size_t y = 0; y < m_size.y; ++y) + { + std::vector::iterator left = m_pixels.begin() + y * rowSize; + std::vector::iterator right = m_pixels.begin() + (y + 1) * rowSize - 4; + + for (std::size_t x = 0; x < m_size.x / 2; ++x) + { + std::swap_ranges(left, left + 4, right); + + left += 4; + right -= 4; + } + } + } +} + + +//////////////////////////////////////////////////////////// +void Image::flipVertically() +{ + if (!m_pixels.empty()) + { + std::size_t rowSize = m_size.x * 4; + + std::vector::iterator top = m_pixels.begin(); + std::vector::iterator bottom = m_pixels.end() - rowSize; + + for (std::size_t y = 0; y < m_size.y / 2; ++y) + { + std::swap_ranges(top, top + rowSize, bottom); + + top += rowSize; + bottom -= rowSize; + } + } +} + +} // namespace sf diff --git a/src/SFML/Graphics/ImageLoader.cpp b/src/SFML/Graphics/ImageLoader.cpp index c9e5cb5b..de9b0922 100644 --- a/src/SFML/Graphics/ImageLoader.cpp +++ b/src/SFML/Graphics/ImageLoader.cpp @@ -1,321 +1,321 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#define STB_IMAGE_WRITE_IMPLEMENTATION -#include -extern "C" -{ - #include - #include -} -#include - - -namespace -{ - // Convert a string to lower case - std::string toLower(std::string str) - { - for (std::string::iterator i = str.begin(); i != str.end(); ++i) - *i = static_cast(std::tolower(*i)); - return str; - } - - // stb_image callbacks that operate on a sf::InputStream - int read(void* user, char* data, int size) - { - sf::InputStream* stream = static_cast(user); - return static_cast(stream->read(data, size)); - } - void skip(void* user, unsigned int size) - { - sf::InputStream* stream = static_cast(user); - stream->seek(stream->tell() + size); - } - int eof(void* user) - { - sf::InputStream* stream = static_cast(user); - return stream->tell() >= stream->getSize(); - } -} - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -ImageLoader& ImageLoader::getInstance() -{ - static ImageLoader Instance; - - return Instance; -} - - -//////////////////////////////////////////////////////////// -ImageLoader::ImageLoader() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -ImageLoader::~ImageLoader() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -bool ImageLoader::loadImageFromFile(const std::string& filename, std::vector& pixels, Vector2u& size) -{ - // Clear the array (just in case) - pixels.clear(); - - // Load the image and get a pointer to the pixels in memory - int width, height, channels; - unsigned char* ptr = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha); - - if (ptr && width && height) - { - // Assign the image properties - size.x = width; - size.y = height; - - // Copy the loaded pixels to the pixel buffer - pixels.resize(width * height * 4); - memcpy(&pixels[0], ptr, pixels.size()); - - // Free the loaded pixels (they are now in our own pixel buffer) - stbi_image_free(ptr); - - return true; - } - else - { - // Error, failed to load the image - err() << "Failed to load image \"" << filename << "\". Reason : " << stbi_failure_reason() << std::endl; - - return false; - } -} - - -//////////////////////////////////////////////////////////// -bool ImageLoader::loadImageFromMemory(const void* data, std::size_t dataSize, std::vector& pixels, Vector2u& size) -{ - // Check input parameters - if (data && dataSize) - { - // Clear the array (just in case) - pixels.clear(); - - // Load the image and get a pointer to the pixels in memory - int width, height, channels; - const unsigned char* buffer = static_cast(data); - unsigned char* ptr = stbi_load_from_memory(buffer, static_cast(dataSize), &width, &height, &channels, STBI_rgb_alpha); - - if (ptr && width && height) - { - // Assign the image properties - size.x = width; - size.y = height; - - // Copy the loaded pixels to the pixel buffer - pixels.resize(width * height * 4); - memcpy(&pixels[0], ptr, pixels.size()); - - // Free the loaded pixels (they are now in our own pixel buffer) - stbi_image_free(ptr); - - return true; - } - else - { - // Error, failed to load the image - err() << "Failed to load image from memory. Reason : " << stbi_failure_reason() << std::endl; - - return false; - } - } - else - { - err() << "Failed to load image from memory, no data provided" << std::endl; - return false; - } -} - - -//////////////////////////////////////////////////////////// -bool ImageLoader::loadImageFromStream(InputStream& stream, std::vector& pixels, Vector2u& size) -{ - // Clear the array (just in case) - pixels.clear(); - - // Make sure that the stream's reading position is at the beginning - stream.seek(0); - - // Setup the stb_image callbacks - stbi_io_callbacks callbacks; - callbacks.read = &read; - callbacks.skip = &skip; - callbacks.eof = &eof; - - // Load the image and get a pointer to the pixels in memory - int width, height, channels; - unsigned char* ptr = stbi_load_from_callbacks(&callbacks, &stream, &width, &height, &channels, STBI_rgb_alpha); - - if (ptr && width && height) - { - // Assign the image properties - size.x = width; - size.y = height; - - // Copy the loaded pixels to the pixel buffer - pixels.resize(width * height * 4); - memcpy(&pixels[0], ptr, pixels.size()); - - // Free the loaded pixels (they are now in our own pixel buffer) - stbi_image_free(ptr); - - return true; - } - else - { - // Error, failed to load the image - err() << "Failed to load image from stream. Reason : " << stbi_failure_reason() << std::endl; - - return false; - } -} - - -//////////////////////////////////////////////////////////// -bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector& pixels, const Vector2u& size) -{ - // Make sure the image is not empty - if (!pixels.empty() && (size.x > 0) && (size.y > 0)) - { - // Deduce the image type from its extension - if (filename.size() > 3) - { - // Extract the extension - std::string extension = toLower(filename.substr(filename.size() - 3)); - - if (extension == "bmp") - { - // BMP format - if (stbi_write_bmp(filename.c_str(), size.x, size.y, 4, &pixels[0])) - return true; - } - else if (extension == "tga") - { - // TGA format - if (stbi_write_tga(filename.c_str(), size.x, size.y, 4, &pixels[0])) - return true; - } - else if (extension == "png") - { - // PNG format - if (stbi_write_png(filename.c_str(), size.x, size.y, 4, &pixels[0], 0)) - return true; - } - else if (extension == "jpg") - { - // JPG format - if (writeJpg(filename, pixels, size.x, size.y)) - return true; - } - } - } - - err() << "Failed to save image \"" << filename << "\"" << std::endl; - return false; -} - - -//////////////////////////////////////////////////////////// -bool ImageLoader::writeJpg(const std::string& filename, const std::vector& pixels, unsigned int width, unsigned int height) -{ - // Open the file to write in - FILE* file = fopen(filename.c_str(), "wb"); - if (!file) - return false; - - // Initialize the error handler - jpeg_compress_struct compressInfos; - jpeg_error_mgr errorManager; - compressInfos.err = jpeg_std_error(&errorManager); - - // Initialize all the writing and compression infos - jpeg_create_compress(&compressInfos); - compressInfos.image_width = width; - compressInfos.image_height = height; - compressInfos.input_components = 3; - compressInfos.in_color_space = JCS_RGB; - jpeg_stdio_dest(&compressInfos, file); - jpeg_set_defaults(&compressInfos); - jpeg_set_quality(&compressInfos, 90, TRUE); - - // Get rid of the aplha channel - std::vector buffer(width * height * 3); - for (std::size_t i = 0; i < width * height; ++i) - { - buffer[i * 3 + 0] = pixels[i * 4 + 0]; - buffer[i * 3 + 1] = pixels[i * 4 + 1]; - buffer[i * 3 + 2] = pixels[i * 4 + 2]; - } - Uint8* ptr = &buffer[0]; - - // Start compression - jpeg_start_compress(&compressInfos, TRUE); - - // Write each row of the image - while (compressInfos.next_scanline < compressInfos.image_height) - { - JSAMPROW rawPointer = ptr + (compressInfos.next_scanline * width * 3); - jpeg_write_scanlines(&compressInfos, &rawPointer, 1); - } - - // Finish compression - jpeg_finish_compress(&compressInfos); - jpeg_destroy_compress(&compressInfos); - - // Close the file - fclose(file); - - return true; -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include +extern "C" +{ + #include + #include +} +#include + + +namespace +{ + // Convert a string to lower case + std::string toLower(std::string str) + { + for (std::string::iterator i = str.begin(); i != str.end(); ++i) + *i = static_cast(std::tolower(*i)); + return str; + } + + // stb_image callbacks that operate on a sf::InputStream + int read(void* user, char* data, int size) + { + sf::InputStream* stream = static_cast(user); + return static_cast(stream->read(data, size)); + } + void skip(void* user, unsigned int size) + { + sf::InputStream* stream = static_cast(user); + stream->seek(stream->tell() + size); + } + int eof(void* user) + { + sf::InputStream* stream = static_cast(user); + return stream->tell() >= stream->getSize(); + } +} + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +ImageLoader& ImageLoader::getInstance() +{ + static ImageLoader Instance; + + return Instance; +} + + +//////////////////////////////////////////////////////////// +ImageLoader::ImageLoader() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +ImageLoader::~ImageLoader() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +bool ImageLoader::loadImageFromFile(const std::string& filename, std::vector& pixels, Vector2u& size) +{ + // Clear the array (just in case) + pixels.clear(); + + // Load the image and get a pointer to the pixels in memory + int width, height, channels; + unsigned char* ptr = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha); + + if (ptr && width && height) + { + // Assign the image properties + size.x = width; + size.y = height; + + // Copy the loaded pixels to the pixel buffer + pixels.resize(width * height * 4); + memcpy(&pixels[0], ptr, pixels.size()); + + // Free the loaded pixels (they are now in our own pixel buffer) + stbi_image_free(ptr); + + return true; + } + else + { + // Error, failed to load the image + err() << "Failed to load image \"" << filename << "\". Reason: " << stbi_failure_reason() << std::endl; + + return false; + } +} + + +//////////////////////////////////////////////////////////// +bool ImageLoader::loadImageFromMemory(const void* data, std::size_t dataSize, std::vector& pixels, Vector2u& size) +{ + // Check input parameters + if (data && dataSize) + { + // Clear the array (just in case) + pixels.clear(); + + // Load the image and get a pointer to the pixels in memory + int width, height, channels; + const unsigned char* buffer = static_cast(data); + unsigned char* ptr = stbi_load_from_memory(buffer, static_cast(dataSize), &width, &height, &channels, STBI_rgb_alpha); + + if (ptr && width && height) + { + // Assign the image properties + size.x = width; + size.y = height; + + // Copy the loaded pixels to the pixel buffer + pixels.resize(width * height * 4); + memcpy(&pixels[0], ptr, pixels.size()); + + // Free the loaded pixels (they are now in our own pixel buffer) + stbi_image_free(ptr); + + return true; + } + else + { + // Error, failed to load the image + err() << "Failed to load image from memory. Reason: " << stbi_failure_reason() << std::endl; + + return false; + } + } + else + { + err() << "Failed to load image from memory, no data provided" << std::endl; + return false; + } +} + + +//////////////////////////////////////////////////////////// +bool ImageLoader::loadImageFromStream(InputStream& stream, std::vector& pixels, Vector2u& size) +{ + // Clear the array (just in case) + pixels.clear(); + + // Make sure that the stream's reading position is at the beginning + stream.seek(0); + + // Setup the stb_image callbacks + stbi_io_callbacks callbacks; + callbacks.read = &read; + callbacks.skip = &skip; + callbacks.eof = &eof; + + // Load the image and get a pointer to the pixels in memory + int width, height, channels; + unsigned char* ptr = stbi_load_from_callbacks(&callbacks, &stream, &width, &height, &channels, STBI_rgb_alpha); + + if (ptr && width && height) + { + // Assign the image properties + size.x = width; + size.y = height; + + // Copy the loaded pixels to the pixel buffer + pixels.resize(width * height * 4); + memcpy(&pixels[0], ptr, pixels.size()); + + // Free the loaded pixels (they are now in our own pixel buffer) + stbi_image_free(ptr); + + return true; + } + else + { + // Error, failed to load the image + err() << "Failed to load image from stream. Reason: " << stbi_failure_reason() << std::endl; + + return false; + } +} + + +//////////////////////////////////////////////////////////// +bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector& pixels, const Vector2u& size) +{ + // Make sure the image is not empty + if (!pixels.empty() && (size.x > 0) && (size.y > 0)) + { + // Deduce the image type from its extension + if (filename.size() > 3) + { + // Extract the extension + std::string extension = toLower(filename.substr(filename.size() - 3)); + + if (extension == "bmp") + { + // BMP format + if (stbi_write_bmp(filename.c_str(), size.x, size.y, 4, &pixels[0])) + return true; + } + else if (extension == "tga") + { + // TGA format + if (stbi_write_tga(filename.c_str(), size.x, size.y, 4, &pixels[0])) + return true; + } + else if (extension == "png") + { + // PNG format + if (stbi_write_png(filename.c_str(), size.x, size.y, 4, &pixels[0], 0)) + return true; + } + else if (extension == "jpg") + { + // JPG format + if (writeJpg(filename, pixels, size.x, size.y)) + return true; + } + } + } + + err() << "Failed to save image \"" << filename << "\"" << std::endl; + return false; +} + + +//////////////////////////////////////////////////////////// +bool ImageLoader::writeJpg(const std::string& filename, const std::vector& pixels, unsigned int width, unsigned int height) +{ + // Open the file to write in + FILE* file = fopen(filename.c_str(), "wb"); + if (!file) + return false; + + // Initialize the error handler + jpeg_compress_struct compressInfos; + jpeg_error_mgr errorManager; + compressInfos.err = jpeg_std_error(&errorManager); + + // Initialize all the writing and compression infos + jpeg_create_compress(&compressInfos); + compressInfos.image_width = width; + compressInfos.image_height = height; + compressInfos.input_components = 3; + compressInfos.in_color_space = JCS_RGB; + jpeg_stdio_dest(&compressInfos, file); + jpeg_set_defaults(&compressInfos); + jpeg_set_quality(&compressInfos, 90, TRUE); + + // Get rid of the aplha channel + std::vector buffer(width * height * 3); + for (std::size_t i = 0; i < width * height; ++i) + { + buffer[i * 3 + 0] = pixels[i * 4 + 0]; + buffer[i * 3 + 1] = pixels[i * 4 + 1]; + buffer[i * 3 + 2] = pixels[i * 4 + 2]; + } + Uint8* ptr = &buffer[0]; + + // Start compression + jpeg_start_compress(&compressInfos, TRUE); + + // Write each row of the image + while (compressInfos.next_scanline < compressInfos.image_height) + { + JSAMPROW rawPointer = ptr + (compressInfos.next_scanline * width * 3); + jpeg_write_scanlines(&compressInfos, &rawPointer, 1); + } + + // Finish compression + jpeg_finish_compress(&compressInfos); + jpeg_destroy_compress(&compressInfos); + + // Close the file + fclose(file); + + return true; +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/ImageLoader.hpp b/src/SFML/Graphics/ImageLoader.hpp index 24eba307..8d1b71d0 100644 --- a/src/SFML/Graphics/ImageLoader.hpp +++ b/src/SFML/Graphics/ImageLoader.hpp @@ -1,141 +1,141 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_IMAGELOADER_HPP -#define SFML_IMAGELOADER_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -class InputStream; - -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Load/save image files -/// -//////////////////////////////////////////////////////////// -class ImageLoader : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Get the unique instance of the class - /// - /// \return Reference to the ImageLoader instance - /// - //////////////////////////////////////////////////////////// - static ImageLoader& getInstance(); - - //////////////////////////////////////////////////////////// - /// \brief Load an image from a file on disk - /// - /// \param filename Path of image file to load - /// \param pixels Array of pixels to fill with loaded image - /// \param size Size of loaded image, in pixels - /// - /// \return True if loading was successful - /// - //////////////////////////////////////////////////////////// - bool loadImageFromFile(const std::string& filename, std::vector& pixels, Vector2u& size); - - //////////////////////////////////////////////////////////// - /// \brief Load an image from a file in memory - /// - /// \param data Pointer to the file data in memory - /// \param dataSize Size of the data to load, in bytes - /// \param pixels Array of pixels to fill with loaded image - /// \param size Size of loaded image, in pixels - /// - /// \return True if loading was successful - /// - //////////////////////////////////////////////////////////// - bool loadImageFromMemory(const void* data, std::size_t dataSize, std::vector& pixels, Vector2u& size); - - //////////////////////////////////////////////////////////// - /// \brief Load an image from a custom stream - /// - /// \param stream Source stream to read from - /// \param pixels Array of pixels to fill with loaded image - /// \param size Size of loaded image, in pixels - /// - /// \return True if loading was successful - /// - //////////////////////////////////////////////////////////// - bool loadImageFromStream(InputStream& stream, std::vector& pixels, Vector2u& size); - - //////////////////////////////////////////////////////////// - /// \brief Save an array of pixels as an image file - /// - /// \param filename Path of image file to save - /// \param pixels Array of pixels to save to image - /// \param size Size of image to save, in pixels - /// - /// \return True if saving was successful - /// - //////////////////////////////////////////////////////////// - bool saveImageToFile(const std::string& filename, const std::vector& pixels, const Vector2u& size); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - ImageLoader(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~ImageLoader(); - - //////////////////////////////////////////////////////////// - /// \brief Save an image file in JPEG format - /// - /// \param filename Path of image file to save - /// \param pixels Array of pixels to save to image - /// \param width Width of image to save, in pixels - /// \param height Height of image to save, in pixels - /// - /// \return True if saving was successful - /// - //////////////////////////////////////////////////////////// - bool writeJpg(const std::string& filename, const std::vector& pixels, unsigned int width, unsigned int height); -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_IMAGELOADER_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_IMAGELOADER_HPP +#define SFML_IMAGELOADER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +class InputStream; + +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Load/save image files +/// +//////////////////////////////////////////////////////////// +class ImageLoader : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Get the unique instance of the class + /// + /// \return Reference to the ImageLoader instance + /// + //////////////////////////////////////////////////////////// + static ImageLoader& getInstance(); + + //////////////////////////////////////////////////////////// + /// \brief Load an image from a file on disk + /// + /// \param filename Path of image file to load + /// \param pixels Array of pixels to fill with loaded image + /// \param size Size of loaded image, in pixels + /// + /// \return True if loading was successful + /// + //////////////////////////////////////////////////////////// + bool loadImageFromFile(const std::string& filename, std::vector& pixels, Vector2u& size); + + //////////////////////////////////////////////////////////// + /// \brief Load an image from a file in memory + /// + /// \param data Pointer to the file data in memory + /// \param dataSize Size of the data to load, in bytes + /// \param pixels Array of pixels to fill with loaded image + /// \param size Size of loaded image, in pixels + /// + /// \return True if loading was successful + /// + //////////////////////////////////////////////////////////// + bool loadImageFromMemory(const void* data, std::size_t dataSize, std::vector& pixels, Vector2u& size); + + //////////////////////////////////////////////////////////// + /// \brief Load an image from a custom stream + /// + /// \param stream Source stream to read from + /// \param pixels Array of pixels to fill with loaded image + /// \param size Size of loaded image, in pixels + /// + /// \return True if loading was successful + /// + //////////////////////////////////////////////////////////// + bool loadImageFromStream(InputStream& stream, std::vector& pixels, Vector2u& size); + + //////////////////////////////////////////////////////////// + /// \brief Save an array of pixels as an image file + /// + /// \param filename Path of image file to save + /// \param pixels Array of pixels to save to image + /// \param size Size of image to save, in pixels + /// + /// \return True if saving was successful + /// + //////////////////////////////////////////////////////////// + bool saveImageToFile(const std::string& filename, const std::vector& pixels, const Vector2u& size); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + ImageLoader(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~ImageLoader(); + + //////////////////////////////////////////////////////////// + /// \brief Save an image file in JPEG format + /// + /// \param filename Path of image file to save + /// \param pixels Array of pixels to save to image + /// \param width Width of image to save, in pixels + /// \param height Height of image to save, in pixels + /// + /// \return True if saving was successful + /// + //////////////////////////////////////////////////////////// + bool writeJpg(const std::string& filename, const std::vector& pixels, unsigned int width, unsigned int height); +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_IMAGELOADER_HPP diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp index a3f03bf6..cfc7ba6b 100644 --- a/src/SFML/Graphics/RenderTarget.cpp +++ b/src/SFML/Graphics/RenderTarget.cpp @@ -1,514 +1,514 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace -{ - // Convert an sf::BlendMode::Factor constant to the corresponding OpenGL constant. - sf::Uint32 factorToGlConstant(sf::BlendMode::Factor blendFactor) - { - switch (blendFactor) - { - default: - case sf::BlendMode::Zero: return GL_ZERO; - case sf::BlendMode::One: return GL_ONE; - case sf::BlendMode::SrcColor: return GL_SRC_COLOR; - case sf::BlendMode::OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR; - case sf::BlendMode::DstColor: return GL_DST_COLOR; - case sf::BlendMode::OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR; - case sf::BlendMode::SrcAlpha: return GL_SRC_ALPHA; - case sf::BlendMode::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA; - case sf::BlendMode::DstAlpha: return GL_DST_ALPHA; - case sf::BlendMode::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA; - } - } - - - // Convert an sf::BlendMode::BlendEquation constant to the corresponding OpenGL constant. - sf::Uint32 equationToGlConstant(sf::BlendMode::Equation blendEquation) - { - switch (blendEquation) - { - default: - case sf::BlendMode::Add: return GLEXT_GL_FUNC_ADD; - case sf::BlendMode::Subtract: return GLEXT_GL_FUNC_SUBTRACT; - } - } -} - - -namespace sf -{ -//////////////////////////////////////////////////////////// -RenderTarget::RenderTarget() : -m_defaultView(), -m_view (), -m_cache () -{ - m_cache.glStatesSet = false; -} - - -//////////////////////////////////////////////////////////// -RenderTarget::~RenderTarget() -{ -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::clear(const Color& color) -{ - if (activate(true)) - { - // Unbind texture to fix RenderTexture preventing clear - applyTexture(NULL); - - glCheck(glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f)); - glCheck(glClear(GL_COLOR_BUFFER_BIT)); - } -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::setView(const View& view) -{ - m_view = view; - m_cache.viewChanged = true; -} - - -//////////////////////////////////////////////////////////// -const View& RenderTarget::getView() const -{ - return m_view; -} - - -//////////////////////////////////////////////////////////// -const View& RenderTarget::getDefaultView() const -{ - return m_defaultView; -} - - -//////////////////////////////////////////////////////////// -IntRect RenderTarget::getViewport(const View& view) const -{ - float width = static_cast(getSize().x); - float height = static_cast(getSize().y); - const FloatRect& viewport = view.getViewport(); - - return IntRect(static_cast(0.5f + width * viewport.left), - static_cast(0.5f + height * viewport.top), - static_cast(0.5f + width * viewport.width), - static_cast(0.5f + height * viewport.height)); -} - - -//////////////////////////////////////////////////////////// -Vector2f RenderTarget::mapPixelToCoords(const Vector2i& point) const -{ - return mapPixelToCoords(point, getView()); -} - - -//////////////////////////////////////////////////////////// -Vector2f RenderTarget::mapPixelToCoords(const Vector2i& point, const View& view) const -{ - // First, convert from viewport coordinates to homogeneous coordinates - Vector2f normalized; - IntRect viewport = getViewport(view); - normalized.x = -1.f + 2.f * (point.x - viewport.left) / viewport.width; - normalized.y = 1.f - 2.f * (point.y - viewport.top) / viewport.height; - - // Then transform by the inverse of the view matrix - return view.getInverseTransform().transformPoint(normalized); -} - - -//////////////////////////////////////////////////////////// -Vector2i RenderTarget::mapCoordsToPixel(const Vector2f& point) const -{ - return mapCoordsToPixel(point, getView()); -} - - -//////////////////////////////////////////////////////////// -Vector2i RenderTarget::mapCoordsToPixel(const Vector2f& point, const View& view) const -{ - // First, transform the point by the view matrix - Vector2f normalized = view.getTransform().transformPoint(point); - - // Then convert to viewport coordinates - Vector2i pixel; - IntRect viewport = getViewport(view); - pixel.x = static_cast(( normalized.x + 1.f) / 2.f * viewport.width + viewport.left); - pixel.y = static_cast((-normalized.y + 1.f) / 2.f * viewport.height + viewport.top); - - return pixel; -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::draw(const Drawable& drawable, const RenderStates& states) -{ - drawable.draw(*this, states); -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::draw(const Vertex* vertices, unsigned int vertexCount, - PrimitiveType type, const RenderStates& states) -{ - // Nothing to draw? - if (!vertices || (vertexCount == 0)) - return; - - // GL_QUADS is unavailable on OpenGL ES - #ifdef SFML_OPENGL_ES - if (type == Quads) - { - err() << "sf::Quads primitive type is not supported on OpenGL ES platforms, drawing skipped" << std::endl; - return; - } - #define GL_QUADS 0 - #endif - - if (activate(true)) - { - // First set the persistent OpenGL states if it's the very first call - if (!m_cache.glStatesSet) - resetGLStates(); - - // Check if the vertex count is low enough so that we can pre-transform them - bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize); - if (useVertexCache) - { - // Pre-transform the vertices and store them into the vertex cache - for (unsigned int i = 0; i < vertexCount; ++i) - { - Vertex& vertex = m_cache.vertexCache[i]; - vertex.position = states.transform * vertices[i].position; - vertex.color = vertices[i].color; - vertex.texCoords = vertices[i].texCoords; - } - - // Since vertices are transformed, we must use an identity transform to render them - if (!m_cache.useVertexCache) - applyTransform(Transform::Identity); - } - else - { - applyTransform(states.transform); - } - - // Apply the view - if (m_cache.viewChanged) - applyCurrentView(); - - // Apply the blend mode - if (states.blendMode != m_cache.lastBlendMode) - applyBlendMode(states.blendMode); - - // Apply the texture - Uint64 textureId = states.texture ? states.texture->m_cacheId : 0; - if (textureId != m_cache.lastTextureId) - applyTexture(states.texture); - - // Apply the shader - if (states.shader) - applyShader(states.shader); - - // If we pre-transform the vertices, we must use our internal vertex cache - if (useVertexCache) - { - // ... and if we already used it previously, we don't need to set the pointers again - if (!m_cache.useVertexCache) - vertices = m_cache.vertexCache; - else - vertices = NULL; - } - - // Setup the pointers to the vertices' components - if (vertices) - { - const char* data = reinterpret_cast(vertices); - glCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), data + 0)); - glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 8)); - glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 12)); - } - - // Find the OpenGL primitive type - static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, - GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS}; - GLenum mode = modes[type]; - - // Draw the primitives - glCheck(glDrawArrays(mode, 0, vertexCount)); - - // Unbind the shader, if any - if (states.shader) - applyShader(NULL); - - // Update the cache - m_cache.useVertexCache = useVertexCache; - } -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::pushGLStates() -{ - if (activate(true)) - { - #ifdef SFML_DEBUG - // make sure that the user didn't leave an unchecked OpenGL error - GLenum error = glGetError(); - if (error != GL_NO_ERROR) - { - err() << "OpenGL error (" << error << ") detected in user code, " - << "you should check for errors with glGetError()" - << std::endl; - } - #endif - - #ifndef SFML_OPENGL_ES - glCheck(glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)); - glCheck(glPushAttrib(GL_ALL_ATTRIB_BITS)); - #endif - glCheck(glMatrixMode(GL_MODELVIEW)); - glCheck(glPushMatrix()); - glCheck(glMatrixMode(GL_PROJECTION)); - glCheck(glPushMatrix()); - glCheck(glMatrixMode(GL_TEXTURE)); - glCheck(glPushMatrix()); - } - - resetGLStates(); -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::popGLStates() -{ - if (activate(true)) - { - glCheck(glMatrixMode(GL_PROJECTION)); - glCheck(glPopMatrix()); - glCheck(glMatrixMode(GL_MODELVIEW)); - glCheck(glPopMatrix()); - glCheck(glMatrixMode(GL_TEXTURE)); - glCheck(glPopMatrix()); - #ifndef SFML_OPENGL_ES - glCheck(glPopClientAttrib()); - glCheck(glPopAttrib()); - #endif - } -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::resetGLStates() -{ - // Check here to make sure a context change does not happen after activate(true) - bool shaderAvailable = Shader::isAvailable(); - - if (activate(true)) - { - // Make sure that extensions are initialized - priv::ensureExtensionsInit(); - - // Make sure that the texture unit which is active is the number 0 - if (GLEXT_multitexture) - { - glCheck(GLEXT_glClientActiveTexture(GLEXT_GL_TEXTURE0)); - glCheck(GLEXT_glActiveTexture(GLEXT_GL_TEXTURE0)); - } - - // Define the default OpenGL states - glCheck(glDisable(GL_CULL_FACE)); - glCheck(glDisable(GL_LIGHTING)); - glCheck(glDisable(GL_DEPTH_TEST)); - glCheck(glDisable(GL_ALPHA_TEST)); - glCheck(glEnable(GL_TEXTURE_2D)); - glCheck(glEnable(GL_BLEND)); - glCheck(glMatrixMode(GL_MODELVIEW)); - glCheck(glEnableClientState(GL_VERTEX_ARRAY)); - glCheck(glEnableClientState(GL_COLOR_ARRAY)); - glCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); - m_cache.glStatesSet = true; - - // Apply the default SFML states - applyBlendMode(BlendAlpha); - applyTransform(Transform::Identity); - applyTexture(NULL); - if (shaderAvailable) - applyShader(NULL); - - m_cache.useVertexCache = false; - - // Set the default view - setView(getView()); - } -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::initialize() -{ - // Setup the default and current views - m_defaultView.reset(FloatRect(0, 0, static_cast(getSize().x), static_cast(getSize().y))); - m_view = m_defaultView; - - // Set GL states only on first draw, so that we don't pollute user's states - m_cache.glStatesSet = false; -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::applyCurrentView() -{ - // Set the viewport - IntRect viewport = getViewport(m_view); - int top = getSize().y - (viewport.top + viewport.height); - glCheck(glViewport(viewport.left, top, viewport.width, viewport.height)); - - // Set the projection matrix - glCheck(glMatrixMode(GL_PROJECTION)); - glCheck(glLoadMatrixf(m_view.getTransform().getMatrix())); - - // Go back to model-view mode - glCheck(glMatrixMode(GL_MODELVIEW)); - - m_cache.viewChanged = false; -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::applyBlendMode(const BlendMode& mode) -{ - // Apply the blend mode, falling back to the non-separate versions if necessary - if (GLEXT_blend_func_separate) - { - glCheck(GLEXT_glBlendFuncSeparate( - factorToGlConstant(mode.colorSrcFactor), factorToGlConstant(mode.colorDstFactor), - factorToGlConstant(mode.alphaSrcFactor), factorToGlConstant(mode.alphaDstFactor))); - } - else - { - glCheck(glBlendFunc( - factorToGlConstant(mode.colorSrcFactor), - factorToGlConstant(mode.colorDstFactor))); - } - - if (GLEXT_blend_equation_separate) - { - glCheck(GLEXT_glBlendEquationSeparate( - equationToGlConstant(mode.colorEquation), - equationToGlConstant(mode.alphaEquation))); - } - else - { - glCheck(GLEXT_glBlendEquation(equationToGlConstant(mode.colorEquation))); - } - - m_cache.lastBlendMode = mode; -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::applyTransform(const Transform& transform) -{ - // No need to call glMatrixMode(GL_MODELVIEW), it is always the - // current mode (for optimization purpose, since it's the most used) - glCheck(glLoadMatrixf(transform.getMatrix())); -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::applyTexture(const Texture* texture) -{ - Texture::bind(texture, Texture::Pixels); - - m_cache.lastTextureId = texture ? texture->m_cacheId : 0; -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::applyShader(const Shader* shader) -{ - Shader::bind(shader); -} - -} // namespace sf - - -//////////////////////////////////////////////////////////// -// Render states caching strategies -// -// * View -// If SetView was called since last draw, the projection -// matrix is updated. We don't need more, the view doesn't -// change frequently. -// -// * Transform -// The transform matrix is usually expensive because each -// entity will most likely use a different transform. This can -// lead, in worst case, to changing it every 4 vertices. -// To avoid that, when the vertex count is low enough, we -// pre-transform them and therefore use an identity transform -// to render them. -// -// * Blending mode -// Since it overloads the == operator, we can easily check -// whether any of the 6 blending components changed and, -// thus, whether we need to update the blend mode. -// -// * Texture -// Storing the pointer or OpenGL ID of the last used texture -// is not enough; if the sf::Texture instance is destroyed, -// both the pointer and the OpenGL ID might be recycled in -// a new texture instance. We need to use our own unique -// identifier system to ensure consistent caching. -// -// * Shader -// Shaders are very hard to optimize, because they have -// parameters that can be hard (if not impossible) to track, -// like matrices or textures. The only optimization that we -// do is that we avoid setting a null shader if there was -// already none for the previous draw. -// -//////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace +{ + // Convert an sf::BlendMode::Factor constant to the corresponding OpenGL constant. + sf::Uint32 factorToGlConstant(sf::BlendMode::Factor blendFactor) + { + switch (blendFactor) + { + default: + case sf::BlendMode::Zero: return GL_ZERO; + case sf::BlendMode::One: return GL_ONE; + case sf::BlendMode::SrcColor: return GL_SRC_COLOR; + case sf::BlendMode::OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR; + case sf::BlendMode::DstColor: return GL_DST_COLOR; + case sf::BlendMode::OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR; + case sf::BlendMode::SrcAlpha: return GL_SRC_ALPHA; + case sf::BlendMode::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA; + case sf::BlendMode::DstAlpha: return GL_DST_ALPHA; + case sf::BlendMode::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA; + } + } + + + // Convert an sf::BlendMode::BlendEquation constant to the corresponding OpenGL constant. + sf::Uint32 equationToGlConstant(sf::BlendMode::Equation blendEquation) + { + switch (blendEquation) + { + default: + case sf::BlendMode::Add: return GLEXT_GL_FUNC_ADD; + case sf::BlendMode::Subtract: return GLEXT_GL_FUNC_SUBTRACT; + } + } +} + + +namespace sf +{ +//////////////////////////////////////////////////////////// +RenderTarget::RenderTarget() : +m_defaultView(), +m_view (), +m_cache () +{ + m_cache.glStatesSet = false; +} + + +//////////////////////////////////////////////////////////// +RenderTarget::~RenderTarget() +{ +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::clear(const Color& color) +{ + if (activate(true)) + { + // Unbind texture to fix RenderTexture preventing clear + applyTexture(NULL); + + glCheck(glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f)); + glCheck(glClear(GL_COLOR_BUFFER_BIT)); + } +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::setView(const View& view) +{ + m_view = view; + m_cache.viewChanged = true; +} + + +//////////////////////////////////////////////////////////// +const View& RenderTarget::getView() const +{ + return m_view; +} + + +//////////////////////////////////////////////////////////// +const View& RenderTarget::getDefaultView() const +{ + return m_defaultView; +} + + +//////////////////////////////////////////////////////////// +IntRect RenderTarget::getViewport(const View& view) const +{ + float width = static_cast(getSize().x); + float height = static_cast(getSize().y); + const FloatRect& viewport = view.getViewport(); + + return IntRect(static_cast(0.5f + width * viewport.left), + static_cast(0.5f + height * viewport.top), + static_cast(0.5f + width * viewport.width), + static_cast(0.5f + height * viewport.height)); +} + + +//////////////////////////////////////////////////////////// +Vector2f RenderTarget::mapPixelToCoords(const Vector2i& point) const +{ + return mapPixelToCoords(point, getView()); +} + + +//////////////////////////////////////////////////////////// +Vector2f RenderTarget::mapPixelToCoords(const Vector2i& point, const View& view) const +{ + // First, convert from viewport coordinates to homogeneous coordinates + Vector2f normalized; + IntRect viewport = getViewport(view); + normalized.x = -1.f + 2.f * (point.x - viewport.left) / viewport.width; + normalized.y = 1.f - 2.f * (point.y - viewport.top) / viewport.height; + + // Then transform by the inverse of the view matrix + return view.getInverseTransform().transformPoint(normalized); +} + + +//////////////////////////////////////////////////////////// +Vector2i RenderTarget::mapCoordsToPixel(const Vector2f& point) const +{ + return mapCoordsToPixel(point, getView()); +} + + +//////////////////////////////////////////////////////////// +Vector2i RenderTarget::mapCoordsToPixel(const Vector2f& point, const View& view) const +{ + // First, transform the point by the view matrix + Vector2f normalized = view.getTransform().transformPoint(point); + + // Then convert to viewport coordinates + Vector2i pixel; + IntRect viewport = getViewport(view); + pixel.x = static_cast(( normalized.x + 1.f) / 2.f * viewport.width + viewport.left); + pixel.y = static_cast((-normalized.y + 1.f) / 2.f * viewport.height + viewport.top); + + return pixel; +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::draw(const Drawable& drawable, const RenderStates& states) +{ + drawable.draw(*this, states); +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::draw(const Vertex* vertices, unsigned int vertexCount, + PrimitiveType type, const RenderStates& states) +{ + // Nothing to draw? + if (!vertices || (vertexCount == 0)) + return; + + // GL_QUADS is unavailable on OpenGL ES + #ifdef SFML_OPENGL_ES + if (type == Quads) + { + err() << "sf::Quads primitive type is not supported on OpenGL ES platforms, drawing skipped" << std::endl; + return; + } + #define GL_QUADS 0 + #endif + + if (activate(true)) + { + // First set the persistent OpenGL states if it's the very first call + if (!m_cache.glStatesSet) + resetGLStates(); + + // Check if the vertex count is low enough so that we can pre-transform them + bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize); + if (useVertexCache) + { + // Pre-transform the vertices and store them into the vertex cache + for (unsigned int i = 0; i < vertexCount; ++i) + { + Vertex& vertex = m_cache.vertexCache[i]; + vertex.position = states.transform * vertices[i].position; + vertex.color = vertices[i].color; + vertex.texCoords = vertices[i].texCoords; + } + + // Since vertices are transformed, we must use an identity transform to render them + if (!m_cache.useVertexCache) + applyTransform(Transform::Identity); + } + else + { + applyTransform(states.transform); + } + + // Apply the view + if (m_cache.viewChanged) + applyCurrentView(); + + // Apply the blend mode + if (states.blendMode != m_cache.lastBlendMode) + applyBlendMode(states.blendMode); + + // Apply the texture + Uint64 textureId = states.texture ? states.texture->m_cacheId : 0; + if (textureId != m_cache.lastTextureId) + applyTexture(states.texture); + + // Apply the shader + if (states.shader) + applyShader(states.shader); + + // If we pre-transform the vertices, we must use our internal vertex cache + if (useVertexCache) + { + // ... and if we already used it previously, we don't need to set the pointers again + if (!m_cache.useVertexCache) + vertices = m_cache.vertexCache; + else + vertices = NULL; + } + + // Setup the pointers to the vertices' components + if (vertices) + { + const char* data = reinterpret_cast(vertices); + glCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), data + 0)); + glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 8)); + glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 12)); + } + + // Find the OpenGL primitive type + static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, + GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS}; + GLenum mode = modes[type]; + + // Draw the primitives + glCheck(glDrawArrays(mode, 0, vertexCount)); + + // Unbind the shader, if any + if (states.shader) + applyShader(NULL); + + // Update the cache + m_cache.useVertexCache = useVertexCache; + } +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::pushGLStates() +{ + if (activate(true)) + { + #ifdef SFML_DEBUG + // make sure that the user didn't leave an unchecked OpenGL error + GLenum error = glGetError(); + if (error != GL_NO_ERROR) + { + err() << "OpenGL error (" << error << ") detected in user code, " + << "you should check for errors with glGetError()" + << std::endl; + } + #endif + + #ifndef SFML_OPENGL_ES + glCheck(glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)); + glCheck(glPushAttrib(GL_ALL_ATTRIB_BITS)); + #endif + glCheck(glMatrixMode(GL_MODELVIEW)); + glCheck(glPushMatrix()); + glCheck(glMatrixMode(GL_PROJECTION)); + glCheck(glPushMatrix()); + glCheck(glMatrixMode(GL_TEXTURE)); + glCheck(glPushMatrix()); + } + + resetGLStates(); +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::popGLStates() +{ + if (activate(true)) + { + glCheck(glMatrixMode(GL_PROJECTION)); + glCheck(glPopMatrix()); + glCheck(glMatrixMode(GL_MODELVIEW)); + glCheck(glPopMatrix()); + glCheck(glMatrixMode(GL_TEXTURE)); + glCheck(glPopMatrix()); + #ifndef SFML_OPENGL_ES + glCheck(glPopClientAttrib()); + glCheck(glPopAttrib()); + #endif + } +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::resetGLStates() +{ + // Check here to make sure a context change does not happen after activate(true) + bool shaderAvailable = Shader::isAvailable(); + + if (activate(true)) + { + // Make sure that extensions are initialized + priv::ensureExtensionsInit(); + + // Make sure that the texture unit which is active is the number 0 + if (GLEXT_multitexture) + { + glCheck(GLEXT_glClientActiveTexture(GLEXT_GL_TEXTURE0)); + glCheck(GLEXT_glActiveTexture(GLEXT_GL_TEXTURE0)); + } + + // Define the default OpenGL states + glCheck(glDisable(GL_CULL_FACE)); + glCheck(glDisable(GL_LIGHTING)); + glCheck(glDisable(GL_DEPTH_TEST)); + glCheck(glDisable(GL_ALPHA_TEST)); + glCheck(glEnable(GL_TEXTURE_2D)); + glCheck(glEnable(GL_BLEND)); + glCheck(glMatrixMode(GL_MODELVIEW)); + glCheck(glEnableClientState(GL_VERTEX_ARRAY)); + glCheck(glEnableClientState(GL_COLOR_ARRAY)); + glCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + m_cache.glStatesSet = true; + + // Apply the default SFML states + applyBlendMode(BlendAlpha); + applyTransform(Transform::Identity); + applyTexture(NULL); + if (shaderAvailable) + applyShader(NULL); + + m_cache.useVertexCache = false; + + // Set the default view + setView(getView()); + } +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::initialize() +{ + // Setup the default and current views + m_defaultView.reset(FloatRect(0, 0, static_cast(getSize().x), static_cast(getSize().y))); + m_view = m_defaultView; + + // Set GL states only on first draw, so that we don't pollute user's states + m_cache.glStatesSet = false; +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::applyCurrentView() +{ + // Set the viewport + IntRect viewport = getViewport(m_view); + int top = getSize().y - (viewport.top + viewport.height); + glCheck(glViewport(viewport.left, top, viewport.width, viewport.height)); + + // Set the projection matrix + glCheck(glMatrixMode(GL_PROJECTION)); + glCheck(glLoadMatrixf(m_view.getTransform().getMatrix())); + + // Go back to model-view mode + glCheck(glMatrixMode(GL_MODELVIEW)); + + m_cache.viewChanged = false; +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::applyBlendMode(const BlendMode& mode) +{ + // Apply the blend mode, falling back to the non-separate versions if necessary + if (GLEXT_blend_func_separate) + { + glCheck(GLEXT_glBlendFuncSeparate( + factorToGlConstant(mode.colorSrcFactor), factorToGlConstant(mode.colorDstFactor), + factorToGlConstant(mode.alphaSrcFactor), factorToGlConstant(mode.alphaDstFactor))); + } + else + { + glCheck(glBlendFunc( + factorToGlConstant(mode.colorSrcFactor), + factorToGlConstant(mode.colorDstFactor))); + } + + if (GLEXT_blend_equation_separate) + { + glCheck(GLEXT_glBlendEquationSeparate( + equationToGlConstant(mode.colorEquation), + equationToGlConstant(mode.alphaEquation))); + } + else + { + glCheck(GLEXT_glBlendEquation(equationToGlConstant(mode.colorEquation))); + } + + m_cache.lastBlendMode = mode; +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::applyTransform(const Transform& transform) +{ + // No need to call glMatrixMode(GL_MODELVIEW), it is always the + // current mode (for optimization purpose, since it's the most used) + glCheck(glLoadMatrixf(transform.getMatrix())); +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::applyTexture(const Texture* texture) +{ + Texture::bind(texture, Texture::Pixels); + + m_cache.lastTextureId = texture ? texture->m_cacheId : 0; +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::applyShader(const Shader* shader) +{ + Shader::bind(shader); +} + +} // namespace sf + + +//////////////////////////////////////////////////////////// +// Render states caching strategies +// +// * View +// If SetView was called since last draw, the projection +// matrix is updated. We don't need more, the view doesn't +// change frequently. +// +// * Transform +// The transform matrix is usually expensive because each +// entity will most likely use a different transform. This can +// lead, in worst case, to changing it every 4 vertices. +// To avoid that, when the vertex count is low enough, we +// pre-transform them and therefore use an identity transform +// to render them. +// +// * Blending mode +// Since it overloads the == operator, we can easily check +// whether any of the 6 blending components changed and, +// thus, whether we need to update the blend mode. +// +// * Texture +// Storing the pointer or OpenGL ID of the last used texture +// is not enough; if the sf::Texture instance is destroyed, +// both the pointer and the OpenGL ID might be recycled in +// a new texture instance. We need to use our own unique +// identifier system to ensure consistent caching. +// +// * Shader +// Shaders are very hard to optimize, because they have +// parameters that can be hard (if not impossible) to track, +// like matrices or textures. The only optimization that we +// do is that we avoid setting a null shader if there was +// already none for the previous draw. +// +//////////////////////////////////////////////////////////// diff --git a/src/SFML/Graphics/RenderTexture.cpp b/src/SFML/Graphics/RenderTexture.cpp index bdfab84a..e3669e3b 100644 --- a/src/SFML/Graphics/RenderTexture.cpp +++ b/src/SFML/Graphics/RenderTexture.cpp @@ -1,155 +1,155 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -RenderTexture::RenderTexture() : -m_impl(NULL) -{ - -} - - -//////////////////////////////////////////////////////////// -RenderTexture::~RenderTexture() -{ - delete m_impl; -} - - -//////////////////////////////////////////////////////////// -bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBuffer) -{ - // Create the texture - if (!m_texture.create(width, height)) - { - err() << "Impossible to create render texture (failed to create the target texture)" << std::endl; - return false; - } - - // We disable smoothing by default for render textures - setSmooth(false); - - // Create the implementation - delete m_impl; - if (priv::RenderTextureImplFBO::isAvailable()) - { - // Use frame-buffer object (FBO) - m_impl = new priv::RenderTextureImplFBO; - } - else - { - // Use default implementation - m_impl = new priv::RenderTextureImplDefault; - } - - // Initialize the render texture - if (!m_impl->create(width, height, m_texture.m_texture, depthBuffer)) - return false; - - // We can now initialize the render target part - RenderTarget::initialize(); - - return true; -} - - -//////////////////////////////////////////////////////////// -void RenderTexture::setSmooth(bool smooth) -{ - m_texture.setSmooth(smooth); -} - - -//////////////////////////////////////////////////////////// -bool RenderTexture::isSmooth() const -{ - return m_texture.isSmooth(); -} - - -//////////////////////////////////////////////////////////// -void RenderTexture::setRepeated(bool repeated) -{ - m_texture.setRepeated(repeated); -} - - -//////////////////////////////////////////////////////////// -bool RenderTexture::isRepeated() const -{ - return m_texture.isRepeated(); -} - - -//////////////////////////////////////////////////////////// -bool RenderTexture::setActive(bool active) -{ - return m_impl && m_impl->activate(active); -} - - -//////////////////////////////////////////////////////////// -void RenderTexture::display() -{ - // Update the target texture - if (setActive(true)) - { - m_impl->updateTexture(m_texture.m_texture); - m_texture.m_pixelsFlipped = true; - } -} - - -//////////////////////////////////////////////////////////// -Vector2u RenderTexture::getSize() const -{ - return m_texture.getSize(); -} - - -//////////////////////////////////////////////////////////// -const Texture& RenderTexture::getTexture() const -{ - return m_texture; -} - - -//////////////////////////////////////////////////////////// -bool RenderTexture::activate(bool active) -{ - return setActive(active); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +RenderTexture::RenderTexture() : +m_impl(NULL) +{ + +} + + +//////////////////////////////////////////////////////////// +RenderTexture::~RenderTexture() +{ + delete m_impl; +} + + +//////////////////////////////////////////////////////////// +bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBuffer) +{ + // Create the texture + if (!m_texture.create(width, height)) + { + err() << "Impossible to create render texture (failed to create the target texture)" << std::endl; + return false; + } + + // We disable smoothing by default for render textures + setSmooth(false); + + // Create the implementation + delete m_impl; + if (priv::RenderTextureImplFBO::isAvailable()) + { + // Use frame-buffer object (FBO) + m_impl = new priv::RenderTextureImplFBO; + } + else + { + // Use default implementation + m_impl = new priv::RenderTextureImplDefault; + } + + // Initialize the render texture + if (!m_impl->create(width, height, m_texture.m_texture, depthBuffer)) + return false; + + // We can now initialize the render target part + RenderTarget::initialize(); + + return true; +} + + +//////////////////////////////////////////////////////////// +void RenderTexture::setSmooth(bool smooth) +{ + m_texture.setSmooth(smooth); +} + + +//////////////////////////////////////////////////////////// +bool RenderTexture::isSmooth() const +{ + return m_texture.isSmooth(); +} + + +//////////////////////////////////////////////////////////// +void RenderTexture::setRepeated(bool repeated) +{ + m_texture.setRepeated(repeated); +} + + +//////////////////////////////////////////////////////////// +bool RenderTexture::isRepeated() const +{ + return m_texture.isRepeated(); +} + + +//////////////////////////////////////////////////////////// +bool RenderTexture::setActive(bool active) +{ + return m_impl && m_impl->activate(active); +} + + +//////////////////////////////////////////////////////////// +void RenderTexture::display() +{ + // Update the target texture + if (setActive(true)) + { + m_impl->updateTexture(m_texture.m_texture); + m_texture.m_pixelsFlipped = true; + } +} + + +//////////////////////////////////////////////////////////// +Vector2u RenderTexture::getSize() const +{ + return m_texture.getSize(); +} + + +//////////////////////////////////////////////////////////// +const Texture& RenderTexture::getTexture() const +{ + return m_texture; +} + + +//////////////////////////////////////////////////////////// +bool RenderTexture::activate(bool active) +{ + return setActive(active); +} + +} // namespace sf diff --git a/src/SFML/Graphics/RenderTextureImpl.cpp b/src/SFML/Graphics/RenderTextureImpl.cpp index d1b25882..d57c03b2 100644 --- a/src/SFML/Graphics/RenderTextureImpl.cpp +++ b/src/SFML/Graphics/RenderTextureImpl.cpp @@ -1,43 +1,43 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -RenderTextureImpl::~RenderTextureImpl() -{ - // Nothing to do -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +RenderTextureImpl::~RenderTextureImpl() +{ + // Nothing to do +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/RenderTextureImpl.hpp b/src/SFML/Graphics/RenderTextureImpl.hpp index 742f79e7..dec8152d 100644 --- a/src/SFML/Graphics/RenderTextureImpl.hpp +++ b/src/SFML/Graphics/RenderTextureImpl.hpp @@ -1,89 +1,89 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_RENDERTEXTUREIMPL_HPP -#define SFML_RENDERTEXTUREIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Abstract base class for render-texture implementations -/// -//////////////////////////////////////////////////////////// -class RenderTextureImpl : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - virtual ~RenderTextureImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Create the render texture implementation - /// - /// \param width Width of the texture to render to - /// \param height Height of the texture to render to - /// \param textureId OpenGL identifier of the target texture - /// \param depthBuffer Is a depth buffer requested? - /// - /// \return True if creation has been successful - /// - //////////////////////////////////////////////////////////// - virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Activate or deactivate the render texture for rendering - /// - /// \param active True to activate, false to deactivate - /// - /// \return True on success, false on failure - /// - //////////////////////////////////////////////////////////// - virtual bool activate(bool active) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Update the pixels of the target texture - /// - /// \param textureId OpenGL identifier of the target texture - /// - //////////////////////////////////////////////////////////// - virtual void updateTexture(unsigned int textureId) = 0; -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_RENDERTEXTUREIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERTEXTUREIMPL_HPP +#define SFML_RENDERTEXTUREIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Abstract base class for render-texture implementations +/// +//////////////////////////////////////////////////////////// +class RenderTextureImpl : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~RenderTextureImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Create the render texture implementation + /// + /// \param width Width of the texture to render to + /// \param height Height of the texture to render to + /// \param textureId OpenGL identifier of the target texture + /// \param depthBuffer Is a depth buffer requested? + /// + /// \return True if creation has been successful + /// + //////////////////////////////////////////////////////////// + virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Activate or deactivate the render texture for rendering + /// + /// \param active True to activate, false to deactivate + /// + /// \return True on success, false on failure + /// + //////////////////////////////////////////////////////////// + virtual bool activate(bool active) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Update the pixels of the target texture + /// + /// \param textureId OpenGL identifier of the target texture + /// + //////////////////////////////////////////////////////////// + virtual void updateTexture(unsigned int textureId) = 0; +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_RENDERTEXTUREIMPL_HPP diff --git a/src/SFML/Graphics/RenderTextureImplDefault.hpp b/src/SFML/Graphics/RenderTextureImplDefault.hpp index 04c4cbe9..081b72d1 100644 --- a/src/SFML/Graphics/RenderTextureImplDefault.hpp +++ b/src/SFML/Graphics/RenderTextureImplDefault.hpp @@ -44,7 +44,7 @@ namespace priv //////////////////////////////////////////////////////////// class RenderTextureImplDefault : public RenderTextureImpl, GlResource { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -58,7 +58,7 @@ public : //////////////////////////////////////////////////////////// ~RenderTextureImplDefault(); -private : +private: //////////////////////////////////////////////////////////// /// \brief Create the render texture implementation diff --git a/src/SFML/Graphics/RenderTextureImplFBO.cpp b/src/SFML/Graphics/RenderTextureImplFBO.cpp index 2b73fe28..dca02402 100644 --- a/src/SFML/Graphics/RenderTextureImplFBO.cpp +++ b/src/SFML/Graphics/RenderTextureImplFBO.cpp @@ -1,147 +1,147 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -RenderTextureImplFBO::RenderTextureImplFBO() : -m_frameBuffer(0), -m_depthBuffer(0) -{ - -} - - -//////////////////////////////////////////////////////////// -RenderTextureImplFBO::~RenderTextureImplFBO() -{ - ensureGlContext(); - - // Destroy the depth buffer - if (m_depthBuffer) - { - GLuint depthBuffer = static_cast(m_depthBuffer); - glCheck(GLEXT_glDeleteRenderbuffers(1, &depthBuffer)); - } - - // Destroy the frame buffer - if (m_frameBuffer) - { - GLuint frameBuffer = static_cast(m_frameBuffer); - glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer)); - } - - // Delete the context - delete m_context; -} - - -//////////////////////////////////////////////////////////// -bool RenderTextureImplFBO::isAvailable() -{ - ensureGlContext(); - - // Make sure that extensions are initialized - priv::ensureExtensionsInit(); - - return GLEXT_framebuffer_object != 0; -} - - -//////////////////////////////////////////////////////////// -bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) -{ - // Create the context - m_context = new Context; - - // Create the framebuffer object - GLuint frameBuffer = 0; - glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer)); - m_frameBuffer = static_cast(frameBuffer); - if (!m_frameBuffer) - { - err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl; - return false; - } - glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer)); - - // Create the depth buffer if requested - if (depthBuffer) - { - GLuint depth = 0; - glCheck(GLEXT_glGenRenderbuffers(1, &depth)); - m_depthBuffer = static_cast(depth); - if (!m_depthBuffer) - { - err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl; - return false; - } - glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthBuffer)); - glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height)); - glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthBuffer)); - } - - // Link the texture to the frame buffer - glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0)); - +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +RenderTextureImplFBO::RenderTextureImplFBO() : +m_frameBuffer(0), +m_depthBuffer(0) +{ + +} + + +//////////////////////////////////////////////////////////// +RenderTextureImplFBO::~RenderTextureImplFBO() +{ + ensureGlContext(); + + // Destroy the depth buffer + if (m_depthBuffer) + { + GLuint depthBuffer = static_cast(m_depthBuffer); + glCheck(GLEXT_glDeleteRenderbuffers(1, &depthBuffer)); + } + + // Destroy the frame buffer + if (m_frameBuffer) + { + GLuint frameBuffer = static_cast(m_frameBuffer); + glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer)); + } + + // Delete the context + delete m_context; +} + + +//////////////////////////////////////////////////////////// +bool RenderTextureImplFBO::isAvailable() +{ + ensureGlContext(); + + // Make sure that extensions are initialized + priv::ensureExtensionsInit(); + + return GLEXT_framebuffer_object != 0; +} + + +//////////////////////////////////////////////////////////// +bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) +{ + // Create the context + m_context = new Context; + + // Create the framebuffer object + GLuint frameBuffer = 0; + glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer)); + m_frameBuffer = static_cast(frameBuffer); + if (!m_frameBuffer) + { + err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl; + return false; + } + glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer)); + + // Create the depth buffer if requested + if (depthBuffer) + { + GLuint depth = 0; + glCheck(GLEXT_glGenRenderbuffers(1, &depth)); + m_depthBuffer = static_cast(depth); + if (!m_depthBuffer) + { + err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl; + return false; + } + glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthBuffer)); + glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height)); + glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthBuffer)); + } + + // Link the texture to the frame buffer + glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0)); + // A final check, just to be sure... - GLenum status = glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER)); + GLenum status = glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER)); if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE) - { - glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0)); - err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl; - return false; - } - - return true; -} - - -//////////////////////////////////////////////////////////// -bool RenderTextureImplFBO::activate(bool active) -{ - return m_context->setActive(active); -} - - -//////////////////////////////////////////////////////////// -void RenderTextureImplFBO::updateTexture(unsigned int) -{ - glCheck(glFlush()); -} - -} // namespace priv - -} // namespace sf + { + glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0)); + err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl; + return false; + } + + return true; +} + + +//////////////////////////////////////////////////////////// +bool RenderTextureImplFBO::activate(bool active) +{ + return m_context->setActive(active); +} + + +//////////////////////////////////////////////////////////// +void RenderTextureImplFBO::updateTexture(unsigned int) +{ + glCheck(glFlush()); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Graphics/RenderTextureImplFBO.hpp b/src/SFML/Graphics/RenderTextureImplFBO.hpp index 1904fb32..831876c6 100644 --- a/src/SFML/Graphics/RenderTextureImplFBO.hpp +++ b/src/SFML/Graphics/RenderTextureImplFBO.hpp @@ -1,115 +1,115 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_RENDERTEXTUREIMPLFBO_HPP -#define SFML_RENDERTEXTUREIMPLFBO_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Specialization of RenderTextureImpl using the -/// FrameBuffer Object OpenGL extension -/// -//////////////////////////////////////////////////////////// -class RenderTextureImplFBO : public RenderTextureImpl, GlResource -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - RenderTextureImplFBO(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~RenderTextureImplFBO(); - - //////////////////////////////////////////////////////////// - /// \brief Check whether the system supports FBOs or not - /// - /// \return True if FBO render textures are supported - /// - //////////////////////////////////////////////////////////// - static bool isAvailable(); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Create the render texture implementation - /// - /// \param width Width of the texture to render to - /// \param height Height of the texture to render to - /// \param textureId OpenGL identifier of the target texture - /// \param depthBuffer Is a depth buffer requested? - /// - /// \return True if creation has been successful - /// - //////////////////////////////////////////////////////////// - virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer); - - //////////////////////////////////////////////////////////// - /// \brief Activate or deactivate the render texture for rendering - /// - /// \param active True to activate, false to deactivate - /// - /// \return True on success, false on failure - /// - //////////////////////////////////////////////////////////// - virtual bool activate(bool active); - - //////////////////////////////////////////////////////////// - /// \brief Update the pixels of the target texture - /// - /// \param textureId OpenGL identifier of the target texture - /// - //////////////////////////////////////////////////////////// - virtual void updateTexture(unsigned textureId); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Context* m_context; ///< Needs a separate OpenGL context for not messing up the other ones - unsigned int m_frameBuffer; ///< OpenGL frame buffer object - unsigned int m_depthBuffer; ///< Optional depth buffer attached to the frame buffer -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_RENDERTEXTUREIMPLFBO_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERTEXTUREIMPLFBO_HPP +#define SFML_RENDERTEXTUREIMPLFBO_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Specialization of RenderTextureImpl using the +/// FrameBuffer Object OpenGL extension +/// +//////////////////////////////////////////////////////////// +class RenderTextureImplFBO : public RenderTextureImpl, GlResource +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + RenderTextureImplFBO(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~RenderTextureImplFBO(); + + //////////////////////////////////////////////////////////// + /// \brief Check whether the system supports FBOs or not + /// + /// \return True if FBO render textures are supported + /// + //////////////////////////////////////////////////////////// + static bool isAvailable(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Create the render texture implementation + /// + /// \param width Width of the texture to render to + /// \param height Height of the texture to render to + /// \param textureId OpenGL identifier of the target texture + /// \param depthBuffer Is a depth buffer requested? + /// + /// \return True if creation has been successful + /// + //////////////////////////////////////////////////////////// + virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer); + + //////////////////////////////////////////////////////////// + /// \brief Activate or deactivate the render texture for rendering + /// + /// \param active True to activate, false to deactivate + /// + /// \return True on success, false on failure + /// + //////////////////////////////////////////////////////////// + virtual bool activate(bool active); + + //////////////////////////////////////////////////////////// + /// \brief Update the pixels of the target texture + /// + /// \param textureId OpenGL identifier of the target texture + /// + //////////////////////////////////////////////////////////// + virtual void updateTexture(unsigned textureId); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Context* m_context; ///< Needs a separate OpenGL context for not messing up the other ones + unsigned int m_frameBuffer; ///< OpenGL frame buffer object + unsigned int m_depthBuffer; ///< Optional depth buffer attached to the frame buffer +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_RENDERTEXTUREIMPLFBO_HPP diff --git a/src/SFML/Graphics/RenderWindow.cpp b/src/SFML/Graphics/RenderWindow.cpp index 73a4c91d..ac7ce7d3 100644 --- a/src/SFML/Graphics/RenderWindow.cpp +++ b/src/SFML/Graphics/RenderWindow.cpp @@ -1,117 +1,117 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -RenderWindow::RenderWindow() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -RenderWindow::RenderWindow(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) -{ - // Don't call the base class constructor because it contains virtual function calls - create(mode, title, style, settings); -} - - -//////////////////////////////////////////////////////////// -RenderWindow::RenderWindow(WindowHandle handle, const ContextSettings& settings) -{ - // Don't call the base class constructor because it contains virtual function calls - create(handle, settings); -} - - -//////////////////////////////////////////////////////////// -RenderWindow::~RenderWindow() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -bool RenderWindow::activate(bool active) -{ - return setActive(active); -} - - -//////////////////////////////////////////////////////////// -Vector2u RenderWindow::getSize() const -{ - return Window::getSize(); -} - - -//////////////////////////////////////////////////////////// -Image RenderWindow::capture() const -{ - Image image; - if (setActive()) - { - int width = static_cast(getSize().x); - int height = static_cast(getSize().y); - - // copy rows one by one and flip them (OpenGL's origin is bottom while SFML's origin is top) - std::vector pixels(width * height * 4); - for (int i = 0; i < height; ++i) - { - Uint8* ptr = &pixels[i * width * 4]; - glCheck(glReadPixels(0, height - i - 1, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr)); - } - - image.create(width, height, &pixels[0]); - } - - return image; -} - - -//////////////////////////////////////////////////////////// -void RenderWindow::onCreate() -{ - // Just initialize the render target part - RenderTarget::initialize(); -} - - -//////////////////////////////////////////////////////////// -void RenderWindow::onResize() -{ - // Update the current view (recompute the viewport, which is stored in relative coordinates) - setView(getView()); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +RenderWindow::RenderWindow() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +RenderWindow::RenderWindow(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) +{ + // Don't call the base class constructor because it contains virtual function calls + create(mode, title, style, settings); +} + + +//////////////////////////////////////////////////////////// +RenderWindow::RenderWindow(WindowHandle handle, const ContextSettings& settings) +{ + // Don't call the base class constructor because it contains virtual function calls + create(handle, settings); +} + + +//////////////////////////////////////////////////////////// +RenderWindow::~RenderWindow() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +bool RenderWindow::activate(bool active) +{ + return setActive(active); +} + + +//////////////////////////////////////////////////////////// +Vector2u RenderWindow::getSize() const +{ + return Window::getSize(); +} + + +//////////////////////////////////////////////////////////// +Image RenderWindow::capture() const +{ + Image image; + if (setActive()) + { + int width = static_cast(getSize().x); + int height = static_cast(getSize().y); + + // copy rows one by one and flip them (OpenGL's origin is bottom while SFML's origin is top) + std::vector pixels(width * height * 4); + for (int i = 0; i < height; ++i) + { + Uint8* ptr = &pixels[i * width * 4]; + glCheck(glReadPixels(0, height - i - 1, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr)); + } + + image.create(width, height, &pixels[0]); + } + + return image; +} + + +//////////////////////////////////////////////////////////// +void RenderWindow::onCreate() +{ + // Just initialize the render target part + RenderTarget::initialize(); +} + + +//////////////////////////////////////////////////////////// +void RenderWindow::onResize() +{ + // Update the current view (recompute the viewport, which is stored in relative coordinates) + setView(getView()); +} + +} // namespace sf diff --git a/src/SFML/Graphics/Shader.cpp b/src/SFML/Graphics/Shader.cpp index 0af485a9..29a383ef 100644 --- a/src/SFML/Graphics/Shader.cpp +++ b/src/SFML/Graphics/Shader.cpp @@ -1,786 +1,786 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifndef SFML_OPENGL_ES - -namespace -{ - sf::Mutex mutex; - - GLint checkMaxTextureUnits() - { - GLint maxUnits = 0; - - glCheck(glGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, &maxUnits)); - - return maxUnits; - } - - // Retrieve the maximum number of texture units available - GLint getMaxTextureUnits() - { - // TODO: Remove this lock when it becomes unnecessary in C++11 - sf::Lock lock(mutex); - - static GLint maxUnits = checkMaxTextureUnits(); - - return maxUnits; - } - - // Read the contents of a file into an array of char - bool getFileContents(const std::string& filename, std::vector& buffer) - { - std::ifstream file(filename.c_str(), std::ios_base::binary); - if (file) - { - file.seekg(0, std::ios_base::end); - std::streamsize size = file.tellg(); - if (size > 0) - { - file.seekg(0, std::ios_base::beg); - buffer.resize(static_cast(size)); - file.read(&buffer[0], size); - } - buffer.push_back('\0'); - return true; - } - else - { - return false; - } - } - - // Read the contents of a stream into an array of char - bool getStreamContents(sf::InputStream& stream, std::vector& buffer) - { - bool success = true; - sf::Int64 size = stream.getSize(); - if (size > 0) - { - buffer.resize(static_cast(size)); - stream.seek(0); - sf::Int64 read = stream.read(&buffer[0], size); - success = (read == size); - } - buffer.push_back('\0'); - return success; - } - - bool checkShadersAvailable() - { - // Create a temporary context in case the user checks - // before a GlResource is created, thus initializing - // the shared context - sf::Context context; - - // Make sure that extensions are initialized - sf::priv::ensureExtensionsInit(); - - bool available = GLEW_ARB_shading_language_100 && - GLEW_ARB_shader_objects && - GLEW_ARB_vertex_shader && - GLEW_ARB_fragment_shader; - - return available; - } -} - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Shader::CurrentTextureType Shader::CurrentTexture; - - -//////////////////////////////////////////////////////////// -Shader::Shader() : -m_shaderProgram (0), -m_currentTexture(-1), -m_textures (), -m_params () -{ -} - - -//////////////////////////////////////////////////////////// -Shader::~Shader() -{ - ensureGlContext(); - - // Destroy effect program - if (m_shaderProgram) - glCheck(glDeleteObjectARB(m_shaderProgram)); -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromFile(const std::string& filename, Type type) -{ - // Read the file - std::vector shader; - if (!getFileContents(filename, shader)) - { - err() << "Failed to open shader file \"" << filename << "\"" << std::endl; - return false; - } - - // Compile the shader program - if (type == Vertex) - return compile(&shader[0], NULL); - else - return compile(NULL, &shader[0]); -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename) -{ - // Read the vertex shader file - std::vector vertexShader; - if (!getFileContents(vertexShaderFilename, vertexShader)) - { - err() << "Failed to open vertex shader file \"" << vertexShaderFilename << "\"" << std::endl; - return false; - } - - // Read the fragment shader file - std::vector fragmentShader; - if (!getFileContents(fragmentShaderFilename, fragmentShader)) - { - err() << "Failed to open fragment shader file \"" << fragmentShaderFilename << "\"" << std::endl; - return false; - } - - // Compile the shader program - return compile(&vertexShader[0], &fragmentShader[0]); -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromMemory(const std::string& shader, Type type) -{ - // Compile the shader program - if (type == Vertex) - return compile(shader.c_str(), NULL); - else - return compile(NULL, shader.c_str()); -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader) -{ - // Compile the shader program - return compile(vertexShader.c_str(), fragmentShader.c_str()); -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromStream(InputStream& stream, Type type) -{ - // Read the shader code from the stream - std::vector shader; - if (!getStreamContents(stream, shader)) - { - err() << "Failed to read shader from stream" << std::endl; - return false; - } - - // Compile the shader program - if (type == Vertex) - return compile(&shader[0], NULL); - else - return compile(NULL, &shader[0]); -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream) -{ - // Read the vertex shader code from the stream - std::vector vertexShader; - if (!getStreamContents(vertexShaderStream, vertexShader)) - { - err() << "Failed to read vertex shader from stream" << std::endl; - return false; - } - - // Read the fragment shader code from the stream - std::vector fragmentShader; - if (!getStreamContents(fragmentShaderStream, fragmentShader)) - { - err() << "Failed to read fragment shader from stream" << std::endl; - return false; - } - - // Compile the shader program - return compile(&vertexShader[0], &fragmentShader[0]); -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, float x) -{ - if (m_shaderProgram) - { - ensureGlContext(); - - // Enable program - GLhandleARB program = glCheck(glGetHandleARB(GL_PROGRAM_OBJECT_ARB)); - glCheck(glUseProgramObjectARB(m_shaderProgram)); - - // Get parameter location and assign it new values - GLint location = getParamLocation(name); - if (location != -1) - { - glCheck(glUniform1fARB(location, x)); - } - - // Disable program - glCheck(glUseProgramObjectARB(program)); - } -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, float x, float y) -{ - if (m_shaderProgram) - { - ensureGlContext(); - - // Enable program - GLhandleARB program = glCheck(glGetHandleARB(GL_PROGRAM_OBJECT_ARB)); - glCheck(glUseProgramObjectARB(m_shaderProgram)); - - // Get parameter location and assign it new values - GLint location = getParamLocation(name); - if (location != -1) - { - glCheck(glUniform2fARB(location, x, y)); - } - - // Disable program - glCheck(glUseProgramObjectARB(program)); - } -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, float x, float y, float z) -{ - if (m_shaderProgram) - { - ensureGlContext(); - - // Enable program - GLhandleARB program = glCheck(glGetHandleARB(GL_PROGRAM_OBJECT_ARB)); - glCheck(glUseProgramObjectARB(m_shaderProgram)); - - // Get parameter location and assign it new values - GLint location = getParamLocation(name); - if (location != -1) - { - glCheck(glUniform3fARB(location, x, y, z)); - } - - // Disable program - glCheck(glUseProgramObjectARB(program)); - } -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, float x, float y, float z, float w) -{ - if (m_shaderProgram) - { - ensureGlContext(); - - // Enable program - GLhandleARB program = glCheck(glGetHandleARB(GL_PROGRAM_OBJECT_ARB)); - glCheck(glUseProgramObjectARB(m_shaderProgram)); - - // Get parameter location and assign it new values - GLint location = getParamLocation(name); - if (location != -1) - { - glCheck(glUniform4fARB(location, x, y, z, w)); - } - - // Disable program - glCheck(glUseProgramObjectARB(program)); - } -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const Vector2f& v) -{ - setParameter(name, v.x, v.y); -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const Vector3f& v) -{ - setParameter(name, v.x, v.y, v.z); -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const Color& color) -{ - setParameter(name, color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f); -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const sf::Transform& transform) -{ - if (m_shaderProgram) - { - ensureGlContext(); - - // Enable program - GLhandleARB program = glCheck(glGetHandleARB(GL_PROGRAM_OBJECT_ARB)); - glCheck(glUseProgramObjectARB(m_shaderProgram)); - - // Get parameter location and assign it new values - GLint location = getParamLocation(name); - if (location != -1) - { - glCheck(glUniformMatrix4fvARB(location, 1, GL_FALSE, transform.getMatrix())); - } - - // Disable program - glCheck(glUseProgramObjectARB(program)); - } -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const Texture& texture) -{ - if (m_shaderProgram) - { - ensureGlContext(); - - // Find the location of the variable in the shader - int location = getParamLocation(name); - if (location != -1) - { - // Store the location -> texture mapping - TextureTable::iterator it = m_textures.find(location); - if (it == m_textures.end()) - { - // New entry, make sure there are enough texture units - GLint maxUnits = getMaxTextureUnits(); - if (m_textures.size() + 1 >= static_cast(maxUnits)) - { - err() << "Impossible to use texture \"" << name << "\" for shader: all available texture units are used" << std::endl; - return; - } - - m_textures[location] = &texture; - } - else - { - // Location already used, just replace the texture - it->second = &texture; - } - } - } -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, CurrentTextureType) -{ - if (m_shaderProgram) - { - ensureGlContext(); - - // Find the location of the variable in the shader - m_currentTexture = getParamLocation(name); - } -} - - -//////////////////////////////////////////////////////////// -void Shader::bind(const Shader* shader) -{ - ensureGlContext(); - - if (shader && shader->m_shaderProgram) - { - // Enable the program - glCheck(glUseProgramObjectARB(shader->m_shaderProgram)); - - // Bind the textures - shader->bindTextures(); - - // Bind the current texture - if (shader->m_currentTexture != -1) - glCheck(glUniform1iARB(shader->m_currentTexture, 0)); - } - else - { - // Bind no shader - glCheck(glUseProgramObjectARB(0)); - } -} - - -//////////////////////////////////////////////////////////// -bool Shader::isAvailable() -{ - // TODO: Remove this lock when it becomes unnecessary in C++11 - Lock lock(mutex); - - static bool available = checkShadersAvailable(); - - return available; -} - - -//////////////////////////////////////////////////////////// -bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCode) -{ - ensureGlContext(); - - // First make sure that we can use shaders - if (!isAvailable()) - { - err() << "Failed to create a shader: your system doesn't support shaders " - << "(you should test Shader::isAvailable() before trying to use the Shader class)" << std::endl; - return false; - } - - // Destroy the shader if it was already created - if (m_shaderProgram) - glCheck(glDeleteObjectARB(m_shaderProgram)); - - // Reset the internal state - m_currentTexture = -1; - m_textures.clear(); - m_params.clear(); - - // Create the program - m_shaderProgram = glCheck(glCreateProgramObjectARB()); - - // Create the vertex shader if needed - if (vertexShaderCode) - { - // Create and compile the shader - GLhandleARB vertexShader = glCheck(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); - glCheck(glShaderSourceARB(vertexShader, 1, &vertexShaderCode, NULL)); - glCheck(glCompileShaderARB(vertexShader)); - - // Check the compile log - GLint success; - glCheck(glGetObjectParameterivARB(vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); - if (success == GL_FALSE) - { - char log[1024]; - glCheck(glGetInfoLogARB(vertexShader, sizeof(log), 0, log)); - err() << "Failed to compile vertex shader:" << std::endl - << log << std::endl; - glCheck(glDeleteObjectARB(vertexShader)); - glCheck(glDeleteObjectARB(m_shaderProgram)); - m_shaderProgram = 0; - return false; - } - - // Attach the shader to the program, and delete it (not needed anymore) - glCheck(glAttachObjectARB(m_shaderProgram, vertexShader)); - glCheck(glDeleteObjectARB(vertexShader)); - } - - // Create the fragment shader if needed - if (fragmentShaderCode) - { - // Create and compile the shader - GLhandleARB fragmentShader = glCheck(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)); - glCheck(glShaderSourceARB(fragmentShader, 1, &fragmentShaderCode, NULL)); - glCheck(glCompileShaderARB(fragmentShader)); - - // Check the compile log - GLint success; - glCheck(glGetObjectParameterivARB(fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); - if (success == GL_FALSE) - { - char log[1024]; - glCheck(glGetInfoLogARB(fragmentShader, sizeof(log), 0, log)); - err() << "Failed to compile fragment shader:" << std::endl - << log << std::endl; - glCheck(glDeleteObjectARB(fragmentShader)); - glCheck(glDeleteObjectARB(m_shaderProgram)); - m_shaderProgram = 0; - return false; - } - - // Attach the shader to the program, and delete it (not needed anymore) - glCheck(glAttachObjectARB(m_shaderProgram, fragmentShader)); - glCheck(glDeleteObjectARB(fragmentShader)); - } - - // Link the program - glCheck(glLinkProgramARB(m_shaderProgram)); - - // Check the link log - GLint success; - glCheck(glGetObjectParameterivARB(m_shaderProgram, GL_OBJECT_LINK_STATUS_ARB, &success)); - if (success == GL_FALSE) - { - char log[1024]; - glCheck(glGetInfoLogARB(m_shaderProgram, sizeof(log), 0, log)); - err() << "Failed to link shader:" << std::endl - << log << std::endl; - glCheck(glDeleteObjectARB(m_shaderProgram)); - m_shaderProgram = 0; - return false; - } - - // Force an OpenGL flush, so that the shader will appear updated - // in all contexts immediately (solves problems in multi-threaded apps) - glCheck(glFlush()); - - return true; -} - - -//////////////////////////////////////////////////////////// -void Shader::bindTextures() const -{ - TextureTable::const_iterator it = m_textures.begin(); - for (std::size_t i = 0; i < m_textures.size(); ++i) - { - GLint index = static_cast(i + 1); - glCheck(glUniform1iARB(it->first, index)); - glCheck(glActiveTextureARB(GL_TEXTURE0_ARB + index)); - Texture::bind(it->second); - ++it; - } - - // Make sure that the texture unit which is left active is the number 0 - glCheck(glActiveTextureARB(GL_TEXTURE0_ARB)); -} - - -//////////////////////////////////////////////////////////// -int Shader::getParamLocation(const std::string& name) -{ - // Check the cache - ParamTable::const_iterator it = m_params.find(name); - if (it != m_params.end()) - { - // Already in cache, return it - return it->second; - } - else - { - // Not in cache, request the location from OpenGL - int location = glGetUniformLocationARB(m_shaderProgram, name.c_str()); - m_params.insert(std::make_pair(name, location)); - - if (location == -1) - err() << "Parameter \"" << name << "\" not found in shader" << std::endl; - - return location; - } -} - -} // namespace sf - -#else // SFML_OPENGL_ES - -// OpenGL ES 1 does't support GLSL shaders at all, we have to provide an empty implementation - -namespace sf -{ -//////////////////////////////////////////////////////////// -Shader::CurrentTextureType Shader::CurrentTexture; - - -//////////////////////////////////////////////////////////// -Shader::Shader() : -m_shaderProgram (0), -m_currentTexture(-1) -{ -} - - -//////////////////////////////////////////////////////////// -Shader::~Shader() -{ -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromFile(const std::string& filename, Type type) -{ - return false; -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename) -{ - return false; -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromMemory(const std::string& shader, Type type) -{ - return false; -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader) -{ - return false; -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromStream(InputStream& stream, Type type) -{ - return false; -} - - -//////////////////////////////////////////////////////////// -bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream) -{ - return false; -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, float x) -{ -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, float x, float y) -{ -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, float x, float y, float z) -{ -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, float x, float y, float z, float w) -{ -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const Vector2f& v) -{ -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const Vector3f& v) -{ -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const Color& color) -{ -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const sf::Transform& transform) -{ -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const Texture& texture) -{ -} - - -//////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, CurrentTextureType) -{ -} - - -//////////////////////////////////////////////////////////// -void Shader::bind(const Shader* shader) -{ -} - - -//////////////////////////////////////////////////////////// -bool Shader::isAvailable() -{ - return false; -} - - -//////////////////////////////////////////////////////////// -bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCode) -{ - return false; -} - - -//////////////////////////////////////////////////////////// -void Shader::bindTextures() const -{ -} - -} // namespace sf - -#endif // SFML_OPENGL_ES +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef SFML_OPENGL_ES + +namespace +{ + sf::Mutex mutex; + + GLint checkMaxTextureUnits() + { + GLint maxUnits = 0; + + glCheck(glGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, &maxUnits)); + + return maxUnits; + } + + // Retrieve the maximum number of texture units available + GLint getMaxTextureUnits() + { + // TODO: Remove this lock when it becomes unnecessary in C++11 + sf::Lock lock(mutex); + + static GLint maxUnits = checkMaxTextureUnits(); + + return maxUnits; + } + + // Read the contents of a file into an array of char + bool getFileContents(const std::string& filename, std::vector& buffer) + { + std::ifstream file(filename.c_str(), std::ios_base::binary); + if (file) + { + file.seekg(0, std::ios_base::end); + std::streamsize size = file.tellg(); + if (size > 0) + { + file.seekg(0, std::ios_base::beg); + buffer.resize(static_cast(size)); + file.read(&buffer[0], size); + } + buffer.push_back('\0'); + return true; + } + else + { + return false; + } + } + + // Read the contents of a stream into an array of char + bool getStreamContents(sf::InputStream& stream, std::vector& buffer) + { + bool success = true; + sf::Int64 size = stream.getSize(); + if (size > 0) + { + buffer.resize(static_cast(size)); + stream.seek(0); + sf::Int64 read = stream.read(&buffer[0], size); + success = (read == size); + } + buffer.push_back('\0'); + return success; + } + + bool checkShadersAvailable() + { + // Create a temporary context in case the user checks + // before a GlResource is created, thus initializing + // the shared context + sf::Context context; + + // Make sure that extensions are initialized + sf::priv::ensureExtensionsInit(); + + bool available = GLEW_ARB_shading_language_100 && + GLEW_ARB_shader_objects && + GLEW_ARB_vertex_shader && + GLEW_ARB_fragment_shader; + + return available; + } +} + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Shader::CurrentTextureType Shader::CurrentTexture; + + +//////////////////////////////////////////////////////////// +Shader::Shader() : +m_shaderProgram (0), +m_currentTexture(-1), +m_textures (), +m_params () +{ +} + + +//////////////////////////////////////////////////////////// +Shader::~Shader() +{ + ensureGlContext(); + + // Destroy effect program + if (m_shaderProgram) + glCheck(glDeleteObjectARB(m_shaderProgram)); +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromFile(const std::string& filename, Type type) +{ + // Read the file + std::vector shader; + if (!getFileContents(filename, shader)) + { + err() << "Failed to open shader file \"" << filename << "\"" << std::endl; + return false; + } + + // Compile the shader program + if (type == Vertex) + return compile(&shader[0], NULL); + else + return compile(NULL, &shader[0]); +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename) +{ + // Read the vertex shader file + std::vector vertexShader; + if (!getFileContents(vertexShaderFilename, vertexShader)) + { + err() << "Failed to open vertex shader file \"" << vertexShaderFilename << "\"" << std::endl; + return false; + } + + // Read the fragment shader file + std::vector fragmentShader; + if (!getFileContents(fragmentShaderFilename, fragmentShader)) + { + err() << "Failed to open fragment shader file \"" << fragmentShaderFilename << "\"" << std::endl; + return false; + } + + // Compile the shader program + return compile(&vertexShader[0], &fragmentShader[0]); +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromMemory(const std::string& shader, Type type) +{ + // Compile the shader program + if (type == Vertex) + return compile(shader.c_str(), NULL); + else + return compile(NULL, shader.c_str()); +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader) +{ + // Compile the shader program + return compile(vertexShader.c_str(), fragmentShader.c_str()); +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromStream(InputStream& stream, Type type) +{ + // Read the shader code from the stream + std::vector shader; + if (!getStreamContents(stream, shader)) + { + err() << "Failed to read shader from stream" << std::endl; + return false; + } + + // Compile the shader program + if (type == Vertex) + return compile(&shader[0], NULL); + else + return compile(NULL, &shader[0]); +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream) +{ + // Read the vertex shader code from the stream + std::vector vertexShader; + if (!getStreamContents(vertexShaderStream, vertexShader)) + { + err() << "Failed to read vertex shader from stream" << std::endl; + return false; + } + + // Read the fragment shader code from the stream + std::vector fragmentShader; + if (!getStreamContents(fragmentShaderStream, fragmentShader)) + { + err() << "Failed to read fragment shader from stream" << std::endl; + return false; + } + + // Compile the shader program + return compile(&vertexShader[0], &fragmentShader[0]); +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, float x) +{ + if (m_shaderProgram) + { + ensureGlContext(); + + // Enable program + GLhandleARB program = glCheck(glGetHandleARB(GL_PROGRAM_OBJECT_ARB)); + glCheck(glUseProgramObjectARB(m_shaderProgram)); + + // Get parameter location and assign it new values + GLint location = getParamLocation(name); + if (location != -1) + { + glCheck(glUniform1fARB(location, x)); + } + + // Disable program + glCheck(glUseProgramObjectARB(program)); + } +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, float x, float y) +{ + if (m_shaderProgram) + { + ensureGlContext(); + + // Enable program + GLhandleARB program = glCheck(glGetHandleARB(GL_PROGRAM_OBJECT_ARB)); + glCheck(glUseProgramObjectARB(m_shaderProgram)); + + // Get parameter location and assign it new values + GLint location = getParamLocation(name); + if (location != -1) + { + glCheck(glUniform2fARB(location, x, y)); + } + + // Disable program + glCheck(glUseProgramObjectARB(program)); + } +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, float x, float y, float z) +{ + if (m_shaderProgram) + { + ensureGlContext(); + + // Enable program + GLhandleARB program = glCheck(glGetHandleARB(GL_PROGRAM_OBJECT_ARB)); + glCheck(glUseProgramObjectARB(m_shaderProgram)); + + // Get parameter location and assign it new values + GLint location = getParamLocation(name); + if (location != -1) + { + glCheck(glUniform3fARB(location, x, y, z)); + } + + // Disable program + glCheck(glUseProgramObjectARB(program)); + } +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, float x, float y, float z, float w) +{ + if (m_shaderProgram) + { + ensureGlContext(); + + // Enable program + GLhandleARB program = glCheck(glGetHandleARB(GL_PROGRAM_OBJECT_ARB)); + glCheck(glUseProgramObjectARB(m_shaderProgram)); + + // Get parameter location and assign it new values + GLint location = getParamLocation(name); + if (location != -1) + { + glCheck(glUniform4fARB(location, x, y, z, w)); + } + + // Disable program + glCheck(glUseProgramObjectARB(program)); + } +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, const Vector2f& v) +{ + setParameter(name, v.x, v.y); +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, const Vector3f& v) +{ + setParameter(name, v.x, v.y, v.z); +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, const Color& color) +{ + setParameter(name, color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f); +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, const sf::Transform& transform) +{ + if (m_shaderProgram) + { + ensureGlContext(); + + // Enable program + GLhandleARB program = glCheck(glGetHandleARB(GL_PROGRAM_OBJECT_ARB)); + glCheck(glUseProgramObjectARB(m_shaderProgram)); + + // Get parameter location and assign it new values + GLint location = getParamLocation(name); + if (location != -1) + { + glCheck(glUniformMatrix4fvARB(location, 1, GL_FALSE, transform.getMatrix())); + } + + // Disable program + glCheck(glUseProgramObjectARB(program)); + } +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, const Texture& texture) +{ + if (m_shaderProgram) + { + ensureGlContext(); + + // Find the location of the variable in the shader + int location = getParamLocation(name); + if (location != -1) + { + // Store the location -> texture mapping + TextureTable::iterator it = m_textures.find(location); + if (it == m_textures.end()) + { + // New entry, make sure there are enough texture units + GLint maxUnits = getMaxTextureUnits(); + if (m_textures.size() + 1 >= static_cast(maxUnits)) + { + err() << "Impossible to use texture \"" << name << "\" for shader: all available texture units are used" << std::endl; + return; + } + + m_textures[location] = &texture; + } + else + { + // Location already used, just replace the texture + it->second = &texture; + } + } + } +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, CurrentTextureType) +{ + if (m_shaderProgram) + { + ensureGlContext(); + + // Find the location of the variable in the shader + m_currentTexture = getParamLocation(name); + } +} + + +//////////////////////////////////////////////////////////// +void Shader::bind(const Shader* shader) +{ + ensureGlContext(); + + if (shader && shader->m_shaderProgram) + { + // Enable the program + glCheck(glUseProgramObjectARB(shader->m_shaderProgram)); + + // Bind the textures + shader->bindTextures(); + + // Bind the current texture + if (shader->m_currentTexture != -1) + glCheck(glUniform1iARB(shader->m_currentTexture, 0)); + } + else + { + // Bind no shader + glCheck(glUseProgramObjectARB(0)); + } +} + + +//////////////////////////////////////////////////////////// +bool Shader::isAvailable() +{ + // TODO: Remove this lock when it becomes unnecessary in C++11 + Lock lock(mutex); + + static bool available = checkShadersAvailable(); + + return available; +} + + +//////////////////////////////////////////////////////////// +bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCode) +{ + ensureGlContext(); + + // First make sure that we can use shaders + if (!isAvailable()) + { + err() << "Failed to create a shader: your system doesn't support shaders " + << "(you should test Shader::isAvailable() before trying to use the Shader class)" << std::endl; + return false; + } + + // Destroy the shader if it was already created + if (m_shaderProgram) + glCheck(glDeleteObjectARB(m_shaderProgram)); + + // Reset the internal state + m_currentTexture = -1; + m_textures.clear(); + m_params.clear(); + + // Create the program + m_shaderProgram = glCheck(glCreateProgramObjectARB()); + + // Create the vertex shader if needed + if (vertexShaderCode) + { + // Create and compile the shader + GLhandleARB vertexShader = glCheck(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)); + glCheck(glShaderSourceARB(vertexShader, 1, &vertexShaderCode, NULL)); + glCheck(glCompileShaderARB(vertexShader)); + + // Check the compile log + GLint success; + glCheck(glGetObjectParameterivARB(vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); + if (success == GL_FALSE) + { + char log[1024]; + glCheck(glGetInfoLogARB(vertexShader, sizeof(log), 0, log)); + err() << "Failed to compile vertex shader:" << std::endl + << log << std::endl; + glCheck(glDeleteObjectARB(vertexShader)); + glCheck(glDeleteObjectARB(m_shaderProgram)); + m_shaderProgram = 0; + return false; + } + + // Attach the shader to the program, and delete it (not needed anymore) + glCheck(glAttachObjectARB(m_shaderProgram, vertexShader)); + glCheck(glDeleteObjectARB(vertexShader)); + } + + // Create the fragment shader if needed + if (fragmentShaderCode) + { + // Create and compile the shader + GLhandleARB fragmentShader = glCheck(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)); + glCheck(glShaderSourceARB(fragmentShader, 1, &fragmentShaderCode, NULL)); + glCheck(glCompileShaderARB(fragmentShader)); + + // Check the compile log + GLint success; + glCheck(glGetObjectParameterivARB(fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); + if (success == GL_FALSE) + { + char log[1024]; + glCheck(glGetInfoLogARB(fragmentShader, sizeof(log), 0, log)); + err() << "Failed to compile fragment shader:" << std::endl + << log << std::endl; + glCheck(glDeleteObjectARB(fragmentShader)); + glCheck(glDeleteObjectARB(m_shaderProgram)); + m_shaderProgram = 0; + return false; + } + + // Attach the shader to the program, and delete it (not needed anymore) + glCheck(glAttachObjectARB(m_shaderProgram, fragmentShader)); + glCheck(glDeleteObjectARB(fragmentShader)); + } + + // Link the program + glCheck(glLinkProgramARB(m_shaderProgram)); + + // Check the link log + GLint success; + glCheck(glGetObjectParameterivARB(m_shaderProgram, GL_OBJECT_LINK_STATUS_ARB, &success)); + if (success == GL_FALSE) + { + char log[1024]; + glCheck(glGetInfoLogARB(m_shaderProgram, sizeof(log), 0, log)); + err() << "Failed to link shader:" << std::endl + << log << std::endl; + glCheck(glDeleteObjectARB(m_shaderProgram)); + m_shaderProgram = 0; + return false; + } + + // Force an OpenGL flush, so that the shader will appear updated + // in all contexts immediately (solves problems in multi-threaded apps) + glCheck(glFlush()); + + return true; +} + + +//////////////////////////////////////////////////////////// +void Shader::bindTextures() const +{ + TextureTable::const_iterator it = m_textures.begin(); + for (std::size_t i = 0; i < m_textures.size(); ++i) + { + GLint index = static_cast(i + 1); + glCheck(glUniform1iARB(it->first, index)); + glCheck(glActiveTextureARB(GL_TEXTURE0_ARB + index)); + Texture::bind(it->second); + ++it; + } + + // Make sure that the texture unit which is left active is the number 0 + glCheck(glActiveTextureARB(GL_TEXTURE0_ARB)); +} + + +//////////////////////////////////////////////////////////// +int Shader::getParamLocation(const std::string& name) +{ + // Check the cache + ParamTable::const_iterator it = m_params.find(name); + if (it != m_params.end()) + { + // Already in cache, return it + return it->second; + } + else + { + // Not in cache, request the location from OpenGL + int location = glGetUniformLocationARB(m_shaderProgram, name.c_str()); + m_params.insert(std::make_pair(name, location)); + + if (location == -1) + err() << "Parameter \"" << name << "\" not found in shader" << std::endl; + + return location; + } +} + +} // namespace sf + +#else // SFML_OPENGL_ES + +// OpenGL ES 1 does't support GLSL shaders at all, we have to provide an empty implementation + +namespace sf +{ +//////////////////////////////////////////////////////////// +Shader::CurrentTextureType Shader::CurrentTexture; + + +//////////////////////////////////////////////////////////// +Shader::Shader() : +m_shaderProgram (0), +m_currentTexture(-1) +{ +} + + +//////////////////////////////////////////////////////////// +Shader::~Shader() +{ +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromFile(const std::string& filename, Type type) +{ + return false; +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename) +{ + return false; +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromMemory(const std::string& shader, Type type) +{ + return false; +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader) +{ + return false; +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromStream(InputStream& stream, Type type) +{ + return false; +} + + +//////////////////////////////////////////////////////////// +bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream) +{ + return false; +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, float x) +{ +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, float x, float y) +{ +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, float x, float y, float z) +{ +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, float x, float y, float z, float w) +{ +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, const Vector2f& v) +{ +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, const Vector3f& v) +{ +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, const Color& color) +{ +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, const sf::Transform& transform) +{ +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, const Texture& texture) +{ +} + + +//////////////////////////////////////////////////////////// +void Shader::setParameter(const std::string& name, CurrentTextureType) +{ +} + + +//////////////////////////////////////////////////////////// +void Shader::bind(const Shader* shader) +{ +} + + +//////////////////////////////////////////////////////////// +bool Shader::isAvailable() +{ + return false; +} + + +//////////////////////////////////////////////////////////// +bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCode) +{ + return false; +} + + +//////////////////////////////////////////////////////////// +void Shader::bindTextures() const +{ +} + +} // namespace sf + +#endif // SFML_OPENGL_ES diff --git a/src/SFML/Graphics/Shape.cpp b/src/SFML/Graphics/Shape.cpp index dd8d3933..fa73a5f5 100644 --- a/src/SFML/Graphics/Shape.cpp +++ b/src/SFML/Graphics/Shape.cpp @@ -1,305 +1,305 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace -{ - // Compute the normal of a segment - sf::Vector2f computeNormal(const sf::Vector2f& p1, const sf::Vector2f& p2) - { - sf::Vector2f normal(p1.y - p2.y, p2.x - p1.x); - float length = std::sqrt(normal.x * normal.x + normal.y * normal.y); - if (length != 0.f) - normal /= length; - return normal; - } - - // Compute the dot product of two vectors - float dotProduct(const sf::Vector2f& p1, const sf::Vector2f& p2) - { - return p1.x * p2.x + p1.y * p2.y; - } -} - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Shape::~Shape() -{ -} - - -//////////////////////////////////////////////////////////// -void Shape::setTexture(const Texture* texture, bool resetRect) -{ - if (texture) - { - // Recompute the texture area if requested, or if there was no texture & rect before - if (resetRect || (!m_texture && (m_textureRect == sf::IntRect()))) - setTextureRect(IntRect(0, 0, texture->getSize().x, texture->getSize().y)); - } - - // Assign the new texture - m_texture = texture; -} - - -//////////////////////////////////////////////////////////// -const Texture* Shape::getTexture() const -{ - return m_texture; -} - - -//////////////////////////////////////////////////////////// -void Shape::setTextureRect(const IntRect& rect) -{ - m_textureRect = rect; - updateTexCoords(); -} - - -//////////////////////////////////////////////////////////// -const IntRect& Shape::getTextureRect() const -{ - return m_textureRect; -} - - -//////////////////////////////////////////////////////////// -void Shape::setFillColor(const Color& color) -{ - m_fillColor = color; - updateFillColors(); -} - - -//////////////////////////////////////////////////////////// -const Color& Shape::getFillColor() const -{ - return m_fillColor; -} - - -//////////////////////////////////////////////////////////// -void Shape::setOutlineColor(const Color& color) -{ - m_outlineColor = color; - updateOutlineColors(); -} - - -//////////////////////////////////////////////////////////// -const Color& Shape::getOutlineColor() const -{ - return m_outlineColor; -} - - -//////////////////////////////////////////////////////////// -void Shape::setOutlineThickness(float thickness) -{ - m_outlineThickness = thickness; - update(); // recompute everything because the whole shape must be offset -} - - -//////////////////////////////////////////////////////////// -float Shape::getOutlineThickness() const -{ - return m_outlineThickness; -} - - -//////////////////////////////////////////////////////////// -FloatRect Shape::getLocalBounds() const -{ - return m_bounds; -} - - -//////////////////////////////////////////////////////////// -FloatRect Shape::getGlobalBounds() const -{ - return getTransform().transformRect(getLocalBounds()); -} - - -//////////////////////////////////////////////////////////// -Shape::Shape() : -m_texture (NULL), -m_textureRect (), -m_fillColor (255, 255, 255), -m_outlineColor (255, 255, 255), -m_outlineThickness(0), -m_vertices (TrianglesFan), -m_outlineVertices (TrianglesStrip), -m_insideBounds (), -m_bounds () -{ -} - - -//////////////////////////////////////////////////////////// -void Shape::update() -{ - // Get the total number of points of the shape - unsigned int count = getPointCount(); - if (count < 3) - { - m_vertices.resize(0); - m_outlineVertices.resize(0); - return; - } - - m_vertices.resize(count + 2); // + 2 for center and repeated first point - - // Position - for (unsigned int i = 0; i < count; ++i) - m_vertices[i + 1].position = getPoint(i); - m_vertices[count + 1].position = m_vertices[1].position; - - // Update the bounding rectangle - m_vertices[0] = m_vertices[1]; // so that the result of getBounds() is correct - m_insideBounds = m_vertices.getBounds(); - - // Compute the center and make it the first vertex - m_vertices[0].position.x = m_insideBounds.left + m_insideBounds.width / 2; - m_vertices[0].position.y = m_insideBounds.top + m_insideBounds.height / 2; - - // Color - updateFillColors(); - - // Texture coordinates - updateTexCoords(); - - // Outline - updateOutline(); -} - - -//////////////////////////////////////////////////////////// -void Shape::draw(RenderTarget& target, RenderStates states) const -{ - states.transform *= getTransform(); - - // Render the inside - states.texture = m_texture; - target.draw(m_vertices, states); - - // Render the outline - if (m_outlineThickness != 0) - { - states.texture = NULL; - target.draw(m_outlineVertices, states); - } -} - - -//////////////////////////////////////////////////////////// -void Shape::updateFillColors() -{ - for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i) - m_vertices[i].color = m_fillColor; -} - - -//////////////////////////////////////////////////////////// -void Shape::updateTexCoords() -{ - for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i) - { - float xratio = m_insideBounds.width > 0 ? (m_vertices[i].position.x - m_insideBounds.left) / m_insideBounds.width : 0; - float yratio = m_insideBounds.height > 0 ? (m_vertices[i].position.y - m_insideBounds.top) / m_insideBounds.height : 0; - m_vertices[i].texCoords.x = m_textureRect.left + m_textureRect.width * xratio; - m_vertices[i].texCoords.y = m_textureRect.top + m_textureRect.height * yratio; - } -} - - -//////////////////////////////////////////////////////////// -void Shape::updateOutline() -{ - unsigned int count = m_vertices.getVertexCount() - 2; - m_outlineVertices.resize((count + 1) * 2); - - for (unsigned int i = 0; i < count; ++i) - { - unsigned int index = i + 1; - - // Get the two segments shared by the current point - Vector2f p0 = (i == 0) ? m_vertices[count].position : m_vertices[index - 1].position; - Vector2f p1 = m_vertices[index].position; - Vector2f p2 = m_vertices[index + 1].position; - - // Compute their normal - Vector2f n1 = computeNormal(p0, p1); - Vector2f n2 = computeNormal(p1, p2); - - // Make sure that the normals point towards the outside of the shape - // (this depends on the order in which the points were defined) - if (dotProduct(n1, m_vertices[0].position - p1) > 0) - n1 = -n1; - if (dotProduct(n2, m_vertices[0].position - p1) > 0) - n2 = -n2; - - // Combine them to get the extrusion direction - float factor = 1.f + (n1.x * n2.x + n1.y * n2.y); - Vector2f normal = (n1 + n2) / factor; - - // Update the outline points - m_outlineVertices[i * 2 + 0].position = p1; - m_outlineVertices[i * 2 + 1].position = p1 + normal * m_outlineThickness; - } - - // Duplicate the first point at the end, to close the outline - m_outlineVertices[count * 2 + 0].position = m_outlineVertices[0].position; - m_outlineVertices[count * 2 + 1].position = m_outlineVertices[1].position; - - // Update outline colors - updateOutlineColors(); - - // Update the shape's bounds - m_bounds = m_outlineVertices.getBounds(); -} - - -//////////////////////////////////////////////////////////// -void Shape::updateOutlineColors() -{ - for (unsigned int i = 0; i < m_outlineVertices.getVertexCount(); ++i) - m_outlineVertices[i].color = m_outlineColor; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace +{ + // Compute the normal of a segment + sf::Vector2f computeNormal(const sf::Vector2f& p1, const sf::Vector2f& p2) + { + sf::Vector2f normal(p1.y - p2.y, p2.x - p1.x); + float length = std::sqrt(normal.x * normal.x + normal.y * normal.y); + if (length != 0.f) + normal /= length; + return normal; + } + + // Compute the dot product of two vectors + float dotProduct(const sf::Vector2f& p1, const sf::Vector2f& p2) + { + return p1.x * p2.x + p1.y * p2.y; + } +} + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Shape::~Shape() +{ +} + + +//////////////////////////////////////////////////////////// +void Shape::setTexture(const Texture* texture, bool resetRect) +{ + if (texture) + { + // Recompute the texture area if requested, or if there was no texture & rect before + if (resetRect || (!m_texture && (m_textureRect == sf::IntRect()))) + setTextureRect(IntRect(0, 0, texture->getSize().x, texture->getSize().y)); + } + + // Assign the new texture + m_texture = texture; +} + + +//////////////////////////////////////////////////////////// +const Texture* Shape::getTexture() const +{ + return m_texture; +} + + +//////////////////////////////////////////////////////////// +void Shape::setTextureRect(const IntRect& rect) +{ + m_textureRect = rect; + updateTexCoords(); +} + + +//////////////////////////////////////////////////////////// +const IntRect& Shape::getTextureRect() const +{ + return m_textureRect; +} + + +//////////////////////////////////////////////////////////// +void Shape::setFillColor(const Color& color) +{ + m_fillColor = color; + updateFillColors(); +} + + +//////////////////////////////////////////////////////////// +const Color& Shape::getFillColor() const +{ + return m_fillColor; +} + + +//////////////////////////////////////////////////////////// +void Shape::setOutlineColor(const Color& color) +{ + m_outlineColor = color; + updateOutlineColors(); +} + + +//////////////////////////////////////////////////////////// +const Color& Shape::getOutlineColor() const +{ + return m_outlineColor; +} + + +//////////////////////////////////////////////////////////// +void Shape::setOutlineThickness(float thickness) +{ + m_outlineThickness = thickness; + update(); // recompute everything because the whole shape must be offset +} + + +//////////////////////////////////////////////////////////// +float Shape::getOutlineThickness() const +{ + return m_outlineThickness; +} + + +//////////////////////////////////////////////////////////// +FloatRect Shape::getLocalBounds() const +{ + return m_bounds; +} + + +//////////////////////////////////////////////////////////// +FloatRect Shape::getGlobalBounds() const +{ + return getTransform().transformRect(getLocalBounds()); +} + + +//////////////////////////////////////////////////////////// +Shape::Shape() : +m_texture (NULL), +m_textureRect (), +m_fillColor (255, 255, 255), +m_outlineColor (255, 255, 255), +m_outlineThickness(0), +m_vertices (TrianglesFan), +m_outlineVertices (TrianglesStrip), +m_insideBounds (), +m_bounds () +{ +} + + +//////////////////////////////////////////////////////////// +void Shape::update() +{ + // Get the total number of points of the shape + unsigned int count = getPointCount(); + if (count < 3) + { + m_vertices.resize(0); + m_outlineVertices.resize(0); + return; + } + + m_vertices.resize(count + 2); // + 2 for center and repeated first point + + // Position + for (unsigned int i = 0; i < count; ++i) + m_vertices[i + 1].position = getPoint(i); + m_vertices[count + 1].position = m_vertices[1].position; + + // Update the bounding rectangle + m_vertices[0] = m_vertices[1]; // so that the result of getBounds() is correct + m_insideBounds = m_vertices.getBounds(); + + // Compute the center and make it the first vertex + m_vertices[0].position.x = m_insideBounds.left + m_insideBounds.width / 2; + m_vertices[0].position.y = m_insideBounds.top + m_insideBounds.height / 2; + + // Color + updateFillColors(); + + // Texture coordinates + updateTexCoords(); + + // Outline + updateOutline(); +} + + +//////////////////////////////////////////////////////////// +void Shape::draw(RenderTarget& target, RenderStates states) const +{ + states.transform *= getTransform(); + + // Render the inside + states.texture = m_texture; + target.draw(m_vertices, states); + + // Render the outline + if (m_outlineThickness != 0) + { + states.texture = NULL; + target.draw(m_outlineVertices, states); + } +} + + +//////////////////////////////////////////////////////////// +void Shape::updateFillColors() +{ + for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i) + m_vertices[i].color = m_fillColor; +} + + +//////////////////////////////////////////////////////////// +void Shape::updateTexCoords() +{ + for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i) + { + float xratio = m_insideBounds.width > 0 ? (m_vertices[i].position.x - m_insideBounds.left) / m_insideBounds.width : 0; + float yratio = m_insideBounds.height > 0 ? (m_vertices[i].position.y - m_insideBounds.top) / m_insideBounds.height : 0; + m_vertices[i].texCoords.x = m_textureRect.left + m_textureRect.width * xratio; + m_vertices[i].texCoords.y = m_textureRect.top + m_textureRect.height * yratio; + } +} + + +//////////////////////////////////////////////////////////// +void Shape::updateOutline() +{ + unsigned int count = m_vertices.getVertexCount() - 2; + m_outlineVertices.resize((count + 1) * 2); + + for (unsigned int i = 0; i < count; ++i) + { + unsigned int index = i + 1; + + // Get the two segments shared by the current point + Vector2f p0 = (i == 0) ? m_vertices[count].position : m_vertices[index - 1].position; + Vector2f p1 = m_vertices[index].position; + Vector2f p2 = m_vertices[index + 1].position; + + // Compute their normal + Vector2f n1 = computeNormal(p0, p1); + Vector2f n2 = computeNormal(p1, p2); + + // Make sure that the normals point towards the outside of the shape + // (this depends on the order in which the points were defined) + if (dotProduct(n1, m_vertices[0].position - p1) > 0) + n1 = -n1; + if (dotProduct(n2, m_vertices[0].position - p1) > 0) + n2 = -n2; + + // Combine them to get the extrusion direction + float factor = 1.f + (n1.x * n2.x + n1.y * n2.y); + Vector2f normal = (n1 + n2) / factor; + + // Update the outline points + m_outlineVertices[i * 2 + 0].position = p1; + m_outlineVertices[i * 2 + 1].position = p1 + normal * m_outlineThickness; + } + + // Duplicate the first point at the end, to close the outline + m_outlineVertices[count * 2 + 0].position = m_outlineVertices[0].position; + m_outlineVertices[count * 2 + 1].position = m_outlineVertices[1].position; + + // Update outline colors + updateOutlineColors(); + + // Update the shape's bounds + m_bounds = m_outlineVertices.getBounds(); +} + + +//////////////////////////////////////////////////////////// +void Shape::updateOutlineColors() +{ + for (unsigned int i = 0; i < m_outlineVertices.getVertexCount(); ++i) + m_outlineVertices[i].color = m_outlineColor; +} + +} // namespace sf diff --git a/src/SFML/Graphics/Sprite.cpp b/src/SFML/Graphics/Sprite.cpp index fe8ed266..eeb82e82 100644 --- a/src/SFML/Graphics/Sprite.cpp +++ b/src/SFML/Graphics/Sprite.cpp @@ -1,174 +1,174 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Sprite::Sprite() : -m_texture (NULL), -m_textureRect() -{ -} - - -//////////////////////////////////////////////////////////// -Sprite::Sprite(const Texture& texture) : -m_texture (NULL), -m_textureRect() -{ - setTexture(texture); -} - - -//////////////////////////////////////////////////////////// -Sprite::Sprite(const Texture& texture, const IntRect& rectangle) : -m_texture (NULL), -m_textureRect() -{ - setTexture(texture); - setTextureRect(rectangle); -} - - -//////////////////////////////////////////////////////////// -void Sprite::setTexture(const Texture& texture, bool resetRect) -{ - // Recompute the texture area if requested, or if there was no valid texture & rect before - if (resetRect || (!m_texture && (m_textureRect == sf::IntRect()))) - setTextureRect(IntRect(0, 0, texture.getSize().x, texture.getSize().y)); - - // Assign the new texture - m_texture = &texture; -} - - -//////////////////////////////////////////////////////////// -void Sprite::setTextureRect(const IntRect& rectangle) -{ - if (rectangle != m_textureRect) - { - m_textureRect = rectangle; - updatePositions(); - updateTexCoords(); - } -} - - -//////////////////////////////////////////////////////////// -void Sprite::setColor(const Color& color) -{ - // Update the vertices' color - m_vertices[0].color = color; - m_vertices[1].color = color; - m_vertices[2].color = color; - m_vertices[3].color = color; -} - - -//////////////////////////////////////////////////////////// -const Texture* Sprite::getTexture() const -{ - return m_texture; -} - - -//////////////////////////////////////////////////////////// -const IntRect& Sprite::getTextureRect() const -{ - return m_textureRect; -} - - -//////////////////////////////////////////////////////////// -const Color& Sprite::getColor() const -{ - return m_vertices[0].color; -} - - -//////////////////////////////////////////////////////////// -FloatRect Sprite::getLocalBounds() const -{ - float width = static_cast(std::abs(m_textureRect.width)); - float height = static_cast(std::abs(m_textureRect.height)); - - return FloatRect(0.f, 0.f, width, height); -} - - -//////////////////////////////////////////////////////////// -FloatRect Sprite::getGlobalBounds() const -{ - return getTransform().transformRect(getLocalBounds()); -} - - -//////////////////////////////////////////////////////////// -void Sprite::draw(RenderTarget& target, RenderStates states) const -{ - if (m_texture) - { - states.transform *= getTransform(); - states.texture = m_texture; - target.draw(m_vertices, 4, TrianglesStrip, states); - } -} - - -//////////////////////////////////////////////////////////// -void Sprite::updatePositions() -{ - FloatRect bounds = getLocalBounds(); - - m_vertices[0].position = Vector2f(0, 0); - m_vertices[1].position = Vector2f(0, bounds.height); - m_vertices[2].position = Vector2f(bounds.width, 0); - m_vertices[3].position = Vector2f(bounds.width, bounds.height); -} - - -//////////////////////////////////////////////////////////// -void Sprite::updateTexCoords() -{ - float left = static_cast(m_textureRect.left); - float right = left + m_textureRect.width; - float top = static_cast(m_textureRect.top); - float bottom = top + m_textureRect.height; - - m_vertices[0].texCoords = Vector2f(left, top); - m_vertices[1].texCoords = Vector2f(left, bottom); - m_vertices[2].texCoords = Vector2f(right, top); - m_vertices[3].texCoords = Vector2f(right, bottom); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Sprite::Sprite() : +m_texture (NULL), +m_textureRect() +{ +} + + +//////////////////////////////////////////////////////////// +Sprite::Sprite(const Texture& texture) : +m_texture (NULL), +m_textureRect() +{ + setTexture(texture); +} + + +//////////////////////////////////////////////////////////// +Sprite::Sprite(const Texture& texture, const IntRect& rectangle) : +m_texture (NULL), +m_textureRect() +{ + setTexture(texture); + setTextureRect(rectangle); +} + + +//////////////////////////////////////////////////////////// +void Sprite::setTexture(const Texture& texture, bool resetRect) +{ + // Recompute the texture area if requested, or if there was no valid texture & rect before + if (resetRect || (!m_texture && (m_textureRect == sf::IntRect()))) + setTextureRect(IntRect(0, 0, texture.getSize().x, texture.getSize().y)); + + // Assign the new texture + m_texture = &texture; +} + + +//////////////////////////////////////////////////////////// +void Sprite::setTextureRect(const IntRect& rectangle) +{ + if (rectangle != m_textureRect) + { + m_textureRect = rectangle; + updatePositions(); + updateTexCoords(); + } +} + + +//////////////////////////////////////////////////////////// +void Sprite::setColor(const Color& color) +{ + // Update the vertices' color + m_vertices[0].color = color; + m_vertices[1].color = color; + m_vertices[2].color = color; + m_vertices[3].color = color; +} + + +//////////////////////////////////////////////////////////// +const Texture* Sprite::getTexture() const +{ + return m_texture; +} + + +//////////////////////////////////////////////////////////// +const IntRect& Sprite::getTextureRect() const +{ + return m_textureRect; +} + + +//////////////////////////////////////////////////////////// +const Color& Sprite::getColor() const +{ + return m_vertices[0].color; +} + + +//////////////////////////////////////////////////////////// +FloatRect Sprite::getLocalBounds() const +{ + float width = static_cast(std::abs(m_textureRect.width)); + float height = static_cast(std::abs(m_textureRect.height)); + + return FloatRect(0.f, 0.f, width, height); +} + + +//////////////////////////////////////////////////////////// +FloatRect Sprite::getGlobalBounds() const +{ + return getTransform().transformRect(getLocalBounds()); +} + + +//////////////////////////////////////////////////////////// +void Sprite::draw(RenderTarget& target, RenderStates states) const +{ + if (m_texture) + { + states.transform *= getTransform(); + states.texture = m_texture; + target.draw(m_vertices, 4, TrianglesStrip, states); + } +} + + +//////////////////////////////////////////////////////////// +void Sprite::updatePositions() +{ + FloatRect bounds = getLocalBounds(); + + m_vertices[0].position = Vector2f(0, 0); + m_vertices[1].position = Vector2f(0, bounds.height); + m_vertices[2].position = Vector2f(bounds.width, 0); + m_vertices[3].position = Vector2f(bounds.width, bounds.height); +} + + +//////////////////////////////////////////////////////////// +void Sprite::updateTexCoords() +{ + float left = static_cast(m_textureRect.left); + float right = left + m_textureRect.width; + float top = static_cast(m_textureRect.top); + float bottom = top + m_textureRect.height; + + m_vertices[0].texCoords = Vector2f(left, top); + m_vertices[1].texCoords = Vector2f(left, bottom); + m_vertices[2].texCoords = Vector2f(right, top); + m_vertices[3].texCoords = Vector2f(right, bottom); +} + +} // namespace sf diff --git a/src/SFML/Graphics/Text.cpp b/src/SFML/Graphics/Text.cpp index f333b501..5a83e3b2 100644 --- a/src/SFML/Graphics/Text.cpp +++ b/src/SFML/Graphics/Text.cpp @@ -1,411 +1,411 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Text::Text() : -m_string (), -m_font (NULL), -m_characterSize (30), -m_style (Regular), -m_color (255, 255, 255), -m_vertices (Triangles), -m_bounds (), -m_geometryNeedUpdate(false) -{ - -} - - -//////////////////////////////////////////////////////////// -Text::Text(const String& string, const Font& font, unsigned int characterSize) : -m_string (string), -m_font (&font), -m_characterSize (characterSize), -m_style (Regular), -m_color (255, 255, 255), -m_vertices (Triangles), -m_bounds (), -m_geometryNeedUpdate(true) -{ - -} - - -//////////////////////////////////////////////////////////// -void Text::setString(const String& string) -{ - if (m_string != string) - { - m_string = string; - m_geometryNeedUpdate = true; - } -} - - -//////////////////////////////////////////////////////////// -void Text::setFont(const Font& font) -{ - if (m_font != &font) - { - m_font = &font; - m_geometryNeedUpdate = true; - } -} - - -//////////////////////////////////////////////////////////// -void Text::setCharacterSize(unsigned int size) -{ - if (m_characterSize != size) - { - m_characterSize = size; - m_geometryNeedUpdate = true; - } -} - - -//////////////////////////////////////////////////////////// -void Text::setStyle(Uint32 style) -{ - if (m_style != style) - { - m_style = style; - m_geometryNeedUpdate = true; - } -} - - -//////////////////////////////////////////////////////////// -void Text::setColor(const Color& color) -{ - if (color != m_color) - { - m_color = color; - - // Change vertex colors directly, no need to update whole geometry - // (if geometry is updated anyway, we can skip this step) - if (!m_geometryNeedUpdate) - { - for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i) - m_vertices[i].color = m_color; - } - } -} - - -//////////////////////////////////////////////////////////// -const String& Text::getString() const -{ - return m_string; -} - - -//////////////////////////////////////////////////////////// -const Font* Text::getFont() const -{ - return m_font; -} - - -//////////////////////////////////////////////////////////// -unsigned int Text::getCharacterSize() const -{ - return m_characterSize; -} - - -//////////////////////////////////////////////////////////// -Uint32 Text::getStyle() const -{ - return m_style; -} - - -//////////////////////////////////////////////////////////// -const Color& Text::getColor() const -{ - return m_color; -} - - -//////////////////////////////////////////////////////////// -Vector2f Text::findCharacterPos(std::size_t index) const -{ - // Make sure that we have a valid font - if (!m_font) - return Vector2f(); - - // Adjust the index if it's out of range - if (index > m_string.getSize()) - index = m_string.getSize(); - - // Precompute the variables needed by the algorithm - bool bold = (m_style & Bold) != 0; - float hspace = static_cast(m_font->getGlyph(L' ', m_characterSize, bold).advance); - float vspace = static_cast(m_font->getLineSpacing(m_characterSize)); - - // Compute the position - Vector2f position; - Uint32 prevChar = 0; - for (std::size_t i = 0; i < index; ++i) - { - Uint32 curChar = m_string[i]; - - // Apply the kerning offset - position.x += static_cast(m_font->getKerning(prevChar, curChar, m_characterSize)); - prevChar = curChar; - - // Handle special characters - switch (curChar) - { - case ' ' : position.x += hspace; continue; - case '\t' : position.x += hspace * 4; continue; - case '\n' : position.y += vspace; position.x = 0; continue; - } - - // For regular characters, add the advance offset of the glyph - position.x += static_cast(m_font->getGlyph(curChar, m_characterSize, bold).advance); - } - - // Transform the position to global coordinates - position = getTransform().transformPoint(position); - - return position; -} - - -//////////////////////////////////////////////////////////// -FloatRect Text::getLocalBounds() const -{ - ensureGeometryUpdate(); - - return m_bounds; -} - - -//////////////////////////////////////////////////////////// -FloatRect Text::getGlobalBounds() const -{ - return getTransform().transformRect(getLocalBounds()); -} - - -//////////////////////////////////////////////////////////// -void Text::draw(RenderTarget& target, RenderStates states) const -{ - if (m_font) - { - ensureGeometryUpdate(); - - states.transform *= getTransform(); - states.texture = &m_font->getTexture(m_characterSize); - target.draw(m_vertices, states); - } -} - - -//////////////////////////////////////////////////////////// -void Text::ensureGeometryUpdate() const -{ - // Do nothing, if geometry has not changed - if (!m_geometryNeedUpdate) - return; - - // Mark geometry as updated - m_geometryNeedUpdate = false; - - // Clear the previous geometry - m_vertices.clear(); - m_bounds = FloatRect(); - - // No font: nothing to draw - if (!m_font) - return; - - // No text: nothing to draw - if (m_string.isEmpty()) - return; - - // Compute values related to the text style - bool bold = (m_style & Bold) != 0; - bool underlined = (m_style & Underlined) != 0; - bool strikeThrough = (m_style & StrikeThrough) != 0; - float italic = (m_style & Italic) ? 0.208f : 0.f; // 12 degrees - float underlineOffset = m_font->getUnderlinePosition(m_characterSize); - float underlineThickness = m_font->getUnderlineThickness(m_characterSize); - - // Compute the location of the strike through dynamically - // We use the center point of the lowercase 'x' glyph as the reference - // We reuse the underline thickness as the thickness of the strike through as well - FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, bold).bounds; - float strikeThroughOffset = xBounds.top + xBounds.height / 2.f; - - // Precompute the variables needed by the algorithm - float hspace = static_cast(m_font->getGlyph(L' ', m_characterSize, bold).advance); - float vspace = static_cast(m_font->getLineSpacing(m_characterSize)); - float x = 0.f; - float y = static_cast(m_characterSize); - - // Create one quad for each character - float minX = static_cast(m_characterSize); - float minY = static_cast(m_characterSize); - float maxX = 0.f; - float maxY = 0.f; - Uint32 prevChar = 0; - for (std::size_t i = 0; i < m_string.getSize(); ++i) - { - Uint32 curChar = m_string[i]; - - // Apply the kerning offset - x += static_cast(m_font->getKerning(prevChar, curChar, m_characterSize)); - prevChar = curChar; - - // If we're using the underlined style and there's a new line, draw a line - if (underlined && (curChar == L'\n')) - { - float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f); - float bottom = top + std::floor(underlineThickness + 0.5f); - - m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1))); - } - - // If we're using the strike through style and there's a new line, draw a line across all characters - if (strikeThrough && (curChar == L'\n')) - { - float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f); - float bottom = top + std::floor(underlineThickness + 0.5f); - - m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1))); - } - - // Handle special characters - if ((curChar == ' ') || (curChar == '\t') || (curChar == '\n')) - { - // Update the current bounds (min coordinates) - minX = std::min(minX, x); - minY = std::min(minY, y); - - switch (curChar) - { - case ' ' : x += hspace; break; - case '\t' : x += hspace * 4; break; - case '\n' : y += vspace; x = 0; break; - } - - // Update the current bounds (max coordinates) - maxX = std::max(maxX, x); - maxY = std::max(maxY, y); - - // Next glyph, no need to create a quad for whitespace - continue; - } - - // Extract the current glyph's description - const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, bold); - - float left = glyph.bounds.left; - float top = glyph.bounds.top; - float right = glyph.bounds.left + glyph.bounds.width; - float bottom = glyph.bounds.top + glyph.bounds.height; - - float u1 = static_cast(glyph.textureRect.left); - float v1 = static_cast(glyph.textureRect.top); - float u2 = static_cast(glyph.textureRect.left + glyph.textureRect.width); - float v2 = static_cast(glyph.textureRect.top + glyph.textureRect.height); - - // Add a quad for the current character - m_vertices.append(Vertex(Vector2f(x + left - italic * top, y + top), m_color, Vector2f(u1, v1))); - m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1))); - m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2))); - m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2))); - m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1))); - m_vertices.append(Vertex(Vector2f(x + right - italic * bottom, y + bottom), m_color, Vector2f(u2, v2))); - - // Update the current bounds - minX = std::min(minX, x + left - italic * bottom); - maxX = std::max(maxX, x + right - italic * top); - minY = std::min(minY, y + top); - maxY = std::max(maxY, y + bottom); - - // Advance to the next character - x += glyph.advance; - } - - // If we're using the underlined style, add the last line - if (underlined) - { - float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f); - float bottom = top + std::floor(underlineThickness + 0.5f); - - m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1))); - } - - // If we're using the strike through style, add the last line across all characters - if (strikeThrough) - { - float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f); - float bottom = top + std::floor(underlineThickness + 0.5f); - - m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); - m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1))); - } - - // Update the bounding rectangle - m_bounds.left = minX; - m_bounds.top = minY; - m_bounds.width = maxX - minX; - m_bounds.height = maxY - minY; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Text::Text() : +m_string (), +m_font (NULL), +m_characterSize (30), +m_style (Regular), +m_color (255, 255, 255), +m_vertices (Triangles), +m_bounds (), +m_geometryNeedUpdate(false) +{ + +} + + +//////////////////////////////////////////////////////////// +Text::Text(const String& string, const Font& font, unsigned int characterSize) : +m_string (string), +m_font (&font), +m_characterSize (characterSize), +m_style (Regular), +m_color (255, 255, 255), +m_vertices (Triangles), +m_bounds (), +m_geometryNeedUpdate(true) +{ + +} + + +//////////////////////////////////////////////////////////// +void Text::setString(const String& string) +{ + if (m_string != string) + { + m_string = string; + m_geometryNeedUpdate = true; + } +} + + +//////////////////////////////////////////////////////////// +void Text::setFont(const Font& font) +{ + if (m_font != &font) + { + m_font = &font; + m_geometryNeedUpdate = true; + } +} + + +//////////////////////////////////////////////////////////// +void Text::setCharacterSize(unsigned int size) +{ + if (m_characterSize != size) + { + m_characterSize = size; + m_geometryNeedUpdate = true; + } +} + + +//////////////////////////////////////////////////////////// +void Text::setStyle(Uint32 style) +{ + if (m_style != style) + { + m_style = style; + m_geometryNeedUpdate = true; + } +} + + +//////////////////////////////////////////////////////////// +void Text::setColor(const Color& color) +{ + if (color != m_color) + { + m_color = color; + + // Change vertex colors directly, no need to update whole geometry + // (if geometry is updated anyway, we can skip this step) + if (!m_geometryNeedUpdate) + { + for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i) + m_vertices[i].color = m_color; + } + } +} + + +//////////////////////////////////////////////////////////// +const String& Text::getString() const +{ + return m_string; +} + + +//////////////////////////////////////////////////////////// +const Font* Text::getFont() const +{ + return m_font; +} + + +//////////////////////////////////////////////////////////// +unsigned int Text::getCharacterSize() const +{ + return m_characterSize; +} + + +//////////////////////////////////////////////////////////// +Uint32 Text::getStyle() const +{ + return m_style; +} + + +//////////////////////////////////////////////////////////// +const Color& Text::getColor() const +{ + return m_color; +} + + +//////////////////////////////////////////////////////////// +Vector2f Text::findCharacterPos(std::size_t index) const +{ + // Make sure that we have a valid font + if (!m_font) + return Vector2f(); + + // Adjust the index if it's out of range + if (index > m_string.getSize()) + index = m_string.getSize(); + + // Precompute the variables needed by the algorithm + bool bold = (m_style & Bold) != 0; + float hspace = static_cast(m_font->getGlyph(L' ', m_characterSize, bold).advance); + float vspace = static_cast(m_font->getLineSpacing(m_characterSize)); + + // Compute the position + Vector2f position; + Uint32 prevChar = 0; + for (std::size_t i = 0; i < index; ++i) + { + Uint32 curChar = m_string[i]; + + // Apply the kerning offset + position.x += static_cast(m_font->getKerning(prevChar, curChar, m_characterSize)); + prevChar = curChar; + + // Handle special characters + switch (curChar) + { + case ' ': position.x += hspace; continue; + case '\t': position.x += hspace * 4; continue; + case '\n': position.y += vspace; position.x = 0; continue; + } + + // For regular characters, add the advance offset of the glyph + position.x += static_cast(m_font->getGlyph(curChar, m_characterSize, bold).advance); + } + + // Transform the position to global coordinates + position = getTransform().transformPoint(position); + + return position; +} + + +//////////////////////////////////////////////////////////// +FloatRect Text::getLocalBounds() const +{ + ensureGeometryUpdate(); + + return m_bounds; +} + + +//////////////////////////////////////////////////////////// +FloatRect Text::getGlobalBounds() const +{ + return getTransform().transformRect(getLocalBounds()); +} + + +//////////////////////////////////////////////////////////// +void Text::draw(RenderTarget& target, RenderStates states) const +{ + if (m_font) + { + ensureGeometryUpdate(); + + states.transform *= getTransform(); + states.texture = &m_font->getTexture(m_characterSize); + target.draw(m_vertices, states); + } +} + + +//////////////////////////////////////////////////////////// +void Text::ensureGeometryUpdate() const +{ + // Do nothing, if geometry has not changed + if (!m_geometryNeedUpdate) + return; + + // Mark geometry as updated + m_geometryNeedUpdate = false; + + // Clear the previous geometry + m_vertices.clear(); + m_bounds = FloatRect(); + + // No font: nothing to draw + if (!m_font) + return; + + // No text: nothing to draw + if (m_string.isEmpty()) + return; + + // Compute values related to the text style + bool bold = (m_style & Bold) != 0; + bool underlined = (m_style & Underlined) != 0; + bool strikeThrough = (m_style & StrikeThrough) != 0; + float italic = (m_style & Italic) ? 0.208f : 0.f; // 12 degrees + float underlineOffset = m_font->getUnderlinePosition(m_characterSize); + float underlineThickness = m_font->getUnderlineThickness(m_characterSize); + + // Compute the location of the strike through dynamically + // We use the center point of the lowercase 'x' glyph as the reference + // We reuse the underline thickness as the thickness of the strike through as well + FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, bold).bounds; + float strikeThroughOffset = xBounds.top + xBounds.height / 2.f; + + // Precompute the variables needed by the algorithm + float hspace = static_cast(m_font->getGlyph(L' ', m_characterSize, bold).advance); + float vspace = static_cast(m_font->getLineSpacing(m_characterSize)); + float x = 0.f; + float y = static_cast(m_characterSize); + + // Create one quad for each character + float minX = static_cast(m_characterSize); + float minY = static_cast(m_characterSize); + float maxX = 0.f; + float maxY = 0.f; + Uint32 prevChar = 0; + for (std::size_t i = 0; i < m_string.getSize(); ++i) + { + Uint32 curChar = m_string[i]; + + // Apply the kerning offset + x += static_cast(m_font->getKerning(prevChar, curChar, m_characterSize)); + prevChar = curChar; + + // If we're using the underlined style and there's a new line, draw a line + if (underlined && (curChar == L'\n')) + { + float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f); + float bottom = top + std::floor(underlineThickness + 0.5f); + + m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1))); + } + + // If we're using the strike through style and there's a new line, draw a line across all characters + if (strikeThrough && (curChar == L'\n')) + { + float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f); + float bottom = top + std::floor(underlineThickness + 0.5f); + + m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1))); + } + + // Handle special characters + if ((curChar == ' ') || (curChar == '\t') || (curChar == '\n')) + { + // Update the current bounds (min coordinates) + minX = std::min(minX, x); + minY = std::min(minY, y); + + switch (curChar) + { + case ' ': x += hspace; break; + case '\t': x += hspace * 4; break; + case '\n': y += vspace; x = 0; break; + } + + // Update the current bounds (max coordinates) + maxX = std::max(maxX, x); + maxY = std::max(maxY, y); + + // Next glyph, no need to create a quad for whitespace + continue; + } + + // Extract the current glyph's description + const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, bold); + + float left = glyph.bounds.left; + float top = glyph.bounds.top; + float right = glyph.bounds.left + glyph.bounds.width; + float bottom = glyph.bounds.top + glyph.bounds.height; + + float u1 = static_cast(glyph.textureRect.left); + float v1 = static_cast(glyph.textureRect.top); + float u2 = static_cast(glyph.textureRect.left + glyph.textureRect.width); + float v2 = static_cast(glyph.textureRect.top + glyph.textureRect.height); + + // Add a quad for the current character + m_vertices.append(Vertex(Vector2f(x + left - italic * top, y + top), m_color, Vector2f(u1, v1))); + m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1))); + m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2))); + m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2))); + m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1))); + m_vertices.append(Vertex(Vector2f(x + right - italic * bottom, y + bottom), m_color, Vector2f(u2, v2))); + + // Update the current bounds + minX = std::min(minX, x + left - italic * bottom); + maxX = std::max(maxX, x + right - italic * top); + minY = std::min(minY, y + top); + maxY = std::max(maxY, y + bottom); + + // Advance to the next character + x += glyph.advance; + } + + // If we're using the underlined style, add the last line + if (underlined) + { + float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f); + float bottom = top + std::floor(underlineThickness + 0.5f); + + m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1))); + } + + // If we're using the strike through style, add the last line across all characters + if (strikeThrough) + { + float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f); + float bottom = top + std::floor(underlineThickness + 0.5f); + + m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1))); + m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1))); + } + + // Update the bounding rectangle + m_bounds.left = minX; + m_bounds.top = minY; + m_bounds.width = maxX - minX; + m_bounds.height = maxY - minY; +} + +} // namespace sf diff --git a/src/SFML/Graphics/TextureSaver.hpp b/src/SFML/Graphics/TextureSaver.hpp index 2cd9b11f..2880e196 100644 --- a/src/SFML/Graphics/TextureSaver.hpp +++ b/src/SFML/Graphics/TextureSaver.hpp @@ -41,7 +41,7 @@ namespace priv //////////////////////////////////////////////////////////// class TextureSaver { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -59,7 +59,7 @@ public : //////////////////////////////////////////////////////////// ~TextureSaver(); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/Graphics/View.cpp b/src/SFML/Graphics/View.cpp index e83b837d..ba9f6730 100644 --- a/src/SFML/Graphics/View.cpp +++ b/src/SFML/Graphics/View.cpp @@ -1,240 +1,240 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -View::View() : -m_center (), -m_size (), -m_rotation (0), -m_viewport (0, 0, 1, 1), -m_transformUpdated (false), -m_invTransformUpdated(false) -{ - reset(FloatRect(0, 0, 1000, 1000)); -} - - -//////////////////////////////////////////////////////////// -View::View(const FloatRect& rectangle) : -m_center (), -m_size (), -m_rotation (0), -m_viewport (0, 0, 1, 1), -m_transformUpdated (false), -m_invTransformUpdated(false) -{ - reset(rectangle); -} - - -//////////////////////////////////////////////////////////// -View::View(const Vector2f& center, const Vector2f& size) : -m_center (center), -m_size (size), -m_rotation (0), -m_viewport (0, 0, 1, 1), -m_transformUpdated (false), -m_invTransformUpdated(false) -{ - -} - -//////////////////////////////////////////////////////////// -void View::setCenter(float x, float y) -{ - m_center.x = x; - m_center.y = y; - - m_transformUpdated = false; - m_invTransformUpdated = false; -} - - -//////////////////////////////////////////////////////////// -void View::setCenter(const Vector2f& center) -{ - setCenter(center.x, center.y); -} - - -//////////////////////////////////////////////////////////// -void View::setSize(float width, float height) -{ - m_size.x = width; - m_size.y = height; - - m_transformUpdated = false; - m_invTransformUpdated = false; -} - - -//////////////////////////////////////////////////////////// -void View::setSize(const Vector2f& size) -{ - setSize(size.x, size.y); -} - - -//////////////////////////////////////////////////////////// -void View::setRotation(float angle) -{ - m_rotation = static_cast(fmod(angle, 360)); - if (m_rotation < 0) - m_rotation += 360.f; - - m_transformUpdated = false; - m_invTransformUpdated = false; -} - - -//////////////////////////////////////////////////////////// -void View::setViewport(const FloatRect& viewport) -{ - m_viewport = viewport; -} - - -//////////////////////////////////////////////////////////// -void View::reset(const FloatRect& rectangle) -{ - m_center.x = rectangle.left + rectangle.width / 2.f; - m_center.y = rectangle.top + rectangle.height / 2.f; - m_size.x = rectangle.width; - m_size.y = rectangle.height; - m_rotation = 0; - - m_transformUpdated = false; - m_invTransformUpdated = false; -} - - -//////////////////////////////////////////////////////////// -const Vector2f& View::getCenter() const -{ - return m_center; -} - - -//////////////////////////////////////////////////////////// -const Vector2f& View::getSize() const -{ - return m_size; -} - - -//////////////////////////////////////////////////////////// -float View::getRotation() const -{ - return m_rotation; -} - - -//////////////////////////////////////////////////////////// -const FloatRect& View::getViewport() const -{ - return m_viewport; -} - - -//////////////////////////////////////////////////////////// -void View::move(float offsetX, float offsetY) -{ - setCenter(m_center.x + offsetX, m_center.y + offsetY); -} - - -//////////////////////////////////////////////////////////// -void View::move(const Vector2f& offset) -{ - setCenter(m_center + offset); -} - - -//////////////////////////////////////////////////////////// -void View::rotate(float angle) -{ - setRotation(m_rotation + angle); -} - - -//////////////////////////////////////////////////////////// -void View::zoom(float factor) -{ - setSize(m_size.x * factor, m_size.y * factor); -} - - -//////////////////////////////////////////////////////////// -const Transform& View::getTransform() const -{ - // Recompute the matrix if needed - if (!m_transformUpdated) - { - // Rotation components - float angle = m_rotation * 3.141592654f / 180.f; - float cosine = static_cast(std::cos(angle)); - float sine = static_cast(std::sin(angle)); - float tx = -m_center.x * cosine - m_center.y * sine + m_center.x; - float ty = m_center.x * sine - m_center.y * cosine + m_center.y; - - // Projection components - float a = 2.f / m_size.x; - float b = -2.f / m_size.y; - float c = -a * m_center.x; - float d = -b * m_center.y; - - // Rebuild the projection matrix - m_transform = Transform( a * cosine, a * sine, a * tx + c, - -b * sine, b * cosine, b * ty + d, - 0.f, 0.f, 1.f); - m_transformUpdated = true; - } - - return m_transform; -} - - -//////////////////////////////////////////////////////////// -const Transform& View::getInverseTransform() const -{ - // Recompute the matrix if needed - if (!m_invTransformUpdated) - { - m_inverseTransform = getTransform().getInverse(); - m_invTransformUpdated = true; - } - - return m_inverseTransform; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +View::View() : +m_center (), +m_size (), +m_rotation (0), +m_viewport (0, 0, 1, 1), +m_transformUpdated (false), +m_invTransformUpdated(false) +{ + reset(FloatRect(0, 0, 1000, 1000)); +} + + +//////////////////////////////////////////////////////////// +View::View(const FloatRect& rectangle) : +m_center (), +m_size (), +m_rotation (0), +m_viewport (0, 0, 1, 1), +m_transformUpdated (false), +m_invTransformUpdated(false) +{ + reset(rectangle); +} + + +//////////////////////////////////////////////////////////// +View::View(const Vector2f& center, const Vector2f& size) : +m_center (center), +m_size (size), +m_rotation (0), +m_viewport (0, 0, 1, 1), +m_transformUpdated (false), +m_invTransformUpdated(false) +{ + +} + +//////////////////////////////////////////////////////////// +void View::setCenter(float x, float y) +{ + m_center.x = x; + m_center.y = y; + + m_transformUpdated = false; + m_invTransformUpdated = false; +} + + +//////////////////////////////////////////////////////////// +void View::setCenter(const Vector2f& center) +{ + setCenter(center.x, center.y); +} + + +//////////////////////////////////////////////////////////// +void View::setSize(float width, float height) +{ + m_size.x = width; + m_size.y = height; + + m_transformUpdated = false; + m_invTransformUpdated = false; +} + + +//////////////////////////////////////////////////////////// +void View::setSize(const Vector2f& size) +{ + setSize(size.x, size.y); +} + + +//////////////////////////////////////////////////////////// +void View::setRotation(float angle) +{ + m_rotation = static_cast(fmod(angle, 360)); + if (m_rotation < 0) + m_rotation += 360.f; + + m_transformUpdated = false; + m_invTransformUpdated = false; +} + + +//////////////////////////////////////////////////////////// +void View::setViewport(const FloatRect& viewport) +{ + m_viewport = viewport; +} + + +//////////////////////////////////////////////////////////// +void View::reset(const FloatRect& rectangle) +{ + m_center.x = rectangle.left + rectangle.width / 2.f; + m_center.y = rectangle.top + rectangle.height / 2.f; + m_size.x = rectangle.width; + m_size.y = rectangle.height; + m_rotation = 0; + + m_transformUpdated = false; + m_invTransformUpdated = false; +} + + +//////////////////////////////////////////////////////////// +const Vector2f& View::getCenter() const +{ + return m_center; +} + + +//////////////////////////////////////////////////////////// +const Vector2f& View::getSize() const +{ + return m_size; +} + + +//////////////////////////////////////////////////////////// +float View::getRotation() const +{ + return m_rotation; +} + + +//////////////////////////////////////////////////////////// +const FloatRect& View::getViewport() const +{ + return m_viewport; +} + + +//////////////////////////////////////////////////////////// +void View::move(float offsetX, float offsetY) +{ + setCenter(m_center.x + offsetX, m_center.y + offsetY); +} + + +//////////////////////////////////////////////////////////// +void View::move(const Vector2f& offset) +{ + setCenter(m_center + offset); +} + + +//////////////////////////////////////////////////////////// +void View::rotate(float angle) +{ + setRotation(m_rotation + angle); +} + + +//////////////////////////////////////////////////////////// +void View::zoom(float factor) +{ + setSize(m_size.x * factor, m_size.y * factor); +} + + +//////////////////////////////////////////////////////////// +const Transform& View::getTransform() const +{ + // Recompute the matrix if needed + if (!m_transformUpdated) + { + // Rotation components + float angle = m_rotation * 3.141592654f / 180.f; + float cosine = static_cast(std::cos(angle)); + float sine = static_cast(std::sin(angle)); + float tx = -m_center.x * cosine - m_center.y * sine + m_center.x; + float ty = m_center.x * sine - m_center.y * cosine + m_center.y; + + // Projection components + float a = 2.f / m_size.x; + float b = -2.f / m_size.y; + float c = -a * m_center.x; + float d = -b * m_center.y; + + // Rebuild the projection matrix + m_transform = Transform( a * cosine, a * sine, a * tx + c, + -b * sine, b * cosine, b * ty + d, + 0.f, 0.f, 1.f); + m_transformUpdated = true; + } + + return m_transform; +} + + +//////////////////////////////////////////////////////////// +const Transform& View::getInverseTransform() const +{ + // Recompute the matrix if needed + if (!m_invTransformUpdated) + { + m_inverseTransform = getTransform().getInverse(); + m_invTransformUpdated = true; + } + + return m_inverseTransform; +} + +} // namespace sf diff --git a/src/SFML/Main/CMakeLists.txt b/src/SFML/Main/CMakeLists.txt index c4c0d540..ac006c39 100644 --- a/src/SFML/Main/CMakeLists.txt +++ b/src/SFML/Main/CMakeLists.txt @@ -1,37 +1,37 @@ - -set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Main) -set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Main) - -# sources -if(SFML_OS_WINDOWS) - set(SRC ${SRC} ${SRCROOT}/MainWin32.cpp) -elseif(SFML_OS_IOS) - set(SRC ${SRC} ${SRCROOT}/MainiOS.mm) -elseif(SFML_OS_ANDROID) - set(SRC ${SRC} ${SRCROOT}/MainAndroid.cpp) -else() - return() -endif() -source_group("" FILES ${SRC}) - -# define the sfml-main target -add_library(sfml-main STATIC ${SRC}) - -# set the debug suffix -set_target_properties(sfml-main PROPERTIES DEBUG_POSTFIX -d) - -# insert the major version number in the output filename -set_target_properties(sfml-main PROPERTIES OUTPUT_NAME "sfml-main") - -# set the target's folder (for IDEs that support it, e.g. Visual Studio) -set_target_properties(sfml-main PROPERTIES FOLDER "SFML") - -# setup the install rule -install(TARGETS sfml-main ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel) - -# because of a current limitation on Android (which prevents one library -# from depending on shared libraries), we need a boostrap activity which -# will load our shared libraries manually -if(SFML_OS_ANDROID) - sfml_add_library(sfml-activity SOURCES ${PROJECT_SOURCE_DIR}/src/SFML/Main/SFMLActivity.cpp) -endif() + +set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Main) +set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Main) + +# sources +if(SFML_OS_WINDOWS) + set(SRC ${SRC} ${SRCROOT}/MainWin32.cpp) +elseif(SFML_OS_IOS) + set(SRC ${SRC} ${SRCROOT}/MainiOS.mm) +elseif(SFML_OS_ANDROID) + set(SRC ${SRC} ${SRCROOT}/MainAndroid.cpp) +else() + return() +endif() +source_group("" FILES ${SRC}) + +# define the sfml-main target +add_library(sfml-main STATIC ${SRC}) + +# set the debug suffix +set_target_properties(sfml-main PROPERTIES DEBUG_POSTFIX -d) + +# insert the major version number in the output filename +set_target_properties(sfml-main PROPERTIES OUTPUT_NAME "sfml-main") + +# set the target's folder (for IDEs that support it, e.g. Visual Studio) +set_target_properties(sfml-main PROPERTIES FOLDER "SFML") + +# setup the install rule +install(TARGETS sfml-main ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel) + +# because of a current limitation on Android (which prevents one library +# from depending on shared libraries), we need a boostrap activity which +# will load our shared libraries manually +if(SFML_OS_ANDROID) + sfml_add_library(sfml-activity SOURCES ${PROJECT_SOURCE_DIR}/src/SFML/Main/SFMLActivity.cpp) +endif() diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index 67d88db8..db79d1f3 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -1,512 +1,512 @@ -//////////////////////////////////////////////////////////// -// +//////////////////////////////////////////////////////////// +// // SFML - Simple and Fast Multimedia Library // Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -// Android specific: we define the ANativeActivity_onCreate -// entry point, handling all the native activity stuff, then -// we call the user defined (and portable) main function in -// an external thread so developers can keep a portable code -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#ifdef SFML_SYSTEM_ANDROID - -#include -#include -#include -#include -#include -#include -#include - - -extern int main(int argc, char *argv[]); - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -ActivityStates* retrieveStates(ANativeActivity* activity) -{ - // Hide the ugly cast we find in each callback function - return (ActivityStates*)activity->instance; -} - - -//////////////////////////////////////////////////////////// -static void initializeMain(ActivityStates* states) -{ - // Protect from concurent access - Lock lock(states->mutex); - - // Prepare and share the looper to be read later - ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); - states->looper = looper; - - // Get the default configuration - states->config = AConfiguration_new(); - AConfiguration_fromAssetManager(states->config, states->activity->assetManager); -} - - -//////////////////////////////////////////////////////////// -static void terminateMain(ActivityStates* states) -{ - // Protect from concurent access - Lock lock(states->mutex); - - // The main thread has finished, we must explicitly ask the activity to finish - states->mainOver = true; - ANativeActivity_finish(states->activity); -} - - -//////////////////////////////////////////////////////////// -void* main(ActivityStates* states) -{ - // Initialize the thread before giving the hand - initializeMain(states); - - sleep(seconds(0.5)); - ::main(0, NULL); - - // Terminate properly the main thread and wait until it's done - terminateMain(states); - - { - Lock lock(states->mutex); - - states->terminated = true; - } - - return NULL; -} - -} // namespace priv -} // namespace sf - - -//////////////////////////////////////////////////////////// -void goToFullscreenMode(ANativeActivity* activity) -{ - // Hide the status bar - ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_FULLSCREEN, - AWINDOW_FLAG_FULLSCREEN); - - // Hide the navigation bar - JavaVM* lJavaVM = activity->vm; - JNIEnv* lJNIEnv = activity->env; - - jobject objectActivity = activity->clazz; - jclass classActivity = lJNIEnv->GetObjectClass(objectActivity); - - jmethodID methodGetWindow = lJNIEnv->GetMethodID(classActivity, "getWindow", "()Landroid/view/Window;"); - jobject objectWindow = lJNIEnv->CallObjectMethod(objectActivity, methodGetWindow); - - jclass classWindow = lJNIEnv->FindClass("android/view/Window"); - jmethodID methodGetDecorView = lJNIEnv->GetMethodID(classWindow, "getDecorView", "()Landroid/view/View;"); - jobject objectDecorView = lJNIEnv->CallObjectMethod(objectWindow, methodGetDecorView); - - jclass classView = lJNIEnv->FindClass("android/view/View"); - - jfieldID FieldSYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_LOW_PROFILE", "I"); - jint SYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_LOW_PROFILE); - - jfieldID FieldSYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_FULLSCREEN", "I"); - jint SYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_FULLSCREEN); - - //jfieldID FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY", "I"); - //jint SYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY); - - jmethodID methodsetSystemUiVisibility = lJNIEnv->GetMethodID(classView, "setSystemUiVisibility", "(I)V"); - lJNIEnv->CallVoidMethod(objectDecorView, methodsetSystemUiVisibility, SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN | 0x00001000); -} - -//////////////////////////////////////////////////////////// - -void getScreenSizeInPixels(ANativeActivity* activity, int* width, int* height) -{ - // Perform the following java code: - // - // DisplayMetrics dm = new DisplayMetrics(); - // getWindowManager().getDefaultDisplay().getMetrics(dm); - - JavaVM* lJavaVM = activity->vm; - JNIEnv* lJNIEnv = activity->env; - - jobject objectActivity = activity->clazz; - jclass classActivity = lJNIEnv->GetObjectClass(objectActivity); - - jclass classDisplayMetrics = lJNIEnv->FindClass("android/util/DisplayMetrics"); - jmethodID initDisplayMetrics = lJNIEnv->GetMethodID(classDisplayMetrics, "", "()V"); - jobject objectDisplayMetrics = lJNIEnv->NewObject(classDisplayMetrics, initDisplayMetrics); - - jmethodID methodGetWindowManager = lJNIEnv->GetMethodID(classActivity, "getWindowManager", "()Landroid/view/WindowManager;"); - jobject objectWindowManager = lJNIEnv->CallObjectMethod(objectActivity, methodGetWindowManager); - - jclass classWindowManager = lJNIEnv->FindClass("android/view/WindowManager"); - jmethodID methodGetDefaultDisplay = lJNIEnv->GetMethodID(classWindowManager, "getDefaultDisplay", "()Landroid/view/Display;"); - jobject objectDisplay = lJNIEnv->CallObjectMethod(objectWindowManager, methodGetDefaultDisplay); - - jclass classDisplay = lJNIEnv->FindClass("android/view/Display"); - jmethodID methodGetMetrics = lJNIEnv->GetMethodID(classDisplay, "getMetrics", "(Landroid/util/DisplayMetrics;)V"); - lJNIEnv->CallVoidMethod(objectDisplay, methodGetMetrics, objectDisplayMetrics); - - jfieldID fieldWidthPixels = lJNIEnv->GetFieldID(classDisplayMetrics, "widthPixels", "I"); - jfieldID fieldHeightPixels = lJNIEnv->GetFieldID(classDisplayMetrics, "heightPixels", "I"); - - *width = lJNIEnv->GetIntField(objectDisplayMetrics, fieldWidthPixels); - *height = lJNIEnv->GetIntField(objectDisplayMetrics, fieldHeightPixels); -} - - -//////////////////////////////////////////////////////////// -static void onStart(ANativeActivity* activity) -{ -} - - -//////////////////////////////////////////////////////////// -static void onResume(ANativeActivity* activity) -{ - // Retrieve our activity states from the activity instance - sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - sf::Lock lock(states->mutex); - - if (states->fullscreen) - goToFullscreenMode(activity); - - // Send an event to warn people the activity has been resumed - sf::Event event; - event.type = sf::Event::MouseEntered; - - states->forwardEvent(event); -} - - -//////////////////////////////////////////////////////////// -static void onPause(ANativeActivity* activity) -{ - // Retrieve our activity states from the activity instance - sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - sf::Lock lock(states->mutex); - - // Send an event to warn people the activity has been paused - sf::Event event; - event.type = sf::Event::MouseLeft; - - states->forwardEvent(event); -} - - -//////////////////////////////////////////////////////////// -static void onStop(ANativeActivity* activity) -{ -} - - -//////////////////////////////////////////////////////////// -static void onDestroy(ANativeActivity* activity) -{ - // Retrieve our activity states from the activity instance - sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - - // Send an event to warn people the activity is being destroyed - { - sf::Lock lock(states->mutex); - - // If the main thread hasn't yet finished, send the event and wait for - // it to finish. - if (!states->mainOver) - { - sf::Event event; - event.type = sf::Event::Closed; - - states->forwardEvent(event); - } - } - - // Wait for the main thread to be terminated - states->mutex.lock(); - - while (!states->terminated) - { - states->mutex.unlock(); - sf::sleep(sf::milliseconds(20)); - states->mutex.lock(); - } - - states->mutex.unlock(); - - // Terminate EGL display - eglTerminate(states->display); - - // Delete our allocated states - delete states; - - // Reset the activity pointer for all modules - sf::priv::getActivity(NULL, true); - - // The application should now terminate -} - - -//////////////////////////////////////////////////////////// -static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) -{ - sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - sf::Lock lock(states->mutex); - - // Update the activity states - states->window = window; - - // Notify SFML mechanism - sf::Event event; - event.type = sf::Event::GainedFocus; - states->forwardEvent(event); - - // Wait for the event to be taken into account by SFML - states->updated = false; - while(!states->updated) - { - states->mutex.unlock(); - sf::sleep(sf::milliseconds(10)); - states->mutex.lock(); - } -} - - -//////////////////////////////////////////////////////////// -static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) -{ - sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - sf::Lock lock(states->mutex); - - // Update the activity states - states->window = NULL; - - // Notify SFML mechanism - sf::Event event; - event.type = sf::Event::LostFocus; - states->forwardEvent(event); - - // Wait for the event to be taken into account by SFML - states->updated = false; - while(!states->updated) - { - states->mutex.unlock(); - sf::sleep(sf::milliseconds(10)); - states->mutex.lock(); - } -} - - -//////////////////////////////////////////////////////////// -static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) -{ -} - - -//////////////////////////////////////////////////////////// -static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) -{ -} - - -//////////////////////////////////////////////////////////// -static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) -{ - // Retrieve our activity states from the activity instance - sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - - // Attach the input queue - { - sf::Lock lock(states->mutex); - - AInputQueue_attachLooper(queue, states->looper, 1, states->processEvent, NULL); - states->inputQueue = queue; - } -} - - -//////////////////////////////////////////////////////////// -static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) -{ - // Retrieve our activity states from the activity instance - sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - - // Detach the input queue - { - sf::Lock lock(states->mutex); - - states->inputQueue = NULL; - AInputQueue_detachLooper(queue); - } -} - - -//////////////////////////////////////////////////////////// -static void onWindowFocusChanged(ANativeActivity* activity, int focused) -{ -} - - -//////////////////////////////////////////////////////////// -static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) -{ - // Retrieve our activity states from the activity instance - sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - sf::Lock lock(states->mutex); - - // Send an event to warn people about the window move/resize - sf::Event event; - event.type = sf::Event::Resized; - event.size.width = ANativeWindow_getWidth(states->window); - event.size.height = ANativeWindow_getHeight(states->window); - - states->forwardEvent(event); -} - - -//////////////////////////////////////////////////////////// -static void onConfigurationChanged(ANativeActivity* activity) -{ -} - - -//////////////////////////////////////////////////////////// -static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) -{ - *outLen = 0; - - return NULL; -} - - -//////////////////////////////////////////////////////////// -static void onLowMemory(ANativeActivity* activity) -{ -} - - -//////////////////////////////////////////////////////////// -void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) -{ - // Create an activity states (will keep us in the know, about events we care) - sf::priv::ActivityStates* states = NULL; - states = new sf::priv::ActivityStates; - - // Initialize the states value - states->activity = NULL; - states->window = NULL; - states->looper = NULL; - states->inputQueue = NULL; - states->config = NULL; - - for (unsigned int i = 0; i < sf::Mouse::ButtonCount; i++) - states->isButtonPressed[i] = false; +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// - states->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - - if (savedState != NULL) - { - states->savedState = malloc(savedStateSize); - states->savedStateSize = savedStateSize; - memcpy(states->savedState, savedState, savedStateSize); - } - - states->mainOver = false; - - states->initialized = false; - states->terminated = false; - - // Share it across the SFML modules - sf::priv::getActivity(states, true); - - // These functions will update the activity states and therefore, will allow - // SFML to be kept in the know - activity->callbacks->onStart = onStart; - activity->callbacks->onResume = onResume; - activity->callbacks->onPause = onPause; - activity->callbacks->onStop = onStop; - activity->callbacks->onDestroy = onDestroy; - - activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; - activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; - activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded; - activity->callbacks->onNativeWindowResized = onNativeWindowResized; - - activity->callbacks->onInputQueueCreated = onInputQueueCreated; - activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; - - activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; - activity->callbacks->onContentRectChanged = onContentRectChanged; - activity->callbacks->onConfigurationChanged = onConfigurationChanged; - - activity->callbacks->onSaveInstanceState = onSaveInstanceState; - activity->callbacks->onLowMemory = onLowMemory; - - // Share this activity with the callback functions - states->activity = activity; - - // Keep the screen turned on and bright - ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON, - AWINDOW_FLAG_KEEP_SCREEN_ON); - - // Initialize the display - eglInitialize(states->display, NULL, NULL); - - getScreenSizeInPixels(activity, &states->screenSize.x, &states->screenSize.y); - - // Redirect error messages to logcat - sf::err().rdbuf(&states->logcat); - - // Launch the main thread - sf::Thread* thread = new sf::Thread(sf::priv::main, states); - thread->launch(); - - // Wait for the main thread to be initialized - states->mutex.lock(); - - while (!states->initialized) - { - states->mutex.unlock(); - sf::sleep(sf::milliseconds(20)); - states->mutex.lock(); - } - - states->mutex.unlock(); - - // Share this state with the callback functions - activity->instance = states; -} - -#endif // SFML_SYSTEM_ANDROID + +//////////////////////////////////////////////////////////// +// Android specific: we define the ANativeActivity_onCreate +// entry point, handling all the native activity stuff, then +// we call the user defined (and portable) main function in +// an external thread so developers can keep a portable code +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#ifdef SFML_SYSTEM_ANDROID + +#include +#include +#include +#include +#include +#include +#include + + +extern int main(int argc, char *argv[]); + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +ActivityStates* retrieveStates(ANativeActivity* activity) +{ + // Hide the ugly cast we find in each callback function + return (ActivityStates*)activity->instance; +} + + +//////////////////////////////////////////////////////////// +static void initializeMain(ActivityStates* states) +{ + // Protect from concurent access + Lock lock(states->mutex); + + // Prepare and share the looper to be read later + ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); + states->looper = looper; + + // Get the default configuration + states->config = AConfiguration_new(); + AConfiguration_fromAssetManager(states->config, states->activity->assetManager); +} + + +//////////////////////////////////////////////////////////// +static void terminateMain(ActivityStates* states) +{ + // Protect from concurent access + Lock lock(states->mutex); + + // The main thread has finished, we must explicitly ask the activity to finish + states->mainOver = true; + ANativeActivity_finish(states->activity); +} + + +//////////////////////////////////////////////////////////// +void* main(ActivityStates* states) +{ + // Initialize the thread before giving the hand + initializeMain(states); + + sleep(seconds(0.5)); + ::main(0, NULL); + + // Terminate properly the main thread and wait until it's done + terminateMain(states); + + { + Lock lock(states->mutex); + + states->terminated = true; + } + + return NULL; +} + +} // namespace priv +} // namespace sf + + +//////////////////////////////////////////////////////////// +void goToFullscreenMode(ANativeActivity* activity) +{ + // Hide the status bar + ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_FULLSCREEN, + AWINDOW_FLAG_FULLSCREEN); + + // Hide the navigation bar + JavaVM* lJavaVM = activity->vm; + JNIEnv* lJNIEnv = activity->env; + + jobject objectActivity = activity->clazz; + jclass classActivity = lJNIEnv->GetObjectClass(objectActivity); + + jmethodID methodGetWindow = lJNIEnv->GetMethodID(classActivity, "getWindow", "()Landroid/view/Window;"); + jobject objectWindow = lJNIEnv->CallObjectMethod(objectActivity, methodGetWindow); + + jclass classWindow = lJNIEnv->FindClass("android/view/Window"); + jmethodID methodGetDecorView = lJNIEnv->GetMethodID(classWindow, "getDecorView", "()Landroid/view/View;"); + jobject objectDecorView = lJNIEnv->CallObjectMethod(objectWindow, methodGetDecorView); + + jclass classView = lJNIEnv->FindClass("android/view/View"); + + jfieldID FieldSYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_LOW_PROFILE", "I"); + jint SYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_LOW_PROFILE); + + jfieldID FieldSYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_FULLSCREEN", "I"); + jint SYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_FULLSCREEN); + + //jfieldID FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY", "I"); + //jint SYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY); + + jmethodID methodsetSystemUiVisibility = lJNIEnv->GetMethodID(classView, "setSystemUiVisibility", "(I)V"); + lJNIEnv->CallVoidMethod(objectDecorView, methodsetSystemUiVisibility, SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN | 0x00001000); +} + +//////////////////////////////////////////////////////////// + +void getScreenSizeInPixels(ANativeActivity* activity, int* width, int* height) +{ + // Perform the following java code: + // + // DisplayMetrics dm = new DisplayMetrics(); + // getWindowManager().getDefaultDisplay().getMetrics(dm); + + JavaVM* lJavaVM = activity->vm; + JNIEnv* lJNIEnv = activity->env; + + jobject objectActivity = activity->clazz; + jclass classActivity = lJNIEnv->GetObjectClass(objectActivity); + + jclass classDisplayMetrics = lJNIEnv->FindClass("android/util/DisplayMetrics"); + jmethodID initDisplayMetrics = lJNIEnv->GetMethodID(classDisplayMetrics, "", "()V"); + jobject objectDisplayMetrics = lJNIEnv->NewObject(classDisplayMetrics, initDisplayMetrics); + + jmethodID methodGetWindowManager = lJNIEnv->GetMethodID(classActivity, "getWindowManager", "()Landroid/view/WindowManager;"); + jobject objectWindowManager = lJNIEnv->CallObjectMethod(objectActivity, methodGetWindowManager); + + jclass classWindowManager = lJNIEnv->FindClass("android/view/WindowManager"); + jmethodID methodGetDefaultDisplay = lJNIEnv->GetMethodID(classWindowManager, "getDefaultDisplay", "()Landroid/view/Display;"); + jobject objectDisplay = lJNIEnv->CallObjectMethod(objectWindowManager, methodGetDefaultDisplay); + + jclass classDisplay = lJNIEnv->FindClass("android/view/Display"); + jmethodID methodGetMetrics = lJNIEnv->GetMethodID(classDisplay, "getMetrics", "(Landroid/util/DisplayMetrics;)V"); + lJNIEnv->CallVoidMethod(objectDisplay, methodGetMetrics, objectDisplayMetrics); + + jfieldID fieldWidthPixels = lJNIEnv->GetFieldID(classDisplayMetrics, "widthPixels", "I"); + jfieldID fieldHeightPixels = lJNIEnv->GetFieldID(classDisplayMetrics, "heightPixels", "I"); + + *width = lJNIEnv->GetIntField(objectDisplayMetrics, fieldWidthPixels); + *height = lJNIEnv->GetIntField(objectDisplayMetrics, fieldHeightPixels); +} + + +//////////////////////////////////////////////////////////// +static void onStart(ANativeActivity* activity) +{ +} + + +//////////////////////////////////////////////////////////// +static void onResume(ANativeActivity* activity) +{ + // Retrieve our activity states from the activity instance + sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); + sf::Lock lock(states->mutex); + + if (states->fullscreen) + goToFullscreenMode(activity); + + // Send an event to warn people the activity has been resumed + sf::Event event; + event.type = sf::Event::MouseEntered; + + states->forwardEvent(event); +} + + +//////////////////////////////////////////////////////////// +static void onPause(ANativeActivity* activity) +{ + // Retrieve our activity states from the activity instance + sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); + sf::Lock lock(states->mutex); + + // Send an event to warn people the activity has been paused + sf::Event event; + event.type = sf::Event::MouseLeft; + + states->forwardEvent(event); +} + + +//////////////////////////////////////////////////////////// +static void onStop(ANativeActivity* activity) +{ +} + + +//////////////////////////////////////////////////////////// +static void onDestroy(ANativeActivity* activity) +{ + // Retrieve our activity states from the activity instance + sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); + + // Send an event to warn people the activity is being destroyed + { + sf::Lock lock(states->mutex); + + // If the main thread hasn't yet finished, send the event and wait for + // it to finish. + if (!states->mainOver) + { + sf::Event event; + event.type = sf::Event::Closed; + + states->forwardEvent(event); + } + } + + // Wait for the main thread to be terminated + states->mutex.lock(); + + while (!states->terminated) + { + states->mutex.unlock(); + sf::sleep(sf::milliseconds(20)); + states->mutex.lock(); + } + + states->mutex.unlock(); + + // Terminate EGL display + eglTerminate(states->display); + + // Delete our allocated states + delete states; + + // Reset the activity pointer for all modules + sf::priv::getActivity(NULL, true); + + // The application should now terminate +} + + +//////////////////////////////////////////////////////////// +static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) +{ + sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); + sf::Lock lock(states->mutex); + + // Update the activity states + states->window = window; + + // Notify SFML mechanism + sf::Event event; + event.type = sf::Event::GainedFocus; + states->forwardEvent(event); + + // Wait for the event to be taken into account by SFML + states->updated = false; + while(!states->updated) + { + states->mutex.unlock(); + sf::sleep(sf::milliseconds(10)); + states->mutex.lock(); + } +} + + +//////////////////////////////////////////////////////////// +static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) +{ + sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); + sf::Lock lock(states->mutex); + + // Update the activity states + states->window = NULL; + + // Notify SFML mechanism + sf::Event event; + event.type = sf::Event::LostFocus; + states->forwardEvent(event); + + // Wait for the event to be taken into account by SFML + states->updated = false; + while(!states->updated) + { + states->mutex.unlock(); + sf::sleep(sf::milliseconds(10)); + states->mutex.lock(); + } +} + + +//////////////////////////////////////////////////////////// +static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) +{ +} + + +//////////////////////////////////////////////////////////// +static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) +{ +} + + +//////////////////////////////////////////////////////////// +static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) +{ + // Retrieve our activity states from the activity instance + sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); + + // Attach the input queue + { + sf::Lock lock(states->mutex); + + AInputQueue_attachLooper(queue, states->looper, 1, states->processEvent, NULL); + states->inputQueue = queue; + } +} + + +//////////////////////////////////////////////////////////// +static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) +{ + // Retrieve our activity states from the activity instance + sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); + + // Detach the input queue + { + sf::Lock lock(states->mutex); + + states->inputQueue = NULL; + AInputQueue_detachLooper(queue); + } +} + + +//////////////////////////////////////////////////////////// +static void onWindowFocusChanged(ANativeActivity* activity, int focused) +{ +} + + +//////////////////////////////////////////////////////////// +static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) +{ + // Retrieve our activity states from the activity instance + sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); + sf::Lock lock(states->mutex); + + // Send an event to warn people about the window move/resize + sf::Event event; + event.type = sf::Event::Resized; + event.size.width = ANativeWindow_getWidth(states->window); + event.size.height = ANativeWindow_getHeight(states->window); + + states->forwardEvent(event); +} + + +//////////////////////////////////////////////////////////// +static void onConfigurationChanged(ANativeActivity* activity) +{ +} + + +//////////////////////////////////////////////////////////// +static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) +{ + *outLen = 0; + + return NULL; +} + + +//////////////////////////////////////////////////////////// +static void onLowMemory(ANativeActivity* activity) +{ +} + + +//////////////////////////////////////////////////////////// +void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) +{ + // Create an activity states (will keep us in the know, about events we care) + sf::priv::ActivityStates* states = NULL; + states = new sf::priv::ActivityStates; + + // Initialize the states value + states->activity = NULL; + states->window = NULL; + states->looper = NULL; + states->inputQueue = NULL; + states->config = NULL; + + for (unsigned int i = 0; i < sf::Mouse::ButtonCount; i++) + states->isButtonPressed[i] = false; + + states->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + if (savedState != NULL) + { + states->savedState = malloc(savedStateSize); + states->savedStateSize = savedStateSize; + memcpy(states->savedState, savedState, savedStateSize); + } + + states->mainOver = false; + + states->initialized = false; + states->terminated = false; + + // Share it across the SFML modules + sf::priv::getActivity(states, true); + + // These functions will update the activity states and therefore, will allow + // SFML to be kept in the know + activity->callbacks->onStart = onStart; + activity->callbacks->onResume = onResume; + activity->callbacks->onPause = onPause; + activity->callbacks->onStop = onStop; + activity->callbacks->onDestroy = onDestroy; + + activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; + activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; + activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded; + activity->callbacks->onNativeWindowResized = onNativeWindowResized; + + activity->callbacks->onInputQueueCreated = onInputQueueCreated; + activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; + + activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; + activity->callbacks->onContentRectChanged = onContentRectChanged; + activity->callbacks->onConfigurationChanged = onConfigurationChanged; + + activity->callbacks->onSaveInstanceState = onSaveInstanceState; + activity->callbacks->onLowMemory = onLowMemory; + + // Share this activity with the callback functions + states->activity = activity; + + // Keep the screen turned on and bright + ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON, + AWINDOW_FLAG_KEEP_SCREEN_ON); + + // Initialize the display + eglInitialize(states->display, NULL, NULL); + + getScreenSizeInPixels(activity, &states->screenSize.x, &states->screenSize.y); + + // Redirect error messages to logcat + sf::err().rdbuf(&states->logcat); + + // Launch the main thread + sf::Thread* thread = new sf::Thread(sf::priv::main, states); + thread->launch(); + + // Wait for the main thread to be initialized + states->mutex.lock(); + + while (!states->initialized) + { + states->mutex.unlock(); + sf::sleep(sf::milliseconds(20)); + states->mutex.lock(); + } + + states->mutex.unlock(); + + // Share this state with the callback functions + activity->instance = states; +} + +#endif // SFML_SYSTEM_ANDROID diff --git a/src/SFML/Main/MainWin32.cpp b/src/SFML/Main/MainWin32.cpp index 33374e55..25a6247a 100644 --- a/src/SFML/Main/MainWin32.cpp +++ b/src/SFML/Main/MainWin32.cpp @@ -1,54 +1,54 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) -// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -// Windows specific: we define the WinMain entry point, -// so that developers can use the standard main function -// even in a Win32 Application project, and thus keep a -// portable code -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#ifdef SFML_SYSTEM_WINDOWS - -#include - - -extern int main(int argc, char* argv[]); - -//////////////////////////////////////////////////////////// -int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT) -{ - return main(__argc, __argv); -} - -#endif // SFML_SYSTEM_WINDOWS - +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +// Windows specific: we define the WinMain entry point, +// so that developers can use the standard main function +// even in a Win32 Application project, and thus keep a +// portable code +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#ifdef SFML_SYSTEM_WINDOWS + +#include + + +extern int main(int argc, char* argv[]); + +//////////////////////////////////////////////////////////// +int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT) +{ + return main(__argc, __argv); +} + +#endif // SFML_SYSTEM_WINDOWS + diff --git a/src/SFML/Main/MainiOS.mm b/src/SFML/Main/MainiOS.mm index 5a362c3d..ec07810e 100644 --- a/src/SFML/Main/MainiOS.mm +++ b/src/SFML/Main/MainiOS.mm @@ -1,63 +1,63 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) -// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -// iOS specific: SFML needs to hook the main function, to -// launch the iOS application (event loop), and then call the -// user main from inside it. -// -// Our strategy is to rename the user main to 'sfmlMain' with -// a macro (see Main.hpp), and call this modified main ourselves. -// -// Note that half of this trick (the sfmlMain placeholders and -// the application delegate) is defined sfml-window; see there -// for the full implementation. -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#ifdef SFML_SYSTEM_IOS - -#include - - -//////////////////////////////////////////////////////////// -int main(int argc, char** argv) -{ - // Note: we intentionally drop command line arguments, - // there's no such thing as a command line on an iOS device :) - - // Important: "SFAppDelegate" must always match the name of the - // application delegate class defined in sfml-window - - return UIApplicationMain(argc, argv, nil, @"SFAppDelegate"); -} - -#endif // SFML_SYSTEM_IOS +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +// iOS specific: SFML needs to hook the main function, to +// launch the iOS application (event loop), and then call the +// user main from inside it. +// +// Our strategy is to rename the user main to 'sfmlMain' with +// a macro (see Main.hpp), and call this modified main ourselves. +// +// Note that half of this trick (the sfmlMain placeholders and +// the application delegate) is defined sfml-window; see there +// for the full implementation. +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#ifdef SFML_SYSTEM_IOS + +#include + + +//////////////////////////////////////////////////////////// +int main(int argc, char** argv) +{ + // Note: we intentionally drop command line arguments, + // there's no such thing as a command line on an iOS device :) + + // Important: "SFAppDelegate" must always match the name of the + // application delegate class defined in sfml-window + + return UIApplicationMain(argc, argv, nil, @"SFAppDelegate"); +} + +#endif // SFML_SYSTEM_IOS diff --git a/src/SFML/Network/CMakeLists.txt b/src/SFML/Network/CMakeLists.txt index 60bc50f3..d1ff7572 100644 --- a/src/SFML/Network/CMakeLists.txt +++ b/src/SFML/Network/CMakeLists.txt @@ -1,57 +1,57 @@ - -set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Network) -set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Network) - -# all source files -set(SRC - ${INCROOT}/Export.hpp - ${SRCROOT}/Ftp.cpp - ${INCROOT}/Ftp.hpp - ${SRCROOT}/Http.cpp - ${INCROOT}/Http.hpp - ${SRCROOT}/IpAddress.cpp - ${INCROOT}/IpAddress.hpp - ${SRCROOT}/Packet.cpp - ${INCROOT}/Packet.hpp - ${SRCROOT}/Socket.cpp - ${INCROOT}/Socket.hpp - ${SRCROOT}/SocketImpl.hpp - ${INCROOT}/SocketHandle.hpp - ${SRCROOT}/SocketSelector.cpp - ${INCROOT}/SocketSelector.hpp - ${SRCROOT}/TcpListener.cpp - ${INCROOT}/TcpListener.hpp - ${SRCROOT}/TcpSocket.cpp - ${INCROOT}/TcpSocket.hpp - ${SRCROOT}/UdpSocket.cpp - ${INCROOT}/UdpSocket.hpp -) - -# add platform specific sources -if(SFML_OS_WINDOWS) - set(SRC - ${SRC} - ${SRCROOT}/Win32/SocketImpl.cpp - ${SRCROOT}/Win32/SocketImpl.hpp - ) -else() - set(SRC - ${SRC} - ${SRCROOT}/Unix/SocketImpl.cpp - ${SRCROOT}/Unix/SocketImpl.hpp - ) -endif() - -source_group("" FILES ${SRC}) - -# build the list of external libraries to link -set(NETWORK_EXT_LIBS) -if(SFML_OS_WINDOWS) - set(NETWORK_EXT_LIBS ${NETWORK_EXT_LIBS} ws2_32) -endif() - -# define the sfml-network target -sfml_add_library(sfml-network - SOURCES ${SRC} - DEPENDS sfml-system - EXTERNAL_LIBS ${NETWORK_EXT_LIBS}) + +set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Network) +set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Network) + +# all source files +set(SRC + ${INCROOT}/Export.hpp + ${SRCROOT}/Ftp.cpp + ${INCROOT}/Ftp.hpp + ${SRCROOT}/Http.cpp + ${INCROOT}/Http.hpp + ${SRCROOT}/IpAddress.cpp + ${INCROOT}/IpAddress.hpp + ${SRCROOT}/Packet.cpp + ${INCROOT}/Packet.hpp + ${SRCROOT}/Socket.cpp + ${INCROOT}/Socket.hpp + ${SRCROOT}/SocketImpl.hpp + ${INCROOT}/SocketHandle.hpp + ${SRCROOT}/SocketSelector.cpp + ${INCROOT}/SocketSelector.hpp + ${SRCROOT}/TcpListener.cpp + ${INCROOT}/TcpListener.hpp + ${SRCROOT}/TcpSocket.cpp + ${INCROOT}/TcpSocket.hpp + ${SRCROOT}/UdpSocket.cpp + ${INCROOT}/UdpSocket.hpp +) + +# add platform specific sources +if(SFML_OS_WINDOWS) + set(SRC + ${SRC} + ${SRCROOT}/Win32/SocketImpl.cpp + ${SRCROOT}/Win32/SocketImpl.hpp + ) +else() + set(SRC + ${SRC} + ${SRCROOT}/Unix/SocketImpl.cpp + ${SRCROOT}/Unix/SocketImpl.hpp + ) +endif() + +source_group("" FILES ${SRC}) + +# build the list of external libraries to link +set(NETWORK_EXT_LIBS) +if(SFML_OS_WINDOWS) + set(NETWORK_EXT_LIBS ${NETWORK_EXT_LIBS} ws2_32) +endif() + +# define the sfml-network target +sfml_add_library(sfml-network + SOURCES ${SRC} + DEPENDS sfml-system + EXTERNAL_LIBS ${NETWORK_EXT_LIBS}) diff --git a/src/SFML/Network/Ftp.cpp b/src/SFML/Network/Ftp.cpp index ddaad408..0f4049e4 100644 --- a/src/SFML/Network/Ftp.cpp +++ b/src/SFML/Network/Ftp.cpp @@ -1,640 +1,640 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -class Ftp::DataChannel : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - DataChannel(Ftp& owner); - - //////////////////////////////////////////////////////////// - Ftp::Response open(Ftp::TransferMode mode); - - //////////////////////////////////////////////////////////// - void send(std::istream& stream); - - //////////////////////////////////////////////////////////// - void receive(std::ostream& stream); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Ftp& m_ftp; ///< Reference to the owner Ftp instance - TcpSocket m_dataSocket; ///< Socket used for data transfers -}; - - -//////////////////////////////////////////////////////////// -Ftp::Response::Response(Status code, const std::string& message) : -m_status (code), -m_message(message) -{ - -} - - -//////////////////////////////////////////////////////////// -bool Ftp::Response::isOk() const -{ - return m_status < 400; -} - - -//////////////////////////////////////////////////////////// -Ftp::Response::Status Ftp::Response::getStatus() const -{ - return m_status; -} - - -//////////////////////////////////////////////////////////// -const std::string& Ftp::Response::getMessage() const -{ - return m_message; -} - - -//////////////////////////////////////////////////////////// -Ftp::DirectoryResponse::DirectoryResponse(const Ftp::Response& response) : -Ftp::Response(response) -{ - if (isOk()) - { - // Extract the directory from the server response - std::string::size_type begin = getMessage().find('"', 0); - std::string::size_type end = getMessage().find('"', begin + 1); - m_directory = getMessage().substr(begin + 1, end - begin - 1); - } -} - - -//////////////////////////////////////////////////////////// -const std::string& Ftp::DirectoryResponse::getDirectory() const -{ - return m_directory; -} - - -//////////////////////////////////////////////////////////// -Ftp::ListingResponse::ListingResponse(const Ftp::Response& response, const std::string& data) : -Ftp::Response(response) -{ - if (isOk()) - { - // Fill the array of strings - std::string::size_type lastPos = 0; - for (std::string::size_type pos = data.find("\r\n"); pos != std::string::npos; pos = data.find("\r\n", lastPos)) - { - m_listing.push_back(data.substr(lastPos, pos - lastPos)); - lastPos = pos + 2; - } - } -} - - -//////////////////////////////////////////////////////////// -const std::vector& Ftp::ListingResponse::getListing() const -{ - return m_listing; -} - - -//////////////////////////////////////////////////////////// -Ftp::~Ftp() -{ - disconnect(); -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::connect(const IpAddress& server, unsigned short port, Time timeout) -{ - // Connect to the server - if (m_commandSocket.connect(server, port, timeout) != Socket::Done) - return Response(Response::ConnectionFailed); - - // Get the response to the connection - return getResponse(); -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::login() -{ - return login("anonymous", "user@sfml-dev.org"); -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::login(const std::string& name, const std::string& password) -{ - Response response = sendCommand("USER", name); - if (response.isOk()) - response = sendCommand("PASS", password); - - return response; -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::disconnect() -{ - // Send the exit command - Response response = sendCommand("QUIT"); - if (response.isOk()) - m_commandSocket.disconnect(); - - return response; -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::keepAlive() -{ - return sendCommand("NOOP"); -} - - -//////////////////////////////////////////////////////////// -Ftp::DirectoryResponse Ftp::getWorkingDirectory() -{ - return DirectoryResponse(sendCommand("PWD")); -} - - -//////////////////////////////////////////////////////////// -Ftp::ListingResponse Ftp::getDirectoryListing(const std::string& directory) -{ - // Open a data channel on default port (20) using ASCII transfer mode - std::ostringstream directoryData; - DataChannel data(*this); - Response response = data.open(Ascii); - if (response.isOk()) - { - // Tell the server to send us the listing - response = sendCommand("NLST", directory); - if (response.isOk()) - { - // Receive the listing - data.receive(directoryData); - - // Get the response from the server - response = getResponse(); - } - } - - return ListingResponse(response, directoryData.str()); -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::changeDirectory(const std::string& directory) -{ - return sendCommand("CWD", directory); -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::parentDirectory() -{ - return sendCommand("CDUP"); -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::createDirectory(const std::string& name) -{ - return sendCommand("MKD", name); -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::deleteDirectory(const std::string& name) -{ - return sendCommand("RMD", name); -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::renameFile(const std::string& file, const std::string& newName) -{ - Response response = sendCommand("RNFR", file); - if (response.isOk()) - response = sendCommand("RNTO", newName); - - return response; -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::deleteFile(const std::string& name) -{ - return sendCommand("DELE", name); -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::download(const std::string& remoteFile, const std::string& localPath, TransferMode mode) -{ - // Open a data channel using the given transfer mode - DataChannel data(*this); - Response response = data.open(mode); - if (response.isOk()) - { - // Tell the server to start the transfer - response = sendCommand("RETR", remoteFile); - if (response.isOk()) - { - // Extract the filename from the file path - std::string filename = remoteFile; - std::string::size_type pos = filename.find_last_of("/\\"); - if (pos != std::string::npos) - filename = filename.substr(pos + 1); - - // Make sure the destination path ends with a slash - std::string path = localPath; - if (!path.empty() && (path[path.size() - 1] != '\\') && (path[path.size() - 1] != '/')) - path += "/"; - - // Create the file and truncate it if necessary - std::ofstream file((path + filename).c_str(), std::ios_base::binary | std::ios_base::trunc); - if (!file) - return Response(Response::InvalidFile); - - // Receive the file data - data.receive(file); - - // Close the file - file.close(); - - // Get the response from the server - response = getResponse(); - - // If the download was unsuccessful, delete the partial file - if (!response.isOk()) - std::remove((path + filename).c_str()); - } - } - - return response; -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::upload(const std::string& localFile, const std::string& remotePath, TransferMode mode) -{ - // Get the contents of the file to send - std::ifstream file(localFile.c_str(), std::ios_base::binary); - if (!file) - return Response(Response::InvalidFile); - - // Extract the filename from the file path - std::string filename = localFile; - std::string::size_type pos = filename.find_last_of("/\\"); - if (pos != std::string::npos) - filename = filename.substr(pos + 1); - - // Make sure the destination path ends with a slash - std::string path = remotePath; - if (!path.empty() && (path[path.size() - 1] != '\\') && (path[path.size() - 1] != '/')) - path += "/"; - - // Open a data channel using the given transfer mode - DataChannel data(*this); - Response response = data.open(mode); - if (response.isOk()) - { - // Tell the server to start the transfer - response = sendCommand("STOR", path + filename); - if (response.isOk()) - { - // Send the file data - data.send(file); - - // Get the response from the server - response = getResponse(); - } - } - - return response; -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::sendCommand(const std::string& command, const std::string& parameter) -{ - // Build the command string - std::string commandStr; - if (parameter != "") - commandStr = command + " " + parameter + "\r\n"; - else - commandStr = command + "\r\n"; - - // Send it to the server - if (m_commandSocket.send(commandStr.c_str(), commandStr.length()) != Socket::Done) - return Response(Response::ConnectionClosed); - - // Get the response - return getResponse(); -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::getResponse() -{ - // We'll use a variable to keep track of the last valid code. - // It is useful in case of multi-lines responses, because the end of such a response - // will start by the same code - unsigned int lastCode = 0; - bool isInsideMultiline = false; - std::string message; - - for (;;) - { - // Receive the response from the server - char buffer[1024]; - std::size_t length; - if (m_commandSocket.receive(buffer, sizeof(buffer), length) != Socket::Done) - return Response(Response::ConnectionClosed); - - // There can be several lines inside the received buffer, extract them all - std::istringstream in(std::string(buffer, length), std::ios_base::binary); - while (in) - { - // Try to extract the code - unsigned int code; - if (in >> code) - { - // Extract the separator - char separator; - in.get(separator); - - // The '-' character means a multiline response - if ((separator == '-') && !isInsideMultiline) - { - // Set the multiline flag - isInsideMultiline = true; - - // Keep track of the code - if (lastCode == 0) - lastCode = code; - - // Extract the line - std::getline(in, message); - - // Remove the ending '\r' (all lines are terminated by "\r\n") - message.erase(message.length() - 1); - message = separator + message + "\n"; - } - else - { - // We must make sure that the code is the same, otherwise it means - // we haven't reached the end of the multiline response - if ((separator != '-') && ((code == lastCode) || (lastCode == 0))) - { - // Extract the line - std::string line; - std::getline(in, line); - - // Remove the ending '\r' (all lines are terminated by "\r\n") - line.erase(line.length() - 1); - - // Append it to the message - if (code == lastCode) - { - std::ostringstream out; - out << code << separator << line; - message += out.str(); - } - else - { - message = separator + line; - } - - // Return the response code and message - return Response(static_cast(code), message); - } - else - { - // The line we just read was actually not a response, - // only a new part of the current multiline response - - // Extract the line - std::string line; - std::getline(in, line); - - if (!line.empty()) - { - // Remove the ending '\r' (all lines are terminated by "\r\n") - line.erase(line.length() - 1); - - // Append it to the current message - std::ostringstream out; - out << code << separator << line << "\n"; - message += out.str(); - } - } - } - } - else if (lastCode != 0) - { - // It seems we are in the middle of a multiline response - - // Clear the error bits of the stream - in.clear(); - - // Extract the line - std::string line; - std::getline(in, line); - - if (!line.empty()) - { - // Remove the ending '\r' (all lines are terminated by "\r\n") - line.erase(line.length() - 1); - - // Append it to the current message - message += line + "\n"; - } - } - else - { - // Error : cannot extract the code, and we are not in a multiline response - return Response(Response::InvalidResponse); - } - } - } - - // We never reach there -} - - -//////////////////////////////////////////////////////////// -Ftp::DataChannel::DataChannel(Ftp& owner) : -m_ftp(owner) -{ - -} - - -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::DataChannel::open(Ftp::TransferMode mode) -{ - // Open a data connection in active mode (we connect to the server) - Ftp::Response response = m_ftp.sendCommand("PASV"); - if (response.isOk()) - { - // Extract the connection address and port from the response - std::string::size_type begin = response.getMessage().find_first_of("0123456789"); - if (begin != std::string::npos) - { - Uint8 data[6] = {0, 0, 0, 0, 0, 0}; - std::string str = response.getMessage().substr(begin); - std::size_t index = 0; - for (int i = 0; i < 6; ++i) - { - // Extract the current number - while (isdigit(str[index])) - { - data[i] = data[i] * 10 + (str[index] - '0'); - index++; - } - - // Skip separator - index++; - } - - // Reconstruct connection port and address - unsigned short port = data[4] * 256 + data[5]; - IpAddress address(static_cast(data[0]), - static_cast(data[1]), - static_cast(data[2]), - static_cast(data[3])); - - // Connect the data channel to the server - if (m_dataSocket.connect(address, port) == Socket::Done) - { - // Translate the transfer mode to the corresponding FTP parameter - std::string modeStr; - switch (mode) - { - case Ftp::Binary : modeStr = "I"; break; - case Ftp::Ascii : modeStr = "A"; break; - case Ftp::Ebcdic : modeStr = "E"; break; - } - - // Set the transfer mode - response = m_ftp.sendCommand("TYPE", modeStr); - } - else - { - // Failed to connect to the server - response = Ftp::Response(Ftp::Response::ConnectionFailed); - } - } - } - - return response; -} - - -//////////////////////////////////////////////////////////// -void Ftp::DataChannel::receive(std::ostream& stream) -{ - // Receive data - char buffer[1024]; - std::size_t received; - while (m_dataSocket.receive(buffer, sizeof(buffer), received) == Socket::Done) - { - stream.write(buffer, static_cast(received)); - - if (!stream.good()) - { - err() << "FTP Error: Writing to the file has failed" << std::endl; - break; - } - } - - // Close the data socket - m_dataSocket.disconnect(); -} - - -//////////////////////////////////////////////////////////// -void Ftp::DataChannel::send(std::istream& stream) -{ - // Send data - char buffer[1024]; - std::size_t count; - - for (;;) - { - // read some data from the stream - stream.read(buffer, sizeof(buffer)); - - if (!stream.good() && !stream.eof()) - { - err() << "FTP Error: Reading from the file has failed" << std::endl; - break; - } - - count = stream.gcount(); - - if (count > 0) - { - // we could read more data from the stream: send them - if (m_dataSocket.send(buffer, count) != Socket::Done) - break; - } - else - { - // no more data: exit the loop - break; - } - } - - // Close the data socket - m_dataSocket.disconnect(); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +class Ftp::DataChannel : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + DataChannel(Ftp& owner); + + //////////////////////////////////////////////////////////// + Ftp::Response open(Ftp::TransferMode mode); + + //////////////////////////////////////////////////////////// + void send(std::istream& stream); + + //////////////////////////////////////////////////////////// + void receive(std::ostream& stream); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Ftp& m_ftp; ///< Reference to the owner Ftp instance + TcpSocket m_dataSocket; ///< Socket used for data transfers +}; + + +//////////////////////////////////////////////////////////// +Ftp::Response::Response(Status code, const std::string& message) : +m_status (code), +m_message(message) +{ + +} + + +//////////////////////////////////////////////////////////// +bool Ftp::Response::isOk() const +{ + return m_status < 400; +} + + +//////////////////////////////////////////////////////////// +Ftp::Response::Status Ftp::Response::getStatus() const +{ + return m_status; +} + + +//////////////////////////////////////////////////////////// +const std::string& Ftp::Response::getMessage() const +{ + return m_message; +} + + +//////////////////////////////////////////////////////////// +Ftp::DirectoryResponse::DirectoryResponse(const Ftp::Response& response) : +Ftp::Response(response) +{ + if (isOk()) + { + // Extract the directory from the server response + std::string::size_type begin = getMessage().find('"', 0); + std::string::size_type end = getMessage().find('"', begin + 1); + m_directory = getMessage().substr(begin + 1, end - begin - 1); + } +} + + +//////////////////////////////////////////////////////////// +const std::string& Ftp::DirectoryResponse::getDirectory() const +{ + return m_directory; +} + + +//////////////////////////////////////////////////////////// +Ftp::ListingResponse::ListingResponse(const Ftp::Response& response, const std::string& data) : +Ftp::Response(response) +{ + if (isOk()) + { + // Fill the array of strings + std::string::size_type lastPos = 0; + for (std::string::size_type pos = data.find("\r\n"); pos != std::string::npos; pos = data.find("\r\n", lastPos)) + { + m_listing.push_back(data.substr(lastPos, pos - lastPos)); + lastPos = pos + 2; + } + } +} + + +//////////////////////////////////////////////////////////// +const std::vector& Ftp::ListingResponse::getListing() const +{ + return m_listing; +} + + +//////////////////////////////////////////////////////////// +Ftp::~Ftp() +{ + disconnect(); +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::connect(const IpAddress& server, unsigned short port, Time timeout) +{ + // Connect to the server + if (m_commandSocket.connect(server, port, timeout) != Socket::Done) + return Response(Response::ConnectionFailed); + + // Get the response to the connection + return getResponse(); +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::login() +{ + return login("anonymous", "user@sfml-dev.org"); +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::login(const std::string& name, const std::string& password) +{ + Response response = sendCommand("USER", name); + if (response.isOk()) + response = sendCommand("PASS", password); + + return response; +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::disconnect() +{ + // Send the exit command + Response response = sendCommand("QUIT"); + if (response.isOk()) + m_commandSocket.disconnect(); + + return response; +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::keepAlive() +{ + return sendCommand("NOOP"); +} + + +//////////////////////////////////////////////////////////// +Ftp::DirectoryResponse Ftp::getWorkingDirectory() +{ + return DirectoryResponse(sendCommand("PWD")); +} + + +//////////////////////////////////////////////////////////// +Ftp::ListingResponse Ftp::getDirectoryListing(const std::string& directory) +{ + // Open a data channel on default port (20) using ASCII transfer mode + std::ostringstream directoryData; + DataChannel data(*this); + Response response = data.open(Ascii); + if (response.isOk()) + { + // Tell the server to send us the listing + response = sendCommand("NLST", directory); + if (response.isOk()) + { + // Receive the listing + data.receive(directoryData); + + // Get the response from the server + response = getResponse(); + } + } + + return ListingResponse(response, directoryData.str()); +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::changeDirectory(const std::string& directory) +{ + return sendCommand("CWD", directory); +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::parentDirectory() +{ + return sendCommand("CDUP"); +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::createDirectory(const std::string& name) +{ + return sendCommand("MKD", name); +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::deleteDirectory(const std::string& name) +{ + return sendCommand("RMD", name); +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::renameFile(const std::string& file, const std::string& newName) +{ + Response response = sendCommand("RNFR", file); + if (response.isOk()) + response = sendCommand("RNTO", newName); + + return response; +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::deleteFile(const std::string& name) +{ + return sendCommand("DELE", name); +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::download(const std::string& remoteFile, const std::string& localPath, TransferMode mode) +{ + // Open a data channel using the given transfer mode + DataChannel data(*this); + Response response = data.open(mode); + if (response.isOk()) + { + // Tell the server to start the transfer + response = sendCommand("RETR", remoteFile); + if (response.isOk()) + { + // Extract the filename from the file path + std::string filename = remoteFile; + std::string::size_type pos = filename.find_last_of("/\\"); + if (pos != std::string::npos) + filename = filename.substr(pos + 1); + + // Make sure the destination path ends with a slash + std::string path = localPath; + if (!path.empty() && (path[path.size() - 1] != '\\') && (path[path.size() - 1] != '/')) + path += "/"; + + // Create the file and truncate it if necessary + std::ofstream file((path + filename).c_str(), std::ios_base::binary | std::ios_base::trunc); + if (!file) + return Response(Response::InvalidFile); + + // Receive the file data + data.receive(file); + + // Close the file + file.close(); + + // Get the response from the server + response = getResponse(); + + // If the download was unsuccessful, delete the partial file + if (!response.isOk()) + std::remove((path + filename).c_str()); + } + } + + return response; +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::upload(const std::string& localFile, const std::string& remotePath, TransferMode mode) +{ + // Get the contents of the file to send + std::ifstream file(localFile.c_str(), std::ios_base::binary); + if (!file) + return Response(Response::InvalidFile); + + // Extract the filename from the file path + std::string filename = localFile; + std::string::size_type pos = filename.find_last_of("/\\"); + if (pos != std::string::npos) + filename = filename.substr(pos + 1); + + // Make sure the destination path ends with a slash + std::string path = remotePath; + if (!path.empty() && (path[path.size() - 1] != '\\') && (path[path.size() - 1] != '/')) + path += "/"; + + // Open a data channel using the given transfer mode + DataChannel data(*this); + Response response = data.open(mode); + if (response.isOk()) + { + // Tell the server to start the transfer + response = sendCommand("STOR", path + filename); + if (response.isOk()) + { + // Send the file data + data.send(file); + + // Get the response from the server + response = getResponse(); + } + } + + return response; +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::sendCommand(const std::string& command, const std::string& parameter) +{ + // Build the command string + std::string commandStr; + if (parameter != "") + commandStr = command + " " + parameter + "\r\n"; + else + commandStr = command + "\r\n"; + + // Send it to the server + if (m_commandSocket.send(commandStr.c_str(), commandStr.length()) != Socket::Done) + return Response(Response::ConnectionClosed); + + // Get the response + return getResponse(); +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::getResponse() +{ + // We'll use a variable to keep track of the last valid code. + // It is useful in case of multi-lines responses, because the end of such a response + // will start by the same code + unsigned int lastCode = 0; + bool isInsideMultiline = false; + std::string message; + + for (;;) + { + // Receive the response from the server + char buffer[1024]; + std::size_t length; + if (m_commandSocket.receive(buffer, sizeof(buffer), length) != Socket::Done) + return Response(Response::ConnectionClosed); + + // There can be several lines inside the received buffer, extract them all + std::istringstream in(std::string(buffer, length), std::ios_base::binary); + while (in) + { + // Try to extract the code + unsigned int code; + if (in >> code) + { + // Extract the separator + char separator; + in.get(separator); + + // The '-' character means a multiline response + if ((separator == '-') && !isInsideMultiline) + { + // Set the multiline flag + isInsideMultiline = true; + + // Keep track of the code + if (lastCode == 0) + lastCode = code; + + // Extract the line + std::getline(in, message); + + // Remove the ending '\r' (all lines are terminated by "\r\n") + message.erase(message.length() - 1); + message = separator + message + "\n"; + } + else + { + // We must make sure that the code is the same, otherwise it means + // we haven't reached the end of the multiline response + if ((separator != '-') && ((code == lastCode) || (lastCode == 0))) + { + // Extract the line + std::string line; + std::getline(in, line); + + // Remove the ending '\r' (all lines are terminated by "\r\n") + line.erase(line.length() - 1); + + // Append it to the message + if (code == lastCode) + { + std::ostringstream out; + out << code << separator << line; + message += out.str(); + } + else + { + message = separator + line; + } + + // Return the response code and message + return Response(static_cast(code), message); + } + else + { + // The line we just read was actually not a response, + // only a new part of the current multiline response + + // Extract the line + std::string line; + std::getline(in, line); + + if (!line.empty()) + { + // Remove the ending '\r' (all lines are terminated by "\r\n") + line.erase(line.length() - 1); + + // Append it to the current message + std::ostringstream out; + out << code << separator << line << "\n"; + message += out.str(); + } + } + } + } + else if (lastCode != 0) + { + // It seems we are in the middle of a multiline response + + // Clear the error bits of the stream + in.clear(); + + // Extract the line + std::string line; + std::getline(in, line); + + if (!line.empty()) + { + // Remove the ending '\r' (all lines are terminated by "\r\n") + line.erase(line.length() - 1); + + // Append it to the current message + message += line + "\n"; + } + } + else + { + // Error: cannot extract the code, and we are not in a multiline response + return Response(Response::InvalidResponse); + } + } + } + + // We never reach there +} + + +//////////////////////////////////////////////////////////// +Ftp::DataChannel::DataChannel(Ftp& owner) : +m_ftp(owner) +{ + +} + + +//////////////////////////////////////////////////////////// +Ftp::Response Ftp::DataChannel::open(Ftp::TransferMode mode) +{ + // Open a data connection in active mode (we connect to the server) + Ftp::Response response = m_ftp.sendCommand("PASV"); + if (response.isOk()) + { + // Extract the connection address and port from the response + std::string::size_type begin = response.getMessage().find_first_of("0123456789"); + if (begin != std::string::npos) + { + Uint8 data[6] = {0, 0, 0, 0, 0, 0}; + std::string str = response.getMessage().substr(begin); + std::size_t index = 0; + for (int i = 0; i < 6; ++i) + { + // Extract the current number + while (isdigit(str[index])) + { + data[i] = data[i] * 10 + (str[index] - '0'); + index++; + } + + // Skip separator + index++; + } + + // Reconstruct connection port and address + unsigned short port = data[4] * 256 + data[5]; + IpAddress address(static_cast(data[0]), + static_cast(data[1]), + static_cast(data[2]), + static_cast(data[3])); + + // Connect the data channel to the server + if (m_dataSocket.connect(address, port) == Socket::Done) + { + // Translate the transfer mode to the corresponding FTP parameter + std::string modeStr; + switch (mode) + { + case Ftp::Binary: modeStr = "I"; break; + case Ftp::Ascii: modeStr = "A"; break; + case Ftp::Ebcdic: modeStr = "E"; break; + } + + // Set the transfer mode + response = m_ftp.sendCommand("TYPE", modeStr); + } + else + { + // Failed to connect to the server + response = Ftp::Response(Ftp::Response::ConnectionFailed); + } + } + } + + return response; +} + + +//////////////////////////////////////////////////////////// +void Ftp::DataChannel::receive(std::ostream& stream) +{ + // Receive data + char buffer[1024]; + std::size_t received; + while (m_dataSocket.receive(buffer, sizeof(buffer), received) == Socket::Done) + { + stream.write(buffer, static_cast(received)); + + if (!stream.good()) + { + err() << "FTP Error: Writing to the file has failed" << std::endl; + break; + } + } + + // Close the data socket + m_dataSocket.disconnect(); +} + + +//////////////////////////////////////////////////////////// +void Ftp::DataChannel::send(std::istream& stream) +{ + // Send data + char buffer[1024]; + std::size_t count; + + for (;;) + { + // read some data from the stream + stream.read(buffer, sizeof(buffer)); + + if (!stream.good() && !stream.eof()) + { + err() << "FTP Error: Reading from the file has failed" << std::endl; + break; + } + + count = stream.gcount(); + + if (count > 0) + { + // we could read more data from the stream: send them + if (m_dataSocket.send(buffer, count) != Socket::Done) + break; + } + else + { + // no more data: exit the loop + break; + } + } + + // Close the data socket + m_dataSocket.disconnect(); +} + +} // namespace sf diff --git a/src/SFML/Network/Http.cpp b/src/SFML/Network/Http.cpp index 998287b9..df3ebb45 100644 --- a/src/SFML/Network/Http.cpp +++ b/src/SFML/Network/Http.cpp @@ -1,415 +1,415 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include - - -namespace -{ - // Convert a string to lower case - std::string toLower(std::string str) - { - for (std::string::iterator i = str.begin(); i != str.end(); ++i) - *i = static_cast(std::tolower(*i)); - return str; - } -} - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Http::Request::Request(const std::string& uri, Method method, const std::string& body) -{ - setMethod(method); - setUri(uri); - setHttpVersion(1, 0); - setBody(body); -} - - -//////////////////////////////////////////////////////////// -void Http::Request::setField(const std::string& field, const std::string& value) -{ - m_fields[toLower(field)] = value; -} - - -//////////////////////////////////////////////////////////// -void Http::Request::setMethod(Http::Request::Method method) -{ - m_method = method; -} - - -//////////////////////////////////////////////////////////// -void Http::Request::setUri(const std::string& uri) -{ - m_uri = uri; - - // Make sure it starts with a '/' - if (m_uri.empty() || (m_uri[0] != '/')) - m_uri.insert(0, "/"); -} - - -//////////////////////////////////////////////////////////// -void Http::Request::setHttpVersion(unsigned int major, unsigned int minor) -{ - m_majorVersion = major; - m_minorVersion = minor; -} - - -//////////////////////////////////////////////////////////// -void Http::Request::setBody(const std::string& body) -{ - m_body = body; -} - - -//////////////////////////////////////////////////////////// -std::string Http::Request::prepare() const -{ - std::ostringstream out; - - // Convert the method to its string representation - std::string method; - switch (m_method) - { - default : - case Get : method = "GET"; break; - case Post : method = "POST"; break; - case Head : method = "HEAD"; break; - case Put : method = "PUT"; break; - case Delete : method = "DELETE"; break; - } - - // Write the first line containing the request type - out << method << " " << m_uri << " "; - out << "HTTP/" << m_majorVersion << "." << m_minorVersion << "\r\n"; - - // Write fields - for (FieldTable::const_iterator i = m_fields.begin(); i != m_fields.end(); ++i) - { - out << i->first << ": " << i->second << "\r\n"; - } - - // Use an extra \r\n to separate the header from the body - out << "\r\n"; - - // Add the body - out << m_body; - - return out.str(); -} - - -//////////////////////////////////////////////////////////// -bool Http::Request::hasField(const std::string& field) const -{ - return m_fields.find(toLower(field)) != m_fields.end(); -} - - -//////////////////////////////////////////////////////////// -Http::Response::Response() : -m_status (ConnectionFailed), -m_majorVersion(0), -m_minorVersion(0) -{ - -} - - -//////////////////////////////////////////////////////////// -const std::string& Http::Response::getField(const std::string& field) const -{ - FieldTable::const_iterator it = m_fields.find(toLower(field)); - if (it != m_fields.end()) - { - return it->second; - } - else - { - static const std::string empty = ""; - return empty; - } -} - - -//////////////////////////////////////////////////////////// -Http::Response::Status Http::Response::getStatus() const -{ - return m_status; -} - - -//////////////////////////////////////////////////////////// -unsigned int Http::Response::getMajorHttpVersion() const -{ - return m_majorVersion; -} - - -//////////////////////////////////////////////////////////// -unsigned int Http::Response::getMinorHttpVersion() const -{ - return m_minorVersion; -} - - -//////////////////////////////////////////////////////////// -const std::string& Http::Response::getBody() const -{ - return m_body; -} - - -//////////////////////////////////////////////////////////// -void Http::Response::parse(const std::string& data) -{ - std::istringstream in(data); - - // Extract the HTTP version from the first line - std::string version; - if (in >> version) - { - if ((version.size() >= 8) && (version[6] == '.') && - (toLower(version.substr(0, 5)) == "http/") && - isdigit(version[5]) && isdigit(version[7])) - { - m_majorVersion = version[5] - '0'; - m_minorVersion = version[7] - '0'; - } - else - { - // Invalid HTTP version - m_status = InvalidResponse; - return; - } - } - - // Extract the status code from the first line - int status; - if (in >> status) - { - m_status = static_cast(status); - } - else - { - // Invalid status code - m_status = InvalidResponse; - return; - } - - // Ignore the end of the first line - in.ignore(std::numeric_limits::max(), '\n'); - - // Parse the other lines, which contain fields, one by one - parseFields(in); - - m_body.clear(); - - // Determine whether the transfer is chunked - if (toLower(getField("transfer-encoding")) != "chunked") - { - // Not chunked - just read everything at once - std::copy(std::istreambuf_iterator(in), std::istreambuf_iterator(), std::back_inserter(m_body)); - } - else - { - // Chunked - have to read chunk by chunk - std::size_t length; - - // Read all chunks, identified by a chunk-size not being 0 - while (in >> std::hex >> length) - { - // Drop the rest of the line (chunk-extension) - in.ignore(std::numeric_limits::max(), '\n'); - - // Copy the actual content data - std::istreambuf_iterator it(in); - for (std::size_t i = 0; i < length; i++) - m_body.push_back(*it++); - } - - // Drop the rest of the line (chunk-extension) - in.ignore(std::numeric_limits::max(), '\n'); - - // Read all trailers (if present) - parseFields(in); - } -} - - -//////////////////////////////////////////////////////////// -void Http::Response::parseFields(std::istream &in) -{ - std::string line; - while (std::getline(in, line) && (line.size() > 2)) - { - std::string::size_type pos = line.find(": "); - if (pos != std::string::npos) - { - // Extract the field name and its value - std::string field = line.substr(0, pos); - std::string value = line.substr(pos + 2); - - // Remove any trailing \r - if (!value.empty() && (*value.rbegin() == '\r')) - value.erase(value.size() - 1); - - // Add the field - m_fields[toLower(field)] = value; - } - } -} - - -//////////////////////////////////////////////////////////// -Http::Http() : -m_host(), -m_port(0) -{ - -} - - -//////////////////////////////////////////////////////////// -Http::Http(const std::string& host, unsigned short port) -{ - setHost(host, port); -} - - -//////////////////////////////////////////////////////////// -void Http::setHost(const std::string& host, unsigned short port) -{ - // Check the protocol - if (toLower(host.substr(0, 7)) == "http://") - { - // HTTP protocol - m_hostName = host.substr(7); - m_port = (port != 0 ? port : 80); - } - else if (toLower(host.substr(0, 8)) == "https://") - { - // HTTPS protocol -- unsupported (requires encryption and certificates and stuff...) - err() << "HTTPS protocol is not supported by sf::Http" << std::endl; - m_hostName = ""; - m_port = 0; - } - else - { - // Undefined protocol - use HTTP - m_hostName = host; - m_port = (port != 0 ? port : 80); - } - - // Remove any trailing '/' from the host name - if (!m_hostName.empty() && (*m_hostName.rbegin() == '/')) - m_hostName.erase(m_hostName.size() - 1); - - m_host = IpAddress(m_hostName); -} - - -//////////////////////////////////////////////////////////// -Http::Response Http::sendRequest(const Http::Request& request, Time timeout) -{ - // First make sure that the request is valid -- add missing mandatory fields - Request toSend(request); - if (!toSend.hasField("From")) - { - toSend.setField("From", "user@sfml-dev.org"); - } - if (!toSend.hasField("User-Agent")) - { - toSend.setField("User-Agent", "libsfml-network/2.x"); - } - if (!toSend.hasField("Host")) - { - toSend.setField("Host", m_hostName); - } - if (!toSend.hasField("Content-Length")) - { - std::ostringstream out; - out << toSend.m_body.size(); - toSend.setField("Content-Length", out.str()); - } - if ((toSend.m_method == Request::Post) && !toSend.hasField("Content-Type")) - { - toSend.setField("Content-Type", "application/x-www-form-urlencoded"); - } - if ((toSend.m_majorVersion * 10 + toSend.m_minorVersion >= 11) && !toSend.hasField("Connection")) - { - toSend.setField("Connection", "close"); - } - - // Prepare the response - Response received; - - // Connect the socket to the host - if (m_connection.connect(m_host, m_port, timeout) == Socket::Done) - { - // Convert the request to string and send it through the connected socket - std::string requestStr = toSend.prepare(); - - if (!requestStr.empty()) - { - // Send it through the socket - if (m_connection.send(requestStr.c_str(), requestStr.size()) == Socket::Done) - { - // Wait for the server's response - std::string receivedStr; - std::size_t size = 0; - char buffer[1024]; - while (m_connection.receive(buffer, sizeof(buffer), size) == Socket::Done) - { - receivedStr.append(buffer, buffer + size); - } - - // Build the Response object from the received data - received.parse(receivedStr); - } - } - - // Close the connection - m_connection.disconnect(); - } - - return received; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + + +namespace +{ + // Convert a string to lower case + std::string toLower(std::string str) + { + for (std::string::iterator i = str.begin(); i != str.end(); ++i) + *i = static_cast(std::tolower(*i)); + return str; + } +} + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Http::Request::Request(const std::string& uri, Method method, const std::string& body) +{ + setMethod(method); + setUri(uri); + setHttpVersion(1, 0); + setBody(body); +} + + +//////////////////////////////////////////////////////////// +void Http::Request::setField(const std::string& field, const std::string& value) +{ + m_fields[toLower(field)] = value; +} + + +//////////////////////////////////////////////////////////// +void Http::Request::setMethod(Http::Request::Method method) +{ + m_method = method; +} + + +//////////////////////////////////////////////////////////// +void Http::Request::setUri(const std::string& uri) +{ + m_uri = uri; + + // Make sure it starts with a '/' + if (m_uri.empty() || (m_uri[0] != '/')) + m_uri.insert(0, "/"); +} + + +//////////////////////////////////////////////////////////// +void Http::Request::setHttpVersion(unsigned int major, unsigned int minor) +{ + m_majorVersion = major; + m_minorVersion = minor; +} + + +//////////////////////////////////////////////////////////// +void Http::Request::setBody(const std::string& body) +{ + m_body = body; +} + + +//////////////////////////////////////////////////////////// +std::string Http::Request::prepare() const +{ + std::ostringstream out; + + // Convert the method to its string representation + std::string method; + switch (m_method) + { + default: + case Get: method = "GET"; break; + case Post: method = "POST"; break; + case Head: method = "HEAD"; break; + case Put: method = "PUT"; break; + case Delete: method = "DELETE"; break; + } + + // Write the first line containing the request type + out << method << " " << m_uri << " "; + out << "HTTP/" << m_majorVersion << "." << m_minorVersion << "\r\n"; + + // Write fields + for (FieldTable::const_iterator i = m_fields.begin(); i != m_fields.end(); ++i) + { + out << i->first << ": " << i->second << "\r\n"; + } + + // Use an extra \r\n to separate the header from the body + out << "\r\n"; + + // Add the body + out << m_body; + + return out.str(); +} + + +//////////////////////////////////////////////////////////// +bool Http::Request::hasField(const std::string& field) const +{ + return m_fields.find(toLower(field)) != m_fields.end(); +} + + +//////////////////////////////////////////////////////////// +Http::Response::Response() : +m_status (ConnectionFailed), +m_majorVersion(0), +m_minorVersion(0) +{ + +} + + +//////////////////////////////////////////////////////////// +const std::string& Http::Response::getField(const std::string& field) const +{ + FieldTable::const_iterator it = m_fields.find(toLower(field)); + if (it != m_fields.end()) + { + return it->second; + } + else + { + static const std::string empty = ""; + return empty; + } +} + + +//////////////////////////////////////////////////////////// +Http::Response::Status Http::Response::getStatus() const +{ + return m_status; +} + + +//////////////////////////////////////////////////////////// +unsigned int Http::Response::getMajorHttpVersion() const +{ + return m_majorVersion; +} + + +//////////////////////////////////////////////////////////// +unsigned int Http::Response::getMinorHttpVersion() const +{ + return m_minorVersion; +} + + +//////////////////////////////////////////////////////////// +const std::string& Http::Response::getBody() const +{ + return m_body; +} + + +//////////////////////////////////////////////////////////// +void Http::Response::parse(const std::string& data) +{ + std::istringstream in(data); + + // Extract the HTTP version from the first line + std::string version; + if (in >> version) + { + if ((version.size() >= 8) && (version[6] == '.') && + (toLower(version.substr(0, 5)) == "http/") && + isdigit(version[5]) && isdigit(version[7])) + { + m_majorVersion = version[5] - '0'; + m_minorVersion = version[7] - '0'; + } + else + { + // Invalid HTTP version + m_status = InvalidResponse; + return; + } + } + + // Extract the status code from the first line + int status; + if (in >> status) + { + m_status = static_cast(status); + } + else + { + // Invalid status code + m_status = InvalidResponse; + return; + } + + // Ignore the end of the first line + in.ignore(std::numeric_limits::max(), '\n'); + + // Parse the other lines, which contain fields, one by one + parseFields(in); + + m_body.clear(); + + // Determine whether the transfer is chunked + if (toLower(getField("transfer-encoding")) != "chunked") + { + // Not chunked - just read everything at once + std::copy(std::istreambuf_iterator(in), std::istreambuf_iterator(), std::back_inserter(m_body)); + } + else + { + // Chunked - have to read chunk by chunk + std::size_t length; + + // Read all chunks, identified by a chunk-size not being 0 + while (in >> std::hex >> length) + { + // Drop the rest of the line (chunk-extension) + in.ignore(std::numeric_limits::max(), '\n'); + + // Copy the actual content data + std::istreambuf_iterator it(in); + for (std::size_t i = 0; i < length; i++) + m_body.push_back(*it++); + } + + // Drop the rest of the line (chunk-extension) + in.ignore(std::numeric_limits::max(), '\n'); + + // Read all trailers (if present) + parseFields(in); + } +} + + +//////////////////////////////////////////////////////////// +void Http::Response::parseFields(std::istream &in) +{ + std::string line; + while (std::getline(in, line) && (line.size() > 2)) + { + std::string::size_type pos = line.find(": "); + if (pos != std::string::npos) + { + // Extract the field name and its value + std::string field = line.substr(0, pos); + std::string value = line.substr(pos + 2); + + // Remove any trailing \r + if (!value.empty() && (*value.rbegin() == '\r')) + value.erase(value.size() - 1); + + // Add the field + m_fields[toLower(field)] = value; + } + } +} + + +//////////////////////////////////////////////////////////// +Http::Http() : +m_host(), +m_port(0) +{ + +} + + +//////////////////////////////////////////////////////////// +Http::Http(const std::string& host, unsigned short port) +{ + setHost(host, port); +} + + +//////////////////////////////////////////////////////////// +void Http::setHost(const std::string& host, unsigned short port) +{ + // Check the protocol + if (toLower(host.substr(0, 7)) == "http://") + { + // HTTP protocol + m_hostName = host.substr(7); + m_port = (port != 0 ? port : 80); + } + else if (toLower(host.substr(0, 8)) == "https://") + { + // HTTPS protocol -- unsupported (requires encryption and certificates and stuff...) + err() << "HTTPS protocol is not supported by sf::Http" << std::endl; + m_hostName = ""; + m_port = 0; + } + else + { + // Undefined protocol - use HTTP + m_hostName = host; + m_port = (port != 0 ? port : 80); + } + + // Remove any trailing '/' from the host name + if (!m_hostName.empty() && (*m_hostName.rbegin() == '/')) + m_hostName.erase(m_hostName.size() - 1); + + m_host = IpAddress(m_hostName); +} + + +//////////////////////////////////////////////////////////// +Http::Response Http::sendRequest(const Http::Request& request, Time timeout) +{ + // First make sure that the request is valid -- add missing mandatory fields + Request toSend(request); + if (!toSend.hasField("From")) + { + toSend.setField("From", "user@sfml-dev.org"); + } + if (!toSend.hasField("User-Agent")) + { + toSend.setField("User-Agent", "libsfml-network/2.x"); + } + if (!toSend.hasField("Host")) + { + toSend.setField("Host", m_hostName); + } + if (!toSend.hasField("Content-Length")) + { + std::ostringstream out; + out << toSend.m_body.size(); + toSend.setField("Content-Length", out.str()); + } + if ((toSend.m_method == Request::Post) && !toSend.hasField("Content-Type")) + { + toSend.setField("Content-Type", "application/x-www-form-urlencoded"); + } + if ((toSend.m_majorVersion * 10 + toSend.m_minorVersion >= 11) && !toSend.hasField("Connection")) + { + toSend.setField("Connection", "close"); + } + + // Prepare the response + Response received; + + // Connect the socket to the host + if (m_connection.connect(m_host, m_port, timeout) == Socket::Done) + { + // Convert the request to string and send it through the connected socket + std::string requestStr = toSend.prepare(); + + if (!requestStr.empty()) + { + // Send it through the socket + if (m_connection.send(requestStr.c_str(), requestStr.size()) == Socket::Done) + { + // Wait for the server's response + std::string receivedStr; + std::size_t size = 0; + char buffer[1024]; + while (m_connection.receive(buffer, sizeof(buffer), size) == Socket::Done) + { + receivedStr.append(buffer, buffer + size); + } + + // Build the Response object from the received data + received.parse(receivedStr); + } + } + + // Close the connection + m_connection.disconnect(); + } + + return received; +} + +} // namespace sf diff --git a/src/SFML/Network/IpAddress.cpp b/src/SFML/Network/IpAddress.cpp index 8dab3a98..ea78aad5 100644 --- a/src/SFML/Network/IpAddress.cpp +++ b/src/SFML/Network/IpAddress.cpp @@ -1,255 +1,255 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace -{ - sf::Uint32 resolve(const std::string& address) - { - if (address == "255.255.255.255") - { - // The broadcast address needs to be handled explicitely, - // because it is also the value returned by inet_addr on error - return INADDR_BROADCAST; - } - else - { - // Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx") - sf::Uint32 ip = inet_addr(address.c_str()); - if (ip != INADDR_NONE) - return ip; - - // Not a valid address, try to convert it as a host name - addrinfo hints; - std::memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - addrinfo* result = NULL; - if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0) - { - if (result) - { - ip = reinterpret_cast(result->ai_addr)->sin_addr.s_addr; - freeaddrinfo(result); - return ip; - } - } - - // Not a valid address nor a host name - return 0; - } - } -} - - -namespace sf -{ -//////////////////////////////////////////////////////////// -const IpAddress IpAddress::None; -const IpAddress IpAddress::LocalHost(127, 0, 0, 1); -const IpAddress IpAddress::Broadcast(255, 255, 255, 255); - - -//////////////////////////////////////////////////////////// -IpAddress::IpAddress() : -m_address(0) -{ - // We're using 0 (INADDR_ANY) instead of INADDR_NONE to represent the invalid address, - // because the latter is also the broadcast address (255.255.255.255); it's ok because - // SFML doesn't publicly use INADDR_ANY (it is always used implicitely) -} - - -//////////////////////////////////////////////////////////// -IpAddress::IpAddress(const std::string& address) : -m_address(resolve(address)) -{ -} - - -//////////////////////////////////////////////////////////// -IpAddress::IpAddress(const char* address) : -m_address(resolve(address)) -{ -} - - -//////////////////////////////////////////////////////////// -IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) : -m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3)) -{ -} - - -//////////////////////////////////////////////////////////// -IpAddress::IpAddress(Uint32 address) : -m_address(htonl(address)) -{ -} - - -//////////////////////////////////////////////////////////// -std::string IpAddress::toString() const -{ - in_addr address; - address.s_addr = m_address; - - return inet_ntoa(address); -} - - -//////////////////////////////////////////////////////////// -Uint32 IpAddress::toInteger() const -{ - return ntohl(m_address); -} - - -//////////////////////////////////////////////////////////// -IpAddress IpAddress::getLocalAddress() -{ - // The method here is to connect a UDP socket to anyone (here to localhost), - // and get the local socket address with the getsockname function. - // UDP connection will not send anything to the network, so this function won't cause any overhead. - - IpAddress localAddress; - - // Create the socket - SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0); - if (sock == priv::SocketImpl::invalidSocket()) - return localAddress; - - // Connect the socket to localhost on any port - sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9); - if (connect(sock, reinterpret_cast(&address), sizeof(address)) == -1) - { - priv::SocketImpl::close(sock); - return localAddress; - } - - // Get the local address of the socket connection - priv::SocketImpl::AddrLength size = sizeof(address); - if (getsockname(sock, reinterpret_cast(&address), &size) == -1) - { - priv::SocketImpl::close(sock); - return localAddress; - } - - // Close the socket - priv::SocketImpl::close(sock); - - // Finally build the IP address - localAddress = IpAddress(ntohl(address.sin_addr.s_addr)); - - return localAddress; -} - - -//////////////////////////////////////////////////////////// -IpAddress IpAddress::getPublicAddress(Time timeout) -{ - // The trick here is more complicated, because the only way - // to get our public IP address is to get it from a distant computer. - // Here we get the web page from http://www.sfml-dev.org/ip-provider.php - // and parse the result to extract our IP address - // (not very hard: the web page contains only our IP address). - - Http server("www.sfml-dev.org"); - Http::Request request("/ip-provider.php", Http::Request::Get); - Http::Response page = server.sendRequest(request, timeout); - if (page.getStatus() == Http::Response::Ok) - return IpAddress(page.getBody()); - - // Something failed: return an invalid address - return IpAddress(); -} - - -//////////////////////////////////////////////////////////// -bool operator ==(const IpAddress& left, const IpAddress& right) -{ - return left.toInteger() == right.toInteger(); -} - - -//////////////////////////////////////////////////////////// -bool operator !=(const IpAddress& left, const IpAddress& right) -{ - return !(left == right); -} - - -//////////////////////////////////////////////////////////// -bool operator <(const IpAddress& left, const IpAddress& right) -{ - return left.toInteger() < right.toInteger(); -} - - -//////////////////////////////////////////////////////////// -bool operator >(const IpAddress& left, const IpAddress& right) -{ - return right < left; -} - - -//////////////////////////////////////////////////////////// -bool operator <=(const IpAddress& left, const IpAddress& right) -{ - return !(right < left); -} - - -//////////////////////////////////////////////////////////// -bool operator >=(const IpAddress& left, const IpAddress& right) -{ - return !(left < right); -} - - -//////////////////////////////////////////////////////////// -std::istream& operator >>(std::istream& stream, IpAddress& address) -{ - std::string str; - stream >> str; - address = IpAddress(str); - - return stream; -} - - -//////////////////////////////////////////////////////////// -std::ostream& operator <<(std::ostream& stream, const IpAddress& address) -{ - return stream << address.toString(); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace +{ + sf::Uint32 resolve(const std::string& address) + { + if (address == "255.255.255.255") + { + // The broadcast address needs to be handled explicitely, + // because it is also the value returned by inet_addr on error + return INADDR_BROADCAST; + } + else + { + // Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx") + sf::Uint32 ip = inet_addr(address.c_str()); + if (ip != INADDR_NONE) + return ip; + + // Not a valid address, try to convert it as a host name + addrinfo hints; + std::memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + addrinfo* result = NULL; + if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0) + { + if (result) + { + ip = reinterpret_cast(result->ai_addr)->sin_addr.s_addr; + freeaddrinfo(result); + return ip; + } + } + + // Not a valid address nor a host name + return 0; + } + } +} + + +namespace sf +{ +//////////////////////////////////////////////////////////// +const IpAddress IpAddress::None; +const IpAddress IpAddress::LocalHost(127, 0, 0, 1); +const IpAddress IpAddress::Broadcast(255, 255, 255, 255); + + +//////////////////////////////////////////////////////////// +IpAddress::IpAddress() : +m_address(0) +{ + // We're using 0 (INADDR_ANY) instead of INADDR_NONE to represent the invalid address, + // because the latter is also the broadcast address (255.255.255.255); it's ok because + // SFML doesn't publicly use INADDR_ANY (it is always used implicitely) +} + + +//////////////////////////////////////////////////////////// +IpAddress::IpAddress(const std::string& address) : +m_address(resolve(address)) +{ +} + + +//////////////////////////////////////////////////////////// +IpAddress::IpAddress(const char* address) : +m_address(resolve(address)) +{ +} + + +//////////////////////////////////////////////////////////// +IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) : +m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3)) +{ +} + + +//////////////////////////////////////////////////////////// +IpAddress::IpAddress(Uint32 address) : +m_address(htonl(address)) +{ +} + + +//////////////////////////////////////////////////////////// +std::string IpAddress::toString() const +{ + in_addr address; + address.s_addr = m_address; + + return inet_ntoa(address); +} + + +//////////////////////////////////////////////////////////// +Uint32 IpAddress::toInteger() const +{ + return ntohl(m_address); +} + + +//////////////////////////////////////////////////////////// +IpAddress IpAddress::getLocalAddress() +{ + // The method here is to connect a UDP socket to anyone (here to localhost), + // and get the local socket address with the getsockname function. + // UDP connection will not send anything to the network, so this function won't cause any overhead. + + IpAddress localAddress; + + // Create the socket + SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0); + if (sock == priv::SocketImpl::invalidSocket()) + return localAddress; + + // Connect the socket to localhost on any port + sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9); + if (connect(sock, reinterpret_cast(&address), sizeof(address)) == -1) + { + priv::SocketImpl::close(sock); + return localAddress; + } + + // Get the local address of the socket connection + priv::SocketImpl::AddrLength size = sizeof(address); + if (getsockname(sock, reinterpret_cast(&address), &size) == -1) + { + priv::SocketImpl::close(sock); + return localAddress; + } + + // Close the socket + priv::SocketImpl::close(sock); + + // Finally build the IP address + localAddress = IpAddress(ntohl(address.sin_addr.s_addr)); + + return localAddress; +} + + +//////////////////////////////////////////////////////////// +IpAddress IpAddress::getPublicAddress(Time timeout) +{ + // The trick here is more complicated, because the only way + // to get our public IP address is to get it from a distant computer. + // Here we get the web page from http://www.sfml-dev.org/ip-provider.php + // and parse the result to extract our IP address + // (not very hard: the web page contains only our IP address). + + Http server("www.sfml-dev.org"); + Http::Request request("/ip-provider.php", Http::Request::Get); + Http::Response page = server.sendRequest(request, timeout); + if (page.getStatus() == Http::Response::Ok) + return IpAddress(page.getBody()); + + // Something failed: return an invalid address + return IpAddress(); +} + + +//////////////////////////////////////////////////////////// +bool operator ==(const IpAddress& left, const IpAddress& right) +{ + return left.toInteger() == right.toInteger(); +} + + +//////////////////////////////////////////////////////////// +bool operator !=(const IpAddress& left, const IpAddress& right) +{ + return !(left == right); +} + + +//////////////////////////////////////////////////////////// +bool operator <(const IpAddress& left, const IpAddress& right) +{ + return left.toInteger() < right.toInteger(); +} + + +//////////////////////////////////////////////////////////// +bool operator >(const IpAddress& left, const IpAddress& right) +{ + return right < left; +} + + +//////////////////////////////////////////////////////////// +bool operator <=(const IpAddress& left, const IpAddress& right) +{ + return !(right < left); +} + + +//////////////////////////////////////////////////////////// +bool operator >=(const IpAddress& left, const IpAddress& right) +{ + return !(left < right); +} + + +//////////////////////////////////////////////////////////// +std::istream& operator >>(std::istream& stream, IpAddress& address) +{ + std::string str; + stream >> str; + address = IpAddress(str); + + return stream; +} + + +//////////////////////////////////////////////////////////// +std::ostream& operator <<(std::ostream& stream, const IpAddress& address) +{ + return stream << address.toString(); +} + +} // namespace sf diff --git a/src/SFML/Network/Packet.cpp b/src/SFML/Network/Packet.cpp index 089ee606..ab4615ab 100644 --- a/src/SFML/Network/Packet.cpp +++ b/src/SFML/Network/Packet.cpp @@ -1,507 +1,507 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Packet::Packet() : -m_readPos(0), -m_isValid(true) -{ - -} - - -//////////////////////////////////////////////////////////// -Packet::~Packet() -{ - -} - - -//////////////////////////////////////////////////////////// -void Packet::append(const void* data, std::size_t sizeInBytes) -{ - if (data && (sizeInBytes > 0)) - { - std::size_t start = m_data.size(); - m_data.resize(start + sizeInBytes); - std::memcpy(&m_data[start], data, sizeInBytes); - } -} - - -//////////////////////////////////////////////////////////// -void Packet::clear() -{ - m_data.clear(); - m_readPos = 0; - m_isValid = true; -} - - -//////////////////////////////////////////////////////////// -const void* Packet::getData() const -{ - return !m_data.empty() ? &m_data[0] : NULL; -} - - -//////////////////////////////////////////////////////////// -std::size_t Packet::getDataSize() const -{ - return m_data.size(); -} - - -//////////////////////////////////////////////////////////// -bool Packet::endOfPacket() const -{ - return m_readPos >= m_data.size(); -} - - -//////////////////////////////////////////////////////////// -Packet::operator BoolType() const -{ - return m_isValid ? &Packet::checkSize : NULL; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(bool& data) -{ - Uint8 value; - if (*this >> value) - data = (value != 0); - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(Int8& data) -{ - if (checkSize(sizeof(data))) - { - data = *reinterpret_cast(&m_data[m_readPos]); - m_readPos += sizeof(data); - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(Uint8& data) -{ - if (checkSize(sizeof(data))) - { - data = *reinterpret_cast(&m_data[m_readPos]); - m_readPos += sizeof(data); - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(Int16& data) -{ - if (checkSize(sizeof(data))) - { - data = ntohs(*reinterpret_cast(&m_data[m_readPos])); - m_readPos += sizeof(data); - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(Uint16& data) -{ - if (checkSize(sizeof(data))) - { - data = ntohs(*reinterpret_cast(&m_data[m_readPos])); - m_readPos += sizeof(data); - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(Int32& data) -{ - if (checkSize(sizeof(data))) - { - data = ntohl(*reinterpret_cast(&m_data[m_readPos])); - m_readPos += sizeof(data); - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(Uint32& data) -{ - if (checkSize(sizeof(data))) - { - data = ntohl(*reinterpret_cast(&m_data[m_readPos])); - m_readPos += sizeof(data); - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(float& data) -{ - if (checkSize(sizeof(data))) - { - data = *reinterpret_cast(&m_data[m_readPos]); - m_readPos += sizeof(data); - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(double& data) -{ - if (checkSize(sizeof(data))) - { - data = *reinterpret_cast(&m_data[m_readPos]); - m_readPos += sizeof(data); - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(char* data) -{ - // First extract string length - Uint32 length = 0; - *this >> length; - - if ((length > 0) && checkSize(length)) - { - // Then extract characters - std::memcpy(data, &m_data[m_readPos], length); - data[length] = '\0'; - - // Update reading position - m_readPos += length; - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(std::string& data) -{ - // First extract string length - Uint32 length = 0; - *this >> length; - - data.clear(); - if ((length > 0) && checkSize(length)) - { - // Then extract characters - data.assign(&m_data[m_readPos], length); - - // Update reading position - m_readPos += length; - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(wchar_t* data) -{ - // First extract string length - Uint32 length = 0; - *this >> length; - - if ((length > 0) && checkSize(length * sizeof(Uint32))) - { - // Then extract characters - for (Uint32 i = 0; i < length; ++i) - { - Uint32 character = 0; - *this >> character; - data[i] = static_cast(character); - } - data[length] = L'\0'; - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(std::wstring& data) -{ - // First extract string length - Uint32 length = 0; - *this >> length; - - data.clear(); - if ((length > 0) && checkSize(length * sizeof(Uint32))) - { - // Then extract characters - for (Uint32 i = 0; i < length; ++i) - { - Uint32 character = 0; - *this >> character; - data += static_cast(character); - } - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(String& data) -{ - // First extract the string length - Uint32 length = 0; - *this >> length; - - data.clear(); - if ((length > 0) && checkSize(length * sizeof(Uint32))) - { - // Then extract characters - for (Uint32 i = 0; i < length; ++i) - { - Uint32 character = 0; - *this >> character; - data += character; - } - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(bool data) -{ - *this << static_cast(data); - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(Int8 data) -{ - append(&data, sizeof(data)); - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(Uint8 data) -{ - append(&data, sizeof(data)); - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(Int16 data) -{ - Int16 toWrite = htons(data); - append(&toWrite, sizeof(toWrite)); - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(Uint16 data) -{ - Uint16 toWrite = htons(data); - append(&toWrite, sizeof(toWrite)); - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(Int32 data) -{ - Int32 toWrite = htonl(data); - append(&toWrite, sizeof(toWrite)); - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(Uint32 data) -{ - Uint32 toWrite = htonl(data); - append(&toWrite, sizeof(toWrite)); - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(float data) -{ - append(&data, sizeof(data)); - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(double data) -{ - append(&data, sizeof(data)); - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(const char* data) -{ - // First insert string length - Uint32 length = static_cast(std::strlen(data)); - *this << length; - - // Then insert characters - append(data, length * sizeof(char)); - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(const std::string& data) -{ - // First insert string length - Uint32 length = static_cast(data.size()); - *this << length; - - // Then insert characters - if (length > 0) - append(data.c_str(), length * sizeof(std::string::value_type)); - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(const wchar_t* data) -{ - // First insert string length - Uint32 length = static_cast(std::wcslen(data)); - *this << length; - - // Then insert characters - for (const wchar_t* c = data; *c != L'\0'; ++c) - *this << static_cast(*c); - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(const std::wstring& data) -{ - // First insert string length - Uint32 length = static_cast(data.size()); - *this << length; - - // Then insert characters - if (length > 0) - { - for (std::wstring::const_iterator c = data.begin(); c != data.end(); ++c) - *this << static_cast(*c); - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(const String& data) -{ - // First insert the string length - Uint32 length = static_cast(data.getSize()); - *this << length; - - // Then insert characters - if (length > 0) - { - for (String::ConstIterator c = data.begin(); c != data.end(); ++c) - *this << *c; - } - - return *this; -} - - -//////////////////////////////////////////////////////////// -bool Packet::checkSize(std::size_t size) -{ - m_isValid = m_isValid && (m_readPos + size <= m_data.size()); - - return m_isValid; -} - - -//////////////////////////////////////////////////////////// -const void* Packet::onSend(std::size_t& size) -{ - size = getDataSize(); - return getData(); -} - - -//////////////////////////////////////////////////////////// -void Packet::onReceive(const void* data, std::size_t size) -{ - append(data, size); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Packet::Packet() : +m_readPos(0), +m_isValid(true) +{ + +} + + +//////////////////////////////////////////////////////////// +Packet::~Packet() +{ + +} + + +//////////////////////////////////////////////////////////// +void Packet::append(const void* data, std::size_t sizeInBytes) +{ + if (data && (sizeInBytes > 0)) + { + std::size_t start = m_data.size(); + m_data.resize(start + sizeInBytes); + std::memcpy(&m_data[start], data, sizeInBytes); + } +} + + +//////////////////////////////////////////////////////////// +void Packet::clear() +{ + m_data.clear(); + m_readPos = 0; + m_isValid = true; +} + + +//////////////////////////////////////////////////////////// +const void* Packet::getData() const +{ + return !m_data.empty() ? &m_data[0] : NULL; +} + + +//////////////////////////////////////////////////////////// +std::size_t Packet::getDataSize() const +{ + return m_data.size(); +} + + +//////////////////////////////////////////////////////////// +bool Packet::endOfPacket() const +{ + return m_readPos >= m_data.size(); +} + + +//////////////////////////////////////////////////////////// +Packet::operator BoolType() const +{ + return m_isValid ? &Packet::checkSize : NULL; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(bool& data) +{ + Uint8 value; + if (*this >> value) + data = (value != 0); + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Int8& data) +{ + if (checkSize(sizeof(data))) + { + data = *reinterpret_cast(&m_data[m_readPos]); + m_readPos += sizeof(data); + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Uint8& data) +{ + if (checkSize(sizeof(data))) + { + data = *reinterpret_cast(&m_data[m_readPos]); + m_readPos += sizeof(data); + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Int16& data) +{ + if (checkSize(sizeof(data))) + { + data = ntohs(*reinterpret_cast(&m_data[m_readPos])); + m_readPos += sizeof(data); + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Uint16& data) +{ + if (checkSize(sizeof(data))) + { + data = ntohs(*reinterpret_cast(&m_data[m_readPos])); + m_readPos += sizeof(data); + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Int32& data) +{ + if (checkSize(sizeof(data))) + { + data = ntohl(*reinterpret_cast(&m_data[m_readPos])); + m_readPos += sizeof(data); + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Uint32& data) +{ + if (checkSize(sizeof(data))) + { + data = ntohl(*reinterpret_cast(&m_data[m_readPos])); + m_readPos += sizeof(data); + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(float& data) +{ + if (checkSize(sizeof(data))) + { + data = *reinterpret_cast(&m_data[m_readPos]); + m_readPos += sizeof(data); + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(double& data) +{ + if (checkSize(sizeof(data))) + { + data = *reinterpret_cast(&m_data[m_readPos]); + m_readPos += sizeof(data); + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(char* data) +{ + // First extract string length + Uint32 length = 0; + *this >> length; + + if ((length > 0) && checkSize(length)) + { + // Then extract characters + std::memcpy(data, &m_data[m_readPos], length); + data[length] = '\0'; + + // Update reading position + m_readPos += length; + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(std::string& data) +{ + // First extract string length + Uint32 length = 0; + *this >> length; + + data.clear(); + if ((length > 0) && checkSize(length)) + { + // Then extract characters + data.assign(&m_data[m_readPos], length); + + // Update reading position + m_readPos += length; + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(wchar_t* data) +{ + // First extract string length + Uint32 length = 0; + *this >> length; + + if ((length > 0) && checkSize(length * sizeof(Uint32))) + { + // Then extract characters + for (Uint32 i = 0; i < length; ++i) + { + Uint32 character = 0; + *this >> character; + data[i] = static_cast(character); + } + data[length] = L'\0'; + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(std::wstring& data) +{ + // First extract string length + Uint32 length = 0; + *this >> length; + + data.clear(); + if ((length > 0) && checkSize(length * sizeof(Uint32))) + { + // Then extract characters + for (Uint32 i = 0; i < length; ++i) + { + Uint32 character = 0; + *this >> character; + data += static_cast(character); + } + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(String& data) +{ + // First extract the string length + Uint32 length = 0; + *this >> length; + + data.clear(); + if ((length > 0) && checkSize(length * sizeof(Uint32))) + { + // Then extract characters + for (Uint32 i = 0; i < length; ++i) + { + Uint32 character = 0; + *this >> character; + data += character; + } + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(bool data) +{ + *this << static_cast(data); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(Int8 data) +{ + append(&data, sizeof(data)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(Uint8 data) +{ + append(&data, sizeof(data)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(Int16 data) +{ + Int16 toWrite = htons(data); + append(&toWrite, sizeof(toWrite)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(Uint16 data) +{ + Uint16 toWrite = htons(data); + append(&toWrite, sizeof(toWrite)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(Int32 data) +{ + Int32 toWrite = htonl(data); + append(&toWrite, sizeof(toWrite)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(Uint32 data) +{ + Uint32 toWrite = htonl(data); + append(&toWrite, sizeof(toWrite)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(float data) +{ + append(&data, sizeof(data)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(double data) +{ + append(&data, sizeof(data)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(const char* data) +{ + // First insert string length + Uint32 length = static_cast(std::strlen(data)); + *this << length; + + // Then insert characters + append(data, length * sizeof(char)); + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(const std::string& data) +{ + // First insert string length + Uint32 length = static_cast(data.size()); + *this << length; + + // Then insert characters + if (length > 0) + append(data.c_str(), length * sizeof(std::string::value_type)); + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(const wchar_t* data) +{ + // First insert string length + Uint32 length = static_cast(std::wcslen(data)); + *this << length; + + // Then insert characters + for (const wchar_t* c = data; *c != L'\0'; ++c) + *this << static_cast(*c); + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(const std::wstring& data) +{ + // First insert string length + Uint32 length = static_cast(data.size()); + *this << length; + + // Then insert characters + if (length > 0) + { + for (std::wstring::const_iterator c = data.begin(); c != data.end(); ++c) + *this << static_cast(*c); + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(const String& data) +{ + // First insert the string length + Uint32 length = static_cast(data.getSize()); + *this << length; + + // Then insert characters + if (length > 0) + { + for (String::ConstIterator c = data.begin(); c != data.end(); ++c) + *this << *c; + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +bool Packet::checkSize(std::size_t size) +{ + m_isValid = m_isValid && (m_readPos + size <= m_data.size()); + + return m_isValid; +} + + +//////////////////////////////////////////////////////////// +const void* Packet::onSend(std::size_t& size) +{ + size = getDataSize(); + return getData(); +} + + +//////////////////////////////////////////////////////////// +void Packet::onReceive(const void* data, std::size_t size) +{ + append(data, size); +} + +} // namespace sf diff --git a/src/SFML/Network/Socket.cpp b/src/SFML/Network/Socket.cpp index 0251db05..539b738c 100644 --- a/src/SFML/Network/Socket.cpp +++ b/src/SFML/Network/Socket.cpp @@ -1,144 +1,144 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Socket::Socket(Type type) : -m_type (type), -m_socket (priv::SocketImpl::invalidSocket()), -m_isBlocking(true) -{ - -} - - -//////////////////////////////////////////////////////////// -Socket::~Socket() -{ - // Close the socket before it gets destructed - close(); -} - - -//////////////////////////////////////////////////////////// -void Socket::setBlocking(bool blocking) -{ - // Apply if the socket is already created - if (m_socket != priv::SocketImpl::invalidSocket()) - priv::SocketImpl::setBlocking(m_socket, blocking); - - m_isBlocking = blocking; -} - - -//////////////////////////////////////////////////////////// -bool Socket::isBlocking() const -{ - return m_isBlocking; -} - - -//////////////////////////////////////////////////////////// -SocketHandle Socket::getHandle() const -{ - return m_socket; -} - - -//////////////////////////////////////////////////////////// -void Socket::create() -{ - // Don't create the socket if it already exists - if (m_socket == priv::SocketImpl::invalidSocket()) - { - SocketHandle handle = socket(PF_INET, m_type == Tcp ? SOCK_STREAM : SOCK_DGRAM, 0); - create(handle); - } -} - - -//////////////////////////////////////////////////////////// -void Socket::create(SocketHandle handle) -{ - // Don't create the socket if it already exists - if (m_socket == priv::SocketImpl::invalidSocket()) - { - // Assign the new handle - m_socket = handle; - - // Set the current blocking state - setBlocking(m_isBlocking); - - if (m_type == Tcp) - { - // Disable the Nagle algorithm (ie. removes buffering of TCP packets) - int yes = 1; - if (setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&yes), sizeof(yes)) == -1) - { - err() << "Failed to set socket option \"TCP_NODELAY\" ; " - << "all your TCP packets will be buffered" << std::endl; - } - - // On Mac OS X, disable the SIGPIPE signal on disconnection - #ifdef SFML_SYSTEM_MACOS - if (setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast(&yes), sizeof(yes)) == -1) - { - err() << "Failed to set socket option \"SO_NOSIGPIPE\"" << std::endl; - } - #endif - } - else - { - // Enable broadcast by default for UDP sockets - int yes = 1; - if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast(&yes), sizeof(yes)) == -1) - { - err() << "Failed to enable broadcast on UDP socket" << std::endl; - } - } - } -} - - -//////////////////////////////////////////////////////////// -void Socket::close() -{ - // Close the socket - if (m_socket != priv::SocketImpl::invalidSocket()) - { - priv::SocketImpl::close(m_socket); - m_socket = priv::SocketImpl::invalidSocket(); - } -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Socket::Socket(Type type) : +m_type (type), +m_socket (priv::SocketImpl::invalidSocket()), +m_isBlocking(true) +{ + +} + + +//////////////////////////////////////////////////////////// +Socket::~Socket() +{ + // Close the socket before it gets destructed + close(); +} + + +//////////////////////////////////////////////////////////// +void Socket::setBlocking(bool blocking) +{ + // Apply if the socket is already created + if (m_socket != priv::SocketImpl::invalidSocket()) + priv::SocketImpl::setBlocking(m_socket, blocking); + + m_isBlocking = blocking; +} + + +//////////////////////////////////////////////////////////// +bool Socket::isBlocking() const +{ + return m_isBlocking; +} + + +//////////////////////////////////////////////////////////// +SocketHandle Socket::getHandle() const +{ + return m_socket; +} + + +//////////////////////////////////////////////////////////// +void Socket::create() +{ + // Don't create the socket if it already exists + if (m_socket == priv::SocketImpl::invalidSocket()) + { + SocketHandle handle = socket(PF_INET, m_type == Tcp ? SOCK_STREAM : SOCK_DGRAM, 0); + create(handle); + } +} + + +//////////////////////////////////////////////////////////// +void Socket::create(SocketHandle handle) +{ + // Don't create the socket if it already exists + if (m_socket == priv::SocketImpl::invalidSocket()) + { + // Assign the new handle + m_socket = handle; + + // Set the current blocking state + setBlocking(m_isBlocking); + + if (m_type == Tcp) + { + // Disable the Nagle algorithm (ie. removes buffering of TCP packets) + int yes = 1; + if (setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&yes), sizeof(yes)) == -1) + { + err() << "Failed to set socket option \"TCP_NODELAY\" ; " + << "all your TCP packets will be buffered" << std::endl; + } + + // On Mac OS X, disable the SIGPIPE signal on disconnection + #ifdef SFML_SYSTEM_MACOS + if (setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast(&yes), sizeof(yes)) == -1) + { + err() << "Failed to set socket option \"SO_NOSIGPIPE\"" << std::endl; + } + #endif + } + else + { + // Enable broadcast by default for UDP sockets + int yes = 1; + if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast(&yes), sizeof(yes)) == -1) + { + err() << "Failed to enable broadcast on UDP socket" << std::endl; + } + } + } +} + + +//////////////////////////////////////////////////////////// +void Socket::close() +{ + // Close the socket + if (m_socket != priv::SocketImpl::invalidSocket()) + { + priv::SocketImpl::close(m_socket); + m_socket = priv::SocketImpl::invalidSocket(); + } +} + +} // namespace sf diff --git a/src/SFML/Network/SocketImpl.hpp b/src/SFML/Network/SocketImpl.hpp index 8d028d1e..fbe45bcb 100644 --- a/src/SFML/Network/SocketImpl.hpp +++ b/src/SFML/Network/SocketImpl.hpp @@ -1,39 +1,39 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -#if defined(SFML_SYSTEM_WINDOWS) - - #include - -#else - - #include - -#endif +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +#if defined(SFML_SYSTEM_WINDOWS) + + #include + +#else + + #include + +#endif diff --git a/src/SFML/Network/SocketSelector.cpp b/src/SFML/Network/SocketSelector.cpp index 980e825c..8b521bb3 100644 --- a/src/SFML/Network/SocketSelector.cpp +++ b/src/SFML/Network/SocketSelector.cpp @@ -1,205 +1,205 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER - #pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -struct SocketSelector::SocketSelectorImpl -{ - fd_set allSockets; ///< Set containing all the sockets handles - fd_set socketsReady; ///< Set containing handles of the sockets that are ready - int maxSocket; ///< Maximum socket handle - int socketCount; ///< Number of socket handles -}; - - -//////////////////////////////////////////////////////////// -SocketSelector::SocketSelector() : -m_impl(new SocketSelectorImpl) -{ - clear(); -} - - -//////////////////////////////////////////////////////////// -SocketSelector::SocketSelector(const SocketSelector& copy) : -m_impl(new SocketSelectorImpl(*copy.m_impl)) -{ - -} - - -//////////////////////////////////////////////////////////// -SocketSelector::~SocketSelector() -{ - delete m_impl; -} - - -//////////////////////////////////////////////////////////// -void SocketSelector::add(Socket& socket) -{ - SocketHandle handle = socket.getHandle(); - if (handle != priv::SocketImpl::invalidSocket()) - { - -#if defined(SFML_SYSTEM_WINDOWS) - - if (m_impl->socketCount >= FD_SETSIZE) - { - err() << "The socket can't be added to the selector because the " - << "selector is full. This is a limitation of your operating " - << "system's FD_SETSIZE setting."; - return; - } - - if (FD_ISSET(handle, &m_impl->allSockets)) - return; - - m_impl->socketCount++; - -#else - - if (handle >= FD_SETSIZE) - { - err() << "The socket can't be added to the selector because its " - << "ID is too high. This is a limitation of your operating " - << "system's FD_SETSIZE setting."; - return; - } - - // SocketHandle is an int in POSIX - m_impl->maxSocket = std::max(m_impl->maxSocket, handle); - -#endif - - FD_SET(handle, &m_impl->allSockets); - } -} - - -//////////////////////////////////////////////////////////// -void SocketSelector::remove(Socket& socket) -{ - SocketHandle handle = socket.getHandle(); - if (handle != priv::SocketImpl::invalidSocket()) - { - -#if defined(SFML_SYSTEM_WINDOWS) - - if (!FD_ISSET(handle, &m_impl->allSockets)) - return; - - m_impl->socketCount--; - -#else - - if (handle >= FD_SETSIZE) - return; - -#endif - - FD_CLR(handle, &m_impl->allSockets); - FD_CLR(handle, &m_impl->socketsReady); - } -} - - -//////////////////////////////////////////////////////////// -void SocketSelector::clear() -{ - FD_ZERO(&m_impl->allSockets); - FD_ZERO(&m_impl->socketsReady); - - m_impl->maxSocket = 0; - m_impl->socketCount = 0; -} - - -//////////////////////////////////////////////////////////// -bool SocketSelector::wait(Time timeout) -{ - // Setup the timeout - timeval time; - time.tv_sec = static_cast(timeout.asMicroseconds() / 1000000); - time.tv_usec = static_cast(timeout.asMicroseconds() % 1000000); - - // Initialize the set that will contain the sockets that are ready - m_impl->socketsReady = m_impl->allSockets; - - // Wait until one of the sockets is ready for reading, or timeout is reached - // The first parameter is ignored on Windows - int count = select(m_impl->maxSocket + 1, &m_impl->socketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL); - - return count > 0; -} - - -//////////////////////////////////////////////////////////// -bool SocketSelector::isReady(Socket& socket) const -{ - SocketHandle handle = socket.getHandle(); - if (handle != priv::SocketImpl::invalidSocket()) - { - -#if !defined(SFML_SYSTEM_WINDOWS) - - if (handle >= FD_SETSIZE) - return false; - -#endif - - return FD_ISSET(handle, &m_impl->socketsReady) != 0; - } - - return false; -} - - -//////////////////////////////////////////////////////////// -SocketSelector& SocketSelector::operator =(const SocketSelector& right) -{ - SocketSelector temp(right); - - std::swap(m_impl, temp.m_impl); - - return *this; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER + #pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro +#endif + + +namespace sf +{ +//////////////////////////////////////////////////////////// +struct SocketSelector::SocketSelectorImpl +{ + fd_set allSockets; ///< Set containing all the sockets handles + fd_set socketsReady; ///< Set containing handles of the sockets that are ready + int maxSocket; ///< Maximum socket handle + int socketCount; ///< Number of socket handles +}; + + +//////////////////////////////////////////////////////////// +SocketSelector::SocketSelector() : +m_impl(new SocketSelectorImpl) +{ + clear(); +} + + +//////////////////////////////////////////////////////////// +SocketSelector::SocketSelector(const SocketSelector& copy) : +m_impl(new SocketSelectorImpl(*copy.m_impl)) +{ + +} + + +//////////////////////////////////////////////////////////// +SocketSelector::~SocketSelector() +{ + delete m_impl; +} + + +//////////////////////////////////////////////////////////// +void SocketSelector::add(Socket& socket) +{ + SocketHandle handle = socket.getHandle(); + if (handle != priv::SocketImpl::invalidSocket()) + { + +#if defined(SFML_SYSTEM_WINDOWS) + + if (m_impl->socketCount >= FD_SETSIZE) + { + err() << "The socket can't be added to the selector because the " + << "selector is full. This is a limitation of your operating " + << "system's FD_SETSIZE setting."; + return; + } + + if (FD_ISSET(handle, &m_impl->allSockets)) + return; + + m_impl->socketCount++; + +#else + + if (handle >= FD_SETSIZE) + { + err() << "The socket can't be added to the selector because its " + << "ID is too high. This is a limitation of your operating " + << "system's FD_SETSIZE setting."; + return; + } + + // SocketHandle is an int in POSIX + m_impl->maxSocket = std::max(m_impl->maxSocket, handle); + +#endif + + FD_SET(handle, &m_impl->allSockets); + } +} + + +//////////////////////////////////////////////////////////// +void SocketSelector::remove(Socket& socket) +{ + SocketHandle handle = socket.getHandle(); + if (handle != priv::SocketImpl::invalidSocket()) + { + +#if defined(SFML_SYSTEM_WINDOWS) + + if (!FD_ISSET(handle, &m_impl->allSockets)) + return; + + m_impl->socketCount--; + +#else + + if (handle >= FD_SETSIZE) + return; + +#endif + + FD_CLR(handle, &m_impl->allSockets); + FD_CLR(handle, &m_impl->socketsReady); + } +} + + +//////////////////////////////////////////////////////////// +void SocketSelector::clear() +{ + FD_ZERO(&m_impl->allSockets); + FD_ZERO(&m_impl->socketsReady); + + m_impl->maxSocket = 0; + m_impl->socketCount = 0; +} + + +//////////////////////////////////////////////////////////// +bool SocketSelector::wait(Time timeout) +{ + // Setup the timeout + timeval time; + time.tv_sec = static_cast(timeout.asMicroseconds() / 1000000); + time.tv_usec = static_cast(timeout.asMicroseconds() % 1000000); + + // Initialize the set that will contain the sockets that are ready + m_impl->socketsReady = m_impl->allSockets; + + // Wait until one of the sockets is ready for reading, or timeout is reached + // The first parameter is ignored on Windows + int count = select(m_impl->maxSocket + 1, &m_impl->socketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL); + + return count > 0; +} + + +//////////////////////////////////////////////////////////// +bool SocketSelector::isReady(Socket& socket) const +{ + SocketHandle handle = socket.getHandle(); + if (handle != priv::SocketImpl::invalidSocket()) + { + +#if !defined(SFML_SYSTEM_WINDOWS) + + if (handle >= FD_SETSIZE) + return false; + +#endif + + return FD_ISSET(handle, &m_impl->socketsReady) != 0; + } + + return false; +} + + +//////////////////////////////////////////////////////////// +SocketSelector& SocketSelector::operator =(const SocketSelector& right) +{ + SocketSelector temp(right); + + std::swap(m_impl, temp.m_impl); + + return *this; +} + +} // namespace sf diff --git a/src/SFML/Network/TcpListener.cpp b/src/SFML/Network/TcpListener.cpp index 4438d646..78f7f439 100644 --- a/src/SFML/Network/TcpListener.cpp +++ b/src/SFML/Network/TcpListener.cpp @@ -1,124 +1,124 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -TcpListener::TcpListener() : -Socket(Tcp) -{ - -} - - -//////////////////////////////////////////////////////////// -unsigned short TcpListener::getLocalPort() const -{ - if (getHandle() != priv::SocketImpl::invalidSocket()) - { - // Retrieve informations about the local end of the socket - sockaddr_in address; - priv::SocketImpl::AddrLength size = sizeof(address); - if (getsockname(getHandle(), reinterpret_cast(&address), &size) != -1) - { - return ntohs(address.sin_port); - } - } - - // We failed to retrieve the port - return 0; -} - - -//////////////////////////////////////////////////////////// -Socket::Status TcpListener::listen(unsigned short port) -{ - // Create the internal socket if it doesn't exist - create(); - - // Bind the socket to the specified port - sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port); - if (bind(getHandle(), reinterpret_cast(&address), sizeof(address)) == -1) - { - // Not likely to happen, but... - err() << "Failed to bind listener socket to port " << port << std::endl; - return Error; - } - - // Listen to the bound port - if (::listen(getHandle(), 0) == -1) - { - // Oops, socket is deaf - err() << "Failed to listen to port " << port << std::endl; - return Error; - } - - return Done; -} - - -//////////////////////////////////////////////////////////// -void TcpListener::close() -{ - // Simply close the socket - Socket::close(); -} - - -//////////////////////////////////////////////////////////// -Socket::Status TcpListener::accept(TcpSocket& socket) -{ - // Make sure that we're listening - if (getHandle() == priv::SocketImpl::invalidSocket()) - { - err() << "Failed to accept a new connection, the socket is not listening" << std::endl; - return Error; - } - - // Accept a new connection - sockaddr_in address; - priv::SocketImpl::AddrLength length = sizeof(address); - SocketHandle remote = ::accept(getHandle(), reinterpret_cast(&address), &length); - - // Check for errors - if (remote == priv::SocketImpl::invalidSocket()) - return priv::SocketImpl::getErrorStatus(); - - // Initialize the new connected socket - socket.close(); - socket.create(remote); - - return Done; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +TcpListener::TcpListener() : +Socket(Tcp) +{ + +} + + +//////////////////////////////////////////////////////////// +unsigned short TcpListener::getLocalPort() const +{ + if (getHandle() != priv::SocketImpl::invalidSocket()) + { + // Retrieve informations about the local end of the socket + sockaddr_in address; + priv::SocketImpl::AddrLength size = sizeof(address); + if (getsockname(getHandle(), reinterpret_cast(&address), &size) != -1) + { + return ntohs(address.sin_port); + } + } + + // We failed to retrieve the port + return 0; +} + + +//////////////////////////////////////////////////////////// +Socket::Status TcpListener::listen(unsigned short port) +{ + // Create the internal socket if it doesn't exist + create(); + + // Bind the socket to the specified port + sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port); + if (bind(getHandle(), reinterpret_cast(&address), sizeof(address)) == -1) + { + // Not likely to happen, but... + err() << "Failed to bind listener socket to port " << port << std::endl; + return Error; + } + + // Listen to the bound port + if (::listen(getHandle(), 0) == -1) + { + // Oops, socket is deaf + err() << "Failed to listen to port " << port << std::endl; + return Error; + } + + return Done; +} + + +//////////////////////////////////////////////////////////// +void TcpListener::close() +{ + // Simply close the socket + Socket::close(); +} + + +//////////////////////////////////////////////////////////// +Socket::Status TcpListener::accept(TcpSocket& socket) +{ + // Make sure that we're listening + if (getHandle() == priv::SocketImpl::invalidSocket()) + { + err() << "Failed to accept a new connection, the socket is not listening" << std::endl; + return Error; + } + + // Accept a new connection + sockaddr_in address; + priv::SocketImpl::AddrLength length = sizeof(address); + SocketHandle remote = ::accept(getHandle(), reinterpret_cast(&address), &length); + + // Check for errors + if (remote == priv::SocketImpl::invalidSocket()) + return priv::SocketImpl::getErrorStatus(); + + // Initialize the new connected socket + socket.close(); + socket.create(remote); + + return Done; +} + +} // namespace sf diff --git a/src/SFML/Network/TcpSocket.cpp b/src/SFML/Network/TcpSocket.cpp index 8e50f21d..c6dadf91 100644 --- a/src/SFML/Network/TcpSocket.cpp +++ b/src/SFML/Network/TcpSocket.cpp @@ -1,382 +1,382 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER - #pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro -#endif - - -namespace -{ - // Define the low-level send/receive flags, which depend on the OS - #ifdef SFML_SYSTEM_LINUX - const int flags = MSG_NOSIGNAL; - #else - const int flags = 0; - #endif -} - -namespace sf -{ -//////////////////////////////////////////////////////////// -TcpSocket::TcpSocket() : -Socket(Tcp) -{ - -} - - -//////////////////////////////////////////////////////////// -unsigned short TcpSocket::getLocalPort() const -{ - if (getHandle() != priv::SocketImpl::invalidSocket()) - { - // Retrieve informations about the local end of the socket - sockaddr_in address; - priv::SocketImpl::AddrLength size = sizeof(address); - if (getsockname(getHandle(), reinterpret_cast(&address), &size) != -1) - { - return ntohs(address.sin_port); - } - } - - // We failed to retrieve the port - return 0; -} - - -//////////////////////////////////////////////////////////// -IpAddress TcpSocket::getRemoteAddress() const -{ - if (getHandle() != priv::SocketImpl::invalidSocket()) - { - // Retrieve informations about the remote end of the socket - sockaddr_in address; - priv::SocketImpl::AddrLength size = sizeof(address); - if (getpeername(getHandle(), reinterpret_cast(&address), &size) != -1) - { - return IpAddress(ntohl(address.sin_addr.s_addr)); - } - } - - // We failed to retrieve the address - return IpAddress::None; -} - - -//////////////////////////////////////////////////////////// -unsigned short TcpSocket::getRemotePort() const -{ - if (getHandle() != priv::SocketImpl::invalidSocket()) - { - // Retrieve informations about the remote end of the socket - sockaddr_in address; - priv::SocketImpl::AddrLength size = sizeof(address); - if (getpeername(getHandle(), reinterpret_cast(&address), &size) != -1) - { - return ntohs(address.sin_port); - } - } - - // We failed to retrieve the port - return 0; -} - - -//////////////////////////////////////////////////////////// -Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout) -{ - // Create the internal socket if it doesn't exist - create(); - - // Create the remote address - sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort); - - if (timeout <= Time::Zero) - { - // ----- We're not using a timeout: just try to connect ----- - - // Connect the socket - if (::connect(getHandle(), reinterpret_cast(&address), sizeof(address)) == -1) - return priv::SocketImpl::getErrorStatus(); - - // Connection succeeded - return Done; - } - else - { - // ----- We're using a timeout: we'll need a few tricks to make it work ----- - - // Save the previous blocking state - bool blocking = isBlocking(); - - // Switch to non-blocking to enable our connection timeout - if (blocking) - setBlocking(false); - - // Try to connect to the remote address - if (::connect(getHandle(), reinterpret_cast(&address), sizeof(address)) >= 0) - { - // We got instantly connected! (it may no happen a lot...) - setBlocking(blocking); - return Done; - } - - // Get the error status - Status status = priv::SocketImpl::getErrorStatus(); - - // If we were in non-blocking mode, return immediatly - if (!blocking) - return status; - - // Otherwise, wait until something happens to our socket (success, timeout or error) - if (status == Socket::NotReady) - { - // Setup the selector - fd_set selector; - FD_ZERO(&selector); - FD_SET(getHandle(), &selector); - - // Setup the timeout - timeval time; - time.tv_sec = static_cast(timeout.asMicroseconds() / 1000000); - time.tv_usec = static_cast(timeout.asMicroseconds() % 1000000); - - // Wait for something to write on our socket (which means that the connection request has returned) - if (select(static_cast(getHandle() + 1), NULL, &selector, NULL, &time) > 0) - { - // At this point the connection may have been either accepted or refused. - // To know whether it's a success or a failure, we must check the address of the connected peer - if (getRemoteAddress() != sf::IpAddress::None) - { - // Connection accepted - status = Done; - } - else - { - // Connection refused - status = priv::SocketImpl::getErrorStatus(); - } - } - else - { - // Failed to connect before timeout is over - status = priv::SocketImpl::getErrorStatus(); - } - } - - // Switch back to blocking mode - setBlocking(true); - - return status; - } -} - - -//////////////////////////////////////////////////////////// -void TcpSocket::disconnect() -{ - // Close the socket - close(); - - // Reset the pending packet data - m_pendingPacket = PendingPacket(); -} - - -//////////////////////////////////////////////////////////// -Socket::Status TcpSocket::send(const void* data, std::size_t size) -{ - // Check the parameters - if (!data || (size == 0)) - { - err() << "Cannot send data over the network (no data to send)" << std::endl; - return Error; - } - - // Loop until every byte has been sent - int sent = 0; - int sizeToSend = static_cast(size); - for (int length = 0; length < sizeToSend; length += sent) - { - // Send a chunk of data - sent = ::send(getHandle(), static_cast(data) + length, sizeToSend - length, flags); - - // Check for errors - if (sent < 0) - return priv::SocketImpl::getErrorStatus(); - } - - return Done; -} - - -//////////////////////////////////////////////////////////// -Socket::Status TcpSocket::receive(void* data, std::size_t size, std::size_t& received) -{ - // First clear the variables to fill - received = 0; - - // Check the destination buffer - if (!data) - { - err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl; - return Error; - } - - // Receive a chunk of bytes - int sizeReceived = recv(getHandle(), static_cast(data), static_cast(size), flags); - - // Check the number of bytes received - if (sizeReceived > 0) - { - received = static_cast(sizeReceived); - return Done; - } - else if (sizeReceived == 0) - { - return Socket::Disconnected; - } - else - { - return priv::SocketImpl::getErrorStatus(); - } -} - - -//////////////////////////////////////////////////////////// -Socket::Status TcpSocket::send(Packet& packet) -{ - // TCP is a stream protocol, it doesn't preserve messages boundaries. - // This means that we have to send the packet size first, so that the - // receiver knows the actual end of the packet in the data stream. - - // We allocate an extra memory block so that the size can be sent - // together with the data in a single call. This may seem inefficient, - // but it is actually required to avoid partial send, which could cause - // data corruption on the receiving end. - - // Get the data to send from the packet - std::size_t size = 0; - const void* data = packet.onSend(size); - - // First convert the packet size to network byte order - Uint32 packetSize = htonl(static_cast(size)); - - // Allocate memory for the data block to send - std::vector blockToSend(sizeof(packetSize) + size); - - // Copy the packet size and data into the block to send - std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize)); - if (size > 0) - std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size); - - // Send the data block - return send(&blockToSend[0], blockToSend.size()); -} - - -//////////////////////////////////////////////////////////// -Socket::Status TcpSocket::receive(Packet& packet) -{ - // First clear the variables to fill - packet.clear(); - - // We start by getting the size of the incoming packet - Uint32 packetSize = 0; - std::size_t received = 0; - if (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size)) - { - // Loop until we've received the entire size of the packet - // (even a 4 byte variable may be received in more than one call) - while (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size)) - { - char* data = reinterpret_cast(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived; - Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received); - m_pendingPacket.SizeReceived += received; - - if (status != Done) - return status; - } - - // The packet size has been fully received - packetSize = ntohl(m_pendingPacket.Size); - } - else - { - // The packet size has already been received in a previous call - packetSize = ntohl(m_pendingPacket.Size); - } - - // Loop until we receive all the packet data - char buffer[1024]; - while (m_pendingPacket.Data.size() < packetSize) - { - // Receive a chunk of data - std::size_t sizeToGet = std::min(static_cast(packetSize - m_pendingPacket.Data.size()), sizeof(buffer)); - Status status = receive(buffer, sizeToGet, received); - if (status != Done) - return status; - - // Append it into the packet - if (received > 0) - { - m_pendingPacket.Data.resize(m_pendingPacket.Data.size() + received); - char* begin = &m_pendingPacket.Data[0] + m_pendingPacket.Data.size() - received; - std::memcpy(begin, buffer, received); - } - } - - // We have received all the packet data: we can copy it to the user packet - if (!m_pendingPacket.Data.empty()) - packet.onReceive(&m_pendingPacket.Data[0], m_pendingPacket.Data.size()); - - // Clear the pending packet data - m_pendingPacket = PendingPacket(); - - return Done; -} - - -//////////////////////////////////////////////////////////// -TcpSocket::PendingPacket::PendingPacket() : -Size (0), -SizeReceived(0), -Data () -{ - -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER + #pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro +#endif + + +namespace +{ + // Define the low-level send/receive flags, which depend on the OS + #ifdef SFML_SYSTEM_LINUX + const int flags = MSG_NOSIGNAL; + #else + const int flags = 0; + #endif +} + +namespace sf +{ +//////////////////////////////////////////////////////////// +TcpSocket::TcpSocket() : +Socket(Tcp) +{ + +} + + +//////////////////////////////////////////////////////////// +unsigned short TcpSocket::getLocalPort() const +{ + if (getHandle() != priv::SocketImpl::invalidSocket()) + { + // Retrieve informations about the local end of the socket + sockaddr_in address; + priv::SocketImpl::AddrLength size = sizeof(address); + if (getsockname(getHandle(), reinterpret_cast(&address), &size) != -1) + { + return ntohs(address.sin_port); + } + } + + // We failed to retrieve the port + return 0; +} + + +//////////////////////////////////////////////////////////// +IpAddress TcpSocket::getRemoteAddress() const +{ + if (getHandle() != priv::SocketImpl::invalidSocket()) + { + // Retrieve informations about the remote end of the socket + sockaddr_in address; + priv::SocketImpl::AddrLength size = sizeof(address); + if (getpeername(getHandle(), reinterpret_cast(&address), &size) != -1) + { + return IpAddress(ntohl(address.sin_addr.s_addr)); + } + } + + // We failed to retrieve the address + return IpAddress::None; +} + + +//////////////////////////////////////////////////////////// +unsigned short TcpSocket::getRemotePort() const +{ + if (getHandle() != priv::SocketImpl::invalidSocket()) + { + // Retrieve informations about the remote end of the socket + sockaddr_in address; + priv::SocketImpl::AddrLength size = sizeof(address); + if (getpeername(getHandle(), reinterpret_cast(&address), &size) != -1) + { + return ntohs(address.sin_port); + } + } + + // We failed to retrieve the port + return 0; +} + + +//////////////////////////////////////////////////////////// +Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout) +{ + // Create the internal socket if it doesn't exist + create(); + + // Create the remote address + sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort); + + if (timeout <= Time::Zero) + { + // ----- We're not using a timeout: just try to connect ----- + + // Connect the socket + if (::connect(getHandle(), reinterpret_cast(&address), sizeof(address)) == -1) + return priv::SocketImpl::getErrorStatus(); + + // Connection succeeded + return Done; + } + else + { + // ----- We're using a timeout: we'll need a few tricks to make it work ----- + + // Save the previous blocking state + bool blocking = isBlocking(); + + // Switch to non-blocking to enable our connection timeout + if (blocking) + setBlocking(false); + + // Try to connect to the remote address + if (::connect(getHandle(), reinterpret_cast(&address), sizeof(address)) >= 0) + { + // We got instantly connected! (it may no happen a lot...) + setBlocking(blocking); + return Done; + } + + // Get the error status + Status status = priv::SocketImpl::getErrorStatus(); + + // If we were in non-blocking mode, return immediatly + if (!blocking) + return status; + + // Otherwise, wait until something happens to our socket (success, timeout or error) + if (status == Socket::NotReady) + { + // Setup the selector + fd_set selector; + FD_ZERO(&selector); + FD_SET(getHandle(), &selector); + + // Setup the timeout + timeval time; + time.tv_sec = static_cast(timeout.asMicroseconds() / 1000000); + time.tv_usec = static_cast(timeout.asMicroseconds() % 1000000); + + // Wait for something to write on our socket (which means that the connection request has returned) + if (select(static_cast(getHandle() + 1), NULL, &selector, NULL, &time) > 0) + { + // At this point the connection may have been either accepted or refused. + // To know whether it's a success or a failure, we must check the address of the connected peer + if (getRemoteAddress() != sf::IpAddress::None) + { + // Connection accepted + status = Done; + } + else + { + // Connection refused + status = priv::SocketImpl::getErrorStatus(); + } + } + else + { + // Failed to connect before timeout is over + status = priv::SocketImpl::getErrorStatus(); + } + } + + // Switch back to blocking mode + setBlocking(true); + + return status; + } +} + + +//////////////////////////////////////////////////////////// +void TcpSocket::disconnect() +{ + // Close the socket + close(); + + // Reset the pending packet data + m_pendingPacket = PendingPacket(); +} + + +//////////////////////////////////////////////////////////// +Socket::Status TcpSocket::send(const void* data, std::size_t size) +{ + // Check the parameters + if (!data || (size == 0)) + { + err() << "Cannot send data over the network (no data to send)" << std::endl; + return Error; + } + + // Loop until every byte has been sent + int sent = 0; + int sizeToSend = static_cast(size); + for (int length = 0; length < sizeToSend; length += sent) + { + // Send a chunk of data + sent = ::send(getHandle(), static_cast(data) + length, sizeToSend - length, flags); + + // Check for errors + if (sent < 0) + return priv::SocketImpl::getErrorStatus(); + } + + return Done; +} + + +//////////////////////////////////////////////////////////// +Socket::Status TcpSocket::receive(void* data, std::size_t size, std::size_t& received) +{ + // First clear the variables to fill + received = 0; + + // Check the destination buffer + if (!data) + { + err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl; + return Error; + } + + // Receive a chunk of bytes + int sizeReceived = recv(getHandle(), static_cast(data), static_cast(size), flags); + + // Check the number of bytes received + if (sizeReceived > 0) + { + received = static_cast(sizeReceived); + return Done; + } + else if (sizeReceived == 0) + { + return Socket::Disconnected; + } + else + { + return priv::SocketImpl::getErrorStatus(); + } +} + + +//////////////////////////////////////////////////////////// +Socket::Status TcpSocket::send(Packet& packet) +{ + // TCP is a stream protocol, it doesn't preserve messages boundaries. + // This means that we have to send the packet size first, so that the + // receiver knows the actual end of the packet in the data stream. + + // We allocate an extra memory block so that the size can be sent + // together with the data in a single call. This may seem inefficient, + // but it is actually required to avoid partial send, which could cause + // data corruption on the receiving end. + + // Get the data to send from the packet + std::size_t size = 0; + const void* data = packet.onSend(size); + + // First convert the packet size to network byte order + Uint32 packetSize = htonl(static_cast(size)); + + // Allocate memory for the data block to send + std::vector blockToSend(sizeof(packetSize) + size); + + // Copy the packet size and data into the block to send + std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize)); + if (size > 0) + std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size); + + // Send the data block + return send(&blockToSend[0], blockToSend.size()); +} + + +//////////////////////////////////////////////////////////// +Socket::Status TcpSocket::receive(Packet& packet) +{ + // First clear the variables to fill + packet.clear(); + + // We start by getting the size of the incoming packet + Uint32 packetSize = 0; + std::size_t received = 0; + if (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size)) + { + // Loop until we've received the entire size of the packet + // (even a 4 byte variable may be received in more than one call) + while (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size)) + { + char* data = reinterpret_cast(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived; + Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received); + m_pendingPacket.SizeReceived += received; + + if (status != Done) + return status; + } + + // The packet size has been fully received + packetSize = ntohl(m_pendingPacket.Size); + } + else + { + // The packet size has already been received in a previous call + packetSize = ntohl(m_pendingPacket.Size); + } + + // Loop until we receive all the packet data + char buffer[1024]; + while (m_pendingPacket.Data.size() < packetSize) + { + // Receive a chunk of data + std::size_t sizeToGet = std::min(static_cast(packetSize - m_pendingPacket.Data.size()), sizeof(buffer)); + Status status = receive(buffer, sizeToGet, received); + if (status != Done) + return status; + + // Append it into the packet + if (received > 0) + { + m_pendingPacket.Data.resize(m_pendingPacket.Data.size() + received); + char* begin = &m_pendingPacket.Data[0] + m_pendingPacket.Data.size() - received; + std::memcpy(begin, buffer, received); + } + } + + // We have received all the packet data: we can copy it to the user packet + if (!m_pendingPacket.Data.empty()) + packet.onReceive(&m_pendingPacket.Data[0], m_pendingPacket.Data.size()); + + // Clear the pending packet data + m_pendingPacket = PendingPacket(); + + return Done; +} + + +//////////////////////////////////////////////////////////// +TcpSocket::PendingPacket::PendingPacket() : +Size (0), +SizeReceived(0), +Data () +{ + +} + +} // namespace sf diff --git a/src/SFML/Network/UdpSocket.cpp b/src/SFML/Network/UdpSocket.cpp index 290bb29b..af56f5d7 100644 --- a/src/SFML/Network/UdpSocket.cpp +++ b/src/SFML/Network/UdpSocket.cpp @@ -1,193 +1,193 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -UdpSocket::UdpSocket() : -Socket (Udp), -m_buffer(MaxDatagramSize) -{ - -} - - -//////////////////////////////////////////////////////////// -unsigned short UdpSocket::getLocalPort() const -{ - if (getHandle() != priv::SocketImpl::invalidSocket()) - { - // Retrieve informations about the local end of the socket - sockaddr_in address; - priv::SocketImpl::AddrLength size = sizeof(address); - if (getsockname(getHandle(), reinterpret_cast(&address), &size) != -1) - { - return ntohs(address.sin_port); - } - } - - // We failed to retrieve the port - return 0; -} - - -//////////////////////////////////////////////////////////// -Socket::Status UdpSocket::bind(unsigned short port) -{ - // Create the internal socket if it doesn't exist - create(); - - // Bind the socket - sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port); - if (::bind(getHandle(), reinterpret_cast(&address), sizeof(address)) == -1) - { - err() << "Failed to bind socket to port " << port << std::endl; - return Error; - } - - return Done; -} - - -//////////////////////////////////////////////////////////// -void UdpSocket::unbind() -{ - // Simply close the socket - close(); -} - - -//////////////////////////////////////////////////////////// -Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort) -{ - // Create the internal socket if it doesn't exist - create(); - - // Make sure that all the data will fit in one datagram - if (size > MaxDatagramSize) - { - err() << "Cannot send data over the network " - << "(the number of bytes to send is greater than sf::UdpSocket::MaxDatagramSize)" << std::endl; - return Error; - } - - // Build the target address - sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort); - - // Send the data (unlike TCP, all the data is always sent in one call) - int sent = sendto(getHandle(), static_cast(data), static_cast(size), 0, reinterpret_cast(&address), sizeof(address)); - - // Check for errors - if (sent < 0) - return priv::SocketImpl::getErrorStatus(); - - return Done; -} - - -//////////////////////////////////////////////////////////// -Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort) -{ - // First clear the variables to fill - received = 0; - remoteAddress = IpAddress(); - remotePort = 0; - - // Check the destination buffer - if (!data) - { - err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl; - return Error; - } - - // Data that will be filled with the other computer's address - sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, 0); - - // Receive a chunk of bytes - priv::SocketImpl::AddrLength addressSize = sizeof(address); - int sizeReceived = recvfrom(getHandle(), static_cast(data), static_cast(size), 0, reinterpret_cast(&address), &addressSize); - - // Check for errors - if (sizeReceived < 0) - return priv::SocketImpl::getErrorStatus(); - - // Fill the sender informations - received = static_cast(sizeReceived); - remoteAddress = IpAddress(ntohl(address.sin_addr.s_addr)); - remotePort = ntohs(address.sin_port); - - return Done; -} - - -//////////////////////////////////////////////////////////// -Socket::Status UdpSocket::send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort) -{ - // UDP is a datagram-oriented protocol (as opposed to TCP which is a stream protocol). - // Sending one datagram is almost safe: it may be lost but if it's received, then its data - // is guaranteed to be ok. However, splitting a packet into multiple datagrams would be highly - // unreliable, since datagrams may be reordered, dropped or mixed between different sources. - // That's why SFML imposes a limit on packet size so that they can be sent in a single datagram. - // This also removes the overhead associated to packets -- there's no size to send in addition - // to the packet's data. - - // Get the data to send from the packet - std::size_t size = 0; - const void* data = packet.onSend(size); - - // Send it - return send(data, size, remoteAddress, remotePort); -} - - -//////////////////////////////////////////////////////////// -Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort) -{ - // See the detailed comment in send(Packet) above. - - // Receive the datagram - std::size_t received = 0; - Status status = receive(&m_buffer[0], m_buffer.size(), received, remoteAddress, remotePort); - - // If we received valid data, we can copy it to the user packet - packet.clear(); - if ((status == Done) && (received > 0)) - packet.onReceive(&m_buffer[0], received); - - return status; -} - - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +UdpSocket::UdpSocket() : +Socket (Udp), +m_buffer(MaxDatagramSize) +{ + +} + + +//////////////////////////////////////////////////////////// +unsigned short UdpSocket::getLocalPort() const +{ + if (getHandle() != priv::SocketImpl::invalidSocket()) + { + // Retrieve informations about the local end of the socket + sockaddr_in address; + priv::SocketImpl::AddrLength size = sizeof(address); + if (getsockname(getHandle(), reinterpret_cast(&address), &size) != -1) + { + return ntohs(address.sin_port); + } + } + + // We failed to retrieve the port + return 0; +} + + +//////////////////////////////////////////////////////////// +Socket::Status UdpSocket::bind(unsigned short port) +{ + // Create the internal socket if it doesn't exist + create(); + + // Bind the socket + sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port); + if (::bind(getHandle(), reinterpret_cast(&address), sizeof(address)) == -1) + { + err() << "Failed to bind socket to port " << port << std::endl; + return Error; + } + + return Done; +} + + +//////////////////////////////////////////////////////////// +void UdpSocket::unbind() +{ + // Simply close the socket + close(); +} + + +//////////////////////////////////////////////////////////// +Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort) +{ + // Create the internal socket if it doesn't exist + create(); + + // Make sure that all the data will fit in one datagram + if (size > MaxDatagramSize) + { + err() << "Cannot send data over the network " + << "(the number of bytes to send is greater than sf::UdpSocket::MaxDatagramSize)" << std::endl; + return Error; + } + + // Build the target address + sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort); + + // Send the data (unlike TCP, all the data is always sent in one call) + int sent = sendto(getHandle(), static_cast(data), static_cast(size), 0, reinterpret_cast(&address), sizeof(address)); + + // Check for errors + if (sent < 0) + return priv::SocketImpl::getErrorStatus(); + + return Done; +} + + +//////////////////////////////////////////////////////////// +Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort) +{ + // First clear the variables to fill + received = 0; + remoteAddress = IpAddress(); + remotePort = 0; + + // Check the destination buffer + if (!data) + { + err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl; + return Error; + } + + // Data that will be filled with the other computer's address + sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, 0); + + // Receive a chunk of bytes + priv::SocketImpl::AddrLength addressSize = sizeof(address); + int sizeReceived = recvfrom(getHandle(), static_cast(data), static_cast(size), 0, reinterpret_cast(&address), &addressSize); + + // Check for errors + if (sizeReceived < 0) + return priv::SocketImpl::getErrorStatus(); + + // Fill the sender informations + received = static_cast(sizeReceived); + remoteAddress = IpAddress(ntohl(address.sin_addr.s_addr)); + remotePort = ntohs(address.sin_port); + + return Done; +} + + +//////////////////////////////////////////////////////////// +Socket::Status UdpSocket::send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort) +{ + // UDP is a datagram-oriented protocol (as opposed to TCP which is a stream protocol). + // Sending one datagram is almost safe: it may be lost but if it's received, then its data + // is guaranteed to be ok. However, splitting a packet into multiple datagrams would be highly + // unreliable, since datagrams may be reordered, dropped or mixed between different sources. + // That's why SFML imposes a limit on packet size so that they can be sent in a single datagram. + // This also removes the overhead associated to packets -- there's no size to send in addition + // to the packet's data. + + // Get the data to send from the packet + std::size_t size = 0; + const void* data = packet.onSend(size); + + // Send it + return send(data, size, remoteAddress, remotePort); +} + + +//////////////////////////////////////////////////////////// +Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort) +{ + // See the detailed comment in send(Packet) above. + + // Receive the datagram + std::size_t received = 0; + Status status = receive(&m_buffer[0], m_buffer.size(), received, remoteAddress, remotePort); + + // If we received valid data, we can copy it to the user packet + packet.clear(); + if ((status == Done) && (received > 0)) + packet.onReceive(&m_buffer[0], received); + + return status; +} + + +} // namespace sf diff --git a/src/SFML/Network/Unix/SocketImpl.cpp b/src/SFML/Network/Unix/SocketImpl.cpp index 3d840f24..a36e617c 100644 --- a/src/SFML/Network/Unix/SocketImpl.cpp +++ b/src/SFML/Network/Unix/SocketImpl.cpp @@ -1,104 +1,104 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port) -{ - sockaddr_in addr; - std::memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = htonl(address); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - -#if defined(SFML_SYSTEM_MACOS) - addr.sin_len = sizeof(addr); -#endif - - return addr; -} - - -//////////////////////////////////////////////////////////// -SocketHandle SocketImpl::invalidSocket() -{ - return -1; -} - - -//////////////////////////////////////////////////////////// -void SocketImpl::close(SocketHandle sock) -{ - ::close(sock); -} - - -//////////////////////////////////////////////////////////// -void SocketImpl::setBlocking(SocketHandle sock, bool block) -{ - int status = fcntl(sock, F_GETFL); - if (block) - fcntl(sock, F_SETFL, status & ~O_NONBLOCK); - else - fcntl(sock, F_SETFL, status | O_NONBLOCK); -} - - -//////////////////////////////////////////////////////////// -Socket::Status SocketImpl::getErrorStatus() -{ - // The followings are sometimes equal to EWOULDBLOCK, - // so we have to make a special case for them in order - // to avoid having double values in the switch case - if ((errno == EAGAIN) || (errno == EINPROGRESS)) - return Socket::NotReady; - - switch (errno) - { - case EWOULDBLOCK : return Socket::NotReady; - case ECONNABORTED : return Socket::Disconnected; - case ECONNRESET : return Socket::Disconnected; - case ETIMEDOUT : return Socket::Disconnected; - case ENETRESET : return Socket::Disconnected; - case ENOTCONN : return Socket::Disconnected; - case EPIPE : return Socket::Disconnected; - default : return Socket::Error; - } -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port) +{ + sockaddr_in addr; + std::memset(&addr, 0, sizeof(addr)); + addr.sin_addr.s_addr = htonl(address); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + +#if defined(SFML_SYSTEM_MACOS) + addr.sin_len = sizeof(addr); +#endif + + return addr; +} + + +//////////////////////////////////////////////////////////// +SocketHandle SocketImpl::invalidSocket() +{ + return -1; +} + + +//////////////////////////////////////////////////////////// +void SocketImpl::close(SocketHandle sock) +{ + ::close(sock); +} + + +//////////////////////////////////////////////////////////// +void SocketImpl::setBlocking(SocketHandle sock, bool block) +{ + int status = fcntl(sock, F_GETFL); + if (block) + fcntl(sock, F_SETFL, status & ~O_NONBLOCK); + else + fcntl(sock, F_SETFL, status | O_NONBLOCK); +} + + +//////////////////////////////////////////////////////////// +Socket::Status SocketImpl::getErrorStatus() +{ + // The followings are sometimes equal to EWOULDBLOCK, + // so we have to make a special case for them in order + // to avoid having double values in the switch case + if ((errno == EAGAIN) || (errno == EINPROGRESS)) + return Socket::NotReady; + + switch (errno) + { + case EWOULDBLOCK: return Socket::NotReady; + case ECONNABORTED: return Socket::Disconnected; + case ECONNRESET: return Socket::Disconnected; + case ETIMEDOUT: return Socket::Disconnected; + case ENETRESET: return Socket::Disconnected; + case ENOTCONN: return Socket::Disconnected; + case EPIPE: return Socket::Disconnected; + default: return Socket::Error; + } +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Network/Unix/SocketImpl.hpp b/src/SFML/Network/Unix/SocketImpl.hpp index 7d32a965..8a3f29fc 100644 --- a/src/SFML/Network/Unix/SocketImpl.hpp +++ b/src/SFML/Network/Unix/SocketImpl.hpp @@ -1,109 +1,109 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOCKETIMPL_HPP -#define SFML_SOCKETIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Helper class implementing all the non-portable -/// socket stuff; this is the Unix version -/// -//////////////////////////////////////////////////////////// -class SocketImpl -{ -public : - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef socklen_t AddrLength; - - //////////////////////////////////////////////////////////// - /// \brief Create an internal sockaddr_in address - /// - /// \param address Target address - /// \param port Target port - /// - /// \return sockaddr_in ready to be used by socket functions - /// - //////////////////////////////////////////////////////////// - static sockaddr_in createAddress(Uint32 address, unsigned short port); - - //////////////////////////////////////////////////////////// - /// \brief Return the value of the invalid socket - /// - /// \return Special value of the invalid socket - /// - //////////////////////////////////////////////////////////// - static SocketHandle invalidSocket(); - - //////////////////////////////////////////////////////////// - /// \brief Close and destroy a socket - /// - /// \param sock Handle of the socket to close - /// - //////////////////////////////////////////////////////////// - static void close(SocketHandle sock); - - //////////////////////////////////////////////////////////// - /// \brief Set a socket as blocking or non-blocking - /// - /// \param sock Handle of the socket - /// \param block New blocking state of the socket - /// - //////////////////////////////////////////////////////////// - static void setBlocking(SocketHandle sock, bool block); - - //////////////////////////////////////////////////////////// - /// Get the last socket error status - /// - /// \return Status corresponding to the last socket error - /// - //////////////////////////////////////////////////////////// - static Socket::Status getErrorStatus(); -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_SOCKETIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOCKETIMPL_HPP +#define SFML_SOCKETIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Helper class implementing all the non-portable +/// socket stuff; this is the Unix version +/// +//////////////////////////////////////////////////////////// +class SocketImpl +{ +public: + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef socklen_t AddrLength; + + //////////////////////////////////////////////////////////// + /// \brief Create an internal sockaddr_in address + /// + /// \param address Target address + /// \param port Target port + /// + /// \return sockaddr_in ready to be used by socket functions + /// + //////////////////////////////////////////////////////////// + static sockaddr_in createAddress(Uint32 address, unsigned short port); + + //////////////////////////////////////////////////////////// + /// \brief Return the value of the invalid socket + /// + /// \return Special value of the invalid socket + /// + //////////////////////////////////////////////////////////// + static SocketHandle invalidSocket(); + + //////////////////////////////////////////////////////////// + /// \brief Close and destroy a socket + /// + /// \param sock Handle of the socket to close + /// + //////////////////////////////////////////////////////////// + static void close(SocketHandle sock); + + //////////////////////////////////////////////////////////// + /// \brief Set a socket as blocking or non-blocking + /// + /// \param sock Handle of the socket + /// \param block New blocking state of the socket + /// + //////////////////////////////////////////////////////////// + static void setBlocking(SocketHandle sock, bool block); + + //////////////////////////////////////////////////////////// + /// Get the last socket error status + /// + /// \return Status corresponding to the last socket error + /// + //////////////////////////////////////////////////////////// + static Socket::Status getErrorStatus(); +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_SOCKETIMPL_HPP diff --git a/src/SFML/Network/Win32/SocketImpl.cpp b/src/SFML/Network/Win32/SocketImpl.cpp index 89d73032..3fc6bb23 100644 --- a/src/SFML/Network/Win32/SocketImpl.cpp +++ b/src/SFML/Network/Win32/SocketImpl.cpp @@ -1,112 +1,112 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port) -{ - sockaddr_in addr; - std::memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = htonl(address); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - - return addr; -} - - -//////////////////////////////////////////////////////////// -SocketHandle SocketImpl::invalidSocket() -{ - return INVALID_SOCKET; -} - - -//////////////////////////////////////////////////////////// -void SocketImpl::close(SocketHandle sock) -{ - closesocket(sock); -} - - -//////////////////////////////////////////////////////////// -void SocketImpl::setBlocking(SocketHandle sock, bool block) -{ - u_long blocking = block ? 0 : 1; - ioctlsocket(sock, FIONBIO, &blocking); -} - - -//////////////////////////////////////////////////////////// -Socket::Status SocketImpl::getErrorStatus() -{ - switch (WSAGetLastError()) - { - case WSAEWOULDBLOCK : return Socket::NotReady; - case WSAEALREADY : return Socket::NotReady; - case WSAECONNABORTED : return Socket::Disconnected; - case WSAECONNRESET : return Socket::Disconnected; - case WSAETIMEDOUT : return Socket::Disconnected; - case WSAENETRESET : return Socket::Disconnected; - case WSAENOTCONN : return Socket::Disconnected; - case WSAEISCONN : return Socket::Done; // when connecting a non-blocking socket - default : return Socket::Error; - } -} - - -//////////////////////////////////////////////////////////// -// Windows needs some initialization and cleanup to get -// sockets working properly... so let's create a class that will -// do it automatically -//////////////////////////////////////////////////////////// -struct SocketInitializer -{ - SocketInitializer() - { - WSADATA init; - WSAStartup(MAKEWORD(2, 2), &init); - } - - ~SocketInitializer() - { - WSACleanup(); - } -}; - -SocketInitializer globalInitializer; - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port) +{ + sockaddr_in addr; + std::memset(&addr, 0, sizeof(addr)); + addr.sin_addr.s_addr = htonl(address); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + return addr; +} + + +//////////////////////////////////////////////////////////// +SocketHandle SocketImpl::invalidSocket() +{ + return INVALID_SOCKET; +} + + +//////////////////////////////////////////////////////////// +void SocketImpl::close(SocketHandle sock) +{ + closesocket(sock); +} + + +//////////////////////////////////////////////////////////// +void SocketImpl::setBlocking(SocketHandle sock, bool block) +{ + u_long blocking = block ? 0 : 1; + ioctlsocket(sock, FIONBIO, &blocking); +} + + +//////////////////////////////////////////////////////////// +Socket::Status SocketImpl::getErrorStatus() +{ + switch (WSAGetLastError()) + { + case WSAEWOULDBLOCK: return Socket::NotReady; + case WSAEALREADY: return Socket::NotReady; + case WSAECONNABORTED: return Socket::Disconnected; + case WSAECONNRESET: return Socket::Disconnected; + case WSAETIMEDOUT: return Socket::Disconnected; + case WSAENETRESET: return Socket::Disconnected; + case WSAENOTCONN: return Socket::Disconnected; + case WSAEISCONN: return Socket::Done; // when connecting a non-blocking socket + default: return Socket::Error; + } +} + + +//////////////////////////////////////////////////////////// +// Windows needs some initialization and cleanup to get +// sockets working properly... so let's create a class that will +// do it automatically +//////////////////////////////////////////////////////////// +struct SocketInitializer +{ + SocketInitializer() + { + WSADATA init; + WSAStartup(MAKEWORD(2, 2), &init); + } + + ~SocketInitializer() + { + WSACleanup(); + } +}; + +SocketInitializer globalInitializer; + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Network/Win32/SocketImpl.hpp b/src/SFML/Network/Win32/SocketImpl.hpp index 1848afa3..8178c7c6 100644 --- a/src/SFML/Network/Win32/SocketImpl.hpp +++ b/src/SFML/Network/Win32/SocketImpl.hpp @@ -1,112 +1,112 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_SOCKETIMPL_HPP -#define SFML_SOCKETIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#ifdef _WIN32_WINDOWS - #undef _WIN32_WINDOWS -#endif -#ifdef _WIN32_WINNT - #undef _WIN32_WINNT -#endif -#define _WIN32_WINDOWS 0x0501 -#define _WIN32_WINNT 0x0501 -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Helper class implementing all the non-portable -/// socket stuff; this is the Windows version -/// -//////////////////////////////////////////////////////////// -class SocketImpl -{ -public : - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef int AddrLength; - - //////////////////////////////////////////////////////////// - /// \brief Create an internal sockaddr_in address - /// - /// \param address Target address - /// \param port Target port - /// - /// \return sockaddr_in ready to be used by socket functions - /// - //////////////////////////////////////////////////////////// - static sockaddr_in createAddress(Uint32 address, unsigned short port); - - //////////////////////////////////////////////////////////// - /// \brief Return the value of the invalid socket - /// - /// \return Special value of the invalid socket - /// - //////////////////////////////////////////////////////////// - static SocketHandle invalidSocket(); - - //////////////////////////////////////////////////////////// - /// \brief Close and destroy a socket - /// - /// \param sock Handle of the socket to close - /// - //////////////////////////////////////////////////////////// - static void close(SocketHandle sock); - - //////////////////////////////////////////////////////////// - /// \brief Set a socket as blocking or non-blocking - /// - /// \param sock Handle of the socket - /// \param block New blocking state of the socket - /// - //////////////////////////////////////////////////////////// - static void setBlocking(SocketHandle sock, bool block); - - //////////////////////////////////////////////////////////// - /// Get the last socket error status - /// - /// \return Status corresponding to the last socket error - /// - //////////////////////////////////////////////////////////// - static Socket::Status getErrorStatus(); -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_SOCKETIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOCKETIMPL_HPP +#define SFML_SOCKETIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#ifdef _WIN32_WINDOWS + #undef _WIN32_WINDOWS +#endif +#ifdef _WIN32_WINNT + #undef _WIN32_WINNT +#endif +#define _WIN32_WINDOWS 0x0501 +#define _WIN32_WINNT 0x0501 +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Helper class implementing all the non-portable +/// socket stuff; this is the Windows version +/// +//////////////////////////////////////////////////////////// +class SocketImpl +{ +public: + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef int AddrLength; + + //////////////////////////////////////////////////////////// + /// \brief Create an internal sockaddr_in address + /// + /// \param address Target address + /// \param port Target port + /// + /// \return sockaddr_in ready to be used by socket functions + /// + //////////////////////////////////////////////////////////// + static sockaddr_in createAddress(Uint32 address, unsigned short port); + + //////////////////////////////////////////////////////////// + /// \brief Return the value of the invalid socket + /// + /// \return Special value of the invalid socket + /// + //////////////////////////////////////////////////////////// + static SocketHandle invalidSocket(); + + //////////////////////////////////////////////////////////// + /// \brief Close and destroy a socket + /// + /// \param sock Handle of the socket to close + /// + //////////////////////////////////////////////////////////// + static void close(SocketHandle sock); + + //////////////////////////////////////////////////////////// + /// \brief Set a socket as blocking or non-blocking + /// + /// \param sock Handle of the socket + /// \param block New blocking state of the socket + /// + //////////////////////////////////////////////////////////// + static void setBlocking(SocketHandle sock, bool block); + + //////////////////////////////////////////////////////////// + /// Get the last socket error status + /// + /// \return Status corresponding to the last socket error + /// + //////////////////////////////////////////////////////////// + static Socket::Status getErrorStatus(); +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_SOCKETIMPL_HPP diff --git a/src/SFML/System/Android/ResourceStream.hpp b/src/SFML/System/Android/ResourceStream.hpp index 183f55fe..8f5829b9 100644 --- a/src/SFML/System/Android/ResourceStream.hpp +++ b/src/SFML/System/Android/ResourceStream.hpp @@ -44,7 +44,7 @@ namespace priv //////////////////////////////////////////////////////////// class SFML_SYSTEM_API ResourceStream : public InputStream { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -97,7 +97,7 @@ public : //////////////////////////////////////////////////////////// Int64 getSize(); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/System/CMakeLists.txt b/src/SFML/System/CMakeLists.txt index 728cb52f..74c95de4 100644 --- a/src/SFML/System/CMakeLists.txt +++ b/src/SFML/System/CMakeLists.txt @@ -1,99 +1,99 @@ - -set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/System) -set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/System) - -# all source files -set(SRC - ${SRCROOT}/Clock.cpp - ${INCROOT}/Clock.hpp - ${SRCROOT}/Err.cpp - ${INCROOT}/Err.hpp - ${INCROOT}/Export.hpp - ${INCROOT}/InputStream.hpp - ${SRCROOT}/Lock.cpp - ${INCROOT}/Lock.hpp - ${SRCROOT}/Mutex.cpp - ${INCROOT}/Mutex.hpp - ${INCROOT}/NonCopyable.hpp - ${SRCROOT}/Sleep.cpp - ${INCROOT}/Sleep.hpp - ${SRCROOT}/String.cpp - ${INCROOT}/String.hpp - ${INCROOT}/String.inl - ${SRCROOT}/Thread.cpp - ${INCROOT}/Thread.hpp - ${INCROOT}/Thread.inl - ${SRCROOT}/ThreadLocal.cpp - ${INCROOT}/ThreadLocal.hpp - ${INCROOT}/ThreadLocalPtr.hpp - ${INCROOT}/ThreadLocalPtr.inl - ${SRCROOT}/Time.cpp - ${INCROOT}/Time.hpp - ${INCROOT}/Utf.hpp - ${INCROOT}/Utf.inl - ${INCROOT}/Vector2.hpp - ${INCROOT}/Vector2.inl - ${INCROOT}/Vector3.hpp - ${INCROOT}/Vector3.inl -) -source_group("" FILES ${SRC}) - -# add platform specific sources -if(SFML_OS_WINDOWS) - set(PLATFORM_SRC - ${SRCROOT}/Win32/ClockImpl.cpp - ${SRCROOT}/Win32/ClockImpl.hpp - ${SRCROOT}/Win32/MutexImpl.cpp - ${SRCROOT}/Win32/MutexImpl.hpp - ${SRCROOT}/Win32/SleepImpl.cpp - ${SRCROOT}/Win32/SleepImpl.hpp - ${SRCROOT}/Win32/ThreadImpl.cpp - ${SRCROOT}/Win32/ThreadImpl.hpp - ${SRCROOT}/Win32/ThreadLocalImpl.cpp - ${SRCROOT}/Win32/ThreadLocalImpl.hpp - ) - source_group("windows" FILES ${PLATFORM_SRC}) -else() - set(PLATFORM_SRC - ${SRCROOT}/Unix/ClockImpl.cpp - ${SRCROOT}/Unix/ClockImpl.hpp - ${SRCROOT}/Unix/MutexImpl.cpp - ${SRCROOT}/Unix/MutexImpl.hpp - ${SRCROOT}/Unix/SleepImpl.cpp - ${SRCROOT}/Unix/SleepImpl.hpp - ${SRCROOT}/Unix/ThreadImpl.cpp - ${SRCROOT}/Unix/ThreadImpl.hpp - ${SRCROOT}/Unix/ThreadLocalImpl.cpp - ${SRCROOT}/Unix/ThreadLocalImpl.hpp - ) - - if(SFML_OS_ANDROID) - set(PLATFORM_SRC ${PLATFORM_SRC} - ${SRCROOT}/Android/Activity.hpp - ${SRCROOT}/Android/Activity.cpp - ${SRCROOT}/Android/ResourceStream.cpp - ${SRCROOT}/Android/ResourceStream.cpp - ) - endif() - - source_group("unix" FILES ${PLATFORM_SRC}) -endif() - + +set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/System) +set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/System) + +# all source files +set(SRC + ${SRCROOT}/Clock.cpp + ${INCROOT}/Clock.hpp + ${SRCROOT}/Err.cpp + ${INCROOT}/Err.hpp + ${INCROOT}/Export.hpp + ${INCROOT}/InputStream.hpp + ${SRCROOT}/Lock.cpp + ${INCROOT}/Lock.hpp + ${SRCROOT}/Mutex.cpp + ${INCROOT}/Mutex.hpp + ${INCROOT}/NonCopyable.hpp + ${SRCROOT}/Sleep.cpp + ${INCROOT}/Sleep.hpp + ${SRCROOT}/String.cpp + ${INCROOT}/String.hpp + ${INCROOT}/String.inl + ${SRCROOT}/Thread.cpp + ${INCROOT}/Thread.hpp + ${INCROOT}/Thread.inl + ${SRCROOT}/ThreadLocal.cpp + ${INCROOT}/ThreadLocal.hpp + ${INCROOT}/ThreadLocalPtr.hpp + ${INCROOT}/ThreadLocalPtr.inl + ${SRCROOT}/Time.cpp + ${INCROOT}/Time.hpp + ${INCROOT}/Utf.hpp + ${INCROOT}/Utf.inl + ${INCROOT}/Vector2.hpp + ${INCROOT}/Vector2.inl + ${INCROOT}/Vector3.hpp + ${INCROOT}/Vector3.inl +) +source_group("" FILES ${SRC}) + +# add platform specific sources +if(SFML_OS_WINDOWS) + set(PLATFORM_SRC + ${SRCROOT}/Win32/ClockImpl.cpp + ${SRCROOT}/Win32/ClockImpl.hpp + ${SRCROOT}/Win32/MutexImpl.cpp + ${SRCROOT}/Win32/MutexImpl.hpp + ${SRCROOT}/Win32/SleepImpl.cpp + ${SRCROOT}/Win32/SleepImpl.hpp + ${SRCROOT}/Win32/ThreadImpl.cpp + ${SRCROOT}/Win32/ThreadImpl.hpp + ${SRCROOT}/Win32/ThreadLocalImpl.cpp + ${SRCROOT}/Win32/ThreadLocalImpl.hpp + ) + source_group("windows" FILES ${PLATFORM_SRC}) +else() + set(PLATFORM_SRC + ${SRCROOT}/Unix/ClockImpl.cpp + ${SRCROOT}/Unix/ClockImpl.hpp + ${SRCROOT}/Unix/MutexImpl.cpp + ${SRCROOT}/Unix/MutexImpl.hpp + ${SRCROOT}/Unix/SleepImpl.cpp + ${SRCROOT}/Unix/SleepImpl.hpp + ${SRCROOT}/Unix/ThreadImpl.cpp + ${SRCROOT}/Unix/ThreadImpl.hpp + ${SRCROOT}/Unix/ThreadLocalImpl.cpp + ${SRCROOT}/Unix/ThreadLocalImpl.hpp + ) + + if(SFML_OS_ANDROID) + set(PLATFORM_SRC ${PLATFORM_SRC} + ${SRCROOT}/Android/Activity.hpp + ${SRCROOT}/Android/Activity.cpp + ${SRCROOT}/Android/ResourceStream.cpp + ${SRCROOT}/Android/ResourceStream.cpp + ) + endif() + + source_group("unix" FILES ${PLATFORM_SRC}) +endif() + # build the list of external libraries to link if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX) - list(APPEND SYSTEM_EXT_LIBS pthread) -endif() -if(SFML_OS_LINUX) - list(APPEND SYSTEM_EXT_LIBS rt) -endif() -if(SFML_OS_WINDOWS) - list(APPEND SYSTEM_EXT_LIBS winmm) -endif() -if(SFML_OS_ANDROID) - list(APPEND SYSTEM_EXT_LIBS android log) -endif() - -# define the sfml-system target -sfml_add_library(sfml-system - SOURCES ${SRC} ${PLATFORM_SRC} - EXTERNAL_LIBS ${SYSTEM_EXT_LIBS}) + list(APPEND SYSTEM_EXT_LIBS pthread) +endif() +if(SFML_OS_LINUX) + list(APPEND SYSTEM_EXT_LIBS rt) +endif() +if(SFML_OS_WINDOWS) + list(APPEND SYSTEM_EXT_LIBS winmm) +endif() +if(SFML_OS_ANDROID) + list(APPEND SYSTEM_EXT_LIBS android log) +endif() + +# define the sfml-system target +sfml_add_library(sfml-system + SOURCES ${SRC} ${PLATFORM_SRC} + EXTERNAL_LIBS ${SYSTEM_EXT_LIBS}) diff --git a/src/SFML/System/Clock.cpp b/src/SFML/System/Clock.cpp index f315fc2d..d6ccf241 100644 --- a/src/SFML/System/Clock.cpp +++ b/src/SFML/System/Clock.cpp @@ -1,63 +1,63 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#if defined(SFML_SYSTEM_WINDOWS) - #include -#else - #include -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Clock::Clock() : -m_startTime(priv::ClockImpl::getCurrentTime()) -{ -} - - -//////////////////////////////////////////////////////////// -Time Clock::getElapsedTime() const -{ - return priv::ClockImpl::getCurrentTime() - m_startTime; -} - - -//////////////////////////////////////////////////////////// -Time Clock::restart() -{ - Time now = priv::ClockImpl::getCurrentTime(); - Time elapsed = now - m_startTime; - m_startTime = now; - - return elapsed; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#if defined(SFML_SYSTEM_WINDOWS) + #include +#else + #include +#endif + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Clock::Clock() : +m_startTime(priv::ClockImpl::getCurrentTime()) +{ +} + + +//////////////////////////////////////////////////////////// +Time Clock::getElapsedTime() const +{ + return priv::ClockImpl::getCurrentTime() - m_startTime; +} + + +//////////////////////////////////////////////////////////// +Time Clock::restart() +{ + Time now = priv::ClockImpl::getCurrentTime(); + Time elapsed = now - m_startTime; + m_startTime = now; + + return elapsed; +} + +} // namespace sf diff --git a/src/SFML/System/Err.cpp b/src/SFML/System/Err.cpp index 6215a135..bdfbabfe 100644 --- a/src/SFML/System/Err.cpp +++ b/src/SFML/System/Err.cpp @@ -1,110 +1,110 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace -{ -// This class will be used as the default streambuf of sf::Err, -// it outputs to stderr by default (to keep the default behaviour) -class DefaultErrStreamBuf : public std::streambuf -{ -public : - - DefaultErrStreamBuf() - { - // Allocate the write buffer - static const int size = 64; - char* buffer = new char[size]; - setp(buffer, buffer + size); - } - - ~DefaultErrStreamBuf() - { - // Synchronize - sync(); - - // Delete the write buffer - delete[] pbase(); - } - -private : - - virtual int overflow(int character) - { - if ((character != EOF) && (pptr() != epptr())) - { - // Valid character - return sputc(static_cast(character)); - } - else if (character != EOF) - { - // Not enough space in the buffer: synchronize output and try again - sync(); - return overflow(character); - } - else - { - // Invalid character: synchronize output - return sync(); - } - } - - virtual int sync() - { - // Check if there is something into the write buffer - if (pbase() != pptr()) - { - // Print the contents of the write buffer into the standard error output - std::size_t size = static_cast(pptr() - pbase()); - fwrite(pbase(), 1, size, stderr); - - // Reset the pointer position to the beginning of the write buffer - setp(pbase(), epptr()); - } - - return 0; - } -}; -} - -namespace sf -{ -//////////////////////////////////////////////////////////// -std::ostream& err() -{ - static DefaultErrStreamBuf buffer; - static std::ostream stream(&buffer); - - return stream; -} - - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace +{ +// This class will be used as the default streambuf of sf::Err, +// it outputs to stderr by default (to keep the default behaviour) +class DefaultErrStreamBuf : public std::streambuf +{ +public: + + DefaultErrStreamBuf() + { + // Allocate the write buffer + static const int size = 64; + char* buffer = new char[size]; + setp(buffer, buffer + size); + } + + ~DefaultErrStreamBuf() + { + // Synchronize + sync(); + + // Delete the write buffer + delete[] pbase(); + } + +private: + + virtual int overflow(int character) + { + if ((character != EOF) && (pptr() != epptr())) + { + // Valid character + return sputc(static_cast(character)); + } + else if (character != EOF) + { + // Not enough space in the buffer: synchronize output and try again + sync(); + return overflow(character); + } + else + { + // Invalid character: synchronize output + return sync(); + } + } + + virtual int sync() + { + // Check if there is something into the write buffer + if (pbase() != pptr()) + { + // Print the contents of the write buffer into the standard error output + std::size_t size = static_cast(pptr() - pbase()); + fwrite(pbase(), 1, size, stderr); + + // Reset the pointer position to the beginning of the write buffer + setp(pbase(), epptr()); + } + + return 0; + } +}; +} + +namespace sf +{ +//////////////////////////////////////////////////////////// +std::ostream& err() +{ + static DefaultErrStreamBuf buffer; + static std::ostream stream(&buffer); + + return stream; +} + + +} // namespace sf diff --git a/src/SFML/System/Lock.cpp b/src/SFML/System/Lock.cpp index b17efad7..68a85de6 100644 --- a/src/SFML/System/Lock.cpp +++ b/src/SFML/System/Lock.cpp @@ -1,48 +1,48 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Lock::Lock(Mutex& mutex) : -m_mutex(mutex) -{ - m_mutex.lock(); -} - - -//////////////////////////////////////////////////////////// -Lock::~Lock() -{ - m_mutex.unlock(); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Lock::Lock(Mutex& mutex) : +m_mutex(mutex) +{ + m_mutex.lock(); +} + + +//////////////////////////////////////////////////////////// +Lock::~Lock() +{ + m_mutex.unlock(); +} + +} // namespace sf diff --git a/src/SFML/System/Mutex.cpp b/src/SFML/System/Mutex.cpp index 6c37175a..c3390040 100644 --- a/src/SFML/System/Mutex.cpp +++ b/src/SFML/System/Mutex.cpp @@ -1,66 +1,66 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#if defined(SFML_SYSTEM_WINDOWS) - #include -#else - #include -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Mutex::Mutex() -{ - m_mutexImpl = new priv::MutexImpl; -} - - -//////////////////////////////////////////////////////////// -Mutex::~Mutex() -{ - delete m_mutexImpl; -} - - -//////////////////////////////////////////////////////////// -void Mutex::lock() -{ - m_mutexImpl->lock(); -} - - -//////////////////////////////////////////////////////////// -void Mutex::unlock() -{ - m_mutexImpl->unlock(); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#if defined(SFML_SYSTEM_WINDOWS) + #include +#else + #include +#endif + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Mutex::Mutex() +{ + m_mutexImpl = new priv::MutexImpl; +} + + +//////////////////////////////////////////////////////////// +Mutex::~Mutex() +{ + delete m_mutexImpl; +} + + +//////////////////////////////////////////////////////////// +void Mutex::lock() +{ + m_mutexImpl->lock(); +} + + +//////////////////////////////////////////////////////////// +void Mutex::unlock() +{ + m_mutexImpl->unlock(); +} + +} // namespace sf diff --git a/src/SFML/System/Sleep.cpp b/src/SFML/System/Sleep.cpp index 06c6d803..0bd375f6 100644 --- a/src/SFML/System/Sleep.cpp +++ b/src/SFML/System/Sleep.cpp @@ -1,46 +1,46 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#if defined(SFML_SYSTEM_WINDOWS) - #include -#else - #include -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -void sleep(Time duration) -{ - if (duration >= Time::Zero) - priv::sleepImpl(duration); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#if defined(SFML_SYSTEM_WINDOWS) + #include +#else + #include +#endif + + +namespace sf +{ +//////////////////////////////////////////////////////////// +void sleep(Time duration) +{ + if (duration >= Time::Zero) + priv::sleepImpl(duration); +} + +} // namespace sf diff --git a/src/SFML/System/String.cpp b/src/SFML/System/String.cpp index 61f80e82..a41b12f1 100644 --- a/src/SFML/System/String.cpp +++ b/src/SFML/System/String.cpp @@ -1,400 +1,400 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -const std::size_t String::InvalidPos = std::basic_string::npos; - - -//////////////////////////////////////////////////////////// -String::String() -{ -} - - -//////////////////////////////////////////////////////////// -String::String(char ansiChar, const std::locale& locale) -{ - m_string += Utf32::decodeAnsi(ansiChar, locale); -} - - -//////////////////////////////////////////////////////////// -String::String(wchar_t wideChar) -{ - m_string += Utf32::decodeWide(wideChar); -} - - -//////////////////////////////////////////////////////////// -String::String(Uint32 utf32Char) -{ - m_string += utf32Char; -} - - -//////////////////////////////////////////////////////////// -String::String(const char* ansiString, const std::locale& locale) -{ - if (ansiString) - { - std::size_t length = strlen(ansiString); - if (length > 0) - { - m_string.reserve(length + 1); - Utf32::fromAnsi(ansiString, ansiString + length, std::back_inserter(m_string), locale); - } - } -} - - -//////////////////////////////////////////////////////////// -String::String(const std::string& ansiString, const std::locale& locale) -{ - m_string.reserve(ansiString.length() + 1); - Utf32::fromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(m_string), locale); -} - - -//////////////////////////////////////////////////////////// -String::String(const wchar_t* wideString) -{ - if (wideString) - { - std::size_t length = std::wcslen(wideString); - if (length > 0) - { - m_string.reserve(length + 1); - Utf32::fromWide(wideString, wideString + length, std::back_inserter(m_string)); - } - } -} - - -//////////////////////////////////////////////////////////// -String::String(const std::wstring& wideString) -{ - m_string.reserve(wideString.length() + 1); - Utf32::fromWide(wideString.begin(), wideString.end(), std::back_inserter(m_string)); -} - - -//////////////////////////////////////////////////////////// -String::String(const Uint32* utf32String) -{ - if (utf32String) - m_string = utf32String; -} - - -//////////////////////////////////////////////////////////// -String::String(const std::basic_string& utf32String) : -m_string(utf32String) -{ -} - - -//////////////////////////////////////////////////////////// -String::String(const String& copy) : -m_string(copy.m_string) -{ -} - - -//////////////////////////////////////////////////////////// -String::operator std::string() const -{ - return toAnsiString(); -} - - -//////////////////////////////////////////////////////////// -String::operator std::wstring() const -{ - return toWideString(); -} - - -//////////////////////////////////////////////////////////// -std::string String::toAnsiString(const std::locale& locale) const -{ - // Prepare the output string - std::string output; - output.reserve(m_string.length() + 1); - - // Convert - Utf32::toAnsi(m_string.begin(), m_string.end(), std::back_inserter(output), 0, locale); - - return output; -} - - -//////////////////////////////////////////////////////////// -std::wstring String::toWideString() const -{ - // Prepare the output string - std::wstring output; - output.reserve(m_string.length() + 1); - - // Convert - Utf32::toWide(m_string.begin(), m_string.end(), std::back_inserter(output), 0); - - return output; -} - - -//////////////////////////////////////////////////////////// -std::basic_string String::toUtf8() const -{ - // Prepare the output string - std::basic_string output; - output.reserve(m_string.length()); - - // Convert - Utf32::toUtf8(m_string.begin(), m_string.end(), std::back_inserter(output)); - - return output; -} - - -//////////////////////////////////////////////////////////// -std::basic_string String::toUtf16() const -{ - // Prepare the output string - std::basic_string output; - output.reserve(m_string.length()); - - // Convert - Utf32::toUtf16(m_string.begin(), m_string.end(), std::back_inserter(output)); - - return output; -} - - -//////////////////////////////////////////////////////////// -std::basic_string String::toUtf32() const -{ - return m_string; -} - - -//////////////////////////////////////////////////////////// -String& String::operator =(const String& right) -{ - m_string = right.m_string; - return *this; -} - - -//////////////////////////////////////////////////////////// -String& String::operator +=(const String& right) -{ - m_string += right.m_string; - return *this; -} - - -//////////////////////////////////////////////////////////// -Uint32 String::operator [](std::size_t index) const -{ - return m_string[index]; -} - - -//////////////////////////////////////////////////////////// -Uint32& String::operator [](std::size_t index) -{ - return m_string[index]; -} - - -//////////////////////////////////////////////////////////// -void String::clear() -{ - m_string.clear(); -} - - -//////////////////////////////////////////////////////////// -std::size_t String::getSize() const -{ - return m_string.size(); -} - - -//////////////////////////////////////////////////////////// -bool String::isEmpty() const -{ - return m_string.empty(); -} - - -//////////////////////////////////////////////////////////// -void String::erase(std::size_t position, std::size_t count) -{ - m_string.erase(position, count); -} - - -//////////////////////////////////////////////////////////// -void String::insert(std::size_t position, const String& str) -{ - m_string.insert(position, str.m_string); -} - - -//////////////////////////////////////////////////////////// -std::size_t String::find(const String& str, std::size_t start) const -{ - return m_string.find(str.m_string, start); -} - - -//////////////////////////////////////////////////////////// -void String::replace(std::size_t position, std::size_t length, const String& replaceWith) -{ - m_string.replace(position, length, replaceWith.m_string); -} - - -//////////////////////////////////////////////////////////// -void String::replace(const String& searchFor, const String& replaceWith) -{ - std::size_t step = replaceWith.getSize(); - std::size_t len = searchFor.getSize(); - std::size_t pos = find(searchFor); - - // Replace each occurence of search - while (pos != InvalidPos) - { - replace(pos, len, replaceWith); - pos = find(searchFor, pos + step); - } -} - - -//////////////////////////////////////////////////////////// -String String::substring(std::size_t position, std::size_t length) const -{ - return m_string.substr(position, length); -} - - -//////////////////////////////////////////////////////////// -const Uint32* String::getData() const -{ - return m_string.c_str(); -} - - -//////////////////////////////////////////////////////////// -String::Iterator String::begin() -{ - return m_string.begin(); -} - - -//////////////////////////////////////////////////////////// -String::ConstIterator String::begin() const -{ - return m_string.begin(); -} - - -//////////////////////////////////////////////////////////// -String::Iterator String::end() -{ - return m_string.end(); -} - - -//////////////////////////////////////////////////////////// -String::ConstIterator String::end() const -{ - return m_string.end(); -} - - -//////////////////////////////////////////////////////////// -bool operator ==(const String& left, const String& right) -{ - return left.m_string == right.m_string; -} - - -//////////////////////////////////////////////////////////// -bool operator !=(const String& left, const String& right) -{ - return !(left == right); -} - - -//////////////////////////////////////////////////////////// -bool operator <(const String& left, const String& right) -{ - return left.m_string < right.m_string; -} - - -//////////////////////////////////////////////////////////// -bool operator >(const String& left, const String& right) -{ - return right < left; -} - - -//////////////////////////////////////////////////////////// -bool operator <=(const String& left, const String& right) -{ - return !(right < left); -} - - -//////////////////////////////////////////////////////////// -bool operator >=(const String& left, const String& right) -{ - return !(left < right); -} - - -//////////////////////////////////////////////////////////// -String operator +(const String& left, const String& right) -{ - String string = left; - string += right; - - return string; -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +const std::size_t String::InvalidPos = std::basic_string::npos; + + +//////////////////////////////////////////////////////////// +String::String() +{ +} + + +//////////////////////////////////////////////////////////// +String::String(char ansiChar, const std::locale& locale) +{ + m_string += Utf32::decodeAnsi(ansiChar, locale); +} + + +//////////////////////////////////////////////////////////// +String::String(wchar_t wideChar) +{ + m_string += Utf32::decodeWide(wideChar); +} + + +//////////////////////////////////////////////////////////// +String::String(Uint32 utf32Char) +{ + m_string += utf32Char; +} + + +//////////////////////////////////////////////////////////// +String::String(const char* ansiString, const std::locale& locale) +{ + if (ansiString) + { + std::size_t length = strlen(ansiString); + if (length > 0) + { + m_string.reserve(length + 1); + Utf32::fromAnsi(ansiString, ansiString + length, std::back_inserter(m_string), locale); + } + } +} + + +//////////////////////////////////////////////////////////// +String::String(const std::string& ansiString, const std::locale& locale) +{ + m_string.reserve(ansiString.length() + 1); + Utf32::fromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(m_string), locale); +} + + +//////////////////////////////////////////////////////////// +String::String(const wchar_t* wideString) +{ + if (wideString) + { + std::size_t length = std::wcslen(wideString); + if (length > 0) + { + m_string.reserve(length + 1); + Utf32::fromWide(wideString, wideString + length, std::back_inserter(m_string)); + } + } +} + + +//////////////////////////////////////////////////////////// +String::String(const std::wstring& wideString) +{ + m_string.reserve(wideString.length() + 1); + Utf32::fromWide(wideString.begin(), wideString.end(), std::back_inserter(m_string)); +} + + +//////////////////////////////////////////////////////////// +String::String(const Uint32* utf32String) +{ + if (utf32String) + m_string = utf32String; +} + + +//////////////////////////////////////////////////////////// +String::String(const std::basic_string& utf32String) : +m_string(utf32String) +{ +} + + +//////////////////////////////////////////////////////////// +String::String(const String& copy) : +m_string(copy.m_string) +{ +} + + +//////////////////////////////////////////////////////////// +String::operator std::string() const +{ + return toAnsiString(); +} + + +//////////////////////////////////////////////////////////// +String::operator std::wstring() const +{ + return toWideString(); +} + + +//////////////////////////////////////////////////////////// +std::string String::toAnsiString(const std::locale& locale) const +{ + // Prepare the output string + std::string output; + output.reserve(m_string.length() + 1); + + // Convert + Utf32::toAnsi(m_string.begin(), m_string.end(), std::back_inserter(output), 0, locale); + + return output; +} + + +//////////////////////////////////////////////////////////// +std::wstring String::toWideString() const +{ + // Prepare the output string + std::wstring output; + output.reserve(m_string.length() + 1); + + // Convert + Utf32::toWide(m_string.begin(), m_string.end(), std::back_inserter(output), 0); + + return output; +} + + +//////////////////////////////////////////////////////////// +std::basic_string String::toUtf8() const +{ + // Prepare the output string + std::basic_string output; + output.reserve(m_string.length()); + + // Convert + Utf32::toUtf8(m_string.begin(), m_string.end(), std::back_inserter(output)); + + return output; +} + + +//////////////////////////////////////////////////////////// +std::basic_string String::toUtf16() const +{ + // Prepare the output string + std::basic_string output; + output.reserve(m_string.length()); + + // Convert + Utf32::toUtf16(m_string.begin(), m_string.end(), std::back_inserter(output)); + + return output; +} + + +//////////////////////////////////////////////////////////// +std::basic_string String::toUtf32() const +{ + return m_string; +} + + +//////////////////////////////////////////////////////////// +String& String::operator =(const String& right) +{ + m_string = right.m_string; + return *this; +} + + +//////////////////////////////////////////////////////////// +String& String::operator +=(const String& right) +{ + m_string += right.m_string; + return *this; +} + + +//////////////////////////////////////////////////////////// +Uint32 String::operator [](std::size_t index) const +{ + return m_string[index]; +} + + +//////////////////////////////////////////////////////////// +Uint32& String::operator [](std::size_t index) +{ + return m_string[index]; +} + + +//////////////////////////////////////////////////////////// +void String::clear() +{ + m_string.clear(); +} + + +//////////////////////////////////////////////////////////// +std::size_t String::getSize() const +{ + return m_string.size(); +} + + +//////////////////////////////////////////////////////////// +bool String::isEmpty() const +{ + return m_string.empty(); +} + + +//////////////////////////////////////////////////////////// +void String::erase(std::size_t position, std::size_t count) +{ + m_string.erase(position, count); +} + + +//////////////////////////////////////////////////////////// +void String::insert(std::size_t position, const String& str) +{ + m_string.insert(position, str.m_string); +} + + +//////////////////////////////////////////////////////////// +std::size_t String::find(const String& str, std::size_t start) const +{ + return m_string.find(str.m_string, start); +} + + +//////////////////////////////////////////////////////////// +void String::replace(std::size_t position, std::size_t length, const String& replaceWith) +{ + m_string.replace(position, length, replaceWith.m_string); +} + + +//////////////////////////////////////////////////////////// +void String::replace(const String& searchFor, const String& replaceWith) +{ + std::size_t step = replaceWith.getSize(); + std::size_t len = searchFor.getSize(); + std::size_t pos = find(searchFor); + + // Replace each occurence of search + while (pos != InvalidPos) + { + replace(pos, len, replaceWith); + pos = find(searchFor, pos + step); + } +} + + +//////////////////////////////////////////////////////////// +String String::substring(std::size_t position, std::size_t length) const +{ + return m_string.substr(position, length); +} + + +//////////////////////////////////////////////////////////// +const Uint32* String::getData() const +{ + return m_string.c_str(); +} + + +//////////////////////////////////////////////////////////// +String::Iterator String::begin() +{ + return m_string.begin(); +} + + +//////////////////////////////////////////////////////////// +String::ConstIterator String::begin() const +{ + return m_string.begin(); +} + + +//////////////////////////////////////////////////////////// +String::Iterator String::end() +{ + return m_string.end(); +} + + +//////////////////////////////////////////////////////////// +String::ConstIterator String::end() const +{ + return m_string.end(); +} + + +//////////////////////////////////////////////////////////// +bool operator ==(const String& left, const String& right) +{ + return left.m_string == right.m_string; +} + + +//////////////////////////////////////////////////////////// +bool operator !=(const String& left, const String& right) +{ + return !(left == right); +} + + +//////////////////////////////////////////////////////////// +bool operator <(const String& left, const String& right) +{ + return left.m_string < right.m_string; +} + + +//////////////////////////////////////////////////////////// +bool operator >(const String& left, const String& right) +{ + return right < left; +} + + +//////////////////////////////////////////////////////////// +bool operator <=(const String& left, const String& right) +{ + return !(right < left); +} + + +//////////////////////////////////////////////////////////// +bool operator >=(const String& left, const String& right) +{ + return !(left < right); +} + + +//////////////////////////////////////////////////////////// +String operator +(const String& left, const String& right) +{ + String string = left; + string += right; + + return string; +} + +} // namespace sf diff --git a/src/SFML/System/Thread.cpp b/src/SFML/System/Thread.cpp index a74dfc73..43458029 100644 --- a/src/SFML/System/Thread.cpp +++ b/src/SFML/System/Thread.cpp @@ -1,86 +1,86 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -#if defined(SFML_SYSTEM_WINDOWS) - #include -#else - #include -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Thread::~Thread() -{ - wait(); - delete m_entryPoint; -} - - -//////////////////////////////////////////////////////////// -void Thread::launch() -{ - wait(); - m_impl = new priv::ThreadImpl(this); -} - - -//////////////////////////////////////////////////////////// -void Thread::wait() -{ - if (m_impl) - { - m_impl->wait(); - delete m_impl; - m_impl = NULL; - } -} - - -//////////////////////////////////////////////////////////// -void Thread::terminate() -{ - if (m_impl) - { - m_impl->terminate(); - delete m_impl; - m_impl = NULL; - } -} - - -//////////////////////////////////////////////////////////// -void Thread::run() -{ - m_entryPoint->run(); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +#if defined(SFML_SYSTEM_WINDOWS) + #include +#else + #include +#endif + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Thread::~Thread() +{ + wait(); + delete m_entryPoint; +} + + +//////////////////////////////////////////////////////////// +void Thread::launch() +{ + wait(); + m_impl = new priv::ThreadImpl(this); +} + + +//////////////////////////////////////////////////////////// +void Thread::wait() +{ + if (m_impl) + { + m_impl->wait(); + delete m_impl; + m_impl = NULL; + } +} + + +//////////////////////////////////////////////////////////// +void Thread::terminate() +{ + if (m_impl) + { + m_impl->terminate(); + delete m_impl; + m_impl = NULL; + } +} + + +//////////////////////////////////////////////////////////// +void Thread::run() +{ + m_entryPoint->run(); +} + +} // namespace sf diff --git a/src/SFML/System/ThreadLocal.cpp b/src/SFML/System/ThreadLocal.cpp index 32a2ba6f..bac82299 100644 --- a/src/SFML/System/ThreadLocal.cpp +++ b/src/SFML/System/ThreadLocal.cpp @@ -1,67 +1,67 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#if defined(SFML_SYSTEM_WINDOWS) - #include -#else - #include -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -ThreadLocal::ThreadLocal(void* value) -{ - m_impl = new priv::ThreadLocalImpl; - setValue(value); -} - - -//////////////////////////////////////////////////////////// -ThreadLocal::~ThreadLocal() -{ - delete m_impl; -} - - -//////////////////////////////////////////////////////////// -void ThreadLocal::setValue(void* value) -{ - m_impl->setValue(value); -} - - -//////////////////////////////////////////////////////////// -void* ThreadLocal::getValue() const -{ - return m_impl->getValue(); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#if defined(SFML_SYSTEM_WINDOWS) + #include +#else + #include +#endif + + +namespace sf +{ +//////////////////////////////////////////////////////////// +ThreadLocal::ThreadLocal(void* value) +{ + m_impl = new priv::ThreadLocalImpl; + setValue(value); +} + + +//////////////////////////////////////////////////////////// +ThreadLocal::~ThreadLocal() +{ + delete m_impl; +} + + +//////////////////////////////////////////////////////////// +void ThreadLocal::setValue(void* value) +{ + m_impl->setValue(value); +} + + +//////////////////////////////////////////////////////////// +void* ThreadLocal::getValue() const +{ + return m_impl->getValue(); +} + +} // namespace sf diff --git a/src/SFML/System/Unix/ClockImpl.hpp b/src/SFML/System/Unix/ClockImpl.hpp index 452aa448..6b620bf6 100644 --- a/src/SFML/System/Unix/ClockImpl.hpp +++ b/src/SFML/System/Unix/ClockImpl.hpp @@ -42,7 +42,7 @@ namespace priv //////////////////////////////////////////////////////////// class ClockImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Get the current time diff --git a/src/SFML/System/Unix/MutexImpl.cpp b/src/SFML/System/Unix/MutexImpl.cpp index 5703010c..542ab297 100644 --- a/src/SFML/System/Unix/MutexImpl.cpp +++ b/src/SFML/System/Unix/MutexImpl.cpp @@ -1,69 +1,69 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -MutexImpl::MutexImpl() -{ - // Make it recursive to follow the expected behaviour - pthread_mutexattr_t attributes; - pthread_mutexattr_init(&attributes); - pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE); - - pthread_mutex_init(&m_mutex, &attributes); -} - - -//////////////////////////////////////////////////////////// -MutexImpl::~MutexImpl() -{ - pthread_mutex_destroy(&m_mutex); -} - - -//////////////////////////////////////////////////////////// -void MutexImpl::lock() -{ - pthread_mutex_lock(&m_mutex); -} - - -//////////////////////////////////////////////////////////// -void MutexImpl::unlock() -{ - pthread_mutex_unlock(&m_mutex); -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +MutexImpl::MutexImpl() +{ + // Make it recursive to follow the expected behaviour + pthread_mutexattr_t attributes; + pthread_mutexattr_init(&attributes); + pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init(&m_mutex, &attributes); +} + + +//////////////////////////////////////////////////////////// +MutexImpl::~MutexImpl() +{ + pthread_mutex_destroy(&m_mutex); +} + + +//////////////////////////////////////////////////////////// +void MutexImpl::lock() +{ + pthread_mutex_lock(&m_mutex); +} + + +//////////////////////////////////////////////////////////// +void MutexImpl::unlock() +{ + pthread_mutex_unlock(&m_mutex); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/System/Unix/MutexImpl.hpp b/src/SFML/System/Unix/MutexImpl.hpp index 3cc75bee..03cb32e1 100644 --- a/src/SFML/System/Unix/MutexImpl.hpp +++ b/src/SFML/System/Unix/MutexImpl.hpp @@ -1,83 +1,83 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_MUTEXIMPL_HPP -#define SFML_MUTEXIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Unix implementation of mutexes -//////////////////////////////////////////////////////////// -class MutexImpl : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - MutexImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~MutexImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Lock the mutex - /// - //////////////////////////////////////////////////////////// - void lock(); - - //////////////////////////////////////////////////////////// - /// \brief Unlock the mutex - /// - //////////////////////////////////////////////////////////// - void unlock(); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - pthread_mutex_t m_mutex; ///< pthread handle of the mutex -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_MUTEXIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_MUTEXIMPL_HPP +#define SFML_MUTEXIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Unix implementation of mutexes +//////////////////////////////////////////////////////////// +class MutexImpl : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + MutexImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~MutexImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Lock the mutex + /// + //////////////////////////////////////////////////////////// + void lock(); + + //////////////////////////////////////////////////////////// + /// \brief Unlock the mutex + /// + //////////////////////////////////////////////////////////// + void unlock(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + pthread_mutex_t m_mutex; ///< pthread handle of the mutex +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_MUTEXIMPL_HPP diff --git a/src/SFML/System/Unix/ThreadImpl.cpp b/src/SFML/System/Unix/ThreadImpl.cpp index 22d84bbe..5fcc6465 100644 --- a/src/SFML/System/Unix/ThreadImpl.cpp +++ b/src/SFML/System/Unix/ThreadImpl.cpp @@ -1,94 +1,94 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -ThreadImpl::ThreadImpl(Thread* owner) : -m_isActive(true) -{ - m_isActive = pthread_create(&m_thread, NULL, &ThreadImpl::entryPoint, owner) == 0; - - if (!m_isActive) - std::cerr << "Failed to create thread" << std::endl; -} - - -//////////////////////////////////////////////////////////// -void ThreadImpl::wait() -{ - if (m_isActive) - { - assert(pthread_equal(pthread_self(), m_thread) == 0); // A thread cannot wait for itself! - pthread_join(m_thread, NULL); - } -} - - -//////////////////////////////////////////////////////////// -void ThreadImpl::terminate() -{ - if (m_isActive) - { - #ifndef SFML_SYSTEM_ANDROID - pthread_cancel(m_thread); - #else - // See http://stackoverflow.com/questions/4610086/pthread-cancel-al - pthread_kill(m_thread, SIGUSR1); - #endif - } -} - - -//////////////////////////////////////////////////////////// -void* ThreadImpl::entryPoint(void* userData) -{ - // The Thread instance is stored in the user data - Thread* owner = static_cast(userData); - - #ifndef SFML_SYSTEM_ANDROID - // Tell the thread to handle cancel requests immediatly - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - #endif - - // Forward to the owner - owner->run(); - - return NULL; -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +ThreadImpl::ThreadImpl(Thread* owner) : +m_isActive(true) +{ + m_isActive = pthread_create(&m_thread, NULL, &ThreadImpl::entryPoint, owner) == 0; + + if (!m_isActive) + std::cerr << "Failed to create thread" << std::endl; +} + + +//////////////////////////////////////////////////////////// +void ThreadImpl::wait() +{ + if (m_isActive) + { + assert(pthread_equal(pthread_self(), m_thread) == 0); // A thread cannot wait for itself! + pthread_join(m_thread, NULL); + } +} + + +//////////////////////////////////////////////////////////// +void ThreadImpl::terminate() +{ + if (m_isActive) + { + #ifndef SFML_SYSTEM_ANDROID + pthread_cancel(m_thread); + #else + // See http://stackoverflow.com/questions/4610086/pthread-cancel-al + pthread_kill(m_thread, SIGUSR1); + #endif + } +} + + +//////////////////////////////////////////////////////////// +void* ThreadImpl::entryPoint(void* userData) +{ + // The Thread instance is stored in the user data + Thread* owner = static_cast(userData); + + #ifndef SFML_SYSTEM_ANDROID + // Tell the thread to handle cancel requests immediatly + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + #endif + + // Forward to the owner + owner->run(); + + return NULL; +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/System/Unix/ThreadImpl.hpp b/src/SFML/System/Unix/ThreadImpl.hpp index db8eb2d8..d9e7bc94 100644 --- a/src/SFML/System/Unix/ThreadImpl.hpp +++ b/src/SFML/System/Unix/ThreadImpl.hpp @@ -1,93 +1,93 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADIMPL_HPP -#define SFML_THREADIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -class Thread; - -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Unix implementation of threads -//////////////////////////////////////////////////////////// -class ThreadImpl : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor, launch the thread - /// - /// \param owner The Thread instance to run - /// - //////////////////////////////////////////////////////////// - ThreadImpl(Thread* owner); - - //////////////////////////////////////////////////////////// - /// \brief Wait until the thread finishes - /// - //////////////////////////////////////////////////////////// - void wait(); - - //////////////////////////////////////////////////////////// - /// \brief Terminate the thread - /// - //////////////////////////////////////////////////////////// - void terminate(); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Global entry point for all threads - /// - /// \param userData User-defined data (contains the Thread instance) - /// - /// \return Os specific error code - /// - //////////////////////////////////////////////////////////// - static void* entryPoint(void* userData); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - pthread_t m_thread; ///< pthread thread instance - bool m_isActive; ///< Thread state (active or inactive) -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_THREADIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_THREADIMPL_HPP +#define SFML_THREADIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class Thread; + +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Unix implementation of threads +//////////////////////////////////////////////////////////// +class ThreadImpl : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor, launch the thread + /// + /// \param owner The Thread instance to run + /// + //////////////////////////////////////////////////////////// + ThreadImpl(Thread* owner); + + //////////////////////////////////////////////////////////// + /// \brief Wait until the thread finishes + /// + //////////////////////////////////////////////////////////// + void wait(); + + //////////////////////////////////////////////////////////// + /// \brief Terminate the thread + /// + //////////////////////////////////////////////////////////// + void terminate(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Global entry point for all threads + /// + /// \param userData User-defined data (contains the Thread instance) + /// + /// \return Os specific error code + /// + //////////////////////////////////////////////////////////// + static void* entryPoint(void* userData); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + pthread_t m_thread; ///< pthread thread instance + bool m_isActive; ///< Thread state (active or inactive) +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_THREADIMPL_HPP diff --git a/src/SFML/System/Unix/ThreadLocalImpl.cpp b/src/SFML/System/Unix/ThreadLocalImpl.cpp index 4d765045..5ebb5a0a 100644 --- a/src/SFML/System/Unix/ThreadLocalImpl.cpp +++ b/src/SFML/System/Unix/ThreadLocalImpl.cpp @@ -1,64 +1,64 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -ThreadLocalImpl::ThreadLocalImpl() -{ - pthread_key_create(&m_key, NULL); -} - - -//////////////////////////////////////////////////////////// -ThreadLocalImpl::~ThreadLocalImpl() -{ - pthread_key_delete(m_key); -} - - -//////////////////////////////////////////////////////////// -void ThreadLocalImpl::setValue(void* value) -{ - pthread_setspecific(m_key, value); -} - - -//////////////////////////////////////////////////////////// -void* ThreadLocalImpl::getValue() const -{ - return pthread_getspecific(m_key); -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +ThreadLocalImpl::ThreadLocalImpl() +{ + pthread_key_create(&m_key, NULL); +} + + +//////////////////////////////////////////////////////////// +ThreadLocalImpl::~ThreadLocalImpl() +{ + pthread_key_delete(m_key); +} + + +//////////////////////////////////////////////////////////// +void ThreadLocalImpl::setValue(void* value) +{ + pthread_setspecific(m_key, value); +} + + +//////////////////////////////////////////////////////////// +void* ThreadLocalImpl::getValue() const +{ + return pthread_getspecific(m_key); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/System/Unix/ThreadLocalImpl.hpp b/src/SFML/System/Unix/ThreadLocalImpl.hpp index 572a1368..07abdff6 100644 --- a/src/SFML/System/Unix/ThreadLocalImpl.hpp +++ b/src/SFML/System/Unix/ThreadLocalImpl.hpp @@ -1,87 +1,87 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADLOCALIMPL_HPP -#define SFML_THREADLOCALIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Unix implementation of thread-local storage -//////////////////////////////////////////////////////////// -class ThreadLocalImpl : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor -- allocate the storage - /// - //////////////////////////////////////////////////////////// - ThreadLocalImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor -- free the storage - /// - //////////////////////////////////////////////////////////// - ~ThreadLocalImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Set the thread-specific value of the variable - /// - /// \param value Value of the variable for this thread - /// - //////////////////////////////////////////////////////////// - void setValue(void* value); - - //////////////////////////////////////////////////////////// - /// \brief Retrieve the thread-specific value of the variable - /// - /// \return Value of the variable for this thread - /// - //////////////////////////////////////////////////////////// - void* getValue() const; - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - pthread_key_t m_key; ///< Index of our thread-local storage slot -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_THREADLOCALIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_THREADLOCALIMPL_HPP +#define SFML_THREADLOCALIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Unix implementation of thread-local storage +//////////////////////////////////////////////////////////// +class ThreadLocalImpl : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor -- allocate the storage + /// + //////////////////////////////////////////////////////////// + ThreadLocalImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor -- free the storage + /// + //////////////////////////////////////////////////////////// + ~ThreadLocalImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Set the thread-specific value of the variable + /// + /// \param value Value of the variable for this thread + /// + //////////////////////////////////////////////////////////// + void setValue(void* value); + + //////////////////////////////////////////////////////////// + /// \brief Retrieve the thread-specific value of the variable + /// + /// \return Value of the variable for this thread + /// + //////////////////////////////////////////////////////////// + void* getValue() const; + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + pthread_key_t m_key; ///< Index of our thread-local storage slot +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_THREADLOCALIMPL_HPP diff --git a/src/SFML/System/Win32/ClockImpl.hpp b/src/SFML/System/Win32/ClockImpl.hpp index 69ca267e..b57d207e 100644 --- a/src/SFML/System/Win32/ClockImpl.hpp +++ b/src/SFML/System/Win32/ClockImpl.hpp @@ -42,7 +42,7 @@ namespace priv //////////////////////////////////////////////////////////// class ClockImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Get the current time diff --git a/src/SFML/System/Win32/MutexImpl.cpp b/src/SFML/System/Win32/MutexImpl.cpp index 813e4848..f000e8d9 100644 --- a/src/SFML/System/Win32/MutexImpl.cpp +++ b/src/SFML/System/Win32/MutexImpl.cpp @@ -1,64 +1,64 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -MutexImpl::MutexImpl() -{ - InitializeCriticalSection(&m_mutex); -} - - -//////////////////////////////////////////////////////////// -MutexImpl::~MutexImpl() -{ - DeleteCriticalSection(&m_mutex); -} - - -//////////////////////////////////////////////////////////// -void MutexImpl::lock() -{ - EnterCriticalSection(&m_mutex); -} - - -//////////////////////////////////////////////////////////// -void MutexImpl::unlock() -{ - LeaveCriticalSection(&m_mutex); -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +MutexImpl::MutexImpl() +{ + InitializeCriticalSection(&m_mutex); +} + + +//////////////////////////////////////////////////////////// +MutexImpl::~MutexImpl() +{ + DeleteCriticalSection(&m_mutex); +} + + +//////////////////////////////////////////////////////////// +void MutexImpl::lock() +{ + EnterCriticalSection(&m_mutex); +} + + +//////////////////////////////////////////////////////////// +void MutexImpl::unlock() +{ + LeaveCriticalSection(&m_mutex); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/System/Win32/MutexImpl.hpp b/src/SFML/System/Win32/MutexImpl.hpp index 522e9928..9604a5ba 100644 --- a/src/SFML/System/Win32/MutexImpl.hpp +++ b/src/SFML/System/Win32/MutexImpl.hpp @@ -1,83 +1,83 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_MUTEXIMPL_HPP -#define SFML_MUTEXIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Windows implementation of mutexes -//////////////////////////////////////////////////////////// -class MutexImpl : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - MutexImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~MutexImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Lock the mutex - /// - //////////////////////////////////////////////////////////// - void lock(); - - //////////////////////////////////////////////////////////// - /// \brief Unlock the mutex - /// - //////////////////////////////////////////////////////////// - void unlock(); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - CRITICAL_SECTION m_mutex; ///< Win32 handle of the mutex -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_MUTEXIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_MUTEXIMPL_HPP +#define SFML_MUTEXIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows implementation of mutexes +//////////////////////////////////////////////////////////// +class MutexImpl : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + MutexImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~MutexImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Lock the mutex + /// + //////////////////////////////////////////////////////////// + void lock(); + + //////////////////////////////////////////////////////////// + /// \brief Unlock the mutex + /// + //////////////////////////////////////////////////////////// + void unlock(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + CRITICAL_SECTION m_mutex; ///< Win32 handle of the mutex +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_MUTEXIMPL_HPP diff --git a/src/SFML/System/Win32/ThreadImpl.cpp b/src/SFML/System/Win32/ThreadImpl.cpp index 7718e356..16977023 100644 --- a/src/SFML/System/Win32/ThreadImpl.cpp +++ b/src/SFML/System/Win32/ThreadImpl.cpp @@ -1,93 +1,93 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -ThreadImpl::ThreadImpl(Thread* owner) -{ - m_thread = reinterpret_cast(_beginthreadex(NULL, 0, &ThreadImpl::entryPoint, owner, 0, &m_threadId)); - - if (!m_thread) - err() << "Failed to create thread" << std::endl; -} - - -//////////////////////////////////////////////////////////// -ThreadImpl::~ThreadImpl() -{ - if (m_thread) - CloseHandle(m_thread); -} - - -//////////////////////////////////////////////////////////// -void ThreadImpl::wait() -{ - if (m_thread) - { - assert(m_threadId != GetCurrentThreadId()); // A thread cannot wait for itself! - WaitForSingleObject(m_thread, INFINITE); - } -} - - -//////////////////////////////////////////////////////////// -void ThreadImpl::terminate() -{ - if (m_thread) - TerminateThread(m_thread, 0); -} - - -//////////////////////////////////////////////////////////// -unsigned int __stdcall ThreadImpl::entryPoint(void* userData) -{ - // The Thread instance is stored in the user data - Thread* owner = static_cast(userData); - - // Forward to the owner - owner->run(); - - // Optional, but it is cleaner - _endthreadex(0); - - return 0; -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +ThreadImpl::ThreadImpl(Thread* owner) +{ + m_thread = reinterpret_cast(_beginthreadex(NULL, 0, &ThreadImpl::entryPoint, owner, 0, &m_threadId)); + + if (!m_thread) + err() << "Failed to create thread" << std::endl; +} + + +//////////////////////////////////////////////////////////// +ThreadImpl::~ThreadImpl() +{ + if (m_thread) + CloseHandle(m_thread); +} + + +//////////////////////////////////////////////////////////// +void ThreadImpl::wait() +{ + if (m_thread) + { + assert(m_threadId != GetCurrentThreadId()); // A thread cannot wait for itself! + WaitForSingleObject(m_thread, INFINITE); + } +} + + +//////////////////////////////////////////////////////////// +void ThreadImpl::terminate() +{ + if (m_thread) + TerminateThread(m_thread, 0); +} + + +//////////////////////////////////////////////////////////// +unsigned int __stdcall ThreadImpl::entryPoint(void* userData) +{ + // The Thread instance is stored in the user data + Thread* owner = static_cast(userData); + + // Forward to the owner + owner->run(); + + // Optional, but it is cleaner + _endthreadex(0); + + return 0; +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/System/Win32/ThreadImpl.hpp b/src/SFML/System/Win32/ThreadImpl.hpp index 619d5c3a..00df619e 100644 --- a/src/SFML/System/Win32/ThreadImpl.hpp +++ b/src/SFML/System/Win32/ThreadImpl.hpp @@ -1,109 +1,109 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADIMPL_HPP -#define SFML_THREADIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - -// Fix for unaligned stack with clang and GCC on Windows XP 32-bit -#if defined(SFML_SYSTEM_WINDOWS) && (defined(__clang__) || defined(__GNUC__)) - - #define ALIGN_STACK __attribute__((__force_align_arg_pointer__)) - -#else - - #define ALIGN_STACK - -#endif - - -namespace sf -{ -class Thread; - -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Windows implementation of threads -//////////////////////////////////////////////////////////// -class ThreadImpl : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor, launch the thread - /// - /// \param owner The Thread instance to run - /// - //////////////////////////////////////////////////////////// - ThreadImpl(Thread* owner); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~ThreadImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Wait until the thread finishes - /// - //////////////////////////////////////////////////////////// - void wait(); - - //////////////////////////////////////////////////////////// - /// \brief Terminate the thread - /// - //////////////////////////////////////////////////////////// - void terminate(); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Global entry point for all threads - /// - /// \param userData User-defined data (contains the Thread instance) - /// - /// \return OS specific error code - /// - //////////////////////////////////////////////////////////// - ALIGN_STACK static unsigned int __stdcall entryPoint(void* userData); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - HANDLE m_thread; ///< Win32 thread handle - unsigned int m_threadId; ///< Win32 thread identifier -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_THREADIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_THREADIMPL_HPP +#define SFML_THREADIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + +// Fix for unaligned stack with clang and GCC on Windows XP 32-bit +#if defined(SFML_SYSTEM_WINDOWS) && (defined(__clang__) || defined(__GNUC__)) + + #define ALIGN_STACK __attribute__((__force_align_arg_pointer__)) + +#else + + #define ALIGN_STACK + +#endif + + +namespace sf +{ +class Thread; + +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows implementation of threads +//////////////////////////////////////////////////////////// +class ThreadImpl : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor, launch the thread + /// + /// \param owner The Thread instance to run + /// + //////////////////////////////////////////////////////////// + ThreadImpl(Thread* owner); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~ThreadImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Wait until the thread finishes + /// + //////////////////////////////////////////////////////////// + void wait(); + + //////////////////////////////////////////////////////////// + /// \brief Terminate the thread + /// + //////////////////////////////////////////////////////////// + void terminate(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Global entry point for all threads + /// + /// \param userData User-defined data (contains the Thread instance) + /// + /// \return OS specific error code + /// + //////////////////////////////////////////////////////////// + ALIGN_STACK static unsigned int __stdcall entryPoint(void* userData); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + HANDLE m_thread; ///< Win32 thread handle + unsigned int m_threadId; ///< Win32 thread identifier +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_THREADIMPL_HPP diff --git a/src/SFML/System/Win32/ThreadLocalImpl.cpp b/src/SFML/System/Win32/ThreadLocalImpl.cpp index 03e1b370..f617e84d 100644 --- a/src/SFML/System/Win32/ThreadLocalImpl.cpp +++ b/src/SFML/System/Win32/ThreadLocalImpl.cpp @@ -1,64 +1,64 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -ThreadLocalImpl::ThreadLocalImpl() -{ - m_index = TlsAlloc(); -} - - -//////////////////////////////////////////////////////////// -ThreadLocalImpl::~ThreadLocalImpl() -{ - TlsFree(m_index); -} - - -//////////////////////////////////////////////////////////// -void ThreadLocalImpl::setValue(void* value) -{ - TlsSetValue(m_index, value); -} - - -//////////////////////////////////////////////////////////// -void* ThreadLocalImpl::getValue() const -{ - return TlsGetValue(m_index); -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +ThreadLocalImpl::ThreadLocalImpl() +{ + m_index = TlsAlloc(); +} + + +//////////////////////////////////////////////////////////// +ThreadLocalImpl::~ThreadLocalImpl() +{ + TlsFree(m_index); +} + + +//////////////////////////////////////////////////////////// +void ThreadLocalImpl::setValue(void* value) +{ + TlsSetValue(m_index, value); +} + + +//////////////////////////////////////////////////////////// +void* ThreadLocalImpl::getValue() const +{ + return TlsGetValue(m_index); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/System/Win32/ThreadLocalImpl.hpp b/src/SFML/System/Win32/ThreadLocalImpl.hpp index 1e0a577d..83060b17 100644 --- a/src/SFML/System/Win32/ThreadLocalImpl.hpp +++ b/src/SFML/System/Win32/ThreadLocalImpl.hpp @@ -1,87 +1,87 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADLOCALIMPL_HPP -#define SFML_THREADLOCALIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Windows implementation of thread-local storage -//////////////////////////////////////////////////////////// -class ThreadLocalImpl : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor -- allocate the storage - /// - //////////////////////////////////////////////////////////// - ThreadLocalImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor -- free the storage - /// - //////////////////////////////////////////////////////////// - ~ThreadLocalImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Set the thread-specific value of the variable - /// - /// \param value Value of the variable for this thread - /// - //////////////////////////////////////////////////////////// - void setValue(void* value); - - //////////////////////////////////////////////////////////// - /// \brief Retrieve the thread-specific value of the variable - /// - /// \return Value of the variable for this thread - /// - //////////////////////////////////////////////////////////// - void* getValue() const; - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - DWORD m_index; ///< Index of our thread-local storage slot -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_THREADLOCALIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_THREADLOCALIMPL_HPP +#define SFML_THREADLOCALIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows implementation of thread-local storage +//////////////////////////////////////////////////////////// +class ThreadLocalImpl : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor -- allocate the storage + /// + //////////////////////////////////////////////////////////// + ThreadLocalImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor -- free the storage + /// + //////////////////////////////////////////////////////////// + ~ThreadLocalImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Set the thread-specific value of the variable + /// + /// \param value Value of the variable for this thread + /// + //////////////////////////////////////////////////////////// + void setValue(void* value); + + //////////////////////////////////////////////////////////// + /// \brief Retrieve the thread-specific value of the variable + /// + /// \return Value of the variable for this thread + /// + //////////////////////////////////////////////////////////// + void* getValue() const; + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + DWORD m_index; ///< Index of our thread-local storage slot +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_THREADLOCALIMPL_HPP diff --git a/src/SFML/Window/Android/InputImpl.hpp b/src/SFML/Window/Android/InputImpl.hpp index b5276cce..37167b50 100644 --- a/src/SFML/Window/Android/InputImpl.hpp +++ b/src/SFML/Window/Android/InputImpl.hpp @@ -42,7 +42,7 @@ namespace priv //////////////////////////////////////////////////////////// class InputImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Check if a key is pressed diff --git a/src/SFML/Window/Android/JoystickImpl.hpp b/src/SFML/Window/Android/JoystickImpl.hpp index 82d3c375..2fb8cd30 100644 --- a/src/SFML/Window/Android/JoystickImpl.hpp +++ b/src/SFML/Window/Android/JoystickImpl.hpp @@ -36,7 +36,7 @@ namespace priv //////////////////////////////////////////////////////////// class JoystickImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Perform the global initialization of the joystick module @@ -100,7 +100,7 @@ public : //////////////////////////////////////////////////////////// JoystickState update(); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/Window/Android/SensorImpl.hpp b/src/SFML/Window/Android/SensorImpl.hpp index 4fdd791c..d945c114 100644 --- a/src/SFML/Window/Android/SensorImpl.hpp +++ b/src/SFML/Window/Android/SensorImpl.hpp @@ -42,7 +42,7 @@ namespace priv //////////////////////////////////////////////////////////// class SensorImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Perform the global initialization of the sensor module @@ -98,7 +98,7 @@ public : //////////////////////////////////////////////////////////// void setEnabled(bool enabled); -private : +private: //////////////////////////////////////////////////////////// /// \brief Get the default Android sensor matching the sensor type diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index 59a57ce5..1b1a1a4b 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -515,117 +515,117 @@ Keyboard::Key WindowImplAndroid::androidKeyToSF(int32_t key) { switch (key) { - case AKEYCODE_UNKNOWN : - case AKEYCODE_SOFT_LEFT : - case AKEYCODE_SOFT_RIGHT : - case AKEYCODE_HOME : return Keyboard::Unknown; - case AKEYCODE_BACK : return Keyboard::Escape; - case AKEYCODE_CALL : - case AKEYCODE_ENDCALL : return Keyboard::Unknown; - case AKEYCODE_0 : return Keyboard::Num0; - case AKEYCODE_1 : return Keyboard::Num1; - case AKEYCODE_2 : return Keyboard::Num2; - case AKEYCODE_3 : return Keyboard::Num3; - case AKEYCODE_4 : return Keyboard::Num4; - case AKEYCODE_5 : return Keyboard::Num5; - case AKEYCODE_6 : return Keyboard::Num6; - case AKEYCODE_7 : return Keyboard::Num7; - case AKEYCODE_8 : return Keyboard::Num8; - case AKEYCODE_9 : return Keyboard::Num9; - case AKEYCODE_STAR : - case AKEYCODE_POUND : - case AKEYCODE_DPAD_UP : - case AKEYCODE_DPAD_DOWN : - case AKEYCODE_DPAD_LEFT : - case AKEYCODE_DPAD_RIGHT : - case AKEYCODE_DPAD_CENTER : - case AKEYCODE_VOLUME_UP : - case AKEYCODE_VOLUME_DOWN : - case AKEYCODE_POWER : - case AKEYCODE_CAMERA : - case AKEYCODE_CLEAR : return Keyboard::Unknown; - case AKEYCODE_A : return Keyboard::A; - case AKEYCODE_B : return Keyboard::B; - case AKEYCODE_C : return Keyboard::C; - case AKEYCODE_D : return Keyboard::D; - case AKEYCODE_E : return Keyboard::E; - case AKEYCODE_F : return Keyboard::F; - case AKEYCODE_G : return Keyboard::G; - case AKEYCODE_H : return Keyboard::H; - case AKEYCODE_I : return Keyboard::I; - case AKEYCODE_J : return Keyboard::J; - case AKEYCODE_K : return Keyboard::K; - case AKEYCODE_L : return Keyboard::L; - case AKEYCODE_M : return Keyboard::M; - case AKEYCODE_N : return Keyboard::N; - case AKEYCODE_O : return Keyboard::O; - case AKEYCODE_P : return Keyboard::P; - case AKEYCODE_Q : return Keyboard::Q; - case AKEYCODE_R : return Keyboard::R; - case AKEYCODE_S : return Keyboard::S; - case AKEYCODE_T : return Keyboard::T; - case AKEYCODE_U : return Keyboard::U; - case AKEYCODE_V : return Keyboard::V; - case AKEYCODE_W : return Keyboard::W; - case AKEYCODE_X : return Keyboard::X; - case AKEYCODE_Y : return Keyboard::Y; - case AKEYCODE_Z : return Keyboard::Z; - case AKEYCODE_COMMA : return Keyboard::Comma; - case AKEYCODE_PERIOD : return Keyboard::Period; - case AKEYCODE_ALT_LEFT : return Keyboard::LAlt; - case AKEYCODE_ALT_RIGHT : return Keyboard::RAlt; - case AKEYCODE_SHIFT_LEFT : return Keyboard::LShift; - case AKEYCODE_SHIFT_RIGHT : return Keyboard::RShift; - case AKEYCODE_TAB : return Keyboard::Tab; - case AKEYCODE_SPACE : return Keyboard::Space; - case AKEYCODE_SYM : - case AKEYCODE_EXPLORER : - case AKEYCODE_ENVELOPE : return Keyboard::Unknown; - case AKEYCODE_ENTER : return Keyboard::Return; - case AKEYCODE_DEL : return Keyboard::Delete; - case AKEYCODE_GRAVE : return Keyboard::Tilde; - case AKEYCODE_MINUS : return Keyboard::Subtract; - case AKEYCODE_EQUALS : return Keyboard::Equal; - case AKEYCODE_LEFT_BRACKET : return Keyboard::LBracket; - case AKEYCODE_RIGHT_BRACKET : return Keyboard::RBracket; - case AKEYCODE_BACKSLASH : return Keyboard::BackSlash; - case AKEYCODE_SEMICOLON : return Keyboard::SemiColon; - case AKEYCODE_APOSTROPHE : return Keyboard::Quote; - case AKEYCODE_SLASH : return Keyboard::Slash; - case AKEYCODE_AT : - case AKEYCODE_NUM : - case AKEYCODE_HEADSETHOOK : - case AKEYCODE_FOCUS : // *Camera* focus - case AKEYCODE_PLUS : - case AKEYCODE_MENU : - case AKEYCODE_NOTIFICATION : - case AKEYCODE_SEARCH : - case AKEYCODE_MEDIA_PLAY_PAUSE : - case AKEYCODE_MEDIA_STOP : - case AKEYCODE_MEDIA_NEXT : - case AKEYCODE_MEDIA_PREVIOUS : - case AKEYCODE_MEDIA_REWIND : - case AKEYCODE_MEDIA_FAST_FORWARD : - case AKEYCODE_MUTE : return Keyboard::Unknown; - case AKEYCODE_PAGE_UP : return Keyboard::PageUp; - case AKEYCODE_PAGE_DOWN : return Keyboard::PageDown; - case AKEYCODE_PICTSYMBOLS : - case AKEYCODE_SWITCH_CHARSET : - case AKEYCODE_BUTTON_A : - case AKEYCODE_BUTTON_B : - case AKEYCODE_BUTTON_C : - case AKEYCODE_BUTTON_X : - case AKEYCODE_BUTTON_Y : - case AKEYCODE_BUTTON_Z : - case AKEYCODE_BUTTON_L1 : - case AKEYCODE_BUTTON_R1 : - case AKEYCODE_BUTTON_L2 : - case AKEYCODE_BUTTON_R2 : - case AKEYCODE_BUTTON_THUMBL : - case AKEYCODE_BUTTON_THUMBR : - case AKEYCODE_BUTTON_START : - case AKEYCODE_BUTTON_SELECT : - case AKEYCODE_BUTTON_MODE : return Keyboard::Unknown; + case AKEYCODE_UNKNOWN: + case AKEYCODE_SOFT_LEFT: + case AKEYCODE_SOFT_RIGHT: + case AKEYCODE_HOME: return Keyboard::Unknown; + case AKEYCODE_BACK: return Keyboard::Escape; + case AKEYCODE_CALL: + case AKEYCODE_ENDCALL: return Keyboard::Unknown; + case AKEYCODE_0: return Keyboard::Num0; + case AKEYCODE_1: return Keyboard::Num1; + case AKEYCODE_2: return Keyboard::Num2; + case AKEYCODE_3: return Keyboard::Num3; + case AKEYCODE_4: return Keyboard::Num4; + case AKEYCODE_5: return Keyboard::Num5; + case AKEYCODE_6: return Keyboard::Num6; + case AKEYCODE_7: return Keyboard::Num7; + case AKEYCODE_8: return Keyboard::Num8; + case AKEYCODE_9: return Keyboard::Num9; + case AKEYCODE_STAR: + case AKEYCODE_POUND: + case AKEYCODE_DPAD_UP: + case AKEYCODE_DPAD_DOWN: + case AKEYCODE_DPAD_LEFT: + case AKEYCODE_DPAD_RIGHT: + case AKEYCODE_DPAD_CENTER: + case AKEYCODE_VOLUME_UP: + case AKEYCODE_VOLUME_DOWN: + case AKEYCODE_POWER: + case AKEYCODE_CAMERA: + case AKEYCODE_CLEAR: return Keyboard::Unknown; + case AKEYCODE_A: return Keyboard::A; + case AKEYCODE_B: return Keyboard::B; + case AKEYCODE_C: return Keyboard::C; + case AKEYCODE_D: return Keyboard::D; + case AKEYCODE_E: return Keyboard::E; + case AKEYCODE_F: return Keyboard::F; + case AKEYCODE_G: return Keyboard::G; + case AKEYCODE_H: return Keyboard::H; + case AKEYCODE_I: return Keyboard::I; + case AKEYCODE_J: return Keyboard::J; + case AKEYCODE_K: return Keyboard::K; + case AKEYCODE_L: return Keyboard::L; + case AKEYCODE_M: return Keyboard::M; + case AKEYCODE_N: return Keyboard::N; + case AKEYCODE_O: return Keyboard::O; + case AKEYCODE_P: return Keyboard::P; + case AKEYCODE_Q: return Keyboard::Q; + case AKEYCODE_R: return Keyboard::R; + case AKEYCODE_S: return Keyboard::S; + case AKEYCODE_T: return Keyboard::T; + case AKEYCODE_U: return Keyboard::U; + case AKEYCODE_V: return Keyboard::V; + case AKEYCODE_W: return Keyboard::W; + case AKEYCODE_X: return Keyboard::X; + case AKEYCODE_Y: return Keyboard::Y; + case AKEYCODE_Z: return Keyboard::Z; + case AKEYCODE_COMMA: return Keyboard::Comma; + case AKEYCODE_PERIOD: return Keyboard::Period; + case AKEYCODE_ALT_LEFT: return Keyboard::LAlt; + case AKEYCODE_ALT_RIGHT: return Keyboard::RAlt; + case AKEYCODE_SHIFT_LEFT: return Keyboard::LShift; + case AKEYCODE_SHIFT_RIGHT: return Keyboard::RShift; + case AKEYCODE_TAB: return Keyboard::Tab; + case AKEYCODE_SPACE: return Keyboard::Space; + case AKEYCODE_SYM: + case AKEYCODE_EXPLORER: + case AKEYCODE_ENVELOPE: return Keyboard::Unknown; + case AKEYCODE_ENTER: return Keyboard::Return; + case AKEYCODE_DEL: return Keyboard::Delete; + case AKEYCODE_GRAVE: return Keyboard::Tilde; + case AKEYCODE_MINUS: return Keyboard::Subtract; + case AKEYCODE_EQUALS: return Keyboard::Equal; + case AKEYCODE_LEFT_BRACKET: return Keyboard::LBracket; + case AKEYCODE_RIGHT_BRACKET: return Keyboard::RBracket; + case AKEYCODE_BACKSLASH: return Keyboard::BackSlash; + case AKEYCODE_SEMICOLON: return Keyboard::SemiColon; + case AKEYCODE_APOSTROPHE: return Keyboard::Quote; + case AKEYCODE_SLASH: return Keyboard::Slash; + case AKEYCODE_AT: + case AKEYCODE_NUM: + case AKEYCODE_HEADSETHOOK: + case AKEYCODE_FOCUS: // *Camera* focus + case AKEYCODE_PLUS: + case AKEYCODE_MENU: + case AKEYCODE_NOTIFICATION: + case AKEYCODE_SEARCH: + case AKEYCODE_MEDIA_PLAY_PAUSE: + case AKEYCODE_MEDIA_STOP: + case AKEYCODE_MEDIA_NEXT: + case AKEYCODE_MEDIA_PREVIOUS: + case AKEYCODE_MEDIA_REWIND: + case AKEYCODE_MEDIA_FAST_FORWARD: + case AKEYCODE_MUTE: return Keyboard::Unknown; + case AKEYCODE_PAGE_UP: return Keyboard::PageUp; + case AKEYCODE_PAGE_DOWN: return Keyboard::PageDown; + case AKEYCODE_PICTSYMBOLS: + case AKEYCODE_SWITCH_CHARSET: + case AKEYCODE_BUTTON_A: + case AKEYCODE_BUTTON_B: + case AKEYCODE_BUTTON_C: + case AKEYCODE_BUTTON_X: + case AKEYCODE_BUTTON_Y: + case AKEYCODE_BUTTON_Z: + case AKEYCODE_BUTTON_L1: + case AKEYCODE_BUTTON_R1: + case AKEYCODE_BUTTON_L2: + case AKEYCODE_BUTTON_R2: + case AKEYCODE_BUTTON_THUMBL: + case AKEYCODE_BUTTON_THUMBR: + case AKEYCODE_BUTTON_START: + case AKEYCODE_BUTTON_SELECT: + case AKEYCODE_BUTTON_MODE: return Keyboard::Unknown; } } diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp index 1d381aec..7786248b 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.hpp +++ b/src/SFML/Window/Android/WindowImplAndroid.hpp @@ -45,7 +45,7 @@ namespace priv //////////////////////////////////////////////////////////// class WindowImplAndroid : public WindowImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Construct the window implementation from an existing control @@ -157,7 +157,7 @@ public : static void forwardEvent(const Event& event); static WindowImplAndroid* singleInstance; -protected : +protected: //////////////////////////////////////////////////////////// /// \brief Process incoming events from the operating system diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index b066545d..0d447b4c 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -1,246 +1,246 @@ - -set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Window) -set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Window) - -# all source files -set(SRC - ${SRCROOT}/Context.cpp - ${INCROOT}/Context.hpp - ${INCROOT}/Export.hpp - ${SRCROOT}/GlContext.cpp - ${SRCROOT}/GlContext.hpp - ${SRCROOT}/GlResource.cpp - ${INCROOT}/GlResource.hpp - ${INCROOT}/ContextSettings.hpp - ${INCROOT}/Event.hpp - ${SRCROOT}/InputImpl.hpp - ${INCROOT}/Joystick.hpp - ${SRCROOT}/Joystick.cpp - ${SRCROOT}/JoystickImpl.hpp - ${SRCROOT}/JoystickManager.cpp - ${SRCROOT}/JoystickManager.hpp - ${INCROOT}/Keyboard.hpp - ${SRCROOT}/Keyboard.cpp - ${INCROOT}/Mouse.hpp - ${SRCROOT}/Mouse.cpp - ${INCROOT}/Touch.hpp - ${SRCROOT}/Touch.cpp - ${INCROOT}/Sensor.hpp - ${SRCROOT}/Sensor.cpp - ${SRCROOT}/SensorImpl.hpp - ${SRCROOT}/SensorManager.cpp - ${SRCROOT}/SensorManager.hpp - ${SRCROOT}/VideoMode.cpp - ${INCROOT}/VideoMode.hpp - ${SRCROOT}/VideoModeImpl.hpp - ${SRCROOT}/Window.cpp - ${INCROOT}/Window.hpp - ${INCROOT}/WindowHandle.hpp - ${SRCROOT}/WindowImpl.cpp - ${SRCROOT}/WindowImpl.hpp - ${INCROOT}/WindowStyle.hpp -) -if(SFML_OPENGL_ES AND NOT SFML_OS_IOS) - list(APPEND SRC ${SRCROOT}/EGLCheck.cpp) - list(APPEND SRC ${SRCROOT}/EGLCheck.hpp) - list(APPEND SRC ${SRCROOT}/EglContext.cpp) - list(APPEND SRC ${SRCROOT}/EglContext.hpp) -endif() -source_group("" FILES ${SRC}) - -# add platform specific sources -if(SFML_OS_WINDOWS) - set(PLATFORM_SRC - ${SRCROOT}/Win32/WglContext.cpp - ${SRCROOT}/Win32/WglContext.hpp - ${SRCROOT}/Win32/InputImpl.cpp - ${SRCROOT}/Win32/InputImpl.hpp - ${SRCROOT}/Win32/JoystickImpl.cpp - ${SRCROOT}/Win32/JoystickImpl.hpp - ${SRCROOT}/Win32/SensorImpl.hpp - ${SRCROOT}/Win32/SensorImpl.cpp - ${SRCROOT}/Win32/VideoModeImpl.cpp - ${SRCROOT}/Win32/WindowImplWin32.cpp - ${SRCROOT}/Win32/WindowImplWin32.hpp - ) - source_group("windows" FILES ${PLATFORM_SRC}) - - # make sure that we use the Unicode version of the Win API functions - add_definitions(-DUNICODE -D_UNICODE) -elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD) - set(PLATFORM_SRC - ${SRCROOT}/Unix/Display.cpp - ${SRCROOT}/Unix/Display.hpp - ${SRCROOT}/Unix/InputImpl.cpp - ${SRCROOT}/Unix/InputImpl.hpp - ${SRCROOT}/Unix/SensorImpl.cpp - ${SRCROOT}/Unix/SensorImpl.hpp - ${SRCROOT}/Unix/VideoModeImpl.cpp - ${SRCROOT}/Unix/WindowImplX11.cpp - ${SRCROOT}/Unix/WindowImplX11.hpp - ) - if(NOT SFML_OPENGL_ES) - set(PLATFORM_SRC - ${PLATFORM_SRC} - ${SRCROOT}/Unix/GlxContext.cpp - ${SRCROOT}/Unix/GlxContext.hpp - ) - endif() - if(SFML_OS_LINUX) - set(PLATFORM_SRC - ${PLATFORM_SRC} - ${SRCROOT}/Unix/JoystickImpl.cpp - ${SRCROOT}/Unix/JoystickImpl.hpp - ) - elseif(SFML_OS_FREEBSD) - set(PLATFORM_SRC - ${PLATFORM_SRC} - ${SRCROOT}/FreeBSD/JoystickImpl.cpp - ${SRCROOT}/FreeBSD/JoystickImpl.hpp - ) - endif() - source_group("unix" FILES ${PLATFORM_SRC}) -elseif(SFML_OS_MACOSX) - set(PLATFORM_SRC - ${SRCROOT}/OSX/cpp_objc_conversion.h - ${SRCROOT}/OSX/cpp_objc_conversion.mm - ${SRCROOT}/OSX/cg_sf_conversion.hpp - ${SRCROOT}/OSX/cg_sf_conversion.cpp - ${SRCROOT}/OSX/InputImpl.mm - ${SRCROOT}/OSX/InputImpl.hpp - ${SRCROOT}/OSX/HIDInputManager.hpp - ${SRCROOT}/OSX/HIDInputManager.mm - ${SRCROOT}/OSX/HIDJoystickManager.hpp - ${SRCROOT}/OSX/HIDJoystickManager.cpp - ${SRCROOT}/OSX/JoystickImpl.cpp - ${SRCROOT}/OSX/JoystickImpl.hpp - ${SRCROOT}/OSX/SensorImpl.cpp - ${SRCROOT}/OSX/SensorImpl.hpp - ${SRCROOT}/OSX/SFApplication.h - ${SRCROOT}/OSX/SFApplication.m - ${SRCROOT}/OSX/SFApplicationDelegate.h - ${SRCROOT}/OSX/SFApplicationDelegate.m - ${SRCROOT}/OSX/SFContext.hpp - ${SRCROOT}/OSX/SFContext.mm - ${SRCROOT}/OSX/SFKeyboardModifiersHelper.h - ${SRCROOT}/OSX/SFKeyboardModifiersHelper.mm - ${SRCROOT}/OSX/SFOpenGLView.h - ${SRCROOT}/OSX/SFOpenGLView.mm - ${SRCROOT}/OSX/SFSilentResponder.h - ${SRCROOT}/OSX/SFSilentResponder.m - ${SRCROOT}/OSX/SFWindow.h - ${SRCROOT}/OSX/SFWindow.m - ${SRCROOT}/OSX/SFWindowController.h - ${SRCROOT}/OSX/SFWindowController.mm - ${SRCROOT}/OSX/SFViewController.h - ${SRCROOT}/OSX/SFViewController.mm - ${SRCROOT}/OSX/VideoModeImpl.cpp - ${SRCROOT}/OSX/WindowImplCocoa.hpp - ${SRCROOT}/OSX/WindowImplCocoa.mm - ${SRCROOT}/OSX/WindowImplDelegateProtocol.h - ${SRCROOT}/OSX/AutoreleasePoolWrapper.h - ${SRCROOT}/OSX/AutoreleasePoolWrapper.mm - ) - source_group("mac" FILES ${PLATFORM_SRC}) -elseif(SFML_OS_IOS) - set(PLATFORM_SRC - ${SRCROOT}/iOS/EaglContext.mm - ${SRCROOT}/iOS/EaglContext.hpp - ${SRCROOT}/iOS/InputImpl.mm - ${SRCROOT}/iOS/InputImpl.hpp - ${SRCROOT}/iOS/JoystickImpl.mm - ${SRCROOT}/iOS/JoystickImpl.hpp - ${SRCROOT}/iOS/SensorImpl.mm - ${SRCROOT}/iOS/SensorImpl.hpp - ${SRCROOT}/iOS/VideoModeImpl.mm - ${SRCROOT}/iOS/WindowImplUIKit.hpp - ${SRCROOT}/iOS/WindowImplUIKit.mm - ${SRCROOT}/iOS/ObjCType.hpp - ${SRCROOT}/iOS/SFAppDelegate.hpp - ${SRCROOT}/iOS/SFAppDelegate.mm - ${SRCROOT}/iOS/SFView.hpp - ${SRCROOT}/iOS/SFView.mm - ${SRCROOT}/iOS/SFViewController.hpp - ${SRCROOT}/iOS/SFViewController.mm - ${SRCROOT}/iOS/SFMain.hpp - ${SRCROOT}/iOS/SFMain.mm - ) - source_group("ios" FILES ${PLATFORM_SRC}) -elseif(SFML_OS_ANDROID) - set(PLATFORM_SRC - ${SRCROOT}/Android/WindowImplAndroid.hpp - ${SRCROOT}/Android/WindowImplAndroid.cpp - ${SRCROOT}/Android/VideoModeImpl.cpp - ${SRCROOT}/Android/InputImpl.hpp - ${SRCROOT}/Android/InputImpl.cpp - ${SRCROOT}/Android/JoystickImpl.hpp - ${SRCROOT}/Android/JoystickImpl.cpp - ${SRCROOT}/Android/SensorImpl.hpp - ${SRCROOT}/Android/SensorImpl.cpp - ) - source_group("android" FILES ${PLATFORM_SRC}) -endif() - -# find external libraries -if(SFML_OS_LINUX OR SFML_OS_FREEBSD) - find_package(X11 REQUIRED) - if(NOT X11_Xrandr_FOUND) - message(FATAL_ERROR "Xrandr library not found") - endif() - include_directories(${X11_INCLUDE_DIR}) + +set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Window) +set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Window) + +# all source files +set(SRC + ${SRCROOT}/Context.cpp + ${INCROOT}/Context.hpp + ${INCROOT}/Export.hpp + ${SRCROOT}/GlContext.cpp + ${SRCROOT}/GlContext.hpp + ${SRCROOT}/GlResource.cpp + ${INCROOT}/GlResource.hpp + ${INCROOT}/ContextSettings.hpp + ${INCROOT}/Event.hpp + ${SRCROOT}/InputImpl.hpp + ${INCROOT}/Joystick.hpp + ${SRCROOT}/Joystick.cpp + ${SRCROOT}/JoystickImpl.hpp + ${SRCROOT}/JoystickManager.cpp + ${SRCROOT}/JoystickManager.hpp + ${INCROOT}/Keyboard.hpp + ${SRCROOT}/Keyboard.cpp + ${INCROOT}/Mouse.hpp + ${SRCROOT}/Mouse.cpp + ${INCROOT}/Touch.hpp + ${SRCROOT}/Touch.cpp + ${INCROOT}/Sensor.hpp + ${SRCROOT}/Sensor.cpp + ${SRCROOT}/SensorImpl.hpp + ${SRCROOT}/SensorManager.cpp + ${SRCROOT}/SensorManager.hpp + ${SRCROOT}/VideoMode.cpp + ${INCROOT}/VideoMode.hpp + ${SRCROOT}/VideoModeImpl.hpp + ${SRCROOT}/Window.cpp + ${INCROOT}/Window.hpp + ${INCROOT}/WindowHandle.hpp + ${SRCROOT}/WindowImpl.cpp + ${SRCROOT}/WindowImpl.hpp + ${INCROOT}/WindowStyle.hpp +) +if(SFML_OPENGL_ES AND NOT SFML_OS_IOS) + list(APPEND SRC ${SRCROOT}/EGLCheck.cpp) + list(APPEND SRC ${SRCROOT}/EGLCheck.hpp) + list(APPEND SRC ${SRCROOT}/EglContext.cpp) + list(APPEND SRC ${SRCROOT}/EglContext.hpp) +endif() +source_group("" FILES ${SRC}) + +# add platform specific sources +if(SFML_OS_WINDOWS) + set(PLATFORM_SRC + ${SRCROOT}/Win32/WglContext.cpp + ${SRCROOT}/Win32/WglContext.hpp + ${SRCROOT}/Win32/InputImpl.cpp + ${SRCROOT}/Win32/InputImpl.hpp + ${SRCROOT}/Win32/JoystickImpl.cpp + ${SRCROOT}/Win32/JoystickImpl.hpp + ${SRCROOT}/Win32/SensorImpl.hpp + ${SRCROOT}/Win32/SensorImpl.cpp + ${SRCROOT}/Win32/VideoModeImpl.cpp + ${SRCROOT}/Win32/WindowImplWin32.cpp + ${SRCROOT}/Win32/WindowImplWin32.hpp + ) + source_group("windows" FILES ${PLATFORM_SRC}) + + # make sure that we use the Unicode version of the Win API functions + add_definitions(-DUNICODE -D_UNICODE) +elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD) + set(PLATFORM_SRC + ${SRCROOT}/Unix/Display.cpp + ${SRCROOT}/Unix/Display.hpp + ${SRCROOT}/Unix/InputImpl.cpp + ${SRCROOT}/Unix/InputImpl.hpp + ${SRCROOT}/Unix/SensorImpl.cpp + ${SRCROOT}/Unix/SensorImpl.hpp + ${SRCROOT}/Unix/VideoModeImpl.cpp + ${SRCROOT}/Unix/WindowImplX11.cpp + ${SRCROOT}/Unix/WindowImplX11.hpp + ) + if(NOT SFML_OPENGL_ES) + set(PLATFORM_SRC + ${PLATFORM_SRC} + ${SRCROOT}/Unix/GlxContext.cpp + ${SRCROOT}/Unix/GlxContext.hpp + ) + endif() + if(SFML_OS_LINUX) + set(PLATFORM_SRC + ${PLATFORM_SRC} + ${SRCROOT}/Unix/JoystickImpl.cpp + ${SRCROOT}/Unix/JoystickImpl.hpp + ) + elseif(SFML_OS_FREEBSD) + set(PLATFORM_SRC + ${PLATFORM_SRC} + ${SRCROOT}/FreeBSD/JoystickImpl.cpp + ${SRCROOT}/FreeBSD/JoystickImpl.hpp + ) + endif() + source_group("unix" FILES ${PLATFORM_SRC}) +elseif(SFML_OS_MACOSX) + set(PLATFORM_SRC + ${SRCROOT}/OSX/cpp_objc_conversion.h + ${SRCROOT}/OSX/cpp_objc_conversion.mm + ${SRCROOT}/OSX/cg_sf_conversion.hpp + ${SRCROOT}/OSX/cg_sf_conversion.cpp + ${SRCROOT}/OSX/InputImpl.mm + ${SRCROOT}/OSX/InputImpl.hpp + ${SRCROOT}/OSX/HIDInputManager.hpp + ${SRCROOT}/OSX/HIDInputManager.mm + ${SRCROOT}/OSX/HIDJoystickManager.hpp + ${SRCROOT}/OSX/HIDJoystickManager.cpp + ${SRCROOT}/OSX/JoystickImpl.cpp + ${SRCROOT}/OSX/JoystickImpl.hpp + ${SRCROOT}/OSX/SensorImpl.cpp + ${SRCROOT}/OSX/SensorImpl.hpp + ${SRCROOT}/OSX/SFApplication.h + ${SRCROOT}/OSX/SFApplication.m + ${SRCROOT}/OSX/SFApplicationDelegate.h + ${SRCROOT}/OSX/SFApplicationDelegate.m + ${SRCROOT}/OSX/SFContext.hpp + ${SRCROOT}/OSX/SFContext.mm + ${SRCROOT}/OSX/SFKeyboardModifiersHelper.h + ${SRCROOT}/OSX/SFKeyboardModifiersHelper.mm + ${SRCROOT}/OSX/SFOpenGLView.h + ${SRCROOT}/OSX/SFOpenGLView.mm + ${SRCROOT}/OSX/SFSilentResponder.h + ${SRCROOT}/OSX/SFSilentResponder.m + ${SRCROOT}/OSX/SFWindow.h + ${SRCROOT}/OSX/SFWindow.m + ${SRCROOT}/OSX/SFWindowController.h + ${SRCROOT}/OSX/SFWindowController.mm + ${SRCROOT}/OSX/SFViewController.h + ${SRCROOT}/OSX/SFViewController.mm + ${SRCROOT}/OSX/VideoModeImpl.cpp + ${SRCROOT}/OSX/WindowImplCocoa.hpp + ${SRCROOT}/OSX/WindowImplCocoa.mm + ${SRCROOT}/OSX/WindowImplDelegateProtocol.h + ${SRCROOT}/OSX/AutoreleasePoolWrapper.h + ${SRCROOT}/OSX/AutoreleasePoolWrapper.mm + ) + source_group("mac" FILES ${PLATFORM_SRC}) +elseif(SFML_OS_IOS) + set(PLATFORM_SRC + ${SRCROOT}/iOS/EaglContext.mm + ${SRCROOT}/iOS/EaglContext.hpp + ${SRCROOT}/iOS/InputImpl.mm + ${SRCROOT}/iOS/InputImpl.hpp + ${SRCROOT}/iOS/JoystickImpl.mm + ${SRCROOT}/iOS/JoystickImpl.hpp + ${SRCROOT}/iOS/SensorImpl.mm + ${SRCROOT}/iOS/SensorImpl.hpp + ${SRCROOT}/iOS/VideoModeImpl.mm + ${SRCROOT}/iOS/WindowImplUIKit.hpp + ${SRCROOT}/iOS/WindowImplUIKit.mm + ${SRCROOT}/iOS/ObjCType.hpp + ${SRCROOT}/iOS/SFAppDelegate.hpp + ${SRCROOT}/iOS/SFAppDelegate.mm + ${SRCROOT}/iOS/SFView.hpp + ${SRCROOT}/iOS/SFView.mm + ${SRCROOT}/iOS/SFViewController.hpp + ${SRCROOT}/iOS/SFViewController.mm + ${SRCROOT}/iOS/SFMain.hpp + ${SRCROOT}/iOS/SFMain.mm + ) + source_group("ios" FILES ${PLATFORM_SRC}) +elseif(SFML_OS_ANDROID) + set(PLATFORM_SRC + ${SRCROOT}/Android/WindowImplAndroid.hpp + ${SRCROOT}/Android/WindowImplAndroid.cpp + ${SRCROOT}/Android/VideoModeImpl.cpp + ${SRCROOT}/Android/InputImpl.hpp + ${SRCROOT}/Android/InputImpl.cpp + ${SRCROOT}/Android/JoystickImpl.hpp + ${SRCROOT}/Android/JoystickImpl.cpp + ${SRCROOT}/Android/SensorImpl.hpp + ${SRCROOT}/Android/SensorImpl.cpp + ) + source_group("android" FILES ${PLATFORM_SRC}) +endif() + +# find external libraries +if(SFML_OS_LINUX OR SFML_OS_FREEBSD) + find_package(X11 REQUIRED) + if(NOT X11_Xrandr_FOUND) + message(FATAL_ERROR "Xrandr library not found") + endif() + include_directories(${X11_INCLUDE_DIR}) endif() if(NOT SFML_OPENGL_ES) find_package(OpenGL REQUIRED) include_directories(${OPENGL_INCLUDE_DIR}) if(SFML_OS_LINUX OR SFML_OS_FREEBSD) - find_package(X11 REQUIRED) - if(NOT X11_Xrandr_FOUND) - message(FATAL_ERROR "Xrandr library not found") - endif() - include_directories(${X11_INCLUDE_DIR}) + find_package(X11 REQUIRED) + if(NOT X11_Xrandr_FOUND) + message(FATAL_ERROR "Xrandr library not found") + endif() + include_directories(${X11_INCLUDE_DIR}) endif() if(SFML_OS_LINUX) - find_package(UDev REQUIRED) - if(NOT UDEV_FOUND) - message(FATAL_ERROR "udev library not found") - endif() + find_package(UDev REQUIRED) + if(NOT UDEV_FOUND) + message(FATAL_ERROR "udev library not found") + endif() include_directories(${UDEV_INCLUDE_DIR}) endif() -endif() -if(SFML_OPENGL_ES AND SFML_OS_LINUX) - find_package(EGL REQUIRED) - find_package(GLES REQUIRED) - include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR}) -endif() +endif() +if(SFML_OPENGL_ES AND SFML_OS_LINUX) + find_package(EGL REQUIRED) + find_package(GLES REQUIRED) + include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR}) +endif() -# build the list of external libraries to link +# build the list of external libraries to link if(SFML_OS_WINDOWS) - list(APPEND WINDOW_EXT_LIBS winmm gdi32) -elseif(SFML_OS_LINUX) + list(APPEND WINDOW_EXT_LIBS winmm gdi32) +elseif(SFML_OS_LINUX) list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} ${UDEV_LIBRARIES}) -elseif(SFML_OS_FREEBSD) +elseif(SFML_OS_FREEBSD) list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} usbhid) -elseif(SFML_OS_MACOSX) - list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon") -elseif(SFML_OS_IOS) - list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework UIKit -framework CoreGraphics -framework QuartzCore -framework CoreMotion") -elseif(SFML_OS_ANDROID) - list(APPEND WINDOW_EXT_LIBS "-landroid") -endif() -if(SFML_OPENGL_ES) - if(SFML_OS_LINUX) - list(APPEND WINDOW_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY}) - elseif(SFML_OS_IOS) - list(APPEND WINDOW_EXT_LIBS "-framework OpenGLES") - elseif(SFML_OS_ANDROID) - list(APPEND WINDOW_EXT_LIBS "-lEGL -lGLESv1_CM") - endif() -else() - list(APPEND WINDOW_EXT_LIBS ${OPENGL_gl_LIBRARY}) -endif() - -# define the sfml-window target -sfml_add_library(sfml-window - SOURCES ${SRC} ${PLATFORM_SRC} - DEPENDS sfml-system - EXTERNAL_LIBS ${WINDOW_EXT_LIBS}) +elseif(SFML_OS_MACOSX) + list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon") +elseif(SFML_OS_IOS) + list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework UIKit -framework CoreGraphics -framework QuartzCore -framework CoreMotion") +elseif(SFML_OS_ANDROID) + list(APPEND WINDOW_EXT_LIBS "-landroid") +endif() +if(SFML_OPENGL_ES) + if(SFML_OS_LINUX) + list(APPEND WINDOW_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY}) + elseif(SFML_OS_IOS) + list(APPEND WINDOW_EXT_LIBS "-framework OpenGLES") + elseif(SFML_OS_ANDROID) + list(APPEND WINDOW_EXT_LIBS "-lEGL -lGLESv1_CM") + endif() +else() + list(APPEND WINDOW_EXT_LIBS ${OPENGL_gl_LIBRARY}) +endif() + +# define the sfml-window target +sfml_add_library(sfml-window + SOURCES ${SRC} ${PLATFORM_SRC} + DEPENDS sfml-system + EXTERNAL_LIBS ${WINDOW_EXT_LIBS}) diff --git a/src/SFML/Window/Context.cpp b/src/SFML/Window/Context.cpp index 01aec5fe..fc6cb559 100644 --- a/src/SFML/Window/Context.cpp +++ b/src/SFML/Window/Context.cpp @@ -1,63 +1,63 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Context::Context() -{ - m_context = priv::GlContext::create(); - setActive(true); -} - - -//////////////////////////////////////////////////////////// -Context::~Context() -{ - delete m_context; -} - - -//////////////////////////////////////////////////////////// -bool Context::setActive(bool active) -{ - return m_context->setActive(active); -} - - -//////////////////////////////////////////////////////////// -Context::Context(const ContextSettings& settings, unsigned int width, unsigned int height) -{ - m_context = priv::GlContext::create(settings, width, height); - setActive(true); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Context::Context() +{ + m_context = priv::GlContext::create(); + setActive(true); +} + + +//////////////////////////////////////////////////////////// +Context::~Context() +{ + delete m_context; +} + + +//////////////////////////////////////////////////////////// +bool Context::setActive(bool active) +{ + return m_context->setActive(active); +} + + +//////////////////////////////////////////////////////////// +Context::Context(const ContextSettings& settings, unsigned int width, unsigned int height) +{ + m_context = priv::GlContext::create(settings, width, height); + setActive(true); +} + +} // namespace sf diff --git a/src/SFML/Window/EGLCheck.cpp b/src/SFML/Window/EGLCheck.cpp index 5cf80862..ea316c98 100644 --- a/src/SFML/Window/EGLCheck.cpp +++ b/src/SFML/Window/EGLCheck.cpp @@ -50,55 +50,55 @@ void eglCheckError(const char* file, unsigned int line) // Decode the error code returned switch (errorCode) { - case EGL_NOT_INITIALIZED : + case EGL_NOT_INITIALIZED: { error = "EGL_NOT_INITIALIZED"; description = "EGL is not initialized, or could not be initialized, for the specified display"; break; } - case EGL_BAD_ACCESS : + case EGL_BAD_ACCESS: { error = "EGL_BAD_ACCESS"; description = "EGL cannot access a requested resource (for example, a context is bound in another thread)"; break; } - case EGL_BAD_ALLOC : + case EGL_BAD_ALLOC: { error = "EGL_BAD_ALLOC"; description = "EGL failed to allocate resources for the requested operation"; break; } - case EGL_BAD_ATTRIBUTE : + case EGL_BAD_ATTRIBUTE: { error = "EGL_BAD_ATTRIBUTE"; description = "an unrecognized attribute or attribute value was passed in an attribute list"; break; } - case EGL_BAD_CONTEXT : + case EGL_BAD_CONTEXT: { error = "EGL_BAD_CONTEXT"; description = "an EGLContext argument does not name a valid EGLContext"; break; } - case EGL_BAD_CONFIG : + case EGL_BAD_CONFIG: { error = "EGL_BAD_CONFIG"; description = "an EGLConfig argument does not name a valid EGLConfig"; break; } - case EGL_BAD_CURRENT_SURFACE : + case EGL_BAD_CURRENT_SURFACE: { error = "EGL_BAD_CURRENT_SURFACE"; description = "the current surface of the calling thread is a window, pbuffer, or pixmap that is no longer valid"; break; } - case EGL_BAD_DISPLAY : + case EGL_BAD_DISPLAY: { error = "EGL_BAD_DISPLAY"; description = "an EGLDisplay argument does not name a valid EGLDisplay; or, EGL is not initialized on the specified EGLDisplay"; @@ -106,42 +106,42 @@ void eglCheckError(const char* file, unsigned int line) } - case EGL_BAD_SURFACE : + case EGL_BAD_SURFACE: { error = "EGL_BAD_SURFACE"; description = "an EGLSurface argument does not name a valid surface (window, pbuffer, or pixmap) configured for rendering"; break; } - case EGL_BAD_MATCH : + case EGL_BAD_MATCH: { error = "EGL_BAD_MATCH"; description = "arguments are inconsistent; for example, an otherwise valid context requires buffers (e.g. depth or stencil) not allocated by an otherwise valid surface"; break; } - case EGL_BAD_PARAMETER : + case EGL_BAD_PARAMETER: { error = "EGL_BAD_PARAMETER"; description = "one or more argument values are invalid"; break; } - case EGL_BAD_NATIVE_PIXMAP : + case EGL_BAD_NATIVE_PIXMAP: { error = "EGL_BAD_NATIVE_PIXMAP"; description = "an EGLNativePixmapType argument does not refer to a valid native pixmap"; break; } - case EGL_BAD_NATIVE_WINDOW : + case EGL_BAD_NATIVE_WINDOW: { error = "EGL_BAD_NATIVE_WINDOW"; description = "an EGLNativeWindowType argument does not refer to a valid native window"; break; } - case EGL_CONTEXT_LOST : + case EGL_CONTEXT_LOST: { error = "EGL_CONTEXT_LOST"; description = "a power management event has occured. The application must destroy all contexts and reinitialise client API state and objects to continue rendering"; diff --git a/src/SFML/Window/EglContext.hpp b/src/SFML/Window/EglContext.hpp index a5a2cc52..50b366e2 100644 --- a/src/SFML/Window/EglContext.hpp +++ b/src/SFML/Window/EglContext.hpp @@ -41,7 +41,7 @@ namespace priv { class EglContext : public GlContext { -public : +public: //////////////////////////////////////////////////////////// /// \brief Create a new context, not associated to a window @@ -102,7 +102,7 @@ public : /// This can avoid some visual artifacts, and limit the framerate /// to a good value (but not constant across different computers). /// - /// \param enabled : True to enable v-sync, false to deactivate + /// \param enabled: True to enable v-sync, false to deactivate /// //////////////////////////////////////////////////////////// virtual void setVerticalSyncEnabled(bool enabled); @@ -123,7 +123,7 @@ public : /// This function must be called when the activity (re)start, or /// when the orientation change. /// - /// \param window : The native window type + /// \param window: The native window type /// //////////////////////////////////////////////////////////// void createSurface(EGLNativeWindowType window); @@ -163,7 +163,7 @@ public : static XVisualInfo selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings); #endif -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/Window/FreeBSD/JoystickImpl.hpp b/src/SFML/Window/FreeBSD/JoystickImpl.hpp index 19ae180e..106da8c3 100644 --- a/src/SFML/Window/FreeBSD/JoystickImpl.hpp +++ b/src/SFML/Window/FreeBSD/JoystickImpl.hpp @@ -43,7 +43,7 @@ namespace priv //////////////////////////////////////////////////////////// class JoystickImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Perform the global initialization of the joystick module @@ -107,7 +107,7 @@ public : //////////////////////////////////////////////////////////// JoystickState update(); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/Window/GlContext.cpp b/src/SFML/Window/GlContext.cpp index 7ecc524c..53e62806 100644 --- a/src/SFML/Window/GlContext.cpp +++ b/src/SFML/Window/GlContext.cpp @@ -1,300 +1,300 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#ifdef SFML_SYSTEM_IOS - #include -#else - #include -#endif - -#if !defined(SFML_OPENGL_ES) - - #if defined(SFML_SYSTEM_WINDOWS) - - #include - typedef sf::priv::WglContext ContextType; - - #elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) - - #include - typedef sf::priv::GlxContext ContextType; - - #elif defined(SFML_SYSTEM_MACOS) - - #include - typedef sf::priv::SFContext ContextType; - - #endif - -#else - - #if defined(SFML_SYSTEM_IOS) - - #include - typedef sf::priv::EaglContext ContextType; - - #else - - #include - typedef sf::priv::EglContext ContextType; - - #endif - -#endif - - -namespace -{ - // This per-thread variable holds the current context for each thread - sf::ThreadLocalPtr currentContext(NULL); - - // The hidden, inactive context that will be shared with all other contexts - ContextType* sharedContext = NULL; - - // Internal contexts - sf::ThreadLocalPtr internalContext(NULL); - std::set internalContexts; - sf::Mutex internalContextsMutex; - - // Check if the internal context of the current thread is valid - bool hasInternalContext() - { - // The internal context can be null... - if (!internalContext) - return false; - - // ... or non-null but deleted from the list of internal contexts - sf::Lock lock(internalContextsMutex); - return internalContexts.find(internalContext) != internalContexts.end(); - } - - // Retrieve the internal context for the current thread - sf::priv::GlContext* getInternalContext() - { - if (!hasInternalContext()) - { - internalContext = sf::priv::GlContext::create(); - sf::Lock lock(internalContextsMutex); - internalContexts.insert(internalContext); - } - - return internalContext; - } -} - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -void GlContext::globalInit() -{ - // Create the shared context - sharedContext = new ContextType(NULL); - sharedContext->initialize(); - - // This call makes sure that: - // - the shared context is inactive (it must never be) - // - another valid context is activated in the current thread - sharedContext->setActive(false); -} - - -//////////////////////////////////////////////////////////// -void GlContext::globalCleanup() -{ - // Destroy the shared context - delete sharedContext; - sharedContext = NULL; - - // Destroy the internal contexts - sf::Lock lock(internalContextsMutex); - for (std::set::iterator it = internalContexts.begin(); it != internalContexts.end(); ++it) - delete *it; - internalContexts.clear(); -} - - -//////////////////////////////////////////////////////////// -void GlContext::ensureContext() -{ - // If there's no active context on the current thread, activate an internal one - if (!currentContext) - getInternalContext()->setActive(true); -} - - -//////////////////////////////////////////////////////////// -GlContext* GlContext::create() -{ - GlContext* context = new ContextType(sharedContext); - context->initialize(); - - return context; -} - - -//////////////////////////////////////////////////////////// -GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) -{ - // Make sure that there's an active context (context creation may need extensions, and thus a valid context) - ensureContext(); - - // Create the context - GlContext* context = new ContextType(sharedContext, settings, owner, bitsPerPixel); - context->initialize(); - - return context; -} - - -//////////////////////////////////////////////////////////// -GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height) -{ - // Make sure that there's an active context (context creation may need extensions, and thus a valid context) - ensureContext(); - - // Create the context - GlContext* context = new ContextType(sharedContext, settings, width, height); - context->initialize(); - - return context; -} - - -//////////////////////////////////////////////////////////// -GlContext::~GlContext() -{ - // Deactivate the context before killing it, unless we're inside Cleanup() - if (sharedContext) - setActive(false); -} - - -//////////////////////////////////////////////////////////// -const ContextSettings& GlContext::getSettings() const -{ - return m_settings; -} - - -//////////////////////////////////////////////////////////// -bool GlContext::setActive(bool active) -{ - if (active) - { - if (this != currentContext) - { - // Activate the context - if (makeCurrent()) - { - // Set it as the new current context for this thread - currentContext = this; - return true; - } - else - { - return false; - } - } - else - { - // This context is already the active one on this thread, don't do anything - return true; - } - } - else - { - if (this == currentContext) - { - // To deactivate the context, we actually activate another one so that we make - // sure that there is always an active context for subsequent graphics operations - return getInternalContext()->setActive(true); - } - else - { - // This context is not the active one on this thread, don't do anything - return true; - } - } -} - - -//////////////////////////////////////////////////////////// -GlContext::GlContext() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing) -{ - return std::abs(static_cast(bitsPerPixel - colorBits)) + - std::abs(static_cast(settings.depthBits - depthBits)) + - std::abs(static_cast(settings.stencilBits - stencilBits)) + - std::abs(static_cast(settings.antialiasingLevel - antialiasing)); -} - - -//////////////////////////////////////////////////////////// -void GlContext::initialize() -{ - // Activate the context - setActive(true); - - // Retrieve the context version number - const GLubyte* version = glGetString(GL_VERSION); - if (version) - { - // The beginning of the returned string is "major.minor" (this is standard) - m_settings.majorVersion = version[0] - '0'; - m_settings.minorVersion = version[2] - '0'; - } - else - { - // Can't get the version number, assume 2.0 - m_settings.majorVersion = 2; - m_settings.minorVersion = 0; - } - - // Enable antialiasing if needed - if (m_settings.antialiasingLevel > 0) - glEnable(GL_MULTISAMPLE); -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#ifdef SFML_SYSTEM_IOS + #include +#else + #include +#endif + +#if !defined(SFML_OPENGL_ES) + + #if defined(SFML_SYSTEM_WINDOWS) + + #include + typedef sf::priv::WglContext ContextType; + + #elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) + + #include + typedef sf::priv::GlxContext ContextType; + + #elif defined(SFML_SYSTEM_MACOS) + + #include + typedef sf::priv::SFContext ContextType; + + #endif + +#else + + #if defined(SFML_SYSTEM_IOS) + + #include + typedef sf::priv::EaglContext ContextType; + + #else + + #include + typedef sf::priv::EglContext ContextType; + + #endif + +#endif + + +namespace +{ + // This per-thread variable holds the current context for each thread + sf::ThreadLocalPtr currentContext(NULL); + + // The hidden, inactive context that will be shared with all other contexts + ContextType* sharedContext = NULL; + + // Internal contexts + sf::ThreadLocalPtr internalContext(NULL); + std::set internalContexts; + sf::Mutex internalContextsMutex; + + // Check if the internal context of the current thread is valid + bool hasInternalContext() + { + // The internal context can be null... + if (!internalContext) + return false; + + // ... or non-null but deleted from the list of internal contexts + sf::Lock lock(internalContextsMutex); + return internalContexts.find(internalContext) != internalContexts.end(); + } + + // Retrieve the internal context for the current thread + sf::priv::GlContext* getInternalContext() + { + if (!hasInternalContext()) + { + internalContext = sf::priv::GlContext::create(); + sf::Lock lock(internalContextsMutex); + internalContexts.insert(internalContext); + } + + return internalContext; + } +} + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +void GlContext::globalInit() +{ + // Create the shared context + sharedContext = new ContextType(NULL); + sharedContext->initialize(); + + // This call makes sure that: + // - the shared context is inactive (it must never be) + // - another valid context is activated in the current thread + sharedContext->setActive(false); +} + + +//////////////////////////////////////////////////////////// +void GlContext::globalCleanup() +{ + // Destroy the shared context + delete sharedContext; + sharedContext = NULL; + + // Destroy the internal contexts + sf::Lock lock(internalContextsMutex); + for (std::set::iterator it = internalContexts.begin(); it != internalContexts.end(); ++it) + delete *it; + internalContexts.clear(); +} + + +//////////////////////////////////////////////////////////// +void GlContext::ensureContext() +{ + // If there's no active context on the current thread, activate an internal one + if (!currentContext) + getInternalContext()->setActive(true); +} + + +//////////////////////////////////////////////////////////// +GlContext* GlContext::create() +{ + GlContext* context = new ContextType(sharedContext); + context->initialize(); + + return context; +} + + +//////////////////////////////////////////////////////////// +GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) +{ + // Make sure that there's an active context (context creation may need extensions, and thus a valid context) + ensureContext(); + + // Create the context + GlContext* context = new ContextType(sharedContext, settings, owner, bitsPerPixel); + context->initialize(); + + return context; +} + + +//////////////////////////////////////////////////////////// +GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height) +{ + // Make sure that there's an active context (context creation may need extensions, and thus a valid context) + ensureContext(); + + // Create the context + GlContext* context = new ContextType(sharedContext, settings, width, height); + context->initialize(); + + return context; +} + + +//////////////////////////////////////////////////////////// +GlContext::~GlContext() +{ + // Deactivate the context before killing it, unless we're inside Cleanup() + if (sharedContext) + setActive(false); +} + + +//////////////////////////////////////////////////////////// +const ContextSettings& GlContext::getSettings() const +{ + return m_settings; +} + + +//////////////////////////////////////////////////////////// +bool GlContext::setActive(bool active) +{ + if (active) + { + if (this != currentContext) + { + // Activate the context + if (makeCurrent()) + { + // Set it as the new current context for this thread + currentContext = this; + return true; + } + else + { + return false; + } + } + else + { + // This context is already the active one on this thread, don't do anything + return true; + } + } + else + { + if (this == currentContext) + { + // To deactivate the context, we actually activate another one so that we make + // sure that there is always an active context for subsequent graphics operations + return getInternalContext()->setActive(true); + } + else + { + // This context is not the active one on this thread, don't do anything + return true; + } + } +} + + +//////////////////////////////////////////////////////////// +GlContext::GlContext() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing) +{ + return std::abs(static_cast(bitsPerPixel - colorBits)) + + std::abs(static_cast(settings.depthBits - depthBits)) + + std::abs(static_cast(settings.stencilBits - stencilBits)) + + std::abs(static_cast(settings.antialiasingLevel - antialiasing)); +} + + +//////////////////////////////////////////////////////////// +void GlContext::initialize() +{ + // Activate the context + setActive(true); + + // Retrieve the context version number + const GLubyte* version = glGetString(GL_VERSION); + if (version) + { + // The beginning of the returned string is "major.minor" (this is standard) + m_settings.majorVersion = version[0] - '0'; + m_settings.minorVersion = version[2] - '0'; + } + else + { + // Can't get the version number, assume 2.0 + m_settings.majorVersion = 2; + m_settings.minorVersion = 0; + } + + // Enable antialiasing if needed + if (m_settings.antialiasingLevel > 0) + glEnable(GL_MULTISAMPLE); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/GlContext.hpp b/src/SFML/Window/GlContext.hpp index 6aeba672..2e24f4e2 100644 --- a/src/SFML/Window/GlContext.hpp +++ b/src/SFML/Window/GlContext.hpp @@ -1,234 +1,234 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_GLCONTEXT_HPP -#define SFML_GLCONTEXT_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -class WindowImpl; - -//////////////////////////////////////////////////////////// -/// \brief Abstract class representing an OpenGL context -/// -//////////////////////////////////////////////////////////// -class GlContext : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Perform the global initialization - /// - /// This function is called once, before the very first OpenGL - /// resource is created. It makes sure that everything is ready - /// for contexts to work properly. - /// Note: this function doesn't need to be thread-safe, as it - /// can be called only once. - /// - //////////////////////////////////////////////////////////// - static void globalInit(); - - //////////////////////////////////////////////////////////// - /// \brief Perform the global cleanup - /// - /// This function is called after the very last OpenGL resource - /// is destroyed. It makes sure that everything that was - /// created by initialize() is properly released. - /// Note: this function doesn't need to be thread-safe, as it - /// can be called only once. - /// - //////////////////////////////////////////////////////////// - static void globalCleanup(); - - //////////////////////////////////////////////////////////// - /// \brief Ensures that an OpenGL context is active in the current thread - /// - //////////////////////////////////////////////////////////// - static void ensureContext(); - - //////////////////////////////////////////////////////////// - /// \brief Create a new context, not associated to a window - /// - /// This function automatically chooses the specialized class - /// to use according to the OS. - /// - /// \return Pointer to the created context (don't forget to delete it) - /// - //////////////////////////////////////////////////////////// - static GlContext* create(); - - //////////////////////////////////////////////////////////// - /// \brief Create a new context attached to a window - /// - /// This function automatically chooses the specialized class - /// to use according to the OS. - /// - /// \param settings Creation parameters - /// \param owner Pointer to the owner window - /// \param bitsPerPixel Pixel depth (in bits per pixel) - /// - /// \return Pointer to the created context - /// - //////////////////////////////////////////////////////////// - static GlContext* create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); - - //////////////////////////////////////////////////////////// - /// \brief Create a new context that embeds its own rendering target - /// - /// This function automatically chooses the specialized class - /// to use according to the OS. - /// - /// \param settings Creation parameters - /// \param width Back buffer width - /// \param height Back buffer height - /// - /// \return Pointer to the created context - /// - //////////////////////////////////////////////////////////// - static GlContext* create(const ContextSettings& settings, unsigned int width, unsigned int height); - -public : - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - virtual ~GlContext(); - - //////////////////////////////////////////////////////////// - /// \brief Get the settings of the context - /// - /// Note that these settings may be different than the ones - /// passed to the constructor; they are indeed adjusted if the - /// original settings are not directly supported by the system. - /// - /// \return Structure containing the settings - /// - //////////////////////////////////////////////////////////// - const ContextSettings& getSettings() const; - - //////////////////////////////////////////////////////////// - /// \brief Activate or deactivate the context as the current target for rendering - /// - /// A context is active only on the current thread, if you want to - /// make it active on another thread you have to deactivate it - /// on the previous thread first if it was active. - /// Only one context can be active on a thread at a time, thus - /// the context previously active (if any) automatically gets deactivated. - /// - /// \param active True to activate, false to deactivate - /// - /// \return True if operation was successful, false otherwise - /// - //////////////////////////////////////////////////////////// - bool setActive(bool active); - - //////////////////////////////////////////////////////////// - /// \brief Display what has been rendered to the context so far - /// - //////////////////////////////////////////////////////////// - virtual void display() = 0; - - //////////////////////////////////////////////////////////// - /// \brief Enable or disable vertical synchronization - /// - /// Activating vertical synchronization will limit the number - /// of frames displayed to the refresh rate of the monitor. - /// This can avoid some visual artifacts, and limit the framerate - /// to a good value (but not constant across different computers). - /// - /// \param enabled True to enable v-sync, false to deactivate - /// - //////////////////////////////////////////////////////////// - virtual void setVerticalSyncEnabled(bool enabled) = 0; - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor is meant for derived classes only. - /// - //////////////////////////////////////////////////////////// - GlContext(); - - //////////////////////////////////////////////////////////// - /// \brief Activate the context as the current target - /// for rendering - /// - /// \return True on success, false if any error happened - /// - //////////////////////////////////////////////////////////// - virtual bool makeCurrent() = 0; - - //////////////////////////////////////////////////////////// - /// \brief Evaluate a pixel format configuration - /// - /// This functions can be used by implementations that have - /// several valid formats and want to get the best one. - /// A score is returned for the given configuration: the - /// lower the score is, the better the configuration is. - /// - /// \param bitsPerPixel Requested pixel depth (bits per pixel) - /// \param settings Requested additionnal settings - /// \param colorBits Color bits of the configuration to evaluate - /// \param depthBits Depth bits of the configuration to evaluate - /// \param stencilBits Stencil bits of the configuration to evaluate - /// \param antialiasing Antialiasing level of the configuration to evaluate - /// - /// \return Score of the configuration - /// - //////////////////////////////////////////////////////////// - static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - ContextSettings m_settings; ///< Creation settings of the context - -private: - - //////////////////////////////////////////////////////////// - /// \brief Perform various initializations after the context construction - /// - //////////////////////////////////////////////////////////// - void initialize(); -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_GLCONTEXT_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GLCONTEXT_HPP +#define SFML_GLCONTEXT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +class WindowImpl; + +//////////////////////////////////////////////////////////// +/// \brief Abstract class representing an OpenGL context +/// +//////////////////////////////////////////////////////////// +class GlContext : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Perform the global initialization + /// + /// This function is called once, before the very first OpenGL + /// resource is created. It makes sure that everything is ready + /// for contexts to work properly. + /// Note: this function doesn't need to be thread-safe, as it + /// can be called only once. + /// + //////////////////////////////////////////////////////////// + static void globalInit(); + + //////////////////////////////////////////////////////////// + /// \brief Perform the global cleanup + /// + /// This function is called after the very last OpenGL resource + /// is destroyed. It makes sure that everything that was + /// created by initialize() is properly released. + /// Note: this function doesn't need to be thread-safe, as it + /// can be called only once. + /// + //////////////////////////////////////////////////////////// + static void globalCleanup(); + + //////////////////////////////////////////////////////////// + /// \brief Ensures that an OpenGL context is active in the current thread + /// + //////////////////////////////////////////////////////////// + static void ensureContext(); + + //////////////////////////////////////////////////////////// + /// \brief Create a new context, not associated to a window + /// + /// This function automatically chooses the specialized class + /// to use according to the OS. + /// + /// \return Pointer to the created context (don't forget to delete it) + /// + //////////////////////////////////////////////////////////// + static GlContext* create(); + + //////////////////////////////////////////////////////////// + /// \brief Create a new context attached to a window + /// + /// This function automatically chooses the specialized class + /// to use according to the OS. + /// + /// \param settings Creation parameters + /// \param owner Pointer to the owner window + /// \param bitsPerPixel Pixel depth (in bits per pixel) + /// + /// \return Pointer to the created context + /// + //////////////////////////////////////////////////////////// + static GlContext* create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); + + //////////////////////////////////////////////////////////// + /// \brief Create a new context that embeds its own rendering target + /// + /// This function automatically chooses the specialized class + /// to use according to the OS. + /// + /// \param settings Creation parameters + /// \param width Back buffer width + /// \param height Back buffer height + /// + /// \return Pointer to the created context + /// + //////////////////////////////////////////////////////////// + static GlContext* create(const ContextSettings& settings, unsigned int width, unsigned int height); + +public: + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~GlContext(); + + //////////////////////////////////////////////////////////// + /// \brief Get the settings of the context + /// + /// Note that these settings may be different than the ones + /// passed to the constructor; they are indeed adjusted if the + /// original settings are not directly supported by the system. + /// + /// \return Structure containing the settings + /// + //////////////////////////////////////////////////////////// + const ContextSettings& getSettings() const; + + //////////////////////////////////////////////////////////// + /// \brief Activate or deactivate the context as the current target for rendering + /// + /// A context is active only on the current thread, if you want to + /// make it active on another thread you have to deactivate it + /// on the previous thread first if it was active. + /// Only one context can be active on a thread at a time, thus + /// the context previously active (if any) automatically gets deactivated. + /// + /// \param active True to activate, false to deactivate + /// + /// \return True if operation was successful, false otherwise + /// + //////////////////////////////////////////////////////////// + bool setActive(bool active); + + //////////////////////////////////////////////////////////// + /// \brief Display what has been rendered to the context so far + /// + //////////////////////////////////////////////////////////// + virtual void display() = 0; + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable vertical synchronization + /// + /// Activating vertical synchronization will limit the number + /// of frames displayed to the refresh rate of the monitor. + /// This can avoid some visual artifacts, and limit the framerate + /// to a good value (but not constant across different computers). + /// + /// \param enabled True to enable v-sync, false to deactivate + /// + //////////////////////////////////////////////////////////// + virtual void setVerticalSyncEnabled(bool enabled) = 0; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor is meant for derived classes only. + /// + //////////////////////////////////////////////////////////// + GlContext(); + + //////////////////////////////////////////////////////////// + /// \brief Activate the context as the current target + /// for rendering + /// + /// \return True on success, false if any error happened + /// + //////////////////////////////////////////////////////////// + virtual bool makeCurrent() = 0; + + //////////////////////////////////////////////////////////// + /// \brief Evaluate a pixel format configuration + /// + /// This functions can be used by implementations that have + /// several valid formats and want to get the best one. + /// A score is returned for the given configuration: the + /// lower the score is, the better the configuration is. + /// + /// \param bitsPerPixel Requested pixel depth (bits per pixel) + /// \param settings Requested additionnal settings + /// \param colorBits Color bits of the configuration to evaluate + /// \param depthBits Depth bits of the configuration to evaluate + /// \param stencilBits Stencil bits of the configuration to evaluate + /// \param antialiasing Antialiasing level of the configuration to evaluate + /// + /// \return Score of the configuration + /// + //////////////////////////////////////////////////////////// + static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + ContextSettings m_settings; ///< Creation settings of the context + +private: + + //////////////////////////////////////////////////////////// + /// \brief Perform various initializations after the context construction + /// + //////////////////////////////////////////////////////////// + void initialize(); +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_GLCONTEXT_HPP diff --git a/src/SFML/Window/GlResource.cpp b/src/SFML/Window/GlResource.cpp index ffffce63..84725f89 100644 --- a/src/SFML/Window/GlResource.cpp +++ b/src/SFML/Window/GlResource.cpp @@ -1,85 +1,85 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace -{ - // OpenGL resources counter and its mutex - unsigned int count = 0; - sf::Mutex mutex; -} - - -namespace sf -{ -//////////////////////////////////////////////////////////// -GlResource::GlResource() -{ - { - // Protect from concurrent access - Lock lock(mutex); - - // If this is the very first resource, trigger the global context initialization - if (count == 0) - priv::GlContext::globalInit(); - - // Increment the resources counter - count++; - } - - // Now make sure that there is an active OpenGL context in the current thread - priv::GlContext::ensureContext(); -} - - -//////////////////////////////////////////////////////////// -GlResource::~GlResource() -{ - // Protect from concurrent access - Lock lock(mutex); - - // Decrement the resources counter - count--; - - // If there's no more resource alive, we can trigger the global context cleanup - if (count == 0) - priv::GlContext::globalCleanup(); -} - - -//////////////////////////////////////////////////////////// -void GlResource::ensureGlContext() -{ - priv::GlContext::ensureContext(); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace +{ + // OpenGL resources counter and its mutex + unsigned int count = 0; + sf::Mutex mutex; +} + + +namespace sf +{ +//////////////////////////////////////////////////////////// +GlResource::GlResource() +{ + { + // Protect from concurrent access + Lock lock(mutex); + + // If this is the very first resource, trigger the global context initialization + if (count == 0) + priv::GlContext::globalInit(); + + // Increment the resources counter + count++; + } + + // Now make sure that there is an active OpenGL context in the current thread + priv::GlContext::ensureContext(); +} + + +//////////////////////////////////////////////////////////// +GlResource::~GlResource() +{ + // Protect from concurrent access + Lock lock(mutex); + + // Decrement the resources counter + count--; + + // If there's no more resource alive, we can trigger the global context cleanup + if (count == 0) + priv::GlContext::globalCleanup(); +} + + +//////////////////////////////////////////////////////////// +void GlResource::ensureGlContext() +{ + priv::GlContext::ensureContext(); +} + +} // namespace sf diff --git a/src/SFML/Window/JoystickManager.hpp b/src/SFML/Window/JoystickManager.hpp index 22f2d9f7..e0e24921 100644 --- a/src/SFML/Window/JoystickManager.hpp +++ b/src/SFML/Window/JoystickManager.hpp @@ -43,7 +43,7 @@ namespace priv //////////////////////////////////////////////////////////// class JoystickManager : NonCopyable { -public : +public: //////////////////////////////////////////////////////////// /// \brief Get the global unique instance of the manager diff --git a/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm b/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm index 1745abd3..89b6ce7a 100644 --- a/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm +++ b/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm @@ -61,7 +61,7 @@ namespace priv //////////////////////////////////////////////////////////// class PoolWrapper : NonCopyable { -public : +public: //////////////////////////////////////////////////////////// /// \brief Default constructor diff --git a/src/SFML/Window/OSX/HIDInputManager.hpp b/src/SFML/Window/OSX/HIDInputManager.hpp index fc28a366..03ce4a67 100644 --- a/src/SFML/Window/OSX/HIDInputManager.hpp +++ b/src/SFML/Window/OSX/HIDInputManager.hpp @@ -54,7 +54,7 @@ typedef std::vector IOHIDElements; //////////////////////////////////////////////////////////// class HIDInputManager : NonCopyable { -public : +public: //////////////////////////////////////////////////////////// /// \brief Get the unique instance of the class @@ -86,7 +86,7 @@ public : //////////////////////////////////////////////////////////// bool isMouseButtonPressed(Mouse::Button button); -public : +public: //////////////////////////////////////////////////////////// /// \brief Get the usb location ID of a given device @@ -130,7 +130,7 @@ public : //////////////////////////////////////////////////////////// static Keyboard::Key nonLocalizedKeys(UniChar virtualKeycode); -private : +private: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -247,7 +247,7 @@ private : //////////////////////////////////////////////////////////// static UInt8 usageToVirtualCode(UInt32 usage); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/Window/OSX/HIDInputManager.mm b/src/SFML/Window/OSX/HIDInputManager.mm index 64c2d593..7bd10923 100644 --- a/src/SFML/Window/OSX/HIDInputManager.mm +++ b/src/SFML/Window/OSX/HIDInputManager.mm @@ -367,7 +367,7 @@ void HIDInputManager::loadKey(IOHIDElementRef key) } //////////////////////////////////////////////////////////// - // These are known to be unbound : + // These are known to be unbound: // Supposed Virtual | HID | Supposed Key // =============================================== // 0x1b | 0x2d | Hyphen @@ -390,7 +390,7 @@ void HIDInputManager::loadKey(IOHIDElementRef key) } /* if (error == noErr) */ else { - sf::err() << "Cannot translate the virtual key code, error : " + sf::err() << "Cannot translate the virtual key code, error: " << error << std::endl; } diff --git a/src/SFML/Window/OSX/HIDJoystickManager.hpp b/src/SFML/Window/OSX/HIDJoystickManager.hpp index 5e637002..8c49a2bc 100644 --- a/src/SFML/Window/OSX/HIDJoystickManager.hpp +++ b/src/SFML/Window/OSX/HIDJoystickManager.hpp @@ -46,7 +46,7 @@ namespace priv //////////////////////////////////////////////////////////// class HIDJoystickManager : NonCopyable { -public : +public: //////////////////////////////////////////////////////////// /// \brief Get the unique instance of the class @@ -58,7 +58,7 @@ public : //////////////////////////////////////////////////////////// static HIDJoystickManager& getInstance(); -public : +public: //////////////////////////////////////////////////////////// /// \brief Get the number of currently connected joystick @@ -74,7 +74,7 @@ public : //////////////////////////////////////////////////////////// CFSetRef copyJoysticks(); -private : +private: //////////////////////////////////////////////////////////// /// \brief Default constructor @@ -94,7 +94,7 @@ private : //////////////////////////////////////////////////////////// void update(); -private : +private: //////////////////////////////////////////////////////////// /// \brief Private "plug-in" callback @@ -112,7 +112,7 @@ private : //////////////////////////////////////////////////////////// static void pluggedOut(void* context, IOReturn, void*, IOHIDDeviceRef); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/Window/OSX/InputImpl.hpp b/src/SFML/Window/OSX/InputImpl.hpp index 40acdd4d..20bc14f8 100644 --- a/src/SFML/Window/OSX/InputImpl.hpp +++ b/src/SFML/Window/OSX/InputImpl.hpp @@ -43,7 +43,7 @@ namespace priv //////////////////////////////////////////////////////////// class InputImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Check if a key is pressed diff --git a/src/SFML/Window/OSX/InputImpl.mm b/src/SFML/Window/OSX/InputImpl.mm index f0fac750..cf5c0d22 100644 --- a/src/SFML/Window/OSX/InputImpl.mm +++ b/src/SFML/Window/OSX/InputImpl.mm @@ -166,7 +166,7 @@ void InputImpl::setMousePosition(const Vector2i& position) CGEventRef event = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, pos, - /*we don't care about this : */0); + /*we don't care about this: */0); CGEventPost(kCGHIDEventTap, event); CFRelease(event); // This is a workaround to deprecated CGSetLocalEventsSuppressionInterval. diff --git a/src/SFML/Window/OSX/JoystickImpl.cpp b/src/SFML/Window/OSX/JoystickImpl.cpp index 8a34fe19..03e81ee2 100644 --- a/src/SFML/Window/OSX/JoystickImpl.cpp +++ b/src/SFML/Window/OSX/JoystickImpl.cpp @@ -274,7 +274,7 @@ bool JoystickImpl::open(unsigned int index) // HID Usage (assigned by manufacturer and/or a driver). std::sort(m_buttons.begin(), m_buttons.end(), JoystickButtonSortPredicate); - // Note : Joy::AxisPovX/Y are not supported (yet). + // Note: Joy::AxisPovX/Y are not supported (yet). // Maybe kIOHIDElementTypeInput_Axis is the corresponding type but I can't test. // Retain all these objects for personal use @@ -283,7 +283,7 @@ bool JoystickImpl::open(unsigned int index) for (AxisMap::iterator it(m_axis.begin()); it != m_axis.end(); ++it) CFRetain(it->second); - // Note : we didn't retain element in the switch because we might have multiple + // Note: we didn't retain element in the switch because we might have multiple // Axis X (for example) and we want to keep only the last one. So to prevent // leaking we retain objects 'only' now. @@ -411,7 +411,7 @@ JoystickState JoystickImpl::update() // // General formula to bind [a,b] to [c,d] with a linear progression: // - // f : [a, b] -> [c, d] + // f: [a, b] -> [c, d] // x |-> (x-a)(d-c)/(b-a)+c // // This method might not be very accurate (the "0 position" can be diff --git a/src/SFML/Window/OSX/JoystickImpl.hpp b/src/SFML/Window/OSX/JoystickImpl.hpp index c8f3d8b9..21bde63b 100644 --- a/src/SFML/Window/OSX/JoystickImpl.hpp +++ b/src/SFML/Window/OSX/JoystickImpl.hpp @@ -47,7 +47,7 @@ namespace priv //////////////////////////////////////////////////////////// class JoystickImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Perform the global initialization of the joystick module @@ -111,7 +111,7 @@ public : //////////////////////////////////////////////////////////// JoystickState update(); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/Window/OSX/SFContext.hpp b/src/SFML/Window/OSX/SFContext.hpp index 3a83c4ca..797984fc 100644 --- a/src/SFML/Window/OSX/SFContext.hpp +++ b/src/SFML/Window/OSX/SFContext.hpp @@ -117,7 +117,7 @@ public: /// This can avoid some visual artifacts, and limit the framerate /// to a good value (but not constant across different computers). /// - /// \param enabled : True to enable v-sync, false to deactivate + /// \param enabled: True to enable v-sync, false to deactivate /// //////////////////////////////////////////////////////////// virtual void setVerticalSyncEnabled(bool enabled); diff --git a/src/SFML/Window/OSX/SFWindowController.mm b/src/SFML/Window/OSX/SFWindowController.mm index a98b4038..1b0a0de7 100644 --- a/src/SFML/Window/OSX/SFWindowController.mm +++ b/src/SFML/Window/OSX/SFWindowController.mm @@ -472,7 +472,7 @@ { // Create an empty image representation. NSBitmapImageRep* bitmap = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:0 // if 0 : only allocate memory + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:0 // if 0: only allocate memory pixelsWide:width pixelsHigh:height bitsPerSample:8 // The number of bits used to specify diff --git a/src/SFML/Window/OSX/SensorImpl.hpp b/src/SFML/Window/OSX/SensorImpl.hpp index e5e252e6..ea29dd32 100644 --- a/src/SFML/Window/OSX/SensorImpl.hpp +++ b/src/SFML/Window/OSX/SensorImpl.hpp @@ -36,7 +36,7 @@ namespace priv //////////////////////////////////////////////////////////// class SensorImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Perform the global initialization of the sensor module diff --git a/src/SFML/Window/OSX/WindowImplCocoa.hpp b/src/SFML/Window/OSX/WindowImplCocoa.hpp index f8b209a1..723fee71 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.hpp +++ b/src/SFML/Window/OSX/WindowImplCocoa.hpp @@ -63,7 +63,7 @@ namespace priv //////////////////////////////////////////////////////////// class WindowImplCocoa : public WindowImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Construct the window implementation from an existing control /// @@ -236,7 +236,7 @@ public : //////////////////////////////////////////////////////////// static void setUpProcess(void); -public : +public: //////////////////////////////////////////////////////////// /// \brief Get the OS-specific handle of the window @@ -320,7 +320,7 @@ public : //////////////////////////////////////////////////////////// virtual void setKeyRepeatEnabled(bool enabled); -protected : +protected: //////////////////////////////////////////////////////////// /// \brief Process incoming events from the operating system @@ -328,7 +328,7 @@ protected : //////////////////////////////////////////////////////////// virtual void processEvents(); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/Window/OSX/WindowImplCocoa.mm b/src/SFML/Window/OSX/WindowImplCocoa.mm index adff0225..6b1c8be1 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.mm +++ b/src/SFML/Window/OSX/WindowImplCocoa.mm @@ -267,7 +267,7 @@ void WindowImplCocoa::setUpProcess(void) // Tell the application to stop bouncing in the Dock. [[SFApplication sharedApplication] finishLaunching]; - // NOTE : This last call won't harm anything even if SFML window was + // NOTE: This last call won't harm anything even if SFML window was // created with an external handle. } } diff --git a/src/SFML/Window/SensorManager.hpp b/src/SFML/Window/SensorManager.hpp index 50e29392..aa2ec951 100644 --- a/src/SFML/Window/SensorManager.hpp +++ b/src/SFML/Window/SensorManager.hpp @@ -43,7 +43,7 @@ namespace priv //////////////////////////////////////////////////////////// class SensorManager : NonCopyable { -public : +public: //////////////////////////////////////////////////////////// /// \brief Get the global unique instance of the manager diff --git a/src/SFML/Window/Unix/GlxContext.hpp b/src/SFML/Window/Unix/GlxContext.hpp index 72e3cb92..0b5982fb 100644 --- a/src/SFML/Window/Unix/GlxContext.hpp +++ b/src/SFML/Window/Unix/GlxContext.hpp @@ -43,7 +43,7 @@ namespace priv //////////////////////////////////////////////////////////// class GlxContext : public GlContext { -public : +public: //////////////////////////////////////////////////////////// /// \brief Create a new default context @@ -120,7 +120,7 @@ public : //////////////////////////////////////////////////////////// static XVisualInfo selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings); -private : +private: //////////////////////////////////////////////////////////// /// \brief Create the context diff --git a/src/SFML/Window/Unix/InputImpl.hpp b/src/SFML/Window/Unix/InputImpl.hpp index a77690d3..32c8f21a 100644 --- a/src/SFML/Window/Unix/InputImpl.hpp +++ b/src/SFML/Window/Unix/InputImpl.hpp @@ -42,7 +42,7 @@ namespace priv //////////////////////////////////////////////////////////// class InputImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Check if a key is pressed diff --git a/src/SFML/Window/Unix/JoystickImpl.cpp b/src/SFML/Window/Unix/JoystickImpl.cpp index a4e4d6a7..867d076a 100644 --- a/src/SFML/Window/Unix/JoystickImpl.cpp +++ b/src/SFML/Window/Unix/JoystickImpl.cpp @@ -312,17 +312,17 @@ JoystickCaps JoystickImpl::getCapabilities() const { switch (m_mapping[i]) { - case ABS_X : caps.axes[Joystick::X] = true; break; - case ABS_Y : caps.axes[Joystick::Y] = true; break; - case ABS_Z : - case ABS_THROTTLE : caps.axes[Joystick::Z] = true; break; + case ABS_X: caps.axes[Joystick::X] = true; break; + case ABS_Y: caps.axes[Joystick::Y] = true; break; + case ABS_Z: + case ABS_THROTTLE: caps.axes[Joystick::Z] = true; break; case ABS_RZ: - case ABS_RUDDER: caps.axes[Joystick::R] = true; break; - case ABS_RX : caps.axes[Joystick::U] = true; break; - case ABS_RY : caps.axes[Joystick::V] = true; break; - case ABS_HAT0X : caps.axes[Joystick::PovX] = true; break; - case ABS_HAT0Y : caps.axes[Joystick::PovY] = true; break; - default : break; + case ABS_RUDDER: caps.axes[Joystick::R] = true; break; + case ABS_RX: caps.axes[Joystick::U] = true; break; + case ABS_RY: caps.axes[Joystick::V] = true; break; + case ABS_HAT0X: caps.axes[Joystick::PovX] = true; break; + case ABS_HAT0Y: caps.axes[Joystick::PovY] = true; break; + default: break; } } @@ -347,28 +347,28 @@ JoystickState JoystickImpl::JoystickImpl::update() switch (joyState.type & ~JS_EVENT_INIT) { // An axis was moved - case JS_EVENT_AXIS : + case JS_EVENT_AXIS: { float value = joyState.value * 100.f / 32767.f; switch (m_mapping[joyState.number]) { - case ABS_X : m_state.axes[Joystick::X] = value; break; - case ABS_Y : m_state.axes[Joystick::Y] = value; break; - case ABS_Z : - case ABS_THROTTLE : m_state.axes[Joystick::Z] = value; break; + case ABS_X: m_state.axes[Joystick::X] = value; break; + case ABS_Y: m_state.axes[Joystick::Y] = value; break; + case ABS_Z: + case ABS_THROTTLE: m_state.axes[Joystick::Z] = value; break; case ABS_RZ: - case ABS_RUDDER: m_state.axes[Joystick::R] = value; break; - case ABS_RX : m_state.axes[Joystick::U] = value; break; - case ABS_RY : m_state.axes[Joystick::V] = value; break; - case ABS_HAT0X : m_state.axes[Joystick::PovX] = value; break; - case ABS_HAT0Y : m_state.axes[Joystick::PovY] = value; break; - default : break; + case ABS_RUDDER: m_state.axes[Joystick::R] = value; break; + case ABS_RX: m_state.axes[Joystick::U] = value; break; + case ABS_RY: m_state.axes[Joystick::V] = value; break; + case ABS_HAT0X: m_state.axes[Joystick::PovX] = value; break; + case ABS_HAT0Y: m_state.axes[Joystick::PovY] = value; break; + default: break; } break; } // A button was pressed - case JS_EVENT_BUTTON : + case JS_EVENT_BUTTON: { if (joyState.number < Joystick::ButtonCount) m_state.buttons[joyState.number] = (joyState.value != 0); diff --git a/src/SFML/Window/Unix/JoystickImpl.hpp b/src/SFML/Window/Unix/JoystickImpl.hpp index 9620231e..50777eff 100644 --- a/src/SFML/Window/Unix/JoystickImpl.hpp +++ b/src/SFML/Window/Unix/JoystickImpl.hpp @@ -43,7 +43,7 @@ namespace priv //////////////////////////////////////////////////////////// class JoystickImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Perform the global initialization of the joystick module @@ -107,7 +107,7 @@ public : //////////////////////////////////////////////////////////// JoystickState update(); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/Window/Unix/SensorImpl.hpp b/src/SFML/Window/Unix/SensorImpl.hpp index 1d83bee5..bbd705b8 100644 --- a/src/SFML/Window/Unix/SensorImpl.hpp +++ b/src/SFML/Window/Unix/SensorImpl.hpp @@ -36,7 +36,7 @@ namespace priv //////////////////////////////////////////////////////////// class SensorImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Perform the global initialization of the sensor module diff --git a/src/SFML/Window/Unix/VideoModeImpl.cpp b/src/SFML/Window/Unix/VideoModeImpl.cpp index 623af8ad..c7e62040 100644 --- a/src/SFML/Window/Unix/VideoModeImpl.cpp +++ b/src/SFML/Window/Unix/VideoModeImpl.cpp @@ -97,7 +97,7 @@ std::vector VideoModeImpl::getFullscreenModes() } else { - // XRandr extension is not supported : we cannot get the video modes + // XRandr extension is not supported: we cannot get the video modes err() << "Failed to use the XRandR extension while trying to get the supported video modes" << std::endl; } @@ -155,7 +155,7 @@ VideoMode VideoModeImpl::getDesktopMode() } else { - // XRandr extension is not supported : we cannot get the video modes + // XRandr extension is not supported: we cannot get the video modes err() << "Failed to use the XRandR extension while trying to get the desktop video modes" << std::endl; } diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 77624d4c..a9f2f0c3 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -398,7 +398,7 @@ void WindowImplX11::setTitle(const String& title) //////////////////////////////////////////////////////////// void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) { - // X11 wants BGRA pixels : swap red and blue channels + // X11 wants BGRA pixels: swap red and blue channels // Note: this memory will be freed by XDestroyImage Uint8* iconPixels = static_cast(std::malloc(width * height * 4)); for (std::size_t i = 0; i < width * height; ++i) @@ -529,7 +529,7 @@ void WindowImplX11::switchToFullscreen(const VideoMode& mode) } else { - // XRandr extension is not supported : we cannot use fullscreen mode + // XRandr extension is not supported: we cannot use fullscreen mode err() << "Fullscreen is not supported, switching to window mode" << std::endl; } } @@ -663,15 +663,15 @@ bool WindowImplX11::processEvent(XEvent windowEvent) switch (windowEvent.type) { // Destroy event - case DestroyNotify : + case DestroyNotify: { - // The window is about to be destroyed : we must cleanup resources + // The window is about to be destroyed: we must cleanup resources cleanup(); break; } // Gain focus event - case FocusIn : + case FocusIn: { // Update the input context if (m_inputContext) @@ -684,7 +684,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Lost focus event - case FocusOut : + case FocusOut: { // Update the input context if (m_inputContext) @@ -697,7 +697,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Resize event - case ConfigureNotify : + case ConfigureNotify: { // ConfigureNotify can be triggered for other reasons, check if the size has actually changed if ((windowEvent.xconfigure.width != m_previousSize.x) || (windowEvent.xconfigure.height != m_previousSize.y)) @@ -715,7 +715,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Close event - case ClientMessage : + case ClientMessage: { if ((windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast(m_atomClose)) { @@ -727,7 +727,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Key down event - case KeyPress : + case KeyPress: { // Get the keysym of the key that has been pressed static XComposeStatus keyboard; @@ -787,7 +787,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Key up event - case KeyRelease : + case KeyRelease: { // Get the keysym of the key that has been pressed char buffer[32]; @@ -808,7 +808,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Mouse button pressed - case ButtonPress : + case ButtonPress: { unsigned int button = windowEvent.xbutton.button; if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9)) @@ -819,11 +819,11 @@ bool WindowImplX11::processEvent(XEvent windowEvent) event.mouseButton.y = windowEvent.xbutton.y; switch (button) { - case Button1 : event.mouseButton.button = Mouse::Left; break; - case Button2 : event.mouseButton.button = Mouse::Middle; break; - case Button3 : event.mouseButton.button = Mouse::Right; break; - case 8 : event.mouseButton.button = Mouse::XButton1; break; - case 9 : event.mouseButton.button = Mouse::XButton2; break; + case Button1: event.mouseButton.button = Mouse::Left; break; + case Button2: event.mouseButton.button = Mouse::Middle; break; + case Button3: event.mouseButton.button = Mouse::Right; break; + case 8: event.mouseButton.button = Mouse::XButton1; break; + case 9: event.mouseButton.button = Mouse::XButton2; break; } pushEvent(event); } @@ -831,7 +831,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Mouse button released - case ButtonRelease : + case ButtonRelease: { unsigned int button = windowEvent.xbutton.button; if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9)) @@ -842,11 +842,11 @@ bool WindowImplX11::processEvent(XEvent windowEvent) event.mouseButton.y = windowEvent.xbutton.y; switch (button) { - case Button1 : event.mouseButton.button = Mouse::Left; break; - case Button2 : event.mouseButton.button = Mouse::Middle; break; - case Button3 : event.mouseButton.button = Mouse::Right; break; - case 8 : event.mouseButton.button = Mouse::XButton1; break; - case 9 : event.mouseButton.button = Mouse::XButton2; break; + case Button1: event.mouseButton.button = Mouse::Left; break; + case Button2: event.mouseButton.button = Mouse::Middle; break; + case Button3: event.mouseButton.button = Mouse::Right; break; + case 8: event.mouseButton.button = Mouse::XButton1; break; + case 9: event.mouseButton.button = Mouse::XButton2; break; } pushEvent(event); } @@ -863,7 +863,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Mouse moved - case MotionNotify : + case MotionNotify: { Event event; event.type = Event::MouseMoved; @@ -874,7 +874,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Mouse entered - case EnterNotify : + case EnterNotify: { if (windowEvent.xcrossing.mode == NotifyNormal) { @@ -886,7 +886,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Mouse left - case LeaveNotify : + case LeaveNotify: { if (windowEvent.xcrossing.mode == NotifyNormal) { @@ -898,7 +898,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Parent window changed - case ReparentNotify : + case ReparentNotify: { XSync(m_display, True); // Discard remaining events break; @@ -918,108 +918,108 @@ Keyboard::Key WindowImplX11::keysymToSF(KeySym symbol) switch (key) { - case XK_Shift_L : return Keyboard::LShift; - case XK_Shift_R : return Keyboard::RShift; - case XK_Control_L : return Keyboard::LControl; - case XK_Control_R : return Keyboard::RControl; - case XK_Alt_L : return Keyboard::LAlt; - case XK_Alt_R : return Keyboard::RAlt; - case XK_Super_L : return Keyboard::LSystem; - case XK_Super_R : return Keyboard::RSystem; - case XK_Menu : return Keyboard::Menu; - case XK_Escape : return Keyboard::Escape; - case XK_semicolon : return Keyboard::SemiColon; - case XK_slash : return Keyboard::Slash; - case XK_equal : return Keyboard::Equal; - case XK_minus : return Keyboard::Dash; - case XK_bracketleft : return Keyboard::LBracket; - case XK_bracketright : return Keyboard::RBracket; - case XK_comma : return Keyboard::Comma; - case XK_period : return Keyboard::Period; - case XK_dead_acute : return Keyboard::Quote; - case XK_backslash : return Keyboard::BackSlash; - case XK_dead_grave : return Keyboard::Tilde; - case XK_space : return Keyboard::Space; - case XK_Return : return Keyboard::Return; - case XK_KP_Enter : return Keyboard::Return; - case XK_BackSpace : return Keyboard::BackSpace; - case XK_Tab : return Keyboard::Tab; - case XK_Prior : return Keyboard::PageUp; - case XK_Next : return Keyboard::PageDown; - case XK_End : return Keyboard::End; - case XK_Home : return Keyboard::Home; - case XK_Insert : return Keyboard::Insert; - case XK_Delete : return Keyboard::Delete; - case XK_KP_Add : return Keyboard::Add; - case XK_KP_Subtract : return Keyboard::Subtract; - case XK_KP_Multiply : return Keyboard::Multiply; - case XK_KP_Divide : return Keyboard::Divide; - case XK_Pause : return Keyboard::Pause; - case XK_F1 : return Keyboard::F1; - case XK_F2 : return Keyboard::F2; - case XK_F3 : return Keyboard::F3; - case XK_F4 : return Keyboard::F4; - case XK_F5 : return Keyboard::F5; - case XK_F6 : return Keyboard::F6; - case XK_F7 : return Keyboard::F7; - case XK_F8 : return Keyboard::F8; - case XK_F9 : return Keyboard::F9; - case XK_F10 : return Keyboard::F10; - case XK_F11 : return Keyboard::F11; - case XK_F12 : return Keyboard::F12; - case XK_F13 : return Keyboard::F13; - case XK_F14 : return Keyboard::F14; - case XK_F15 : return Keyboard::F15; - case XK_Left : return Keyboard::Left; - case XK_Right : return Keyboard::Right; - case XK_Up : return Keyboard::Up; - case XK_Down : return Keyboard::Down; - case XK_KP_0 : return Keyboard::Numpad0; - case XK_KP_1 : return Keyboard::Numpad1; - case XK_KP_2 : return Keyboard::Numpad2; - case XK_KP_3 : return Keyboard::Numpad3; - case XK_KP_4 : return Keyboard::Numpad4; - case XK_KP_5 : return Keyboard::Numpad5; - case XK_KP_6 : return Keyboard::Numpad6; - case XK_KP_7 : return Keyboard::Numpad7; - case XK_KP_8 : return Keyboard::Numpad8; - case XK_KP_9 : return Keyboard::Numpad9; - case XK_A : return Keyboard::A; - case XK_Z : return Keyboard::Z; - case XK_E : return Keyboard::E; - case XK_R : return Keyboard::R; - case XK_T : return Keyboard::T; - case XK_Y : return Keyboard::Y; - case XK_U : return Keyboard::U; - case XK_I : return Keyboard::I; - case XK_O : return Keyboard::O; - case XK_P : return Keyboard::P; - case XK_Q : return Keyboard::Q; - case XK_S : return Keyboard::S; - case XK_D : return Keyboard::D; - case XK_F : return Keyboard::F; - case XK_G : return Keyboard::G; - case XK_H : return Keyboard::H; - case XK_J : return Keyboard::J; - case XK_K : return Keyboard::K; - case XK_L : return Keyboard::L; - case XK_M : return Keyboard::M; - case XK_W : return Keyboard::W; - case XK_X : return Keyboard::X; - case XK_C : return Keyboard::C; - case XK_V : return Keyboard::V; - case XK_B : return Keyboard::B; - case XK_N : return Keyboard::N; - case XK_0 : return Keyboard::Num0; - case XK_1 : return Keyboard::Num1; - case XK_2 : return Keyboard::Num2; - case XK_3 : return Keyboard::Num3; - case XK_4 : return Keyboard::Num4; - case XK_5 : return Keyboard::Num5; - case XK_6 : return Keyboard::Num6; - case XK_7 : return Keyboard::Num7; - case XK_8 : return Keyboard::Num8; - case XK_9 : return Keyboard::Num9; + case XK_Shift_L: return Keyboard::LShift; + case XK_Shift_R: return Keyboard::RShift; + case XK_Control_L: return Keyboard::LControl; + case XK_Control_R: return Keyboard::RControl; + case XK_Alt_L: return Keyboard::LAlt; + case XK_Alt_R: return Keyboard::RAlt; + case XK_Super_L: return Keyboard::LSystem; + case XK_Super_R: return Keyboard::RSystem; + case XK_Menu: return Keyboard::Menu; + case XK_Escape: return Keyboard::Escape; + case XK_semicolon: return Keyboard::SemiColon; + case XK_slash: return Keyboard::Slash; + case XK_equal: return Keyboard::Equal; + case XK_minus: return Keyboard::Dash; + case XK_bracketleft: return Keyboard::LBracket; + case XK_bracketright: return Keyboard::RBracket; + case XK_comma: return Keyboard::Comma; + case XK_period: return Keyboard::Period; + case XK_dead_acute: return Keyboard::Quote; + case XK_backslash: return Keyboard::BackSlash; + case XK_dead_grave: return Keyboard::Tilde; + case XK_space: return Keyboard::Space; + case XK_Return: return Keyboard::Return; + case XK_KP_Enter: return Keyboard::Return; + case XK_BackSpace: return Keyboard::BackSpace; + case XK_Tab: return Keyboard::Tab; + case XK_Prior: return Keyboard::PageUp; + case XK_Next: return Keyboard::PageDown; + case XK_End: return Keyboard::End; + case XK_Home: return Keyboard::Home; + case XK_Insert: return Keyboard::Insert; + case XK_Delete: return Keyboard::Delete; + case XK_KP_Add: return Keyboard::Add; + case XK_KP_Subtract: return Keyboard::Subtract; + case XK_KP_Multiply: return Keyboard::Multiply; + case XK_KP_Divide: return Keyboard::Divide; + case XK_Pause: return Keyboard::Pause; + case XK_F1: return Keyboard::F1; + case XK_F2: return Keyboard::F2; + case XK_F3: return Keyboard::F3; + case XK_F4: return Keyboard::F4; + case XK_F5: return Keyboard::F5; + case XK_F6: return Keyboard::F6; + case XK_F7: return Keyboard::F7; + case XK_F8: return Keyboard::F8; + case XK_F9: return Keyboard::F9; + case XK_F10: return Keyboard::F10; + case XK_F11: return Keyboard::F11; + case XK_F12: return Keyboard::F12; + case XK_F13: return Keyboard::F13; + case XK_F14: return Keyboard::F14; + case XK_F15: return Keyboard::F15; + case XK_Left: return Keyboard::Left; + case XK_Right: return Keyboard::Right; + case XK_Up: return Keyboard::Up; + case XK_Down: return Keyboard::Down; + case XK_KP_0: return Keyboard::Numpad0; + case XK_KP_1: return Keyboard::Numpad1; + case XK_KP_2: return Keyboard::Numpad2; + case XK_KP_3: return Keyboard::Numpad3; + case XK_KP_4: return Keyboard::Numpad4; + case XK_KP_5: return Keyboard::Numpad5; + case XK_KP_6: return Keyboard::Numpad6; + case XK_KP_7: return Keyboard::Numpad7; + case XK_KP_8: return Keyboard::Numpad8; + case XK_KP_9: return Keyboard::Numpad9; + case XK_A: return Keyboard::A; + case XK_Z: return Keyboard::Z; + case XK_E: return Keyboard::E; + case XK_R: return Keyboard::R; + case XK_T: return Keyboard::T; + case XK_Y: return Keyboard::Y; + case XK_U: return Keyboard::U; + case XK_I: return Keyboard::I; + case XK_O: return Keyboard::O; + case XK_P: return Keyboard::P; + case XK_Q: return Keyboard::Q; + case XK_S: return Keyboard::S; + case XK_D: return Keyboard::D; + case XK_F: return Keyboard::F; + case XK_G: return Keyboard::G; + case XK_H: return Keyboard::H; + case XK_J: return Keyboard::J; + case XK_K: return Keyboard::K; + case XK_L: return Keyboard::L; + case XK_M: return Keyboard::M; + case XK_W: return Keyboard::W; + case XK_X: return Keyboard::X; + case XK_C: return Keyboard::C; + case XK_V: return Keyboard::V; + case XK_B: return Keyboard::B; + case XK_N: return Keyboard::N; + case XK_0: return Keyboard::Num0; + case XK_1: return Keyboard::Num1; + case XK_2: return Keyboard::Num2; + case XK_3: return Keyboard::Num3; + case XK_4: return Keyboard::Num4; + case XK_5: return Keyboard::Num5; + case XK_6: return Keyboard::Num6; + case XK_7: return Keyboard::Num7; + case XK_8: return Keyboard::Num8; + case XK_9: return Keyboard::Num9; } return Keyboard::Unknown; diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp index 94e15d85..7e2b4852 100644 --- a/src/SFML/Window/Unix/WindowImplX11.hpp +++ b/src/SFML/Window/Unix/WindowImplX11.hpp @@ -45,7 +45,7 @@ namespace priv //////////////////////////////////////////////////////////// class WindowImplX11 : public WindowImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Construct the window implementation from an existing control @@ -154,7 +154,7 @@ public : //////////////////////////////////////////////////////////// virtual void setKeyRepeatEnabled(bool enabled); -protected : +protected: //////////////////////////////////////////////////////////// /// \brief Process incoming events from the operating system @@ -162,7 +162,7 @@ protected : //////////////////////////////////////////////////////////// virtual void processEvents(); -private : +private: //////////////////////////////////////////////////////////// /// \brief Switch to fullscreen mode diff --git a/src/SFML/Window/VideoMode.cpp b/src/SFML/Window/VideoMode.cpp index c8371e8c..2f8d8024 100644 --- a/src/SFML/Window/VideoMode.cpp +++ b/src/SFML/Window/VideoMode.cpp @@ -1,146 +1,146 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -VideoMode::VideoMode() : -width (0), -height (0), -bitsPerPixel(0) -{ - -} - - -//////////////////////////////////////////////////////////// -VideoMode::VideoMode(unsigned int modeWidth, unsigned int modeHeight, unsigned int modeBitsPerPixel) : -width (modeWidth), -height (modeHeight), -bitsPerPixel(modeBitsPerPixel) -{ - -} - - -//////////////////////////////////////////////////////////// -VideoMode VideoMode::getDesktopMode() -{ - // Directly forward to the OS-specific implementation - return priv::VideoModeImpl::getDesktopMode(); -} - - -//////////////////////////////////////////////////////////// -const std::vector& VideoMode::getFullscreenModes() -{ - static std::vector modes; - - // Populate the array on first call - if (modes.empty()) - { - modes = priv::VideoModeImpl::getFullscreenModes(); - std::sort(modes.begin(), modes.end(), std::greater()); - } - - return modes; -} - - -//////////////////////////////////////////////////////////// -bool VideoMode::isValid() const -{ - const std::vector& modes = getFullscreenModes(); - - return std::find(modes.begin(), modes.end(), *this) != modes.end(); -} - - -//////////////////////////////////////////////////////////// -bool operator ==(const VideoMode& left, const VideoMode& right) -{ - return (left.width == right.width) && - (left.height == right.height) && - (left.bitsPerPixel == right.bitsPerPixel); -} - - -//////////////////////////////////////////////////////////// -bool operator !=(const VideoMode& left, const VideoMode& right) -{ - return !(left == right); -} - - -//////////////////////////////////////////////////////////// -bool operator <(const VideoMode& left, const VideoMode& right) -{ - if (left.bitsPerPixel == right.bitsPerPixel) - { - if (left.width == right.width) - { - return left.height < right.height; - } - else - { - return left.width < right.width; - } - } - else - { - return left.bitsPerPixel < right.bitsPerPixel; - } -} - - -//////////////////////////////////////////////////////////// -bool operator >(const VideoMode& left, const VideoMode& right) -{ - return right < left; -} - - -//////////////////////////////////////////////////////////// -bool operator <=(const VideoMode& left, const VideoMode& right) -{ - return !(right < left); -} - - -//////////////////////////////////////////////////////////// -bool operator >=(const VideoMode& left, const VideoMode& right) -{ - return !(left < right); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +VideoMode::VideoMode() : +width (0), +height (0), +bitsPerPixel(0) +{ + +} + + +//////////////////////////////////////////////////////////// +VideoMode::VideoMode(unsigned int modeWidth, unsigned int modeHeight, unsigned int modeBitsPerPixel) : +width (modeWidth), +height (modeHeight), +bitsPerPixel(modeBitsPerPixel) +{ + +} + + +//////////////////////////////////////////////////////////// +VideoMode VideoMode::getDesktopMode() +{ + // Directly forward to the OS-specific implementation + return priv::VideoModeImpl::getDesktopMode(); +} + + +//////////////////////////////////////////////////////////// +const std::vector& VideoMode::getFullscreenModes() +{ + static std::vector modes; + + // Populate the array on first call + if (modes.empty()) + { + modes = priv::VideoModeImpl::getFullscreenModes(); + std::sort(modes.begin(), modes.end(), std::greater()); + } + + return modes; +} + + +//////////////////////////////////////////////////////////// +bool VideoMode::isValid() const +{ + const std::vector& modes = getFullscreenModes(); + + return std::find(modes.begin(), modes.end(), *this) != modes.end(); +} + + +//////////////////////////////////////////////////////////// +bool operator ==(const VideoMode& left, const VideoMode& right) +{ + return (left.width == right.width) && + (left.height == right.height) && + (left.bitsPerPixel == right.bitsPerPixel); +} + + +//////////////////////////////////////////////////////////// +bool operator !=(const VideoMode& left, const VideoMode& right) +{ + return !(left == right); +} + + +//////////////////////////////////////////////////////////// +bool operator <(const VideoMode& left, const VideoMode& right) +{ + if (left.bitsPerPixel == right.bitsPerPixel) + { + if (left.width == right.width) + { + return left.height < right.height; + } + else + { + return left.width < right.width; + } + } + else + { + return left.bitsPerPixel < right.bitsPerPixel; + } +} + + +//////////////////////////////////////////////////////////// +bool operator >(const VideoMode& left, const VideoMode& right) +{ + return right < left; +} + + +//////////////////////////////////////////////////////////// +bool operator <=(const VideoMode& left, const VideoMode& right) +{ + return !(right < left); +} + + +//////////////////////////////////////////////////////////// +bool operator >=(const VideoMode& left, const VideoMode& right) +{ + return !(left < right); +} + +} // namespace sf diff --git a/src/SFML/Window/VideoModeImpl.hpp b/src/SFML/Window/VideoModeImpl.hpp index 7c77f583..cbc36a18 100644 --- a/src/SFML/Window/VideoModeImpl.hpp +++ b/src/SFML/Window/VideoModeImpl.hpp @@ -1,68 +1,68 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_VIDEOMODEIMPL_HPP -#define SFML_VIDEOMODEIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief OS-specific implementation of video modes functions -/// -//////////////////////////////////////////////////////////// -class VideoModeImpl -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Get the list of all the supported fullscreen video modes - /// - /// \return Array filled with the fullscreen video modes - /// - //////////////////////////////////////////////////////////// - static std::vector getFullscreenModes(); - - //////////////////////////////////////////////////////////// - /// \brief Get the current desktop video mode - /// - /// \return Current desktop video mode - /// - //////////////////////////////////////////////////////////// - static VideoMode getDesktopMode(); -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_VIDEOMODEIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VIDEOMODEIMPL_HPP +#define SFML_VIDEOMODEIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief OS-specific implementation of video modes functions +/// +//////////////////////////////////////////////////////////// +class VideoModeImpl +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Get the list of all the supported fullscreen video modes + /// + /// \return Array filled with the fullscreen video modes + /// + //////////////////////////////////////////////////////////// + static std::vector getFullscreenModes(); + + //////////////////////////////////////////////////////////// + /// \brief Get the current desktop video mode + /// + /// \return Current desktop video mode + /// + //////////////////////////////////////////////////////////// + static VideoMode getDesktopMode(); +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_VIDEOMODEIMPL_HPP diff --git a/src/SFML/Window/Win32/InputImpl.hpp b/src/SFML/Window/Win32/InputImpl.hpp index 0d1ebeb1..f62f2d2d 100644 --- a/src/SFML/Window/Win32/InputImpl.hpp +++ b/src/SFML/Window/Win32/InputImpl.hpp @@ -42,7 +42,7 @@ namespace priv //////////////////////////////////////////////////////////// class InputImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Check if a key is pressed diff --git a/src/SFML/Window/Win32/JoystickImpl.cpp b/src/SFML/Window/Win32/JoystickImpl.cpp index 22bb467c..ee66005d 100644 --- a/src/SFML/Window/Win32/JoystickImpl.cpp +++ b/src/SFML/Window/Win32/JoystickImpl.cpp @@ -1,302 +1,302 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace -{ - struct ConnectionCache - { - ConnectionCache() : connected(false) {} - bool connected; - sf::Clock timer; - }; - - const sf::Time connectionRefreshDelay = sf::milliseconds(500); - ConnectionCache connectionCache[sf::Joystick::Count]; - - // Get a system error string from an error code - std::string getErrorString(DWORD error) - { - PTCHAR buffer; - - if (FormatMessage(FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, reinterpret_cast(&buffer), 0, NULL) == 0) - return "Unknown error."; - - sf::String message = buffer; - LocalFree(buffer); - return message.toAnsiString(); - } - - // Get the joystick's name - sf::String getDeviceName(unsigned int index, JOYCAPS caps) - { - // Give the joystick a default name - sf::String joystickDescription = "Unknown Joystick"; - - LONG result; - HKEY rootKey; - HKEY currentKey; - std::basic_string subkey; - - subkey = REGSTR_PATH_JOYCONFIG; - subkey += TEXT('\\'); - subkey += caps.szRegKey; - subkey += TEXT('\\'); - subkey += REGSTR_KEY_JOYCURR; - - rootKey = HKEY_CURRENT_USER; - result = RegOpenKeyEx(rootKey, subkey.c_str(), 0, KEY_READ, ¤tKey); - - if (result != ERROR_SUCCESS) - { - rootKey = HKEY_LOCAL_MACHINE; - result = RegOpenKeyEx(rootKey, subkey.c_str(), 0, KEY_READ, ¤tKey); - - if (result != ERROR_SUCCESS) - { - sf::err() << "Unable to open registry for joystick at index " << index << ": " << getErrorString(result) << std::endl; - return joystickDescription; - } - } - - std::basic_ostringstream indexString; - indexString << index + 1; - - subkey = TEXT("Joystick"); - subkey += indexString.str(); - subkey += REGSTR_VAL_JOYOEMNAME; - - TCHAR keyData[256]; - DWORD keyDataSize = sizeof(keyData); - - result = RegQueryValueEx(currentKey, subkey.c_str(), NULL, NULL, reinterpret_cast(keyData), &keyDataSize); - RegCloseKey(currentKey); - - if (result != ERROR_SUCCESS) - { - sf::err() << "Unable to query registry key for joystick at index " << index << ": " << getErrorString(result) << std::endl; - return joystickDescription; - } - - subkey = REGSTR_PATH_JOYOEM; - subkey += TEXT('\\'); - subkey.append(keyData, keyDataSize / sizeof(TCHAR)); - - result = RegOpenKeyEx(rootKey, subkey.c_str(), 0, KEY_READ, ¤tKey); - - if (result != ERROR_SUCCESS) - { - sf::err() << "Unable to open registry key for joystick at index " << index << ": " << getErrorString(result) << std::endl; - return joystickDescription; - } - - keyDataSize = sizeof(keyData); - - result = RegQueryValueEx(currentKey, REGSTR_VAL_JOYOEMNAME, NULL, NULL, reinterpret_cast(keyData), &keyDataSize); - RegCloseKey(currentKey); - - if (result != ERROR_SUCCESS) - { - sf::err() << "Unable to query name for joystick at index " << index << ": " << getErrorString(result) << std::endl; - return joystickDescription; - } - - keyData[255] = TEXT('\0'); // Ensure null terminator in case the data is too long. - joystickDescription = keyData; - - return joystickDescription; - } -} - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -void JoystickImpl::initialize() -{ - // Perform the initial scan and populate the connection cache - for (unsigned int i = 0; i < Joystick::Count; ++i) - { - ConnectionCache& cache = connectionCache[i]; - - // Check if the joystick is connected - JOYINFOEX joyInfo; - joyInfo.dwSize = sizeof(joyInfo); - joyInfo.dwFlags = 0; - cache.connected = joyGetPosEx(JOYSTICKID1 + i, &joyInfo) == JOYERR_NOERROR; - - // start the timeout - cache.timer.restart(); - } -} - - -//////////////////////////////////////////////////////////// -void JoystickImpl::cleanup() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -bool JoystickImpl::isConnected(unsigned int index) -{ - // We check the connection state of joysticks only every N milliseconds, - // because of a strange (buggy?) behaviour of joyGetPosEx when joysticks - // are just plugged/unplugged -- it takes really long and kills the app performances - ConnectionCache& cache = connectionCache[index]; - if (cache.timer.getElapsedTime() > connectionRefreshDelay) - { - cache.timer.restart(); - - JOYINFOEX joyInfo; - joyInfo.dwSize = sizeof(joyInfo); - joyInfo.dwFlags = 0; - - cache.connected = joyGetPosEx(JOYSTICKID1 + index, &joyInfo) == JOYERR_NOERROR; - return cache.connected; - } - else - { - return cache.connected; - } -} - - -//////////////////////////////////////////////////////////// -bool JoystickImpl::open(unsigned int index) -{ - // No explicit "open" action is required - m_index = JOYSTICKID1 + index; - - // Store the joystick capabilities - bool success = joyGetDevCaps(m_index, &m_caps, sizeof(m_caps)) == JOYERR_NOERROR; - - if (success) - { - m_identification.name = getDeviceName(m_index, m_caps); - m_identification.productId = m_caps.wPid; - m_identification.vendorId = m_caps.wMid; - } - - return success; -} - - -//////////////////////////////////////////////////////////// -void JoystickImpl::close() -{ - // Nothing to do -} - -//////////////////////////////////////////////////////////// -JoystickCaps JoystickImpl::getCapabilities() const -{ - JoystickCaps caps; - - caps.buttonCount = m_caps.wNumButtons; - if (caps.buttonCount > Joystick::ButtonCount) - caps.buttonCount = Joystick::ButtonCount; - - caps.axes[Joystick::X] = true; - caps.axes[Joystick::Y] = true; - caps.axes[Joystick::Z] = (m_caps.wCaps & JOYCAPS_HASZ) != 0; - caps.axes[Joystick::R] = (m_caps.wCaps & JOYCAPS_HASR) != 0; - caps.axes[Joystick::U] = (m_caps.wCaps & JOYCAPS_HASU) != 0; - caps.axes[Joystick::V] = (m_caps.wCaps & JOYCAPS_HASV) != 0; - caps.axes[Joystick::PovX] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0; - caps.axes[Joystick::PovY] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0; - - return caps; -} - - -//////////////////////////////////////////////////////////// -Joystick::Identification JoystickImpl::getIdentification() const -{ - return m_identification; -} - - -//////////////////////////////////////////////////////////// -JoystickState JoystickImpl::update() -{ - JoystickState state; - - // Get the current joystick state - JOYINFOEX pos; - pos.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | JOY_RETURNBUTTONS; - pos.dwFlags |= (m_caps.wCaps & JOYCAPS_POVCTS) ? JOY_RETURNPOVCTS : JOY_RETURNPOV; - pos.dwSize = sizeof(JOYINFOEX); - if (joyGetPosEx(m_index, &pos) == JOYERR_NOERROR) - { - // The joystick is connected - state.connected = true; - - // Axes - state.axes[Joystick::X] = (pos.dwXpos - (m_caps.wXmax + m_caps.wXmin) / 2.f) * 200.f / (m_caps.wXmax - m_caps.wXmin); - state.axes[Joystick::Y] = (pos.dwYpos - (m_caps.wYmax + m_caps.wYmin) / 2.f) * 200.f / (m_caps.wYmax - m_caps.wYmin); - state.axes[Joystick::Z] = (pos.dwZpos - (m_caps.wZmax + m_caps.wZmin) / 2.f) * 200.f / (m_caps.wZmax - m_caps.wZmin); - state.axes[Joystick::R] = (pos.dwRpos - (m_caps.wRmax + m_caps.wRmin) / 2.f) * 200.f / (m_caps.wRmax - m_caps.wRmin); - state.axes[Joystick::U] = (pos.dwUpos - (m_caps.wUmax + m_caps.wUmin) / 2.f) * 200.f / (m_caps.wUmax - m_caps.wUmin); - state.axes[Joystick::V] = (pos.dwVpos - (m_caps.wVmax + m_caps.wVmin) / 2.f) * 200.f / (m_caps.wVmax - m_caps.wVmin); - - // Special case for POV, it is given as an angle - if (pos.dwPOV != 0xFFFF) - { - float angle = pos.dwPOV / 18000.f * 3.141592654f; - state.axes[Joystick::PovX] = std::sin(angle) * 100; - state.axes[Joystick::PovY] = std::cos(angle) * 100; - } - else - { - state.axes[Joystick::PovX] = 0; - state.axes[Joystick::PovY] = 0; - } - - // Buttons - for (unsigned int i = 0; i < Joystick::ButtonCount; ++i) - state.buttons[i] = (pos.dwButtons & (1 << i)) != 0; - } - - return state; -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + struct ConnectionCache + { + ConnectionCache() : connected(false) {} + bool connected; + sf::Clock timer; + }; + + const sf::Time connectionRefreshDelay = sf::milliseconds(500); + ConnectionCache connectionCache[sf::Joystick::Count]; + + // Get a system error string from an error code + std::string getErrorString(DWORD error) + { + PTCHAR buffer; + + if (FormatMessage(FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, reinterpret_cast(&buffer), 0, NULL) == 0) + return "Unknown error."; + + sf::String message = buffer; + LocalFree(buffer); + return message.toAnsiString(); + } + + // Get the joystick's name + sf::String getDeviceName(unsigned int index, JOYCAPS caps) + { + // Give the joystick a default name + sf::String joystickDescription = "Unknown Joystick"; + + LONG result; + HKEY rootKey; + HKEY currentKey; + std::basic_string subkey; + + subkey = REGSTR_PATH_JOYCONFIG; + subkey += TEXT('\\'); + subkey += caps.szRegKey; + subkey += TEXT('\\'); + subkey += REGSTR_KEY_JOYCURR; + + rootKey = HKEY_CURRENT_USER; + result = RegOpenKeyEx(rootKey, subkey.c_str(), 0, KEY_READ, ¤tKey); + + if (result != ERROR_SUCCESS) + { + rootKey = HKEY_LOCAL_MACHINE; + result = RegOpenKeyEx(rootKey, subkey.c_str(), 0, KEY_READ, ¤tKey); + + if (result != ERROR_SUCCESS) + { + sf::err() << "Unable to open registry for joystick at index " << index << ": " << getErrorString(result) << std::endl; + return joystickDescription; + } + } + + std::basic_ostringstream indexString; + indexString << index + 1; + + subkey = TEXT("Joystick"); + subkey += indexString.str(); + subkey += REGSTR_VAL_JOYOEMNAME; + + TCHAR keyData[256]; + DWORD keyDataSize = sizeof(keyData); + + result = RegQueryValueEx(currentKey, subkey.c_str(), NULL, NULL, reinterpret_cast(keyData), &keyDataSize); + RegCloseKey(currentKey); + + if (result != ERROR_SUCCESS) + { + sf::err() << "Unable to query registry key for joystick at index " << index << ": " << getErrorString(result) << std::endl; + return joystickDescription; + } + + subkey = REGSTR_PATH_JOYOEM; + subkey += TEXT('\\'); + subkey.append(keyData, keyDataSize / sizeof(TCHAR)); + + result = RegOpenKeyEx(rootKey, subkey.c_str(), 0, KEY_READ, ¤tKey); + + if (result != ERROR_SUCCESS) + { + sf::err() << "Unable to open registry key for joystick at index " << index << ": " << getErrorString(result) << std::endl; + return joystickDescription; + } + + keyDataSize = sizeof(keyData); + + result = RegQueryValueEx(currentKey, REGSTR_VAL_JOYOEMNAME, NULL, NULL, reinterpret_cast(keyData), &keyDataSize); + RegCloseKey(currentKey); + + if (result != ERROR_SUCCESS) + { + sf::err() << "Unable to query name for joystick at index " << index << ": " << getErrorString(result) << std::endl; + return joystickDescription; + } + + keyData[255] = TEXT('\0'); // Ensure null terminator in case the data is too long. + joystickDescription = keyData; + + return joystickDescription; + } +} + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +void JoystickImpl::initialize() +{ + // Perform the initial scan and populate the connection cache + for (unsigned int i = 0; i < Joystick::Count; ++i) + { + ConnectionCache& cache = connectionCache[i]; + + // Check if the joystick is connected + JOYINFOEX joyInfo; + joyInfo.dwSize = sizeof(joyInfo); + joyInfo.dwFlags = 0; + cache.connected = joyGetPosEx(JOYSTICKID1 + i, &joyInfo) == JOYERR_NOERROR; + + // start the timeout + cache.timer.restart(); + } +} + + +//////////////////////////////////////////////////////////// +void JoystickImpl::cleanup() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +bool JoystickImpl::isConnected(unsigned int index) +{ + // We check the connection state of joysticks only every N milliseconds, + // because of a strange (buggy?) behaviour of joyGetPosEx when joysticks + // are just plugged/unplugged -- it takes really long and kills the app performances + ConnectionCache& cache = connectionCache[index]; + if (cache.timer.getElapsedTime() > connectionRefreshDelay) + { + cache.timer.restart(); + + JOYINFOEX joyInfo; + joyInfo.dwSize = sizeof(joyInfo); + joyInfo.dwFlags = 0; + + cache.connected = joyGetPosEx(JOYSTICKID1 + index, &joyInfo) == JOYERR_NOERROR; + return cache.connected; + } + else + { + return cache.connected; + } +} + + +//////////////////////////////////////////////////////////// +bool JoystickImpl::open(unsigned int index) +{ + // No explicit "open" action is required + m_index = JOYSTICKID1 + index; + + // Store the joystick capabilities + bool success = joyGetDevCaps(m_index, &m_caps, sizeof(m_caps)) == JOYERR_NOERROR; + + if (success) + { + m_identification.name = getDeviceName(m_index, m_caps); + m_identification.productId = m_caps.wPid; + m_identification.vendorId = m_caps.wMid; + } + + return success; +} + + +//////////////////////////////////////////////////////////// +void JoystickImpl::close() +{ + // Nothing to do +} + +//////////////////////////////////////////////////////////// +JoystickCaps JoystickImpl::getCapabilities() const +{ + JoystickCaps caps; + + caps.buttonCount = m_caps.wNumButtons; + if (caps.buttonCount > Joystick::ButtonCount) + caps.buttonCount = Joystick::ButtonCount; + + caps.axes[Joystick::X] = true; + caps.axes[Joystick::Y] = true; + caps.axes[Joystick::Z] = (m_caps.wCaps & JOYCAPS_HASZ) != 0; + caps.axes[Joystick::R] = (m_caps.wCaps & JOYCAPS_HASR) != 0; + caps.axes[Joystick::U] = (m_caps.wCaps & JOYCAPS_HASU) != 0; + caps.axes[Joystick::V] = (m_caps.wCaps & JOYCAPS_HASV) != 0; + caps.axes[Joystick::PovX] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0; + caps.axes[Joystick::PovY] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0; + + return caps; +} + + +//////////////////////////////////////////////////////////// +Joystick::Identification JoystickImpl::getIdentification() const +{ + return m_identification; +} + + +//////////////////////////////////////////////////////////// +JoystickState JoystickImpl::update() +{ + JoystickState state; + + // Get the current joystick state + JOYINFOEX pos; + pos.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | JOY_RETURNBUTTONS; + pos.dwFlags |= (m_caps.wCaps & JOYCAPS_POVCTS) ? JOY_RETURNPOVCTS : JOY_RETURNPOV; + pos.dwSize = sizeof(JOYINFOEX); + if (joyGetPosEx(m_index, &pos) == JOYERR_NOERROR) + { + // The joystick is connected + state.connected = true; + + // Axes + state.axes[Joystick::X] = (pos.dwXpos - (m_caps.wXmax + m_caps.wXmin) / 2.f) * 200.f / (m_caps.wXmax - m_caps.wXmin); + state.axes[Joystick::Y] = (pos.dwYpos - (m_caps.wYmax + m_caps.wYmin) / 2.f) * 200.f / (m_caps.wYmax - m_caps.wYmin); + state.axes[Joystick::Z] = (pos.dwZpos - (m_caps.wZmax + m_caps.wZmin) / 2.f) * 200.f / (m_caps.wZmax - m_caps.wZmin); + state.axes[Joystick::R] = (pos.dwRpos - (m_caps.wRmax + m_caps.wRmin) / 2.f) * 200.f / (m_caps.wRmax - m_caps.wRmin); + state.axes[Joystick::U] = (pos.dwUpos - (m_caps.wUmax + m_caps.wUmin) / 2.f) * 200.f / (m_caps.wUmax - m_caps.wUmin); + state.axes[Joystick::V] = (pos.dwVpos - (m_caps.wVmax + m_caps.wVmin) / 2.f) * 200.f / (m_caps.wVmax - m_caps.wVmin); + + // Special case for POV, it is given as an angle + if (pos.dwPOV != 0xFFFF) + { + float angle = pos.dwPOV / 18000.f * 3.141592654f; + state.axes[Joystick::PovX] = std::sin(angle) * 100; + state.axes[Joystick::PovY] = std::cos(angle) * 100; + } + else + { + state.axes[Joystick::PovX] = 0; + state.axes[Joystick::PovY] = 0; + } + + // Buttons + for (unsigned int i = 0; i < Joystick::ButtonCount; ++i) + state.buttons[i] = (pos.dwButtons & (1 << i)) != 0; + } + + return state; +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/Win32/JoystickImpl.hpp b/src/SFML/Window/Win32/JoystickImpl.hpp index 87cb3894..a5d258df 100644 --- a/src/SFML/Window/Win32/JoystickImpl.hpp +++ b/src/SFML/Window/Win32/JoystickImpl.hpp @@ -1,135 +1,135 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_JOYSTICKIMPLWIN32_HPP -#define SFML_JOYSTICKIMPLWIN32_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#ifdef _WIN32_WINDOWS - #undef _WIN32_WINDOWS -#endif -#ifdef _WIN32_WINNT - #undef _WIN32_WINNT -#endif -#define _WIN32_WINDOWS 0x0501 -#define _WIN32_WINNT 0x0501 -#include -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Windows implementation of joysticks -/// -//////////////////////////////////////////////////////////// -class JoystickImpl -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Perform the global initialization of the joystick module - /// - //////////////////////////////////////////////////////////// - static void initialize(); - - //////////////////////////////////////////////////////////// - /// \brief Perform the global cleanup of the joystick module - /// - //////////////////////////////////////////////////////////// - static void cleanup(); - - //////////////////////////////////////////////////////////// - /// \brief Check if a joystick is currently connected - /// - /// \param index Index of the joystick to check - /// - /// \return True if the joystick is connected, false otherwise - /// - //////////////////////////////////////////////////////////// - static bool isConnected(unsigned int index); - - //////////////////////////////////////////////////////////// - /// \brief Open the joystick - /// - /// \param index Index assigned to the joystick - /// - /// \return True on success, false on failure - /// - //////////////////////////////////////////////////////////// - bool open(unsigned int index); - - //////////////////////////////////////////////////////////// - /// \brief Close the joystick - /// - //////////////////////////////////////////////////////////// - void close(); - - //////////////////////////////////////////////////////////// - /// \brief Get the joystick capabilities - /// - /// \return Joystick capabilities - /// - //////////////////////////////////////////////////////////// - JoystickCaps getCapabilities() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the joystick identification - /// - /// \return Joystick identification - /// - //////////////////////////////////////////////////////////// - Joystick::Identification getIdentification() const; - - //////////////////////////////////////////////////////////// - /// \brief Update the joystick and get its new state - /// - /// \return Joystick state - /// - //////////////////////////////////////////////////////////// - JoystickState update(); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - unsigned int m_index; ///< Index of the joystick - JOYCAPS m_caps; ///< Joystick capabilities - Joystick::Identification m_identification; ///< Joystick identification -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_JOYSTICKIMPLWIN32_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_JOYSTICKIMPLWIN32_HPP +#define SFML_JOYSTICKIMPLWIN32_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#ifdef _WIN32_WINDOWS + #undef _WIN32_WINDOWS +#endif +#ifdef _WIN32_WINNT + #undef _WIN32_WINNT +#endif +#define _WIN32_WINDOWS 0x0501 +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows implementation of joysticks +/// +//////////////////////////////////////////////////////////// +class JoystickImpl +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Perform the global initialization of the joystick module + /// + //////////////////////////////////////////////////////////// + static void initialize(); + + //////////////////////////////////////////////////////////// + /// \brief Perform the global cleanup of the joystick module + /// + //////////////////////////////////////////////////////////// + static void cleanup(); + + //////////////////////////////////////////////////////////// + /// \brief Check if a joystick is currently connected + /// + /// \param index Index of the joystick to check + /// + /// \return True if the joystick is connected, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isConnected(unsigned int index); + + //////////////////////////////////////////////////////////// + /// \brief Open the joystick + /// + /// \param index Index assigned to the joystick + /// + /// \return True on success, false on failure + /// + //////////////////////////////////////////////////////////// + bool open(unsigned int index); + + //////////////////////////////////////////////////////////// + /// \brief Close the joystick + /// + //////////////////////////////////////////////////////////// + void close(); + + //////////////////////////////////////////////////////////// + /// \brief Get the joystick capabilities + /// + /// \return Joystick capabilities + /// + //////////////////////////////////////////////////////////// + JoystickCaps getCapabilities() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the joystick identification + /// + /// \return Joystick identification + /// + //////////////////////////////////////////////////////////// + Joystick::Identification getIdentification() const; + + //////////////////////////////////////////////////////////// + /// \brief Update the joystick and get its new state + /// + /// \return Joystick state + /// + //////////////////////////////////////////////////////////// + JoystickState update(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int m_index; ///< Index of the joystick + JOYCAPS m_caps; ///< Joystick capabilities + Joystick::Identification m_identification; ///< Joystick identification +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_JOYSTICKIMPLWIN32_HPP diff --git a/src/SFML/Window/Win32/SensorImpl.hpp b/src/SFML/Window/Win32/SensorImpl.hpp index 887c3d70..e174fa26 100644 --- a/src/SFML/Window/Win32/SensorImpl.hpp +++ b/src/SFML/Window/Win32/SensorImpl.hpp @@ -36,7 +36,7 @@ namespace priv //////////////////////////////////////////////////////////// class SensorImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Perform the global initialization of the sensor module diff --git a/src/SFML/Window/Win32/VideoModeImpl.cpp b/src/SFML/Window/Win32/VideoModeImpl.cpp index 3660e43a..b19588ac 100644 --- a/src/SFML/Window/Win32/VideoModeImpl.cpp +++ b/src/SFML/Window/Win32/VideoModeImpl.cpp @@ -1,71 +1,71 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -std::vector VideoModeImpl::getFullscreenModes() -{ - std::vector modes; - - // Enumerate all available video modes for the primary display adapter - DEVMODE win32Mode; - win32Mode.dmSize = sizeof(win32Mode); - for (int count = 0; EnumDisplaySettings(NULL, count, &win32Mode); ++count) - { - // Convert to sf::VideoMode - VideoMode mode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, win32Mode.dmBitsPerPel); - - // Add it only if it is not already in the array - if (std::find(modes.begin(), modes.end(), mode) == modes.end()) - modes.push_back(mode); - } - - return modes; -} - - -//////////////////////////////////////////////////////////// -VideoMode VideoModeImpl::getDesktopMode() -{ - DEVMODE win32Mode; - win32Mode.dmSize = sizeof(win32Mode); - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &win32Mode); - - return VideoMode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, win32Mode.dmBitsPerPel); -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +std::vector VideoModeImpl::getFullscreenModes() +{ + std::vector modes; + + // Enumerate all available video modes for the primary display adapter + DEVMODE win32Mode; + win32Mode.dmSize = sizeof(win32Mode); + for (int count = 0; EnumDisplaySettings(NULL, count, &win32Mode); ++count) + { + // Convert to sf::VideoMode + VideoMode mode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, win32Mode.dmBitsPerPel); + + // Add it only if it is not already in the array + if (std::find(modes.begin(), modes.end(), mode) == modes.end()) + modes.push_back(mode); + } + + return modes; +} + + +//////////////////////////////////////////////////////////// +VideoMode VideoModeImpl::getDesktopMode() +{ + DEVMODE win32Mode; + win32Mode.dmSize = sizeof(win32Mode); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &win32Mode); + + return VideoMode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, win32Mode.dmBitsPerPel); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/Win32/WglContext.cpp b/src/SFML/Window/Win32/WglContext.cpp index eca331db..c6e7c338 100644 --- a/src/SFML/Window/Win32/WglContext.cpp +++ b/src/SFML/Window/Win32/WglContext.cpp @@ -1,325 +1,325 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include // included first to avoid a warning about macro redefinition -#include -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -WglContext::WglContext(WglContext* shared) : -m_window (NULL), -m_deviceContext(NULL), -m_context (NULL), -m_ownsWindow (true) -{ - // Creating a dummy window is mandatory: we could create a memory DC but then - // its pixel format wouldn't match the regular contexts' format, and thus - // wglShareLists would always fail. Too bad... - - // Create a dummy window (disabled and hidden) - m_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); - ShowWindow(m_window, SW_HIDE); - m_deviceContext = GetDC(m_window); - - // Create the context - if (m_deviceContext) - createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings()); -} - - -//////////////////////////////////////////////////////////// -WglContext::WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) : -m_window (NULL), -m_deviceContext(NULL), -m_context (NULL), -m_ownsWindow (false) -{ - // Get the owner window and its device context - m_window = owner->getSystemHandle(); - m_deviceContext = GetDC(m_window); - - // Create the context - if (m_deviceContext) - createContext(shared, bitsPerPixel, settings); -} - - -//////////////////////////////////////////////////////////// -WglContext::WglContext(WglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) : -m_window (NULL), -m_deviceContext(NULL), -m_context (NULL), -m_ownsWindow (true) -{ - // The target of the context is a hidden window. - // We can't create a memory DC (the resulting context wouldn't be compatible - // with other contexts), and we don't add the extra complexity of P-Buffers; - // we can still support them in the future if this solution is not good enough. - - // Create the hidden window - m_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, width, height, NULL, NULL, GetModuleHandle(NULL), NULL); - ShowWindow(m_window, SW_HIDE); - m_deviceContext = GetDC(m_window); - - // Create the context - if (m_deviceContext) - createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings); -} - - -//////////////////////////////////////////////////////////// -WglContext::~WglContext() -{ - // Destroy the OpenGL context - if (m_context) - { - if (wglGetCurrentContext() == m_context) - wglMakeCurrent(NULL, NULL); - wglDeleteContext(m_context); - } - - // Destroy the device context - if (m_deviceContext) - ReleaseDC(m_window, m_deviceContext); - - // Destroy the window if we own it - if (m_window && m_ownsWindow) - DestroyWindow(m_window); -} - - -//////////////////////////////////////////////////////////// -bool WglContext::makeCurrent() -{ - return m_deviceContext && m_context && wglMakeCurrent(m_deviceContext, m_context); -} - - -//////////////////////////////////////////////////////////// -void WglContext::display() -{ - if (m_deviceContext && m_context) - SwapBuffers(m_deviceContext); -} - - -//////////////////////////////////////////////////////////// -void WglContext::setVerticalSyncEnabled(bool enabled) -{ - PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = reinterpret_cast(wglGetProcAddress("wglSwapIntervalEXT")); - if (wglSwapIntervalEXT) - wglSwapIntervalEXT(enabled ? 1 : 0); -} - - -//////////////////////////////////////////////////////////// -void WglContext::createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) -{ - // Save the creation settings - m_settings = settings; - - // Let's find a suitable pixel format -- first try with antialiasing - int bestFormat = 0; - if (m_settings.antialiasingLevel > 0) - { - // Get the wglChoosePixelFormatARB function (it is an extension) - PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpret_cast(wglGetProcAddress("wglChoosePixelFormatARB")); - if (wglChoosePixelFormatARB) - { - // Define the basic attributes we want for our window - int intAttributes[] = - { - WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, - WGL_SUPPORT_OPENGL_ARB, GL_TRUE, - WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, - WGL_DOUBLE_BUFFER_ARB, GL_TRUE, - WGL_SAMPLE_BUFFERS_ARB, (m_settings.antialiasingLevel ? GL_TRUE : GL_FALSE), - WGL_SAMPLES_ARB, static_cast(m_settings.antialiasingLevel), - 0, 0 - }; - - // Let's check how many formats are supporting our requirements - int formats[128]; - UINT nbFormats; - float floatAttributes[] = {0, 0}; - bool isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; - while ((!isValid || (nbFormats == 0)) && m_settings.antialiasingLevel > 0) - { - // Decrease the antialiasing level until we find a valid one - m_settings.antialiasingLevel--; - intAttributes[11] = m_settings.antialiasingLevel; - isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; - } - - // Get the best format among the returned ones - if (isValid && (nbFormats > 0)) - { - int bestScore = 0xFFFF; - for (UINT i = 0; i < nbFormats; ++i) - { - // Get the current format's attributes - PIXELFORMATDESCRIPTOR attributes; - attributes.nSize = sizeof(attributes); - attributes.nVersion = 1; - DescribePixelFormat(m_deviceContext, formats[i], sizeof(attributes), &attributes); - - // Evaluate the current configuration - int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits; - int score = evaluateFormat(bitsPerPixel, m_settings, color, attributes.cDepthBits, attributes.cStencilBits, m_settings.antialiasingLevel); - - // Keep it if it's better than the current best - if (score < bestScore) - { - bestScore = score; - bestFormat = formats[i]; - } - } - } - } - else - { - // wglChoosePixelFormatARB not supported ; disabling antialiasing - err() << "Antialiasing is not supported ; it will be disabled" << std::endl; - m_settings.antialiasingLevel = 0; - } - } - - // Find a pixel format with no antialiasing, if not needed or not supported - if (bestFormat == 0) - { - // Setup a pixel format descriptor from the rendering settings - PIXELFORMATDESCRIPTOR descriptor; - ZeroMemory(&descriptor, sizeof(descriptor)); - descriptor.nSize = sizeof(descriptor); - descriptor.nVersion = 1; - descriptor.iLayerType = PFD_MAIN_PLANE; - descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - descriptor.iPixelType = PFD_TYPE_RGBA; - descriptor.cColorBits = static_cast(bitsPerPixel); - descriptor.cDepthBits = static_cast(m_settings.depthBits); - descriptor.cStencilBits = static_cast(m_settings.stencilBits); - descriptor.cAlphaBits = bitsPerPixel == 32 ? 8 : 0; - - // Get the pixel format that best matches our requirements - bestFormat = ChoosePixelFormat(m_deviceContext, &descriptor); - if (bestFormat == 0) - { - err() << "Failed to find a suitable pixel format for device context -- cannot create OpenGL context" << std::endl; - return; - } - } - - // Extract the depth and stencil bits from the chosen format - PIXELFORMATDESCRIPTOR actualFormat; - actualFormat.nSize = sizeof(actualFormat); - actualFormat.nVersion = 1; - DescribePixelFormat(m_deviceContext, bestFormat, sizeof(actualFormat), &actualFormat); - m_settings.depthBits = actualFormat.cDepthBits; - m_settings.stencilBits = actualFormat.cStencilBits; - - // Set the chosen pixel format - if (!SetPixelFormat(m_deviceContext, bestFormat, &actualFormat)) - { - err() << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl; - return; - } - - // Get the context to share display lists with - HGLRC sharedContext = shared ? shared->m_context : NULL; - - // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code) - while (!m_context && (m_settings.majorVersion >= 3)) - { - PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = reinterpret_cast(wglGetProcAddress("wglCreateContextAttribsARB")); - if (wglCreateContextAttribsARB) - { - int attributes[] = - { - WGL_CONTEXT_MAJOR_VERSION_ARB, static_cast(m_settings.majorVersion), - WGL_CONTEXT_MINOR_VERSION_ARB, static_cast(m_settings.minorVersion), - WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - 0, 0 - }; - m_context = wglCreateContextAttribsARB(m_deviceContext, sharedContext, attributes); - } - - // If we couldn't create the context, lower the version number and try again -- stop at 3.0 - // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care - if (!m_context) - { - if (m_settings.minorVersion > 0) - { - // If the minor version is not 0, we decrease it and try again - m_settings.minorVersion--; - } - else - { - // If the minor version is 0, we decrease the major version - m_settings.majorVersion--; - m_settings.minorVersion = 9; - } - } - } - - // If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context - if (!m_context) - { - // set the context version to 2.0 (arbitrary) - m_settings.majorVersion = 2; - m_settings.minorVersion = 0; - - m_context = wglCreateContext(m_deviceContext); - if (!m_context) - { - err() << "Failed to create an OpenGL context for this window" << std::endl; - return; - } - - // Share this context with others - if (sharedContext) - { - // wglShareLists doesn't seem to be thread-safe - static Mutex mutex; - Lock lock(mutex); - - if (!wglShareLists(sharedContext, m_context)) - err() << "Failed to share the OpenGL context" << std::endl; - } - } -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include // included first to avoid a warning about macro redefinition +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +WglContext::WglContext(WglContext* shared) : +m_window (NULL), +m_deviceContext(NULL), +m_context (NULL), +m_ownsWindow (true) +{ + // Creating a dummy window is mandatory: we could create a memory DC but then + // its pixel format wouldn't match the regular contexts' format, and thus + // wglShareLists would always fail. Too bad... + + // Create a dummy window (disabled and hidden) + m_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); + ShowWindow(m_window, SW_HIDE); + m_deviceContext = GetDC(m_window); + + // Create the context + if (m_deviceContext) + createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings()); +} + + +//////////////////////////////////////////////////////////// +WglContext::WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) : +m_window (NULL), +m_deviceContext(NULL), +m_context (NULL), +m_ownsWindow (false) +{ + // Get the owner window and its device context + m_window = owner->getSystemHandle(); + m_deviceContext = GetDC(m_window); + + // Create the context + if (m_deviceContext) + createContext(shared, bitsPerPixel, settings); +} + + +//////////////////////////////////////////////////////////// +WglContext::WglContext(WglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) : +m_window (NULL), +m_deviceContext(NULL), +m_context (NULL), +m_ownsWindow (true) +{ + // The target of the context is a hidden window. + // We can't create a memory DC (the resulting context wouldn't be compatible + // with other contexts), and we don't add the extra complexity of P-Buffers; + // we can still support them in the future if this solution is not good enough. + + // Create the hidden window + m_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, width, height, NULL, NULL, GetModuleHandle(NULL), NULL); + ShowWindow(m_window, SW_HIDE); + m_deviceContext = GetDC(m_window); + + // Create the context + if (m_deviceContext) + createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings); +} + + +//////////////////////////////////////////////////////////// +WglContext::~WglContext() +{ + // Destroy the OpenGL context + if (m_context) + { + if (wglGetCurrentContext() == m_context) + wglMakeCurrent(NULL, NULL); + wglDeleteContext(m_context); + } + + // Destroy the device context + if (m_deviceContext) + ReleaseDC(m_window, m_deviceContext); + + // Destroy the window if we own it + if (m_window && m_ownsWindow) + DestroyWindow(m_window); +} + + +//////////////////////////////////////////////////////////// +bool WglContext::makeCurrent() +{ + return m_deviceContext && m_context && wglMakeCurrent(m_deviceContext, m_context); +} + + +//////////////////////////////////////////////////////////// +void WglContext::display() +{ + if (m_deviceContext && m_context) + SwapBuffers(m_deviceContext); +} + + +//////////////////////////////////////////////////////////// +void WglContext::setVerticalSyncEnabled(bool enabled) +{ + PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = reinterpret_cast(wglGetProcAddress("wglSwapIntervalEXT")); + if (wglSwapIntervalEXT) + wglSwapIntervalEXT(enabled ? 1 : 0); +} + + +//////////////////////////////////////////////////////////// +void WglContext::createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) +{ + // Save the creation settings + m_settings = settings; + + // Let's find a suitable pixel format -- first try with antialiasing + int bestFormat = 0; + if (m_settings.antialiasingLevel > 0) + { + // Get the wglChoosePixelFormatARB function (it is an extension) + PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpret_cast(wglGetProcAddress("wglChoosePixelFormatARB")); + if (wglChoosePixelFormatARB) + { + // Define the basic attributes we want for our window + int intAttributes[] = + { + WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, + WGL_SUPPORT_OPENGL_ARB, GL_TRUE, + WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, + WGL_DOUBLE_BUFFER_ARB, GL_TRUE, + WGL_SAMPLE_BUFFERS_ARB, (m_settings.antialiasingLevel ? GL_TRUE : GL_FALSE), + WGL_SAMPLES_ARB, static_cast(m_settings.antialiasingLevel), + 0, 0 + }; + + // Let's check how many formats are supporting our requirements + int formats[128]; + UINT nbFormats; + float floatAttributes[] = {0, 0}; + bool isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; + while ((!isValid || (nbFormats == 0)) && m_settings.antialiasingLevel > 0) + { + // Decrease the antialiasing level until we find a valid one + m_settings.antialiasingLevel--; + intAttributes[11] = m_settings.antialiasingLevel; + isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; + } + + // Get the best format among the returned ones + if (isValid && (nbFormats > 0)) + { + int bestScore = 0xFFFF; + for (UINT i = 0; i < nbFormats; ++i) + { + // Get the current format's attributes + PIXELFORMATDESCRIPTOR attributes; + attributes.nSize = sizeof(attributes); + attributes.nVersion = 1; + DescribePixelFormat(m_deviceContext, formats[i], sizeof(attributes), &attributes); + + // Evaluate the current configuration + int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits; + int score = evaluateFormat(bitsPerPixel, m_settings, color, attributes.cDepthBits, attributes.cStencilBits, m_settings.antialiasingLevel); + + // Keep it if it's better than the current best + if (score < bestScore) + { + bestScore = score; + bestFormat = formats[i]; + } + } + } + } + else + { + // wglChoosePixelFormatARB not supported ; disabling antialiasing + err() << "Antialiasing is not supported ; it will be disabled" << std::endl; + m_settings.antialiasingLevel = 0; + } + } + + // Find a pixel format with no antialiasing, if not needed or not supported + if (bestFormat == 0) + { + // Setup a pixel format descriptor from the rendering settings + PIXELFORMATDESCRIPTOR descriptor; + ZeroMemory(&descriptor, sizeof(descriptor)); + descriptor.nSize = sizeof(descriptor); + descriptor.nVersion = 1; + descriptor.iLayerType = PFD_MAIN_PLANE; + descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + descriptor.iPixelType = PFD_TYPE_RGBA; + descriptor.cColorBits = static_cast(bitsPerPixel); + descriptor.cDepthBits = static_cast(m_settings.depthBits); + descriptor.cStencilBits = static_cast(m_settings.stencilBits); + descriptor.cAlphaBits = bitsPerPixel == 32 ? 8 : 0; + + // Get the pixel format that best matches our requirements + bestFormat = ChoosePixelFormat(m_deviceContext, &descriptor); + if (bestFormat == 0) + { + err() << "Failed to find a suitable pixel format for device context -- cannot create OpenGL context" << std::endl; + return; + } + } + + // Extract the depth and stencil bits from the chosen format + PIXELFORMATDESCRIPTOR actualFormat; + actualFormat.nSize = sizeof(actualFormat); + actualFormat.nVersion = 1; + DescribePixelFormat(m_deviceContext, bestFormat, sizeof(actualFormat), &actualFormat); + m_settings.depthBits = actualFormat.cDepthBits; + m_settings.stencilBits = actualFormat.cStencilBits; + + // Set the chosen pixel format + if (!SetPixelFormat(m_deviceContext, bestFormat, &actualFormat)) + { + err() << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl; + return; + } + + // Get the context to share display lists with + HGLRC sharedContext = shared ? shared->m_context : NULL; + + // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code) + while (!m_context && (m_settings.majorVersion >= 3)) + { + PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = reinterpret_cast(wglGetProcAddress("wglCreateContextAttribsARB")); + if (wglCreateContextAttribsARB) + { + int attributes[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, static_cast(m_settings.majorVersion), + WGL_CONTEXT_MINOR_VERSION_ARB, static_cast(m_settings.minorVersion), + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + 0, 0 + }; + m_context = wglCreateContextAttribsARB(m_deviceContext, sharedContext, attributes); + } + + // If we couldn't create the context, lower the version number and try again -- stop at 3.0 + // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care + if (!m_context) + { + if (m_settings.minorVersion > 0) + { + // If the minor version is not 0, we decrease it and try again + m_settings.minorVersion--; + } + else + { + // If the minor version is 0, we decrease the major version + m_settings.majorVersion--; + m_settings.minorVersion = 9; + } + } + } + + // If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context + if (!m_context) + { + // set the context version to 2.0 (arbitrary) + m_settings.majorVersion = 2; + m_settings.minorVersion = 0; + + m_context = wglCreateContext(m_deviceContext); + if (!m_context) + { + err() << "Failed to create an OpenGL context for this window" << std::endl; + return; + } + + // Share this context with others + if (sharedContext) + { + // wglShareLists doesn't seem to be thread-safe + static Mutex mutex; + Lock lock(mutex); + + if (!wglShareLists(sharedContext, m_context)) + err() << "Failed to share the OpenGL context" << std::endl; + } + } +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/Win32/WglContext.hpp b/src/SFML/Window/Win32/WglContext.hpp index 92486e7b..75ef4d55 100644 --- a/src/SFML/Window/Win32/WglContext.hpp +++ b/src/SFML/Window/Win32/WglContext.hpp @@ -1,136 +1,136 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_WGLCONTEXT_HPP -#define SFML_WGLCONTEXT_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Windows (WGL) implementation of OpenGL contexts -/// -//////////////////////////////////////////////////////////// -class WglContext : public GlContext -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Create a new default context - /// - /// \param shared Context to share the new one with (can be NULL) - /// - //////////////////////////////////////////////////////////// - WglContext(WglContext* shared); - - //////////////////////////////////////////////////////////// - /// \brief Create a new context attached to a window - /// - /// \param shared Context to share the new one with - /// \param settings Creation parameters - /// \param owner Pointer to the owner window - /// \param bitsPerPixel Pixel depth, in bits per pixel - /// - //////////////////////////////////////////////////////////// - WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); - - //////////////////////////////////////////////////////////// - /// \brief Create a new context that embeds its own rendering target - /// - /// \param shared Context to share the new one with - /// \param settings Creation parameters - /// \param width Back buffer width, in pixels - /// \param height Back buffer height, in pixels - /// - //////////////////////////////////////////////////////////// - WglContext(WglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~WglContext(); - - //////////////////////////////////////////////////////////// - /// \brief Activate the context as the current target for rendering - /// - /// \return True on success, false if any error happened - /// - //////////////////////////////////////////////////////////// - virtual bool makeCurrent(); - - //////////////////////////////////////////////////////////// - /// \brief Display what has been rendered to the context so far - /// - //////////////////////////////////////////////////////////// - virtual void display(); - - //////////////////////////////////////////////////////////// - /// \brief Enable or disable vertical synchronization - /// - /// Activating vertical synchronization will limit the number - /// of frames displayed to the refresh rate of the monitor. - /// This can avoid some visual artifacts, and limit the framerate - /// to a good value (but not constant across different computers). - /// - /// \param enabled : True to enable v-sync, false to deactivate - /// - //////////////////////////////////////////////////////////// - virtual void setVerticalSyncEnabled(bool enabled); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Create the context - /// - /// \param shared Context to share the new one with (can be NULL) - /// \param bitsPerPixel Pixel depth, in bits per pixel - /// \param settings Creation parameters - /// - //////////////////////////////////////////////////////////// - void createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - HWND m_window; ///< Window to which the context is attached - HDC m_deviceContext; ///< Device context associated to the context - HGLRC m_context; ///< OpenGL context - bool m_ownsWindow; ///< Do we own the target window? -}; - -} // namespace priv - -} // namespace sf - -#endif // SFML_WGLCONTEXT_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WGLCONTEXT_HPP +#define SFML_WGLCONTEXT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows (WGL) implementation of OpenGL contexts +/// +//////////////////////////////////////////////////////////// +class WglContext : public GlContext +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Create a new default context + /// + /// \param shared Context to share the new one with (can be NULL) + /// + //////////////////////////////////////////////////////////// + WglContext(WglContext* shared); + + //////////////////////////////////////////////////////////// + /// \brief Create a new context attached to a window + /// + /// \param shared Context to share the new one with + /// \param settings Creation parameters + /// \param owner Pointer to the owner window + /// \param bitsPerPixel Pixel depth, in bits per pixel + /// + //////////////////////////////////////////////////////////// + WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); + + //////////////////////////////////////////////////////////// + /// \brief Create a new context that embeds its own rendering target + /// + /// \param shared Context to share the new one with + /// \param settings Creation parameters + /// \param width Back buffer width, in pixels + /// \param height Back buffer height, in pixels + /// + //////////////////////////////////////////////////////////// + WglContext(WglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~WglContext(); + + //////////////////////////////////////////////////////////// + /// \brief Activate the context as the current target for rendering + /// + /// \return True on success, false if any error happened + /// + //////////////////////////////////////////////////////////// + virtual bool makeCurrent(); + + //////////////////////////////////////////////////////////// + /// \brief Display what has been rendered to the context so far + /// + //////////////////////////////////////////////////////////// + virtual void display(); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable vertical synchronization + /// + /// Activating vertical synchronization will limit the number + /// of frames displayed to the refresh rate of the monitor. + /// This can avoid some visual artifacts, and limit the framerate + /// to a good value (but not constant across different computers). + /// + /// \param enabled: True to enable v-sync, false to deactivate + /// + //////////////////////////////////////////////////////////// + virtual void setVerticalSyncEnabled(bool enabled); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Create the context + /// + /// \param shared Context to share the new one with (can be NULL) + /// \param bitsPerPixel Pixel depth, in bits per pixel + /// \param settings Creation parameters + /// + //////////////////////////////////////////////////////////// + void createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + HWND m_window; ///< Window to which the context is attached + HDC m_deviceContext; ///< Device context associated to the context + HGLRC m_context; ///< OpenGL context + bool m_ownsWindow; ///< Do we own the target window? +}; + +} // namespace priv + +} // namespace sf + +#endif // SFML_WGLCONTEXT_HPP diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index 11108731..6d9ac28c 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -1,990 +1,990 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#ifdef _WIN32_WINDOWS - #undef _WIN32_WINDOWS -#endif -#ifdef _WIN32_WINNT - #undef _WIN32_WINNT -#endif -#define _WIN32_WINDOWS 0x0501 -#define _WIN32_WINNT 0x0501 -#include -#include -#include -#include -#include -#include - -// MinGW lacks the definition of some Win32 constants -#ifndef XBUTTON1 - #define XBUTTON1 0x0001 -#endif -#ifndef XBUTTON2 - #define XBUTTON2 0x0002 -#endif -#ifndef MAPVK_VK_TO_VSC - #define MAPVK_VK_TO_VSC (0) -#endif - - -namespace -{ - unsigned int windowCount = 0; - const wchar_t* className = L"SFML_Window"; - sf::priv::WindowImplWin32* fullscreenWindow = NULL; - - void setProcessDpiAware() - { - // Try SetProcessDpiAwareness first - HINSTANCE shCoreDll = LoadLibrary(L"Shcore.dll"); - - if (shCoreDll) - { - enum ProcessDpiAwareness - { - ProcessDpiUnaware = 0, - ProcessSystemDpiAware = 1, - ProcessPerMonitorDpiAware = 2 - }; - - typedef HRESULT (WINAPI* SetProcessDpiAwarenessFuncType)(ProcessDpiAwareness); - SetProcessDpiAwarenessFuncType SetProcessDpiAwarenessFunc = reinterpret_cast(GetProcAddress(shCoreDll, "SetProcessDpiAwareness")); - - if (SetProcessDpiAwarenessFunc) - { - // We only check for E_INVALIDARG because we would get - // E_ACCESSDENIED if the DPI was already set previously - // and S_OK means the call was successful - if (SetProcessDpiAwarenessFunc(ProcessSystemDpiAware) == E_INVALIDARG) - { - sf::err() << "Failed to set process DPI awareness" << std::endl; - } - else - { - FreeLibrary(shCoreDll); - return; - } - } - - FreeLibrary(shCoreDll); - } - - // Fall back to SetProcessDPIAware if SetProcessDpiAwareness - // is not available on this system - HINSTANCE user32Dll = LoadLibrary(L"user32.dll"); - - if (user32Dll) - { - typedef BOOL (WINAPI* SetProcessDPIAwareFuncType)(void); - SetProcessDPIAwareFuncType SetProcessDPIAwareFunc = reinterpret_cast(GetProcAddress(user32Dll, "SetProcessDPIAware")); - - if (SetProcessDPIAwareFunc) - { - if (!SetProcessDPIAwareFunc()) - sf::err() << "Failed to set process DPI awareness" << std::endl; - } - - FreeLibrary(user32Dll); - } - } -} - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -WindowImplWin32::WindowImplWin32(WindowHandle handle) : -m_handle (handle), -m_callback (0), -m_cursor (NULL), -m_icon (NULL), -m_keyRepeatEnabled(true), -m_lastSize (0, 0), -m_resizing (false), -m_surrogate (0), -m_mouseInside (false) -{ - // Set that this process is DPI aware and can handle DPI scaling - setProcessDpiAware(); - - if (m_handle) - { - // We change the event procedure of the control (it is important to save the old one) - SetWindowLongPtrW(m_handle, GWLP_USERDATA, reinterpret_cast(this)); - m_callback = SetWindowLongPtrW(m_handle, GWLP_WNDPROC, reinterpret_cast(&WindowImplWin32::globalOnEvent)); - } -} - - -//////////////////////////////////////////////////////////// -WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& /*settings*/) : -m_handle (NULL), -m_callback (0), -m_cursor (NULL), -m_icon (NULL), -m_keyRepeatEnabled(true), -m_lastSize (mode.width, mode.height), -m_resizing (false), -m_surrogate (0), -m_mouseInside (false) -{ - // Set that this process is DPI aware and can handle DPI scaling - setProcessDpiAware(); - - // Register the window class at first call - if (windowCount == 0) - registerWindowClass(); - - // Compute position and size - HDC screenDC = GetDC(NULL); - int left = (GetDeviceCaps(screenDC, HORZRES) - static_cast(mode.width)) / 2; - int top = (GetDeviceCaps(screenDC, VERTRES) - static_cast(mode.height)) / 2; - int width = mode.width; - int height = mode.height; - ReleaseDC(NULL, screenDC); - - // Choose the window style according to the Style parameter - DWORD win32Style = WS_VISIBLE; - if (style == Style::None) - { - win32Style |= WS_POPUP; - } - else - { - if (style & Style::Titlebar) win32Style |= WS_CAPTION | WS_MINIMIZEBOX; - if (style & Style::Resize) win32Style |= WS_THICKFRAME | WS_MAXIMIZEBOX; - if (style & Style::Close) win32Style |= WS_SYSMENU; - } - - // In windowed mode, adjust width and height so that window will have the requested client area - bool fullscreen = (style & Style::Fullscreen) != 0; - if (!fullscreen) - { - RECT rectangle = {0, 0, width, height}; - AdjustWindowRect(&rectangle, win32Style, false); - width = rectangle.right - rectangle.left; - height = rectangle.bottom - rectangle.top; - } - - // Create the window - m_handle = CreateWindowW(className, title.toWideString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this); - - // By default, the OS limits the size of the window the the desktop size, - // we have to resize it after creation to apply the real size - setSize(Vector2u(mode.width, mode.height)); - - // Switch to fullscreen if requested - if (fullscreen) - switchToFullscreen(mode); - - // Increment window count - windowCount++; -} - - -//////////////////////////////////////////////////////////// -WindowImplWin32::~WindowImplWin32() -{ - // Destroy the custom icon, if any - if (m_icon) - DestroyIcon(m_icon); - - if (!m_callback) - { - // Destroy the window - if (m_handle) - DestroyWindow(m_handle); - - // Decrement the window count - windowCount--; - - // Unregister window class if we were the last window - if (windowCount == 0) - UnregisterClassW(className, GetModuleHandleW(NULL)); - } - else - { - // The window is external : remove the hook on its message callback - SetWindowLongPtrW(m_handle, GWLP_WNDPROC, m_callback); - } -} - - -//////////////////////////////////////////////////////////// -WindowHandle WindowImplWin32::getSystemHandle() const -{ - return m_handle; -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::processEvents() -{ - // We process the window events only if we own it - if (!m_callback) - { - MSG message; - while (PeekMessageW(&message, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage(&message); - DispatchMessageW(&message); - } - } -} - - -//////////////////////////////////////////////////////////// -Vector2i WindowImplWin32::getPosition() const -{ - RECT rect; - GetWindowRect(m_handle, &rect); - - return Vector2i(rect.left, rect.top); -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::setPosition(const Vector2i& position) -{ - SetWindowPos(m_handle, NULL, position.x, position.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); -} - - -//////////////////////////////////////////////////////////// -Vector2u WindowImplWin32::getSize() const -{ - RECT rect; - GetClientRect(m_handle, &rect); - - return Vector2u(rect.right - rect.left, rect.bottom - rect.top); -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::setSize(const Vector2u& size) -{ - // SetWindowPos wants the total size of the window (including title bar and borders), - // so we have to compute it - RECT rectangle = {0, 0, static_cast(size.x), static_cast(size.y)}; - AdjustWindowRect(&rectangle, GetWindowLong(m_handle, GWL_STYLE), false); - int width = rectangle.right - rectangle.left; - int height = rectangle.bottom - rectangle.top; - - SetWindowPos(m_handle, NULL, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER); -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::setTitle(const String& title) -{ - SetWindowTextW(m_handle, title.toWideString().c_str()); -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) -{ - // First destroy the previous one - if (m_icon) - DestroyIcon(m_icon); - - // Windows wants BGRA pixels: swap red and blue channels - std::vector iconPixels(width * height * 4); - for (std::size_t i = 0; i < iconPixels.size() / 4; ++i) - { - iconPixels[i * 4 + 0] = pixels[i * 4 + 2]; - iconPixels[i * 4 + 1] = pixels[i * 4 + 1]; - iconPixels[i * 4 + 2] = pixels[i * 4 + 0]; - iconPixels[i * 4 + 3] = pixels[i * 4 + 3]; - } - - // Create the icon from the pixel array - m_icon = CreateIcon(GetModuleHandleW(NULL), width, height, 1, 32, NULL, &iconPixels[0]); - - // Set it as both big and small icon of the window - if (m_icon) - { - SendMessageW(m_handle, WM_SETICON, ICON_BIG, (LPARAM)m_icon); - SendMessageW(m_handle, WM_SETICON, ICON_SMALL, (LPARAM)m_icon); - } - else - { - err() << "Failed to set the window's icon" << std::endl; - } -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::setVisible(bool visible) -{ - ShowWindow(m_handle, visible ? SW_SHOW : SW_HIDE); -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::setMouseCursorVisible(bool visible) -{ - if (visible) - m_cursor = LoadCursorW(NULL, IDC_ARROW); - else - m_cursor = NULL; - - SetCursor(m_cursor); -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::setKeyRepeatEnabled(bool enabled) -{ - m_keyRepeatEnabled = enabled; -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::registerWindowClass() -{ - WNDCLASSW windowClass; - windowClass.style = 0; - windowClass.lpfnWndProc = &WindowImplWin32::globalOnEvent; - windowClass.cbClsExtra = 0; - windowClass.cbWndExtra = 0; - windowClass.hInstance = GetModuleHandleW(NULL); - windowClass.hIcon = NULL; - windowClass.hCursor = 0; - windowClass.hbrBackground = 0; - windowClass.lpszMenuName = NULL; - windowClass.lpszClassName = className; - RegisterClassW(&windowClass); -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::switchToFullscreen(const VideoMode& mode) -{ - DEVMODE devMode; - devMode.dmSize = sizeof(devMode); - devMode.dmPelsWidth = mode.width; - devMode.dmPelsHeight = mode.height; - devMode.dmBitsPerPel = mode.bitsPerPixel; - devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; - - // Apply fullscreen mode - if (ChangeDisplaySettingsW(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) - { - err() << "Failed to change display mode for fullscreen" << std::endl; - return; - } - - // Make the window flags compatible with fullscreen mode - SetWindowLongW(m_handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - SetWindowLongW(m_handle, GWL_EXSTYLE, WS_EX_APPWINDOW); - - // Resize the window so that it fits the entire screen - SetWindowPos(m_handle, HWND_TOP, 0, 0, mode.width, mode.height, SWP_FRAMECHANGED); - ShowWindow(m_handle, SW_SHOW); - - // Set "this" as the current fullscreen window - fullscreenWindow = this; -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::cleanup() -{ - // Restore the previous video mode (in case we were running in fullscreen) - if (fullscreenWindow == this) - { - ChangeDisplaySettingsW(NULL, 0); - fullscreenWindow = NULL; - } - - // Unhide the mouse cursor (in case it was hidden) - setMouseCursorVisible(true); - - // No longer track the cursor - setTracking(false); - - // No longer capture the cursor - ReleaseCapture(); -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::setTracking(bool track) -{ - TRACKMOUSEEVENT mouseEvent; - mouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); - mouseEvent.dwFlags = track ? TME_LEAVE : TME_CANCEL; - mouseEvent.hwndTrack = m_handle; - mouseEvent.dwHoverTime = HOVER_DEFAULT; - TrackMouseEvent(&mouseEvent); -} - - -//////////////////////////////////////////////////////////// -void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) -{ - // Don't process any message until window is created - if (m_handle == NULL) - return; - - switch (message) - { - // Destroy event - case WM_DESTROY : - { - // Here we must cleanup resources ! - cleanup(); - break; - } - - // Set cursor event - case WM_SETCURSOR : - { - // The mouse has moved, if the cursor is in our window we must refresh the cursor - if (LOWORD(lParam) == HTCLIENT) - SetCursor(m_cursor); - - break; - } - - // Close event - case WM_CLOSE : - { - Event event; - event.type = Event::Closed; - pushEvent(event); - break; - } - - // Resize event - case WM_SIZE : - { - // Consider only events triggered by a maximize or a un-maximize - if (wParam != SIZE_MINIMIZED && !m_resizing && m_lastSize != getSize()) - { - // Update the last handled size - m_lastSize = getSize(); - - // Push a resize event - Event event; - event.type = Event::Resized; - event.size.width = m_lastSize.x; - event.size.height = m_lastSize.y; - pushEvent(event); - } - break; - } - - // Start resizing - case WM_ENTERSIZEMOVE : - { - m_resizing = true; - break; - } - - // Stop resizing - case WM_EXITSIZEMOVE : - { - m_resizing = false; - - // Ignore cases where the window has only been moved - if(m_lastSize != getSize()) - { - // Update the last handled size - m_lastSize = getSize(); - - // Push a resize event - Event event; - event.type = Event::Resized; - event.size.width = m_lastSize.x; - event.size.height = m_lastSize.y; - pushEvent(event); - } - break; - } - - // The system request the min/max window size and position - case WM_GETMINMAXINFO : - { - // We override the returned information to remove the default limit - // (the OS doesn't allow windows bigger than the desktop by default) - MINMAXINFO* info = reinterpret_cast(lParam); - info->ptMaxTrackSize.x = 50000; - info->ptMaxTrackSize.y = 50000; - break; - } - - // Gain focus event - case WM_SETFOCUS : - { - Event event; - event.type = Event::GainedFocus; - pushEvent(event); - break; - } - - // Lost focus event - case WM_KILLFOCUS : - { - Event event; - event.type = Event::LostFocus; - pushEvent(event); - break; - } - - // Text event - case WM_CHAR : - { - if (m_keyRepeatEnabled || ((lParam & (1 << 30)) == 0)) - { - // Get the code of the typed character - Uint32 character = static_cast(wParam); - - // Check if it is the first part of a surrogate pair, or a regular character - if ((character >= 0xD800) && (character <= 0xDBFF)) - { - // First part of a surrogate pair: store it and wait for the second one - m_surrogate = static_cast(character); - } - else - { - // Check if it is the second part of a surrogate pair, or a regular character - if ((character >= 0xDC00) && (character <= 0xDFFF)) - { - // Convert the UTF-16 surrogate pair to a single UTF-32 value - Uint16 utf16[] = {m_surrogate, static_cast(character)}; - sf::Utf16::toUtf32(utf16, utf16 + 2, &character); - m_surrogate = 0; - } - - // Send a TextEntered event - Event event; - event.type = Event::TextEntered; - event.text.unicode = character; - pushEvent(event); - } - } - break; - } - - // Keydown event - case WM_KEYDOWN : - case WM_SYSKEYDOWN : - { - if (m_keyRepeatEnabled || ((HIWORD(lParam) & KF_REPEAT) == 0)) - { - Event event; - event.type = Event::KeyPressed; - event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0; - event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0; - event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0; - event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN)); - event.key.code = virtualKeyCodeToSF(wParam, lParam); - pushEvent(event); - } - break; - } - - // Keyup event - case WM_KEYUP : - case WM_SYSKEYUP : - { - Event event; - event.type = Event::KeyReleased; - event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0; - event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0; - event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0; - event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN)); - event.key.code = virtualKeyCodeToSF(wParam, lParam); - pushEvent(event); - break; - } - - // Mouse wheel event - case WM_MOUSEWHEEL : - { - // Mouse position is in screen coordinates, convert it to window coordinates - POINT position; - position.x = static_cast(LOWORD(lParam)); - position.y = static_cast(HIWORD(lParam)); - ScreenToClient(m_handle, &position); - - Event event; - event.type = Event::MouseWheelMoved; - event.mouseWheel.delta = static_cast(HIWORD(wParam)) / 120; - event.mouseWheel.x = position.x; - event.mouseWheel.y = position.y; - pushEvent(event); - break; - } - - // Mouse left button down event - case WM_LBUTTONDOWN : - { - Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.button = Mouse::Left; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); - pushEvent(event); - break; - } - - // Mouse left button up event - case WM_LBUTTONUP : - { - Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.button = Mouse::Left; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); - pushEvent(event); - break; - } - - // Mouse right button down event - case WM_RBUTTONDOWN : - { - Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.button = Mouse::Right; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); - pushEvent(event); - break; - } - - // Mouse right button up event - case WM_RBUTTONUP : - { - Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.button = Mouse::Right; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); - pushEvent(event); - break; - } - - // Mouse wheel button down event - case WM_MBUTTONDOWN : - { - Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.button = Mouse::Middle; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); - pushEvent(event); - break; - } - - // Mouse wheel button up event - case WM_MBUTTONUP : - { - Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.button = Mouse::Middle; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); - pushEvent(event); - break; - } - - // Mouse X button down event - case WM_XBUTTONDOWN : - { - Event event; - event.type = Event::MouseButtonPressed; - event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); - pushEvent(event); - break; - } - - // Mouse X button up event - case WM_XBUTTONUP : - { - Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; - event.mouseButton.x = static_cast(LOWORD(lParam)); - event.mouseButton.y = static_cast(HIWORD(lParam)); - pushEvent(event); - break; - } - - // Mouse leave event - case WM_MOUSELEAVE : - { - // Avoid this firing a second time in case the cursor is dragged outside - if (m_mouseInside) - { - m_mouseInside = false; - - // Generate a MouseLeft event - Event event; - event.type = Event::MouseLeft; - pushEvent(event); - } - break; - } - - // Mouse move event - case WM_MOUSEMOVE : - { - // Extract the mouse local coordinates - int x = static_cast(LOWORD(lParam)); - int y = static_cast(HIWORD(lParam)); - - // Get the client area of the window - RECT area; - GetClientRect(m_handle, &area); - - // Capture the mouse in case the user wants to drag it outside - if ((wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2)) == 0) - { - // Only release the capture if we really have it - if (GetCapture() == m_handle) - ReleaseCapture(); - } - else if (GetCapture() != m_handle) - { - // Set the capture to continue receiving mouse events - SetCapture(m_handle); - } - - // If the cursor is outside the client area... - if ((x < area.left) || (x > area.right) || (y < area.top) || (y > area.bottom)) - { - // and it used to be inside, the mouse left it. - if (m_mouseInside) - { - m_mouseInside = false; - - // No longer care for the mouse leaving the window - setTracking(false); - - // Generate a MouseLeft event - Event event; - event.type = Event::MouseLeft; - pushEvent(event); - } - } - else - { - // and vice-versa - if (!m_mouseInside) - { - m_mouseInside = true; - - // Look for the mouse leaving the window - setTracking(true); - - // Generate a MouseEntered event - Event event; - event.type = Event::MouseEntered; - pushEvent(event); - } - } - - // Generate a MouseMove event - Event event; - event.type = Event::MouseMoved; - event.mouseMove.x = x; - event.mouseMove.y = y; - pushEvent(event); - break; - } - } -} - - -//////////////////////////////////////////////////////////// -Keyboard::Key WindowImplWin32::virtualKeyCodeToSF(WPARAM key, LPARAM flags) -{ - switch (key) - { - // Check the scancode to distinguish between left and right shift - case VK_SHIFT : - { - static UINT lShift = MapVirtualKeyW(VK_LSHIFT, MAPVK_VK_TO_VSC); - UINT scancode = static_cast((flags & (0xFF << 16)) >> 16); - return scancode == lShift ? Keyboard::LShift : Keyboard::RShift; - } - - // Check the "extended" flag to distinguish between left and right alt - case VK_MENU : return (HIWORD(flags) & KF_EXTENDED) ? Keyboard::RAlt : Keyboard::LAlt; - - // Check the "extended" flag to distinguish between left and right control - case VK_CONTROL : return (HIWORD(flags) & KF_EXTENDED) ? Keyboard::RControl : Keyboard::LControl; - - // Other keys are reported properly - case VK_LWIN : return Keyboard::LSystem; - case VK_RWIN : return Keyboard::RSystem; - case VK_APPS : return Keyboard::Menu; - case VK_OEM_1 : return Keyboard::SemiColon; - case VK_OEM_2 : return Keyboard::Slash; - case VK_OEM_PLUS : return Keyboard::Equal; - case VK_OEM_MINUS : return Keyboard::Dash; - case VK_OEM_4 : return Keyboard::LBracket; - case VK_OEM_6 : return Keyboard::RBracket; - case VK_OEM_COMMA : return Keyboard::Comma; - case VK_OEM_PERIOD : return Keyboard::Period; - case VK_OEM_7 : return Keyboard::Quote; - case VK_OEM_5 : return Keyboard::BackSlash; - case VK_OEM_3 : return Keyboard::Tilde; - case VK_ESCAPE : return Keyboard::Escape; - case VK_SPACE : return Keyboard::Space; - case VK_RETURN : return Keyboard::Return; - case VK_BACK : return Keyboard::BackSpace; - case VK_TAB : return Keyboard::Tab; - case VK_PRIOR : return Keyboard::PageUp; - case VK_NEXT : return Keyboard::PageDown; - case VK_END : return Keyboard::End; - case VK_HOME : return Keyboard::Home; - case VK_INSERT : return Keyboard::Insert; - case VK_DELETE : return Keyboard::Delete; - case VK_ADD : return Keyboard::Add; - case VK_SUBTRACT : return Keyboard::Subtract; - case VK_MULTIPLY : return Keyboard::Multiply; - case VK_DIVIDE : return Keyboard::Divide; - case VK_PAUSE : return Keyboard::Pause; - case VK_F1 : return Keyboard::F1; - case VK_F2 : return Keyboard::F2; - case VK_F3 : return Keyboard::F3; - case VK_F4 : return Keyboard::F4; - case VK_F5 : return Keyboard::F5; - case VK_F6 : return Keyboard::F6; - case VK_F7 : return Keyboard::F7; - case VK_F8 : return Keyboard::F8; - case VK_F9 : return Keyboard::F9; - case VK_F10 : return Keyboard::F10; - case VK_F11 : return Keyboard::F11; - case VK_F12 : return Keyboard::F12; - case VK_F13 : return Keyboard::F13; - case VK_F14 : return Keyboard::F14; - case VK_F15 : return Keyboard::F15; - case VK_LEFT : return Keyboard::Left; - case VK_RIGHT : return Keyboard::Right; - case VK_UP : return Keyboard::Up; - case VK_DOWN : return Keyboard::Down; - case VK_NUMPAD0 : return Keyboard::Numpad0; - case VK_NUMPAD1 : return Keyboard::Numpad1; - case VK_NUMPAD2 : return Keyboard::Numpad2; - case VK_NUMPAD3 : return Keyboard::Numpad3; - case VK_NUMPAD4 : return Keyboard::Numpad4; - case VK_NUMPAD5 : return Keyboard::Numpad5; - case VK_NUMPAD6 : return Keyboard::Numpad6; - case VK_NUMPAD7 : return Keyboard::Numpad7; - case VK_NUMPAD8 : return Keyboard::Numpad8; - case VK_NUMPAD9 : return Keyboard::Numpad9; - case 'A' : return Keyboard::A; - case 'Z' : return Keyboard::Z; - case 'E' : return Keyboard::E; - case 'R' : return Keyboard::R; - case 'T' : return Keyboard::T; - case 'Y' : return Keyboard::Y; - case 'U' : return Keyboard::U; - case 'I' : return Keyboard::I; - case 'O' : return Keyboard::O; - case 'P' : return Keyboard::P; - case 'Q' : return Keyboard::Q; - case 'S' : return Keyboard::S; - case 'D' : return Keyboard::D; - case 'F' : return Keyboard::F; - case 'G' : return Keyboard::G; - case 'H' : return Keyboard::H; - case 'J' : return Keyboard::J; - case 'K' : return Keyboard::K; - case 'L' : return Keyboard::L; - case 'M' : return Keyboard::M; - case 'W' : return Keyboard::W; - case 'X' : return Keyboard::X; - case 'C' : return Keyboard::C; - case 'V' : return Keyboard::V; - case 'B' : return Keyboard::B; - case 'N' : return Keyboard::N; - case '0' : return Keyboard::Num0; - case '1' : return Keyboard::Num1; - case '2' : return Keyboard::Num2; - case '3' : return Keyboard::Num3; - case '4' : return Keyboard::Num4; - case '5' : return Keyboard::Num5; - case '6' : return Keyboard::Num6; - case '7' : return Keyboard::Num7; - case '8' : return Keyboard::Num8; - case '9' : return Keyboard::Num9; - } - - return Keyboard::Unknown; -} - - -//////////////////////////////////////////////////////////// -LRESULT CALLBACK WindowImplWin32::globalOnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) -{ - // Associate handle and Window instance when the creation message is received - if (message == WM_CREATE) - { - // Get WindowImplWin32 instance (it was passed as the last argument of CreateWindow) - LONG_PTR window = (LONG_PTR)reinterpret_cast(lParam)->lpCreateParams; - - // Set as the "user data" parameter of the window - SetWindowLongPtrW(handle, GWLP_USERDATA, window); - } - - // Get the WindowImpl instance corresponding to the window handle - WindowImplWin32* window = handle ? reinterpret_cast(GetWindowLongPtr(handle, GWLP_USERDATA)) : NULL; - - // Forward the event to the appropriate function - if (window) - { - window->processEvent(message, wParam, lParam); - - if (window->m_callback) - return CallWindowProcW(reinterpret_cast(window->m_callback), handle, message, wParam, lParam); - } - - // We don't forward the WM_CLOSE message to prevent the OS from automatically destroying the window - if (message == WM_CLOSE) - return 0; - - // Don't forward the menu system command, so that pressing ALT or F10 doesn't steal the focus - if ((message == WM_SYSCOMMAND) && (wParam == SC_KEYMENU)) - return 0; - - return DefWindowProcW(handle, message, wParam, lParam); -} - -} // namespace priv - -} // namespace sf - +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#ifdef _WIN32_WINDOWS + #undef _WIN32_WINDOWS +#endif +#ifdef _WIN32_WINNT + #undef _WIN32_WINNT +#endif +#define _WIN32_WINDOWS 0x0501 +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include +#include +#include + +// MinGW lacks the definition of some Win32 constants +#ifndef XBUTTON1 + #define XBUTTON1 0x0001 +#endif +#ifndef XBUTTON2 + #define XBUTTON2 0x0002 +#endif +#ifndef MAPVK_VK_TO_VSC + #define MAPVK_VK_TO_VSC (0) +#endif + + +namespace +{ + unsigned int windowCount = 0; + const wchar_t* className = L"SFML_Window"; + sf::priv::WindowImplWin32* fullscreenWindow = NULL; + + void setProcessDpiAware() + { + // Try SetProcessDpiAwareness first + HINSTANCE shCoreDll = LoadLibrary(L"Shcore.dll"); + + if (shCoreDll) + { + enum ProcessDpiAwareness + { + ProcessDpiUnaware = 0, + ProcessSystemDpiAware = 1, + ProcessPerMonitorDpiAware = 2 + }; + + typedef HRESULT (WINAPI* SetProcessDpiAwarenessFuncType)(ProcessDpiAwareness); + SetProcessDpiAwarenessFuncType SetProcessDpiAwarenessFunc = reinterpret_cast(GetProcAddress(shCoreDll, "SetProcessDpiAwareness")); + + if (SetProcessDpiAwarenessFunc) + { + // We only check for E_INVALIDARG because we would get + // E_ACCESSDENIED if the DPI was already set previously + // and S_OK means the call was successful + if (SetProcessDpiAwarenessFunc(ProcessSystemDpiAware) == E_INVALIDARG) + { + sf::err() << "Failed to set process DPI awareness" << std::endl; + } + else + { + FreeLibrary(shCoreDll); + return; + } + } + + FreeLibrary(shCoreDll); + } + + // Fall back to SetProcessDPIAware if SetProcessDpiAwareness + // is not available on this system + HINSTANCE user32Dll = LoadLibrary(L"user32.dll"); + + if (user32Dll) + { + typedef BOOL (WINAPI* SetProcessDPIAwareFuncType)(void); + SetProcessDPIAwareFuncType SetProcessDPIAwareFunc = reinterpret_cast(GetProcAddress(user32Dll, "SetProcessDPIAware")); + + if (SetProcessDPIAwareFunc) + { + if (!SetProcessDPIAwareFunc()) + sf::err() << "Failed to set process DPI awareness" << std::endl; + } + + FreeLibrary(user32Dll); + } + } +} + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +WindowImplWin32::WindowImplWin32(WindowHandle handle) : +m_handle (handle), +m_callback (0), +m_cursor (NULL), +m_icon (NULL), +m_keyRepeatEnabled(true), +m_lastSize (0, 0), +m_resizing (false), +m_surrogate (0), +m_mouseInside (false) +{ + // Set that this process is DPI aware and can handle DPI scaling + setProcessDpiAware(); + + if (m_handle) + { + // We change the event procedure of the control (it is important to save the old one) + SetWindowLongPtrW(m_handle, GWLP_USERDATA, reinterpret_cast(this)); + m_callback = SetWindowLongPtrW(m_handle, GWLP_WNDPROC, reinterpret_cast(&WindowImplWin32::globalOnEvent)); + } +} + + +//////////////////////////////////////////////////////////// +WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& /*settings*/) : +m_handle (NULL), +m_callback (0), +m_cursor (NULL), +m_icon (NULL), +m_keyRepeatEnabled(true), +m_lastSize (mode.width, mode.height), +m_resizing (false), +m_surrogate (0), +m_mouseInside (false) +{ + // Set that this process is DPI aware and can handle DPI scaling + setProcessDpiAware(); + + // Register the window class at first call + if (windowCount == 0) + registerWindowClass(); + + // Compute position and size + HDC screenDC = GetDC(NULL); + int left = (GetDeviceCaps(screenDC, HORZRES) - static_cast(mode.width)) / 2; + int top = (GetDeviceCaps(screenDC, VERTRES) - static_cast(mode.height)) / 2; + int width = mode.width; + int height = mode.height; + ReleaseDC(NULL, screenDC); + + // Choose the window style according to the Style parameter + DWORD win32Style = WS_VISIBLE; + if (style == Style::None) + { + win32Style |= WS_POPUP; + } + else + { + if (style & Style::Titlebar) win32Style |= WS_CAPTION | WS_MINIMIZEBOX; + if (style & Style::Resize) win32Style |= WS_THICKFRAME | WS_MAXIMIZEBOX; + if (style & Style::Close) win32Style |= WS_SYSMENU; + } + + // In windowed mode, adjust width and height so that window will have the requested client area + bool fullscreen = (style & Style::Fullscreen) != 0; + if (!fullscreen) + { + RECT rectangle = {0, 0, width, height}; + AdjustWindowRect(&rectangle, win32Style, false); + width = rectangle.right - rectangle.left; + height = rectangle.bottom - rectangle.top; + } + + // Create the window + m_handle = CreateWindowW(className, title.toWideString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this); + + // By default, the OS limits the size of the window the the desktop size, + // we have to resize it after creation to apply the real size + setSize(Vector2u(mode.width, mode.height)); + + // Switch to fullscreen if requested + if (fullscreen) + switchToFullscreen(mode); + + // Increment window count + windowCount++; +} + + +//////////////////////////////////////////////////////////// +WindowImplWin32::~WindowImplWin32() +{ + // Destroy the custom icon, if any + if (m_icon) + DestroyIcon(m_icon); + + if (!m_callback) + { + // Destroy the window + if (m_handle) + DestroyWindow(m_handle); + + // Decrement the window count + windowCount--; + + // Unregister window class if we were the last window + if (windowCount == 0) + UnregisterClassW(className, GetModuleHandleW(NULL)); + } + else + { + // The window is external: remove the hook on its message callback + SetWindowLongPtrW(m_handle, GWLP_WNDPROC, m_callback); + } +} + + +//////////////////////////////////////////////////////////// +WindowHandle WindowImplWin32::getSystemHandle() const +{ + return m_handle; +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::processEvents() +{ + // We process the window events only if we own it + if (!m_callback) + { + MSG message; + while (PeekMessageW(&message, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&message); + DispatchMessageW(&message); + } + } +} + + +//////////////////////////////////////////////////////////// +Vector2i WindowImplWin32::getPosition() const +{ + RECT rect; + GetWindowRect(m_handle, &rect); + + return Vector2i(rect.left, rect.top); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setPosition(const Vector2i& position) +{ + SetWindowPos(m_handle, NULL, position.x, position.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + + +//////////////////////////////////////////////////////////// +Vector2u WindowImplWin32::getSize() const +{ + RECT rect; + GetClientRect(m_handle, &rect); + + return Vector2u(rect.right - rect.left, rect.bottom - rect.top); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setSize(const Vector2u& size) +{ + // SetWindowPos wants the total size of the window (including title bar and borders), + // so we have to compute it + RECT rectangle = {0, 0, static_cast(size.x), static_cast(size.y)}; + AdjustWindowRect(&rectangle, GetWindowLong(m_handle, GWL_STYLE), false); + int width = rectangle.right - rectangle.left; + int height = rectangle.bottom - rectangle.top; + + SetWindowPos(m_handle, NULL, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setTitle(const String& title) +{ + SetWindowTextW(m_handle, title.toWideString().c_str()); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) +{ + // First destroy the previous one + if (m_icon) + DestroyIcon(m_icon); + + // Windows wants BGRA pixels: swap red and blue channels + std::vector iconPixels(width * height * 4); + for (std::size_t i = 0; i < iconPixels.size() / 4; ++i) + { + iconPixels[i * 4 + 0] = pixels[i * 4 + 2]; + iconPixels[i * 4 + 1] = pixels[i * 4 + 1]; + iconPixels[i * 4 + 2] = pixels[i * 4 + 0]; + iconPixels[i * 4 + 3] = pixels[i * 4 + 3]; + } + + // Create the icon from the pixel array + m_icon = CreateIcon(GetModuleHandleW(NULL), width, height, 1, 32, NULL, &iconPixels[0]); + + // Set it as both big and small icon of the window + if (m_icon) + { + SendMessageW(m_handle, WM_SETICON, ICON_BIG, (LPARAM)m_icon); + SendMessageW(m_handle, WM_SETICON, ICON_SMALL, (LPARAM)m_icon); + } + else + { + err() << "Failed to set the window's icon" << std::endl; + } +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setVisible(bool visible) +{ + ShowWindow(m_handle, visible ? SW_SHOW : SW_HIDE); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setMouseCursorVisible(bool visible) +{ + if (visible) + m_cursor = LoadCursorW(NULL, IDC_ARROW); + else + m_cursor = NULL; + + SetCursor(m_cursor); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setKeyRepeatEnabled(bool enabled) +{ + m_keyRepeatEnabled = enabled; +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::registerWindowClass() +{ + WNDCLASSW windowClass; + windowClass.style = 0; + windowClass.lpfnWndProc = &WindowImplWin32::globalOnEvent; + windowClass.cbClsExtra = 0; + windowClass.cbWndExtra = 0; + windowClass.hInstance = GetModuleHandleW(NULL); + windowClass.hIcon = NULL; + windowClass.hCursor = 0; + windowClass.hbrBackground = 0; + windowClass.lpszMenuName = NULL; + windowClass.lpszClassName = className; + RegisterClassW(&windowClass); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::switchToFullscreen(const VideoMode& mode) +{ + DEVMODE devMode; + devMode.dmSize = sizeof(devMode); + devMode.dmPelsWidth = mode.width; + devMode.dmPelsHeight = mode.height; + devMode.dmBitsPerPel = mode.bitsPerPixel; + devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + + // Apply fullscreen mode + if (ChangeDisplaySettingsW(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + { + err() << "Failed to change display mode for fullscreen" << std::endl; + return; + } + + // Make the window flags compatible with fullscreen mode + SetWindowLongW(m_handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + SetWindowLongW(m_handle, GWL_EXSTYLE, WS_EX_APPWINDOW); + + // Resize the window so that it fits the entire screen + SetWindowPos(m_handle, HWND_TOP, 0, 0, mode.width, mode.height, SWP_FRAMECHANGED); + ShowWindow(m_handle, SW_SHOW); + + // Set "this" as the current fullscreen window + fullscreenWindow = this; +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::cleanup() +{ + // Restore the previous video mode (in case we were running in fullscreen) + if (fullscreenWindow == this) + { + ChangeDisplaySettingsW(NULL, 0); + fullscreenWindow = NULL; + } + + // Unhide the mouse cursor (in case it was hidden) + setMouseCursorVisible(true); + + // No longer track the cursor + setTracking(false); + + // No longer capture the cursor + ReleaseCapture(); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setTracking(bool track) +{ + TRACKMOUSEEVENT mouseEvent; + mouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); + mouseEvent.dwFlags = track ? TME_LEAVE : TME_CANCEL; + mouseEvent.hwndTrack = m_handle; + mouseEvent.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&mouseEvent); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) +{ + // Don't process any message until window is created + if (m_handle == NULL) + return; + + switch (message) + { + // Destroy event + case WM_DESTROY: + { + // Here we must cleanup resources ! + cleanup(); + break; + } + + // Set cursor event + case WM_SETCURSOR: + { + // The mouse has moved, if the cursor is in our window we must refresh the cursor + if (LOWORD(lParam) == HTCLIENT) + SetCursor(m_cursor); + + break; + } + + // Close event + case WM_CLOSE: + { + Event event; + event.type = Event::Closed; + pushEvent(event); + break; + } + + // Resize event + case WM_SIZE: + { + // Consider only events triggered by a maximize or a un-maximize + if (wParam != SIZE_MINIMIZED && !m_resizing && m_lastSize != getSize()) + { + // Update the last handled size + m_lastSize = getSize(); + + // Push a resize event + Event event; + event.type = Event::Resized; + event.size.width = m_lastSize.x; + event.size.height = m_lastSize.y; + pushEvent(event); + } + break; + } + + // Start resizing + case WM_ENTERSIZEMOVE: + { + m_resizing = true; + break; + } + + // Stop resizing + case WM_EXITSIZEMOVE: + { + m_resizing = false; + + // Ignore cases where the window has only been moved + if(m_lastSize != getSize()) + { + // Update the last handled size + m_lastSize = getSize(); + + // Push a resize event + Event event; + event.type = Event::Resized; + event.size.width = m_lastSize.x; + event.size.height = m_lastSize.y; + pushEvent(event); + } + break; + } + + // The system request the min/max window size and position + case WM_GETMINMAXINFO: + { + // We override the returned information to remove the default limit + // (the OS doesn't allow windows bigger than the desktop by default) + MINMAXINFO* info = reinterpret_cast(lParam); + info->ptMaxTrackSize.x = 50000; + info->ptMaxTrackSize.y = 50000; + break; + } + + // Gain focus event + case WM_SETFOCUS: + { + Event event; + event.type = Event::GainedFocus; + pushEvent(event); + break; + } + + // Lost focus event + case WM_KILLFOCUS: + { + Event event; + event.type = Event::LostFocus; + pushEvent(event); + break; + } + + // Text event + case WM_CHAR: + { + if (m_keyRepeatEnabled || ((lParam & (1 << 30)) == 0)) + { + // Get the code of the typed character + Uint32 character = static_cast(wParam); + + // Check if it is the first part of a surrogate pair, or a regular character + if ((character >= 0xD800) && (character <= 0xDBFF)) + { + // First part of a surrogate pair: store it and wait for the second one + m_surrogate = static_cast(character); + } + else + { + // Check if it is the second part of a surrogate pair, or a regular character + if ((character >= 0xDC00) && (character <= 0xDFFF)) + { + // Convert the UTF-16 surrogate pair to a single UTF-32 value + Uint16 utf16[] = {m_surrogate, static_cast(character)}; + sf::Utf16::toUtf32(utf16, utf16 + 2, &character); + m_surrogate = 0; + } + + // Send a TextEntered event + Event event; + event.type = Event::TextEntered; + event.text.unicode = character; + pushEvent(event); + } + } + break; + } + + // Keydown event + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + { + if (m_keyRepeatEnabled || ((HIWORD(lParam) & KF_REPEAT) == 0)) + { + Event event; + event.type = Event::KeyPressed; + event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0; + event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0; + event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0; + event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN)); + event.key.code = virtualKeyCodeToSF(wParam, lParam); + pushEvent(event); + } + break; + } + + // Keyup event + case WM_KEYUP: + case WM_SYSKEYUP: + { + Event event; + event.type = Event::KeyReleased; + event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0; + event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0; + event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0; + event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN)); + event.key.code = virtualKeyCodeToSF(wParam, lParam); + pushEvent(event); + break; + } + + // Mouse wheel event + case WM_MOUSEWHEEL: + { + // Mouse position is in screen coordinates, convert it to window coordinates + POINT position; + position.x = static_cast(LOWORD(lParam)); + position.y = static_cast(HIWORD(lParam)); + ScreenToClient(m_handle, &position); + + Event event; + event.type = Event::MouseWheelMoved; + event.mouseWheel.delta = static_cast(HIWORD(wParam)) / 120; + event.mouseWheel.x = position.x; + event.mouseWheel.y = position.y; + pushEvent(event); + break; + } + + // Mouse left button down event + case WM_LBUTTONDOWN: + { + Event event; + event.type = Event::MouseButtonPressed; + event.mouseButton.button = Mouse::Left; + event.mouseButton.x = static_cast(LOWORD(lParam)); + event.mouseButton.y = static_cast(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse left button up event + case WM_LBUTTONUP: + { + Event event; + event.type = Event::MouseButtonReleased; + event.mouseButton.button = Mouse::Left; + event.mouseButton.x = static_cast(LOWORD(lParam)); + event.mouseButton.y = static_cast(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse right button down event + case WM_RBUTTONDOWN: + { + Event event; + event.type = Event::MouseButtonPressed; + event.mouseButton.button = Mouse::Right; + event.mouseButton.x = static_cast(LOWORD(lParam)); + event.mouseButton.y = static_cast(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse right button up event + case WM_RBUTTONUP: + { + Event event; + event.type = Event::MouseButtonReleased; + event.mouseButton.button = Mouse::Right; + event.mouseButton.x = static_cast(LOWORD(lParam)); + event.mouseButton.y = static_cast(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse wheel button down event + case WM_MBUTTONDOWN: + { + Event event; + event.type = Event::MouseButtonPressed; + event.mouseButton.button = Mouse::Middle; + event.mouseButton.x = static_cast(LOWORD(lParam)); + event.mouseButton.y = static_cast(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse wheel button up event + case WM_MBUTTONUP: + { + Event event; + event.type = Event::MouseButtonReleased; + event.mouseButton.button = Mouse::Middle; + event.mouseButton.x = static_cast(LOWORD(lParam)); + event.mouseButton.y = static_cast(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse X button down event + case WM_XBUTTONDOWN: + { + Event event; + event.type = Event::MouseButtonPressed; + event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; + event.mouseButton.x = static_cast(LOWORD(lParam)); + event.mouseButton.y = static_cast(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse X button up event + case WM_XBUTTONUP: + { + Event event; + event.type = Event::MouseButtonReleased; + event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; + event.mouseButton.x = static_cast(LOWORD(lParam)); + event.mouseButton.y = static_cast(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse leave event + case WM_MOUSELEAVE: + { + // Avoid this firing a second time in case the cursor is dragged outside + if (m_mouseInside) + { + m_mouseInside = false; + + // Generate a MouseLeft event + Event event; + event.type = Event::MouseLeft; + pushEvent(event); + } + break; + } + + // Mouse move event + case WM_MOUSEMOVE: + { + // Extract the mouse local coordinates + int x = static_cast(LOWORD(lParam)); + int y = static_cast(HIWORD(lParam)); + + // Get the client area of the window + RECT area; + GetClientRect(m_handle, &area); + + // Capture the mouse in case the user wants to drag it outside + if ((wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2)) == 0) + { + // Only release the capture if we really have it + if (GetCapture() == m_handle) + ReleaseCapture(); + } + else if (GetCapture() != m_handle) + { + // Set the capture to continue receiving mouse events + SetCapture(m_handle); + } + + // If the cursor is outside the client area... + if ((x < area.left) || (x > area.right) || (y < area.top) || (y > area.bottom)) + { + // and it used to be inside, the mouse left it. + if (m_mouseInside) + { + m_mouseInside = false; + + // No longer care for the mouse leaving the window + setTracking(false); + + // Generate a MouseLeft event + Event event; + event.type = Event::MouseLeft; + pushEvent(event); + } + } + else + { + // and vice-versa + if (!m_mouseInside) + { + m_mouseInside = true; + + // Look for the mouse leaving the window + setTracking(true); + + // Generate a MouseEntered event + Event event; + event.type = Event::MouseEntered; + pushEvent(event); + } + } + + // Generate a MouseMove event + Event event; + event.type = Event::MouseMoved; + event.mouseMove.x = x; + event.mouseMove.y = y; + pushEvent(event); + break; + } + } +} + + +//////////////////////////////////////////////////////////// +Keyboard::Key WindowImplWin32::virtualKeyCodeToSF(WPARAM key, LPARAM flags) +{ + switch (key) + { + // Check the scancode to distinguish between left and right shift + case VK_SHIFT: + { + static UINT lShift = MapVirtualKeyW(VK_LSHIFT, MAPVK_VK_TO_VSC); + UINT scancode = static_cast((flags & (0xFF << 16)) >> 16); + return scancode == lShift ? Keyboard::LShift : Keyboard::RShift; + } + + // Check the "extended" flag to distinguish between left and right alt + case VK_MENU : return (HIWORD(flags) & KF_EXTENDED) ? Keyboard::RAlt : Keyboard::LAlt; + + // Check the "extended" flag to distinguish between left and right control + case VK_CONTROL : return (HIWORD(flags) & KF_EXTENDED) ? Keyboard::RControl : Keyboard::LControl; + + // Other keys are reported properly + case VK_LWIN: return Keyboard::LSystem; + case VK_RWIN: return Keyboard::RSystem; + case VK_APPS: return Keyboard::Menu; + case VK_OEM_1: return Keyboard::SemiColon; + case VK_OEM_2: return Keyboard::Slash; + case VK_OEM_PLUS: return Keyboard::Equal; + case VK_OEM_MINUS: return Keyboard::Dash; + case VK_OEM_4: return Keyboard::LBracket; + case VK_OEM_6: return Keyboard::RBracket; + case VK_OEM_COMMA: return Keyboard::Comma; + case VK_OEM_PERIOD: return Keyboard::Period; + case VK_OEM_7: return Keyboard::Quote; + case VK_OEM_5: return Keyboard::BackSlash; + case VK_OEM_3: return Keyboard::Tilde; + case VK_ESCAPE: return Keyboard::Escape; + case VK_SPACE: return Keyboard::Space; + case VK_RETURN: return Keyboard::Return; + case VK_BACK: return Keyboard::BackSpace; + case VK_TAB: return Keyboard::Tab; + case VK_PRIOR: return Keyboard::PageUp; + case VK_NEXT: return Keyboard::PageDown; + case VK_END: return Keyboard::End; + case VK_HOME: return Keyboard::Home; + case VK_INSERT: return Keyboard::Insert; + case VK_DELETE: return Keyboard::Delete; + case VK_ADD: return Keyboard::Add; + case VK_SUBTRACT: return Keyboard::Subtract; + case VK_MULTIPLY: return Keyboard::Multiply; + case VK_DIVIDE: return Keyboard::Divide; + case VK_PAUSE: return Keyboard::Pause; + case VK_F1: return Keyboard::F1; + case VK_F2: return Keyboard::F2; + case VK_F3: return Keyboard::F3; + case VK_F4: return Keyboard::F4; + case VK_F5: return Keyboard::F5; + case VK_F6: return Keyboard::F6; + case VK_F7: return Keyboard::F7; + case VK_F8: return Keyboard::F8; + case VK_F9: return Keyboard::F9; + case VK_F10: return Keyboard::F10; + case VK_F11: return Keyboard::F11; + case VK_F12: return Keyboard::F12; + case VK_F13: return Keyboard::F13; + case VK_F14: return Keyboard::F14; + case VK_F15: return Keyboard::F15; + case VK_LEFT: return Keyboard::Left; + case VK_RIGHT: return Keyboard::Right; + case VK_UP: return Keyboard::Up; + case VK_DOWN: return Keyboard::Down; + case VK_NUMPAD0: return Keyboard::Numpad0; + case VK_NUMPAD1: return Keyboard::Numpad1; + case VK_NUMPAD2: return Keyboard::Numpad2; + case VK_NUMPAD3: return Keyboard::Numpad3; + case VK_NUMPAD4: return Keyboard::Numpad4; + case VK_NUMPAD5: return Keyboard::Numpad5; + case VK_NUMPAD6: return Keyboard::Numpad6; + case VK_NUMPAD7: return Keyboard::Numpad7; + case VK_NUMPAD8: return Keyboard::Numpad8; + case VK_NUMPAD9: return Keyboard::Numpad9; + case 'A': return Keyboard::A; + case 'Z': return Keyboard::Z; + case 'E': return Keyboard::E; + case 'R': return Keyboard::R; + case 'T': return Keyboard::T; + case 'Y': return Keyboard::Y; + case 'U': return Keyboard::U; + case 'I': return Keyboard::I; + case 'O': return Keyboard::O; + case 'P': return Keyboard::P; + case 'Q': return Keyboard::Q; + case 'S': return Keyboard::S; + case 'D': return Keyboard::D; + case 'F': return Keyboard::F; + case 'G': return Keyboard::G; + case 'H': return Keyboard::H; + case 'J': return Keyboard::J; + case 'K': return Keyboard::K; + case 'L': return Keyboard::L; + case 'M': return Keyboard::M; + case 'W': return Keyboard::W; + case 'X': return Keyboard::X; + case 'C': return Keyboard::C; + case 'V': return Keyboard::V; + case 'B': return Keyboard::B; + case 'N': return Keyboard::N; + case '0': return Keyboard::Num0; + case '1': return Keyboard::Num1; + case '2': return Keyboard::Num2; + case '3': return Keyboard::Num3; + case '4': return Keyboard::Num4; + case '5': return Keyboard::Num5; + case '6': return Keyboard::Num6; + case '7': return Keyboard::Num7; + case '8': return Keyboard::Num8; + case '9': return Keyboard::Num9; + } + + return Keyboard::Unknown; +} + + +//////////////////////////////////////////////////////////// +LRESULT CALLBACK WindowImplWin32::globalOnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) +{ + // Associate handle and Window instance when the creation message is received + if (message == WM_CREATE) + { + // Get WindowImplWin32 instance (it was passed as the last argument of CreateWindow) + LONG_PTR window = (LONG_PTR)reinterpret_cast(lParam)->lpCreateParams; + + // Set as the "user data" parameter of the window + SetWindowLongPtrW(handle, GWLP_USERDATA, window); + } + + // Get the WindowImpl instance corresponding to the window handle + WindowImplWin32* window = handle ? reinterpret_cast(GetWindowLongPtr(handle, GWLP_USERDATA)) : NULL; + + // Forward the event to the appropriate function + if (window) + { + window->processEvent(message, wParam, lParam); + + if (window->m_callback) + return CallWindowProcW(reinterpret_cast(window->m_callback), handle, message, wParam, lParam); + } + + // We don't forward the WM_CLOSE message to prevent the OS from automatically destroying the window + if (message == WM_CLOSE) + return 0; + + // Don't forward the menu system command, so that pressing ALT or F10 doesn't steal the focus + if ((message == WM_SYSCOMMAND) && (wParam == SC_KEYMENU)) + return 0; + + return DefWindowProcW(handle, message, wParam, lParam); +} + +} // namespace priv + +} // namespace sf + diff --git a/src/SFML/Window/Win32/WindowImplWin32.hpp b/src/SFML/Window/Win32/WindowImplWin32.hpp index d59d24b6..3678d79e 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.hpp +++ b/src/SFML/Window/Win32/WindowImplWin32.hpp @@ -1,246 +1,246 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_WINDOWIMPLWIN32_HPP -#define SFML_WINDOWIMPLWIN32_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Windows implementation of WindowImpl -/// -//////////////////////////////////////////////////////////// -class WindowImplWin32 : public WindowImpl -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Construct the window implementation from an existing control - /// - /// \param handle Platform-specific handle of the control - /// - //////////////////////////////////////////////////////////// - WindowImplWin32(WindowHandle handle); - - //////////////////////////////////////////////////////////// - /// \brief Create the window implementation - /// - /// \param mode Video mode to use - /// \param title Title of the window - /// \param style Window style - /// \param settings Additional settings for the underlying OpenGL context - /// - //////////////////////////////////////////////////////////// - WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~WindowImplWin32(); - - //////////////////////////////////////////////////////////// - /// \brief Get the OS-specific handle of the window - /// - /// \return Handle of the window - /// - //////////////////////////////////////////////////////////// - virtual WindowHandle getSystemHandle() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the position of the window - /// - /// \return Position of the window, in pixels - /// - //////////////////////////////////////////////////////////// - virtual Vector2i getPosition() const; - - //////////////////////////////////////////////////////////// - /// \brief Change the position of the window on screen - /// - /// \param position New position of the window, in pixels - /// - //////////////////////////////////////////////////////////// - virtual void setPosition(const Vector2i& position); - - //////////////////////////////////////////////////////////// - /// \brief Get the client size of the window - /// - /// \return Size of the window, in pixels - /// - //////////////////////////////////////////////////////////// - virtual Vector2u getSize() const; - - //////////////////////////////////////////////////////////// - /// \brief Change the size of the rendering region of the window - /// - /// \param size New size, in pixels - /// - //////////////////////////////////////////////////////////// - virtual void setSize(const Vector2u& size); - - //////////////////////////////////////////////////////////// - /// \brief Change the title of the window - /// - /// \param title New title - /// - //////////////////////////////////////////////////////////// - virtual void setTitle(const String& title); - - //////////////////////////////////////////////////////////// - /// \brief Change the window's icon - /// - /// \param width Icon's width, in pixels - /// \param height Icon's height, in pixels - /// \param pixels Pointer to the pixels in memory, format must be RGBA 32 bits - /// - //////////////////////////////////////////////////////////// - virtual void setIcon(unsigned int width, unsigned int height, const Uint8* pixels); - - //////////////////////////////////////////////////////////// - /// \brief Show or hide the window - /// - /// \param visible True to show, false to hide - /// - //////////////////////////////////////////////////////////// - virtual void setVisible(bool visible); - - //////////////////////////////////////////////////////////// - /// \brief Show or hide the mouse cursor - /// - /// \param visible True to show, false to hide - /// - //////////////////////////////////////////////////////////// - virtual void setMouseCursorVisible(bool visible); - - //////////////////////////////////////////////////////////// - /// \brief Enable or disable automatic key-repeat - /// - /// \param enabled True to enable, false to disable - /// - //////////////////////////////////////////////////////////// - virtual void setKeyRepeatEnabled(bool enabled); - -protected: - - //////////////////////////////////////////////////////////// - /// \brief Process incoming events from the operating system - /// - //////////////////////////////////////////////////////////// - virtual void processEvents(); - -private : - - //////////////////////////////////////////////////////////// - /// Register the window class - /// - //////////////////////////////////////////////////////////// - void registerWindowClass(); - - //////////////////////////////////////////////////////////// - /// \brief Switch to fullscreen mode - /// - /// \param mode Video mode to switch to - /// - //////////////////////////////////////////////////////////// - void switchToFullscreen(const VideoMode& mode); - - //////////////////////////////////////////////////////////// - /// \brief Free all the graphical resources attached to the window - /// - //////////////////////////////////////////////////////////// - void cleanup(); - - //////////////////////////////////////////////////////////// - /// \brief Process a Win32 event - /// - /// \param message Message to process - /// \param wParam First parameter of the event - /// \param lParam Second parameter of the event - /// - //////////////////////////////////////////////////////////// - void processEvent(UINT message, WPARAM wParam, LPARAM lParam); - - //////////////////////////////////////////////////////////// - /// \brief Enables or disables tracking for the mouse cursor leaving the window - /// - /// \param track True to enable, false to disable - /// - //////////////////////////////////////////////////////////// - void setTracking(bool track); - - //////////////////////////////////////////////////////////// - /// \brief Convert a Win32 virtual key code to a SFML key code - /// - /// \param key Virtual key code to convert - /// \param flags Additional flags - /// - /// \return SFML key code corresponding to the key - /// - //////////////////////////////////////////////////////////// - static Keyboard::Key virtualKeyCodeToSF(WPARAM key, LPARAM flags); - - //////////////////////////////////////////////////////////// - /// \brief Function called whenever one of our windows receives a message - /// - /// \param handle Win32 handle of the window - /// \param message Message received - /// \param wParam First parameter of the message - /// \param lParam Second parameter of the message - /// - /// \return True to discard the event after it has been processed - /// - //////////////////////////////////////////////////////////// - static LRESULT CALLBACK globalOnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - HWND m_handle; ///< Win32 handle of the window - LONG_PTR m_callback; ///< Stores the original event callback function of the control - HCURSOR m_cursor; ///< The system cursor to display into the window - HICON m_icon; ///< Custom icon assigned to the window - bool m_keyRepeatEnabled; ///< Automatic key-repeat state for keydown events - Vector2u m_lastSize; ///< The last handled size of the window - bool m_resizing; ///< Is the window being resized? - Uint16 m_surrogate; ///< First half of the surrogate pair, in case we're receiving a Unicode character in two events - bool m_mouseInside; ///< Mouse is inside the window? -}; - -} // namespace priv - -} // namespace sf - -#endif // SFML_WINDOWIMPLWIN32_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WINDOWIMPLWIN32_HPP +#define SFML_WINDOWIMPLWIN32_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows implementation of WindowImpl +/// +//////////////////////////////////////////////////////////// +class WindowImplWin32 : public WindowImpl +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Construct the window implementation from an existing control + /// + /// \param handle Platform-specific handle of the control + /// + //////////////////////////////////////////////////////////// + WindowImplWin32(WindowHandle handle); + + //////////////////////////////////////////////////////////// + /// \brief Create the window implementation + /// + /// \param mode Video mode to use + /// \param title Title of the window + /// \param style Window style + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~WindowImplWin32(); + + //////////////////////////////////////////////////////////// + /// \brief Get the OS-specific handle of the window + /// + /// \return Handle of the window + /// + //////////////////////////////////////////////////////////// + virtual WindowHandle getSystemHandle() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the position of the window + /// + /// \return Position of the window, in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2i getPosition() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the position of the window on screen + /// + /// \param position New position of the window, in pixels + /// + //////////////////////////////////////////////////////////// + virtual void setPosition(const Vector2i& position); + + //////////////////////////////////////////////////////////// + /// \brief Get the client size of the window + /// + /// \return Size of the window, in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the size of the rendering region of the window + /// + /// \param size New size, in pixels + /// + //////////////////////////////////////////////////////////// + virtual void setSize(const Vector2u& size); + + //////////////////////////////////////////////////////////// + /// \brief Change the title of the window + /// + /// \param title New title + /// + //////////////////////////////////////////////////////////// + virtual void setTitle(const String& title); + + //////////////////////////////////////////////////////////// + /// \brief Change the window's icon + /// + /// \param width Icon's width, in pixels + /// \param height Icon's height, in pixels + /// \param pixels Pointer to the pixels in memory, format must be RGBA 32 bits + /// + //////////////////////////////////////////////////////////// + virtual void setIcon(unsigned int width, unsigned int height, const Uint8* pixels); + + //////////////////////////////////////////////////////////// + /// \brief Show or hide the window + /// + /// \param visible True to show, false to hide + /// + //////////////////////////////////////////////////////////// + virtual void setVisible(bool visible); + + //////////////////////////////////////////////////////////// + /// \brief Show or hide the mouse cursor + /// + /// \param visible True to show, false to hide + /// + //////////////////////////////////////////////////////////// + virtual void setMouseCursorVisible(bool visible); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable automatic key-repeat + /// + /// \param enabled True to enable, false to disable + /// + //////////////////////////////////////////////////////////// + virtual void setKeyRepeatEnabled(bool enabled); + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Process incoming events from the operating system + /// + //////////////////////////////////////////////////////////// + virtual void processEvents(); + +private: + + //////////////////////////////////////////////////////////// + /// Register the window class + /// + //////////////////////////////////////////////////////////// + void registerWindowClass(); + + //////////////////////////////////////////////////////////// + /// \brief Switch to fullscreen mode + /// + /// \param mode Video mode to switch to + /// + //////////////////////////////////////////////////////////// + void switchToFullscreen(const VideoMode& mode); + + //////////////////////////////////////////////////////////// + /// \brief Free all the graphical resources attached to the window + /// + //////////////////////////////////////////////////////////// + void cleanup(); + + //////////////////////////////////////////////////////////// + /// \brief Process a Win32 event + /// + /// \param message Message to process + /// \param wParam First parameter of the event + /// \param lParam Second parameter of the event + /// + //////////////////////////////////////////////////////////// + void processEvent(UINT message, WPARAM wParam, LPARAM lParam); + + //////////////////////////////////////////////////////////// + /// \brief Enables or disables tracking for the mouse cursor leaving the window + /// + /// \param track True to enable, false to disable + /// + //////////////////////////////////////////////////////////// + void setTracking(bool track); + + //////////////////////////////////////////////////////////// + /// \brief Convert a Win32 virtual key code to a SFML key code + /// + /// \param key Virtual key code to convert + /// \param flags Additional flags + /// + /// \return SFML key code corresponding to the key + /// + //////////////////////////////////////////////////////////// + static Keyboard::Key virtualKeyCodeToSF(WPARAM key, LPARAM flags); + + //////////////////////////////////////////////////////////// + /// \brief Function called whenever one of our windows receives a message + /// + /// \param handle Win32 handle of the window + /// \param message Message received + /// \param wParam First parameter of the message + /// \param lParam Second parameter of the message + /// + /// \return True to discard the event after it has been processed + /// + //////////////////////////////////////////////////////////// + static LRESULT CALLBACK globalOnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + HWND m_handle; ///< Win32 handle of the window + LONG_PTR m_callback; ///< Stores the original event callback function of the control + HCURSOR m_cursor; ///< The system cursor to display into the window + HICON m_icon; ///< Custom icon assigned to the window + bool m_keyRepeatEnabled; ///< Automatic key-repeat state for keydown events + Vector2u m_lastSize; ///< The last handled size of the window + bool m_resizing; ///< Is the window being resized? + Uint16 m_surrogate; ///< First half of the surrogate pair, in case we're receiving a Unicode character in two events + bool m_mouseInside; ///< Mouse is inside the window? +}; + +} // namespace priv + +} // namespace sf + +#endif // SFML_WINDOWIMPLWIN32_HPP diff --git a/src/SFML/Window/Window.cpp b/src/SFML/Window/Window.cpp index cd447b12..397cbbf2 100644 --- a/src/SFML/Window/Window.cpp +++ b/src/SFML/Window/Window.cpp @@ -1,417 +1,417 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace -{ - const sf::Window* fullscreenWindow = NULL; -} - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Window::Window() : -m_impl (NULL), -m_context (NULL), -m_frameTimeLimit(Time::Zero), -m_size (0, 0) -{ - -} - - -//////////////////////////////////////////////////////////// -Window::Window(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) : -m_impl (NULL), -m_context (NULL), -m_frameTimeLimit(Time::Zero), -m_size (0, 0) -{ - create(mode, title, style, settings); -} - - -//////////////////////////////////////////////////////////// -Window::Window(WindowHandle handle, const ContextSettings& settings) : -m_impl (NULL), -m_context (NULL), -m_frameTimeLimit(Time::Zero), -m_size (0, 0) -{ - create(handle, settings); -} - - -//////////////////////////////////////////////////////////// -Window::~Window() -{ - close(); -} - - -//////////////////////////////////////////////////////////// -void Window::create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) -{ - // Destroy the previous window implementation - close(); - - // Fullscreen style requires some tests - if (style & Style::Fullscreen) - { - // Make sure there's not already a fullscreen window (only one is allowed) - if (fullscreenWindow) - { - err() << "Creating two fullscreen windows is not allowed, switching to windowed mode" << std::endl; - style &= ~Style::Fullscreen; - } - else - { - // Make sure that the chosen video mode is compatible - if (!mode.isValid()) - { - err() << "The requested video mode is not available, switching to a valid mode" << std::endl; - mode = VideoMode::getFullscreenModes()[0]; - } - - // Update the fullscreen window - fullscreenWindow = this; - } - } - - // Check validity of style according to the underlying platform - #if defined(SFML_SYSTEM_IOS) || defined(SFML_SYSTEM_ANDROID) - if (style & Style::Fullscreen) - style &= ~Style::Titlebar; - else - style |= Style::Titlebar; - #else - if ((style & Style::Close) || (style & Style::Resize)) - style |= Style::Titlebar; - #endif - - // Recreate the window implementation - m_impl = priv::WindowImpl::create(mode, title, style, settings); - - // Recreate the context - m_context = priv::GlContext::create(settings, m_impl, mode.bitsPerPixel); - - // Perform common initializations - initialize(); -} - - -//////////////////////////////////////////////////////////// -void Window::create(WindowHandle handle, const ContextSettings& settings) -{ - // Destroy the previous window implementation - close(); - - // Recreate the window implementation - m_impl = priv::WindowImpl::create(handle); - - // Recreate the context - m_context = priv::GlContext::create(settings, m_impl, VideoMode::getDesktopMode().bitsPerPixel); - - // Perform common initializations - initialize(); -} - - -//////////////////////////////////////////////////////////// -void Window::close() -{ - // Delete the context - delete m_context; - m_context = NULL; - - // Delete the window implementation - delete m_impl; - m_impl = NULL; - - // Update the fullscreen window - if (this == fullscreenWindow) - fullscreenWindow = NULL; -} - - -//////////////////////////////////////////////////////////// -bool Window::isOpen() const -{ - return m_impl != NULL; -} - - -//////////////////////////////////////////////////////////// -const ContextSettings& Window::getSettings() const -{ - static const ContextSettings empty(0, 0, 0); - - return m_context ? m_context->getSettings() : empty; -} - - -//////////////////////////////////////////////////////////// -bool Window::pollEvent(Event& event) -{ - if (m_impl && m_impl->popEvent(event, false)) - { - return filterEvent(event); - } - else - { - return false; - } -} - - -//////////////////////////////////////////////////////////// -bool Window::waitEvent(Event& event) -{ - if (m_impl && m_impl->popEvent(event, true)) - { - return filterEvent(event); - } - else - { - return false; - } -} - - -//////////////////////////////////////////////////////////// -Vector2i Window::getPosition() const -{ - return m_impl ? m_impl->getPosition() : Vector2i(); -} - - -//////////////////////////////////////////////////////////// -void Window::setPosition(const Vector2i& position) -{ - if (m_impl) - m_impl->setPosition(position); -} - - -//////////////////////////////////////////////////////////// -Vector2u Window::getSize() const -{ - return m_size; -} - - -//////////////////////////////////////////////////////////// -void Window::setSize(const Vector2u& size) -{ - if (m_impl) - { - m_impl->setSize(size); - - // Cache the new size - m_size.x = size.x; - m_size.y = size.y; - - // Notify the derived class - onResize(); - } -} - - -//////////////////////////////////////////////////////////// -void Window::setTitle(const String& title) -{ - if (m_impl) - m_impl->setTitle(title); -} - - -//////////////////////////////////////////////////////////// -void Window::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) -{ - if (m_impl) - m_impl->setIcon(width, height, pixels); -} - - -//////////////////////////////////////////////////////////// -void Window::setVisible(bool visible) -{ - if (m_impl) - m_impl->setVisible(visible); -} - - -//////////////////////////////////////////////////////////// -void Window::setVerticalSyncEnabled(bool enabled) -{ - if (setActive()) - m_context->setVerticalSyncEnabled(enabled); -} - - -//////////////////////////////////////////////////////////// -void Window::setMouseCursorVisible(bool visible) -{ - if (m_impl) - m_impl->setMouseCursorVisible(visible); -} - - -//////////////////////////////////////////////////////////// -void Window::setKeyRepeatEnabled(bool enabled) -{ - if (m_impl) - m_impl->setKeyRepeatEnabled(enabled); -} - - -//////////////////////////////////////////////////////////// -void Window::setFramerateLimit(unsigned int limit) -{ - if (limit > 0) - m_frameTimeLimit = seconds(1.f / limit); - else - m_frameTimeLimit = Time::Zero; -} - - -//////////////////////////////////////////////////////////// -void Window::setJoystickThreshold(float threshold) -{ - if (m_impl) - m_impl->setJoystickThreshold(threshold); -} - - -//////////////////////////////////////////////////////////// -bool Window::setActive(bool active) const -{ - if (m_context) - { - if (m_context->setActive(active)) - { - return true; - } - else - { - err() << "Failed to activate the window's context" << std::endl; - return false; - } - } - else - { - return false; - } -} - - -//////////////////////////////////////////////////////////// -void Window::display() -{ - // Display the backbuffer on screen - if (setActive()) - m_context->display(); - - // Limit the framerate if needed - if (m_frameTimeLimit != Time::Zero) - { - sleep(m_frameTimeLimit - m_clock.getElapsedTime()); - m_clock.restart(); - } -} - - -//////////////////////////////////////////////////////////// -WindowHandle Window::getSystemHandle() const -{ - return m_impl ? m_impl->getSystemHandle() : 0; -} - - -//////////////////////////////////////////////////////////// -void Window::onCreate() -{ - // Nothing by default -} - - -//////////////////////////////////////////////////////////// -void Window::onResize() -{ - // Nothing by default -} - - -//////////////////////////////////////////////////////////// -bool Window::filterEvent(const Event& event) -{ - // Notify resize events to the derived class - if (event.type == Event::Resized) - { - // Cache the new size - m_size.x = event.size.width; - m_size.y = event.size.height; - - // Notify the derived class - onResize(); - } - - return true; -} - - -//////////////////////////////////////////////////////////// -void Window::initialize() -{ - // Setup default behaviours (to get a consistent behaviour across different implementations) - setVisible(true); - setMouseCursorVisible(true); - setVerticalSyncEnabled(false); - setKeyRepeatEnabled(true); - setFramerateLimit(0); - - // Get and cache the initial size of the window - m_size = m_impl->getSize(); - - // Reset frame time - m_clock.restart(); - - // Activate the window - setActive(); - - // Notify the derived class - onCreate(); -} - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace +{ + const sf::Window* fullscreenWindow = NULL; +} + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Window::Window() : +m_impl (NULL), +m_context (NULL), +m_frameTimeLimit(Time::Zero), +m_size (0, 0) +{ + +} + + +//////////////////////////////////////////////////////////// +Window::Window(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) : +m_impl (NULL), +m_context (NULL), +m_frameTimeLimit(Time::Zero), +m_size (0, 0) +{ + create(mode, title, style, settings); +} + + +//////////////////////////////////////////////////////////// +Window::Window(WindowHandle handle, const ContextSettings& settings) : +m_impl (NULL), +m_context (NULL), +m_frameTimeLimit(Time::Zero), +m_size (0, 0) +{ + create(handle, settings); +} + + +//////////////////////////////////////////////////////////// +Window::~Window() +{ + close(); +} + + +//////////////////////////////////////////////////////////// +void Window::create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) +{ + // Destroy the previous window implementation + close(); + + // Fullscreen style requires some tests + if (style & Style::Fullscreen) + { + // Make sure there's not already a fullscreen window (only one is allowed) + if (fullscreenWindow) + { + err() << "Creating two fullscreen windows is not allowed, switching to windowed mode" << std::endl; + style &= ~Style::Fullscreen; + } + else + { + // Make sure that the chosen video mode is compatible + if (!mode.isValid()) + { + err() << "The requested video mode is not available, switching to a valid mode" << std::endl; + mode = VideoMode::getFullscreenModes()[0]; + } + + // Update the fullscreen window + fullscreenWindow = this; + } + } + + // Check validity of style according to the underlying platform + #if defined(SFML_SYSTEM_IOS) || defined(SFML_SYSTEM_ANDROID) + if (style & Style::Fullscreen) + style &= ~Style::Titlebar; + else + style |= Style::Titlebar; + #else + if ((style & Style::Close) || (style & Style::Resize)) + style |= Style::Titlebar; + #endif + + // Recreate the window implementation + m_impl = priv::WindowImpl::create(mode, title, style, settings); + + // Recreate the context + m_context = priv::GlContext::create(settings, m_impl, mode.bitsPerPixel); + + // Perform common initializations + initialize(); +} + + +//////////////////////////////////////////////////////////// +void Window::create(WindowHandle handle, const ContextSettings& settings) +{ + // Destroy the previous window implementation + close(); + + // Recreate the window implementation + m_impl = priv::WindowImpl::create(handle); + + // Recreate the context + m_context = priv::GlContext::create(settings, m_impl, VideoMode::getDesktopMode().bitsPerPixel); + + // Perform common initializations + initialize(); +} + + +//////////////////////////////////////////////////////////// +void Window::close() +{ + // Delete the context + delete m_context; + m_context = NULL; + + // Delete the window implementation + delete m_impl; + m_impl = NULL; + + // Update the fullscreen window + if (this == fullscreenWindow) + fullscreenWindow = NULL; +} + + +//////////////////////////////////////////////////////////// +bool Window::isOpen() const +{ + return m_impl != NULL; +} + + +//////////////////////////////////////////////////////////// +const ContextSettings& Window::getSettings() const +{ + static const ContextSettings empty(0, 0, 0); + + return m_context ? m_context->getSettings() : empty; +} + + +//////////////////////////////////////////////////////////// +bool Window::pollEvent(Event& event) +{ + if (m_impl && m_impl->popEvent(event, false)) + { + return filterEvent(event); + } + else + { + return false; + } +} + + +//////////////////////////////////////////////////////////// +bool Window::waitEvent(Event& event) +{ + if (m_impl && m_impl->popEvent(event, true)) + { + return filterEvent(event); + } + else + { + return false; + } +} + + +//////////////////////////////////////////////////////////// +Vector2i Window::getPosition() const +{ + return m_impl ? m_impl->getPosition() : Vector2i(); +} + + +//////////////////////////////////////////////////////////// +void Window::setPosition(const Vector2i& position) +{ + if (m_impl) + m_impl->setPosition(position); +} + + +//////////////////////////////////////////////////////////// +Vector2u Window::getSize() const +{ + return m_size; +} + + +//////////////////////////////////////////////////////////// +void Window::setSize(const Vector2u& size) +{ + if (m_impl) + { + m_impl->setSize(size); + + // Cache the new size + m_size.x = size.x; + m_size.y = size.y; + + // Notify the derived class + onResize(); + } +} + + +//////////////////////////////////////////////////////////// +void Window::setTitle(const String& title) +{ + if (m_impl) + m_impl->setTitle(title); +} + + +//////////////////////////////////////////////////////////// +void Window::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) +{ + if (m_impl) + m_impl->setIcon(width, height, pixels); +} + + +//////////////////////////////////////////////////////////// +void Window::setVisible(bool visible) +{ + if (m_impl) + m_impl->setVisible(visible); +} + + +//////////////////////////////////////////////////////////// +void Window::setVerticalSyncEnabled(bool enabled) +{ + if (setActive()) + m_context->setVerticalSyncEnabled(enabled); +} + + +//////////////////////////////////////////////////////////// +void Window::setMouseCursorVisible(bool visible) +{ + if (m_impl) + m_impl->setMouseCursorVisible(visible); +} + + +//////////////////////////////////////////////////////////// +void Window::setKeyRepeatEnabled(bool enabled) +{ + if (m_impl) + m_impl->setKeyRepeatEnabled(enabled); +} + + +//////////////////////////////////////////////////////////// +void Window::setFramerateLimit(unsigned int limit) +{ + if (limit > 0) + m_frameTimeLimit = seconds(1.f / limit); + else + m_frameTimeLimit = Time::Zero; +} + + +//////////////////////////////////////////////////////////// +void Window::setJoystickThreshold(float threshold) +{ + if (m_impl) + m_impl->setJoystickThreshold(threshold); +} + + +//////////////////////////////////////////////////////////// +bool Window::setActive(bool active) const +{ + if (m_context) + { + if (m_context->setActive(active)) + { + return true; + } + else + { + err() << "Failed to activate the window's context" << std::endl; + return false; + } + } + else + { + return false; + } +} + + +//////////////////////////////////////////////////////////// +void Window::display() +{ + // Display the backbuffer on screen + if (setActive()) + m_context->display(); + + // Limit the framerate if needed + if (m_frameTimeLimit != Time::Zero) + { + sleep(m_frameTimeLimit - m_clock.getElapsedTime()); + m_clock.restart(); + } +} + + +//////////////////////////////////////////////////////////// +WindowHandle Window::getSystemHandle() const +{ + return m_impl ? m_impl->getSystemHandle() : 0; +} + + +//////////////////////////////////////////////////////////// +void Window::onCreate() +{ + // Nothing by default +} + + +//////////////////////////////////////////////////////////// +void Window::onResize() +{ + // Nothing by default +} + + +//////////////////////////////////////////////////////////// +bool Window::filterEvent(const Event& event) +{ + // Notify resize events to the derived class + if (event.type == Event::Resized) + { + // Cache the new size + m_size.x = event.size.width; + m_size.y = event.size.height; + + // Notify the derived class + onResize(); + } + + return true; +} + + +//////////////////////////////////////////////////////////// +void Window::initialize() +{ + // Setup default behaviours (to get a consistent behaviour across different implementations) + setVisible(true); + setMouseCursorVisible(true); + setVerticalSyncEnabled(false); + setKeyRepeatEnabled(true); + setFramerateLimit(0); + + // Get and cache the initial size of the window + m_size = m_impl->getSize(); + + // Reset frame time + m_clock.restart(); + + // Activate the window + setActive(); + + // Notify the derived class + onCreate(); +} + +} // namespace sf diff --git a/src/SFML/Window/WindowImpl.cpp b/src/SFML/Window/WindowImpl.cpp index 7d3cd52e..db4518ed 100644 --- a/src/SFML/Window/WindowImpl.cpp +++ b/src/SFML/Window/WindowImpl.cpp @@ -1,257 +1,257 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include - -#if defined(SFML_SYSTEM_WINDOWS) - - #include - typedef sf::priv::WindowImplWin32 WindowImplType; - -#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) - - #include - typedef sf::priv::WindowImplX11 WindowImplType; - -#elif defined(SFML_SYSTEM_MACOS) - - #include - typedef sf::priv::WindowImplCocoa WindowImplType; - -#elif defined(SFML_SYSTEM_IOS) - - #include - typedef sf::priv::WindowImplUIKit WindowImplType; - -#elif defined(SFML_SYSTEM_ANDROID) - - #include - typedef sf::priv::WindowImplAndroid WindowImplType; - -#endif - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -WindowImpl* WindowImpl::create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) -{ - return new WindowImplType(mode, title, style, settings); -} - - -//////////////////////////////////////////////////////////// -WindowImpl* WindowImpl::create(WindowHandle handle) -{ - return new WindowImplType(handle); -} - - -//////////////////////////////////////////////////////////// -WindowImpl::WindowImpl() : -m_joystickThreshold(0.1f) -{ - // Get the initial joystick states - JoystickManager::getInstance().update(); - for (unsigned int i = 0; i < Joystick::Count; ++i) - m_joystickStates[i] = JoystickManager::getInstance().getState(i); - - // Get the initial sensor states - for (unsigned int i = 0; i < Sensor::Count; ++i) - m_sensorValue[i] = Vector3f(0, 0, 0); -} - - -//////////////////////////////////////////////////////////// -WindowImpl::~WindowImpl() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -void WindowImpl::setJoystickThreshold(float threshold) -{ - m_joystickThreshold = threshold; -} - - -//////////////////////////////////////////////////////////// -bool WindowImpl::popEvent(Event& event, bool block) -{ - // If the event queue is empty, let's first check if new events are available from the OS - if (m_events.empty()) - { - // Get events from the system - processJoystickEvents(); - processSensorEvents(); - processEvents(); - - // In blocking mode, we must process events until one is triggered - if (block) - { - // Here we use a manual wait loop instead of the optimized - // wait-event provided by the OS, so that we don't skip joystick - // events (which require polling) - while (m_events.empty()) - { - sleep(milliseconds(10)); - processJoystickEvents(); - processSensorEvents(); - processEvents(); - } - } - } - - // Pop the first event of the queue, if it is not empty - if (!m_events.empty()) - { - event = m_events.front(); - m_events.pop(); - - return true; - } - - return false; -} - - -//////////////////////////////////////////////////////////// -void WindowImpl::pushEvent(const Event& event) -{ - m_events.push(event); -} - - -//////////////////////////////////////////////////////////// -void WindowImpl::processJoystickEvents() -{ - // First update the global joystick states - JoystickManager::getInstance().update(); - - for (unsigned int i = 0; i < Joystick::Count; ++i) - { - // Copy the previous state of the joystick and get the new one - JoystickState previousState = m_joystickStates[i]; - m_joystickStates[i] = JoystickManager::getInstance().getState(i); - JoystickCaps caps = JoystickManager::getInstance().getCapabilities(i); - - // Connection state - bool connected = m_joystickStates[i].connected; - if (previousState.connected ^ connected) - { - Event event; - event.type = connected ? Event::JoystickConnected : Event::JoystickDisconnected; - event.joystickButton.joystickId = i; - pushEvent(event); - } - - if (connected) - { - // Axes - for (unsigned int j = 0; j < Joystick::AxisCount; ++j) - { - if (caps.axes[j]) - { - Joystick::Axis axis = static_cast(j); - float prevPos = previousState.axes[axis]; - float currPos = m_joystickStates[i].axes[axis]; - if (fabs(currPos - prevPos) >= m_joystickThreshold) - { - Event event; - event.type = Event::JoystickMoved; - event.joystickMove.joystickId = i; - event.joystickMove.axis = axis; - event.joystickMove.position = currPos; - pushEvent(event); - } - } - } - - // Buttons - for (unsigned int j = 0; j < caps.buttonCount; ++j) - { - bool prevPressed = previousState.buttons[j]; - bool currPressed = m_joystickStates[i].buttons[j]; - - if (prevPressed ^ currPressed) - { - Event event; - event.type = currPressed ? Event::JoystickButtonPressed : Event::JoystickButtonReleased; - event.joystickButton.joystickId = i; - event.joystickButton.button = j; - pushEvent(event); - } - } - } - } -} - - -//////////////////////////////////////////////////////////// -void WindowImpl::processSensorEvents() -{ - // First update the sensor states - SensorManager::getInstance().update(); - - for (unsigned int i = 0; i < Sensor::Count; ++i) - { - Sensor::Type sensor = static_cast(i); - - // Only process enabled sensors - if (SensorManager::getInstance().isEnabled(sensor)) - { - // Copy the previous value of the sensor and get the new one - Vector3f previousValue = m_sensorValue[i]; - m_sensorValue[i] = SensorManager::getInstance().getValue(sensor); - - // If the value has changed, trigger an event - if (m_sensorValue[i] != previousValue) // @todo use a threshold? - { - Event event; - event.type = Event::SensorChanged; - event.sensor.type = sensor; - event.sensor.x = m_sensorValue[i].x; - event.sensor.y = m_sensorValue[i].y; - event.sensor.z = m_sensorValue[i].z; - pushEvent(event); - } - } - } -} - -} // namespace priv - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + +#if defined(SFML_SYSTEM_WINDOWS) + + #include + typedef sf::priv::WindowImplWin32 WindowImplType; + +#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) + + #include + typedef sf::priv::WindowImplX11 WindowImplType; + +#elif defined(SFML_SYSTEM_MACOS) + + #include + typedef sf::priv::WindowImplCocoa WindowImplType; + +#elif defined(SFML_SYSTEM_IOS) + + #include + typedef sf::priv::WindowImplUIKit WindowImplType; + +#elif defined(SFML_SYSTEM_ANDROID) + + #include + typedef sf::priv::WindowImplAndroid WindowImplType; + +#endif + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +WindowImpl* WindowImpl::create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) +{ + return new WindowImplType(mode, title, style, settings); +} + + +//////////////////////////////////////////////////////////// +WindowImpl* WindowImpl::create(WindowHandle handle) +{ + return new WindowImplType(handle); +} + + +//////////////////////////////////////////////////////////// +WindowImpl::WindowImpl() : +m_joystickThreshold(0.1f) +{ + // Get the initial joystick states + JoystickManager::getInstance().update(); + for (unsigned int i = 0; i < Joystick::Count; ++i) + m_joystickStates[i] = JoystickManager::getInstance().getState(i); + + // Get the initial sensor states + for (unsigned int i = 0; i < Sensor::Count; ++i) + m_sensorValue[i] = Vector3f(0, 0, 0); +} + + +//////////////////////////////////////////////////////////// +WindowImpl::~WindowImpl() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +void WindowImpl::setJoystickThreshold(float threshold) +{ + m_joystickThreshold = threshold; +} + + +//////////////////////////////////////////////////////////// +bool WindowImpl::popEvent(Event& event, bool block) +{ + // If the event queue is empty, let's first check if new events are available from the OS + if (m_events.empty()) + { + // Get events from the system + processJoystickEvents(); + processSensorEvents(); + processEvents(); + + // In blocking mode, we must process events until one is triggered + if (block) + { + // Here we use a manual wait loop instead of the optimized + // wait-event provided by the OS, so that we don't skip joystick + // events (which require polling) + while (m_events.empty()) + { + sleep(milliseconds(10)); + processJoystickEvents(); + processSensorEvents(); + processEvents(); + } + } + } + + // Pop the first event of the queue, if it is not empty + if (!m_events.empty()) + { + event = m_events.front(); + m_events.pop(); + + return true; + } + + return false; +} + + +//////////////////////////////////////////////////////////// +void WindowImpl::pushEvent(const Event& event) +{ + m_events.push(event); +} + + +//////////////////////////////////////////////////////////// +void WindowImpl::processJoystickEvents() +{ + // First update the global joystick states + JoystickManager::getInstance().update(); + + for (unsigned int i = 0; i < Joystick::Count; ++i) + { + // Copy the previous state of the joystick and get the new one + JoystickState previousState = m_joystickStates[i]; + m_joystickStates[i] = JoystickManager::getInstance().getState(i); + JoystickCaps caps = JoystickManager::getInstance().getCapabilities(i); + + // Connection state + bool connected = m_joystickStates[i].connected; + if (previousState.connected ^ connected) + { + Event event; + event.type = connected ? Event::JoystickConnected : Event::JoystickDisconnected; + event.joystickButton.joystickId = i; + pushEvent(event); + } + + if (connected) + { + // Axes + for (unsigned int j = 0; j < Joystick::AxisCount; ++j) + { + if (caps.axes[j]) + { + Joystick::Axis axis = static_cast(j); + float prevPos = previousState.axes[axis]; + float currPos = m_joystickStates[i].axes[axis]; + if (fabs(currPos - prevPos) >= m_joystickThreshold) + { + Event event; + event.type = Event::JoystickMoved; + event.joystickMove.joystickId = i; + event.joystickMove.axis = axis; + event.joystickMove.position = currPos; + pushEvent(event); + } + } + } + + // Buttons + for (unsigned int j = 0; j < caps.buttonCount; ++j) + { + bool prevPressed = previousState.buttons[j]; + bool currPressed = m_joystickStates[i].buttons[j]; + + if (prevPressed ^ currPressed) + { + Event event; + event.type = currPressed ? Event::JoystickButtonPressed : Event::JoystickButtonReleased; + event.joystickButton.joystickId = i; + event.joystickButton.button = j; + pushEvent(event); + } + } + } + } +} + + +//////////////////////////////////////////////////////////// +void WindowImpl::processSensorEvents() +{ + // First update the sensor states + SensorManager::getInstance().update(); + + for (unsigned int i = 0; i < Sensor::Count; ++i) + { + Sensor::Type sensor = static_cast(i); + + // Only process enabled sensors + if (SensorManager::getInstance().isEnabled(sensor)) + { + // Copy the previous value of the sensor and get the new one + Vector3f previousValue = m_sensorValue[i]; + m_sensorValue[i] = SensorManager::getInstance().getValue(sensor); + + // If the value has changed, trigger an event + if (m_sensorValue[i] != previousValue) // @todo use a threshold? + { + Event event; + event.type = Event::SensorChanged; + event.sensor.type = sensor; + event.sensor.x = m_sensorValue[i].x; + event.sensor.y = m_sensorValue[i].y; + event.sensor.z = m_sensorValue[i].z; + pushEvent(event); + } + } + } +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/WindowImpl.hpp b/src/SFML/Window/WindowImpl.hpp index 33c0f379..b4d715ed 100644 --- a/src/SFML/Window/WindowImpl.hpp +++ b/src/SFML/Window/WindowImpl.hpp @@ -1,251 +1,251 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_WINDOWIMPL_HPP -#define SFML_WINDOWIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace sf -{ -class WindowListener; - -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Abstract base class for OS-specific window implementation -/// -//////////////////////////////////////////////////////////// -class WindowImpl : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Create a new window depending on the current OS - /// - /// \param mode Video mode to use - /// \param title Title of the window - /// \param style Window style - /// \param settings Additional settings for the underlying OpenGL context - /// - /// \return Pointer to the created window (don't forget to delete it) - /// - //////////////////////////////////////////////////////////// - static WindowImpl* create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings); - - //////////////////////////////////////////////////////////// - /// \brief Create a new window depending on to the current OS - /// - /// \param handle Platform-specific handle of the control - /// - /// \return Pointer to the created window (don't forget to delete it) - /// - //////////////////////////////////////////////////////////// - static WindowImpl* create(WindowHandle handle); - -public : - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - virtual ~WindowImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Change the joystick threshold, ie. the value below which - /// no move event will be generated - /// - /// \param threshold : New threshold, in range [0, 100] - /// - //////////////////////////////////////////////////////////// - void setJoystickThreshold(float threshold); - - //////////////////////////////////////////////////////////// - /// \brief Return the next window event available - /// - /// If there's no event available, this function calls the - /// window's internal event processing function. - /// The \a block parameter controls the behaviour of the function - /// if no event is available: if it is true then the function - /// doesn't return until a new event is triggered; otherwise it - /// returns false to indicate that no event is available. - /// - /// \param event Event to be returned - /// \param block Use true to block the thread until an event arrives - /// - //////////////////////////////////////////////////////////// - bool popEvent(Event& event, bool block); - - //////////////////////////////////////////////////////////// - /// \brief Get the OS-specific handle of the window - /// - /// \return Handle of the window - /// - //////////////////////////////////////////////////////////// - virtual WindowHandle getSystemHandle() const = 0; - - //////////////////////////////////////////////////////////// - /// \brief Get the position of the window - /// - /// \return Position of the window, in pixels - /// - //////////////////////////////////////////////////////////// - virtual Vector2i getPosition() const = 0; - - //////////////////////////////////////////////////////////// - /// \brief Change the position of the window on screen - /// - /// \param position New position of the window, in pixels - /// - //////////////////////////////////////////////////////////// - virtual void setPosition(const Vector2i& position) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Get the client size of the window - /// - /// \return Size of the window, in pixels - /// - //////////////////////////////////////////////////////////// - virtual Vector2u getSize() const = 0; - - //////////////////////////////////////////////////////////// - /// \brief Change the size of the rendering region of the window - /// - /// \param size New size, in pixels - /// - //////////////////////////////////////////////////////////// - virtual void setSize(const Vector2u& size) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Change the title of the window - /// - /// \param title New title - /// - //////////////////////////////////////////////////////////// - virtual void setTitle(const String& title) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Change the window's icon - /// - /// \param width Icon's width, in pixels - /// \param height Icon's height, in pixels - /// \param pixels Pointer to the pixels in memory, format must be RGBA 32 bits - /// - //////////////////////////////////////////////////////////// - virtual void setIcon(unsigned int width, unsigned int height, const Uint8* pixels) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Show or hide the window - /// - /// \param visible True to show, false to hide - /// - //////////////////////////////////////////////////////////// - virtual void setVisible(bool visible) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Show or hide the mouse cursor - /// - /// \param visible True to show, false to hide - /// - //////////////////////////////////////////////////////////// - virtual void setMouseCursorVisible(bool visible) = 0; - - //////////////////////////////////////////////////////////// - /// \brief Enable or disable automatic key-repeat - /// - /// \param enabled True to enable, false to disable - /// - //////////////////////////////////////////////////////////// - virtual void setKeyRepeatEnabled(bool enabled) = 0; - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - WindowImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Push a new event into the event queue - /// - /// This function is to be used by derived classes, to - /// notify the SFML window that a new event was triggered - /// by the system. - /// - /// \param event Event to push - /// - //////////////////////////////////////////////////////////// - void pushEvent(const Event& event); - - //////////////////////////////////////////////////////////// - /// \brief Process incoming events from the operating system - /// - //////////////////////////////////////////////////////////// - virtual void processEvents() = 0; - -private : - - //////////////////////////////////////////////////////////// - /// \brief Read the joysticks state and generate the appropriate events - /// - //////////////////////////////////////////////////////////// - void processJoystickEvents(); - - //////////////////////////////////////////////////////////// - /// \brief Read the sensors state and generate the appropriate events - /// - //////////////////////////////////////////////////////////// - void processSensorEvents(); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - std::queue m_events; ///< Queue of available events - JoystickState m_joystickStates[Joystick::Count]; ///< Previous state of the joysticks - Vector3f m_sensorValue[Sensor::Count]; ///< Previous value of the sensors - float m_joystickThreshold; ///< Joystick threshold (minimum motion for "move" event to be generated) -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_WINDOWIMPL_HPP +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WINDOWIMPL_HPP +#define SFML_WINDOWIMPL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sf +{ +class WindowListener; + +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Abstract base class for OS-specific window implementation +/// +//////////////////////////////////////////////////////////// +class WindowImpl : NonCopyable +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Create a new window depending on the current OS + /// + /// \param mode Video mode to use + /// \param title Title of the window + /// \param style Window style + /// \param settings Additional settings for the underlying OpenGL context + /// + /// \return Pointer to the created window (don't forget to delete it) + /// + //////////////////////////////////////////////////////////// + static WindowImpl* create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings); + + //////////////////////////////////////////////////////////// + /// \brief Create a new window depending on to the current OS + /// + /// \param handle Platform-specific handle of the control + /// + /// \return Pointer to the created window (don't forget to delete it) + /// + //////////////////////////////////////////////////////////// + static WindowImpl* create(WindowHandle handle); + +public: + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~WindowImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Change the joystick threshold, ie. the value below which + /// no move event will be generated + /// + /// \param threshold: New threshold, in range [0, 100] + /// + //////////////////////////////////////////////////////////// + void setJoystickThreshold(float threshold); + + //////////////////////////////////////////////////////////// + /// \brief Return the next window event available + /// + /// If there's no event available, this function calls the + /// window's internal event processing function. + /// The \a block parameter controls the behaviour of the function + /// if no event is available: if it is true then the function + /// doesn't return until a new event is triggered; otherwise it + /// returns false to indicate that no event is available. + /// + /// \param event Event to be returned + /// \param block Use true to block the thread until an event arrives + /// + //////////////////////////////////////////////////////////// + bool popEvent(Event& event, bool block); + + //////////////////////////////////////////////////////////// + /// \brief Get the OS-specific handle of the window + /// + /// \return Handle of the window + /// + //////////////////////////////////////////////////////////// + virtual WindowHandle getSystemHandle() const = 0; + + //////////////////////////////////////////////////////////// + /// \brief Get the position of the window + /// + /// \return Position of the window, in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2i getPosition() const = 0; + + //////////////////////////////////////////////////////////// + /// \brief Change the position of the window on screen + /// + /// \param position New position of the window, in pixels + /// + //////////////////////////////////////////////////////////// + virtual void setPosition(const Vector2i& position) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Get the client size of the window + /// + /// \return Size of the window, in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2u getSize() const = 0; + + //////////////////////////////////////////////////////////// + /// \brief Change the size of the rendering region of the window + /// + /// \param size New size, in pixels + /// + //////////////////////////////////////////////////////////// + virtual void setSize(const Vector2u& size) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Change the title of the window + /// + /// \param title New title + /// + //////////////////////////////////////////////////////////// + virtual void setTitle(const String& title) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Change the window's icon + /// + /// \param width Icon's width, in pixels + /// \param height Icon's height, in pixels + /// \param pixels Pointer to the pixels in memory, format must be RGBA 32 bits + /// + //////////////////////////////////////////////////////////// + virtual void setIcon(unsigned int width, unsigned int height, const Uint8* pixels) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Show or hide the window + /// + /// \param visible True to show, false to hide + /// + //////////////////////////////////////////////////////////// + virtual void setVisible(bool visible) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Show or hide the mouse cursor + /// + /// \param visible True to show, false to hide + /// + //////////////////////////////////////////////////////////// + virtual void setMouseCursorVisible(bool visible) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable automatic key-repeat + /// + /// \param enabled True to enable, false to disable + /// + //////////////////////////////////////////////////////////// + virtual void setKeyRepeatEnabled(bool enabled) = 0; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + WindowImpl(); + + //////////////////////////////////////////////////////////// + /// \brief Push a new event into the event queue + /// + /// This function is to be used by derived classes, to + /// notify the SFML window that a new event was triggered + /// by the system. + /// + /// \param event Event to push + /// + //////////////////////////////////////////////////////////// + void pushEvent(const Event& event); + + //////////////////////////////////////////////////////////// + /// \brief Process incoming events from the operating system + /// + //////////////////////////////////////////////////////////// + virtual void processEvents() = 0; + +private: + + //////////////////////////////////////////////////////////// + /// \brief Read the joysticks state and generate the appropriate events + /// + //////////////////////////////////////////////////////////// + void processJoystickEvents(); + + //////////////////////////////////////////////////////////// + /// \brief Read the sensors state and generate the appropriate events + /// + //////////////////////////////////////////////////////////// + void processSensorEvents(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::queue m_events; ///< Queue of available events + JoystickState m_joystickStates[Joystick::Count]; ///< Previous state of the joysticks + Vector3f m_sensorValue[Sensor::Count]; ///< Previous value of the sensors + float m_joystickThreshold; ///< Joystick threshold (minimum motion for "move" event to be generated) +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_WINDOWIMPL_HPP diff --git a/src/SFML/Window/iOS/EaglContext.hpp b/src/SFML/Window/iOS/EaglContext.hpp index 6abc4278..cda83d61 100644 --- a/src/SFML/Window/iOS/EaglContext.hpp +++ b/src/SFML/Window/iOS/EaglContext.hpp @@ -96,7 +96,7 @@ public: /// This function must be called whenever the containing view /// changes (typically after an orientation change) /// - /// \param glView : Container of the context + /// \param glView: Container of the context /// //////////////////////////////////////////////////////////// void recreateRenderBuffers(SFView* glView); @@ -115,7 +115,7 @@ public: /// This can avoid some visual artifacts, and limit the framerate /// to a good value (but not constant across different computers). /// - /// \param enabled : True to enable v-sync, false to deactivate + /// \param enabled: True to enable v-sync, false to deactivate /// //////////////////////////////////////////////////////////// virtual void setVerticalSyncEnabled(bool enabled); diff --git a/src/SFML/Window/iOS/InputImpl.hpp b/src/SFML/Window/iOS/InputImpl.hpp index 066b8818..1c01fa3e 100644 --- a/src/SFML/Window/iOS/InputImpl.hpp +++ b/src/SFML/Window/iOS/InputImpl.hpp @@ -42,7 +42,7 @@ namespace priv //////////////////////////////////////////////////////////// class InputImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Check if a key is pressed diff --git a/src/SFML/Window/iOS/JoystickImpl.hpp b/src/SFML/Window/iOS/JoystickImpl.hpp index 460b6e70..46a7b9e5 100644 --- a/src/SFML/Window/iOS/JoystickImpl.hpp +++ b/src/SFML/Window/iOS/JoystickImpl.hpp @@ -41,7 +41,7 @@ namespace priv //////////////////////////////////////////////////////////// class JoystickImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Perform the global initialization of the joystick module diff --git a/src/SFML/Window/iOS/SensorImpl.hpp b/src/SFML/Window/iOS/SensorImpl.hpp index 399fd8f1..b9dd5c25 100644 --- a/src/SFML/Window/iOS/SensorImpl.hpp +++ b/src/SFML/Window/iOS/SensorImpl.hpp @@ -41,7 +41,7 @@ namespace priv //////////////////////////////////////////////////////////// class SensorImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Perform the global initialization of the sensor module @@ -97,7 +97,7 @@ public : //////////////////////////////////////////////////////////// void setEnabled(bool enabled); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/src/SFML/Window/iOS/WindowImplUIKit.hpp b/src/SFML/Window/iOS/WindowImplUIKit.hpp index 3d7a5c46..9f56fe90 100644 --- a/src/SFML/Window/iOS/WindowImplUIKit.hpp +++ b/src/SFML/Window/iOS/WindowImplUIKit.hpp @@ -48,7 +48,7 @@ namespace priv //////////////////////////////////////////////////////////// class WindowImplUIKit : public WindowImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Construct the window implementation from an existing control @@ -177,7 +177,7 @@ public: //////////////////////////////////////////////////////////// void setVirtualKeyboardVisible(bool visible); -protected : +protected: //////////////////////////////////////////////////////////// /// \brief Process incoming events from the operating system @@ -185,7 +185,7 @@ protected : //////////////////////////////////////////////////////////// virtual void processEvents(); -private : +private: //////////////////////////////////////////////////////////// // Member data diff --git a/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp b/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp index 94e62106..7eff0b96 100644 --- a/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp +++ b/tools/xcode/templates/SFML/SFML App.xctemplate/main.cpp @@ -63,12 +63,12 @@ int main(int, char const**) sf::Event event; while (window.pollEvent(event)) { - // Close window : exit + // Close window: exit if (event.type == sf::Event::Closed) { window.close(); } - // Escape pressed : exit + // Escape pressed: exit if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) { window.close(); } diff --git a/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp b/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp index f5e5d2e7..dda3255c 100644 --- a/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp +++ b/tools/xcode/templates/SFML/SFML CLT.xctemplate/main.cpp @@ -6,7 +6,7 @@ // This code will work only if you selected window, graphics and audio. // // In order to load the resources like cute_image.png, you have to set up -// your target scheme : +// your target scheme: // // - Select "Edit Scheme…" in the "Product" menu; // - Check the box "use custom working directory"; @@ -61,12 +61,12 @@ int main(int argc, char const** argv) sf::Event event; while (window.pollEvent(event)) { - // Close window : exit + // Close window: exit if (event.type == sf::Event::Closed) { window.close(); } - // Escape pressed : exit + // Escape pressed: exit if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) { window.close(); } diff --git a/tools/xcode/templates/readme.txt b/tools/xcode/templates/readme.txt index ccc85593..981121ce 100644 --- a/tools/xcode/templates/readme.txt +++ b/tools/xcode/templates/readme.txt @@ -16,7 +16,7 @@ You can find more resources and information on the official web site: http://www Author & License ---------------- -The templates were written by Marco Antognini and are provided under the terms of the zlib/png license : http://opensource.org/licenses/zlib-license.php +The templates were written by Marco Antognini and are provided under the terms of the zlib/png license: http://opensource.org/licenses/zlib-license.php @@ -56,7 +56,7 @@ If you are building SFML from sources you can set CMake's INSTALL_XCODE_TEMPLATE Usage ----- -To use these templates follow these steps : +To use these templates follow these steps: 1. open Xcode, 2. select "create a new Xcode project" from the "Welcome to Xcode" window or select menus File > New > New Project, @@ -64,7 +64,7 @@ To use these templates follow these steps : 4. then select either "SFML App", if you want an application bundle, or "SFML CLT", if you prefer a classic Unix executable, 5. fill in the requested information and you're ready to go ! -Note : some settings are marked as "[ADVANCED]" in the wizard. If you're not sure what they are, simply keep the default settings. If you get errors later you would probably want to explore their meaning. +Note: some settings are marked as "[ADVANCED]" in the wizard. If you're not sure what they are, simply keep the default settings. If you get errors later you would probably want to explore their meaning.