Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 5695


Ignore:
Timestamp:
Aug 30, 2009, 2:22:00 AM (15 years ago)
Author:
rgrieder
Message:

Merged resource2 branch back to trunk.

IMPORTANT NOTE:
Upon this merge you need to specifically call your data directory "data_extern" when checking it out (when you don't provide a name, it will be just called 'trunk').
The new CMake variable is EXTERNAL_DATA_DIRECTORY. DATA_DIRECTORY now points to the one the source part of the repository.
UPDATE YOUR DATA DIRECTORY AS WELL!!!

Location:
code/trunk
Files:
6 deleted
93 edited
191 copied

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/CMakeLists.txt

    r3316 r5695  
    1717 #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    1818 #
    19  
     19 #
     20 #  Author:
     21 #    Reto Grieder
     22 #  Description:
     23 #    Configures some basics and controls the configuration scripts
     24 #
     25
    2026CMAKE_MINIMUM_REQUIRED(VERSION 2.6 FATAL_ERROR)
    2127
     
    2733ENDIF()
    2834
    29 
    3035PROJECT(Orxonox C CXX)
    3136
     37################ General Config #################
     38
     39# Version info
    3240SET(ORXONOX_VERSION_MAJOR 0)
    3341SET(ORXONOX_VERSION_MINOR 0)
     
    3644SET(ORXONOX_VERSION_NAME "Arcturus")
    3745
     46# Standard path suffixes
     47SET(DEFAULT_RUNTIME_PATH bin)
     48SET(DEFAULT_LIBRARY_PATH lib)
     49SET(DEFAULT_ARCHIVE_PATH lib/static)
     50SET(DEFAULT_MODULE_PATH  lib/modules)
     51SET(DEFAULT_DOC_PATH     doc)
     52SET(DEFAULT_DATA_PATH    data)
     53SET(DEFAULT_CONFIG_PATH  config)
     54SET(DEFAULT_LOG_PATH     log)
    3855
    39 # This sets where to look for modules (e.g. "Find*.cmake" files)
     56# Set output directories
     57SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DEFAULT_RUNTIME_PATH})
     58SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DEFAULT_LIBRARY_PATH})
     59SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DEFAULT_ARCHIVE_PATH})
     60SET(CMAKE_MODULE_OUTPUT_DIRECTORY  ${CMAKE_BINARY_DIR}/${DEFAULT_MODULE_PATH})
     61SET(CMAKE_DOC_OUTPUT_DIRECTORY     ${CMAKE_BINARY_DIR}/${DEFAULT_DOC_PATH})
     62# Data directories are only inputs, no delclaration here
     63SET(CMAKE_CONFIG_OUTPUT_DIRECTORY  ${CMAKE_BINARY_DIR}/${DEFAULT_CONFIG_PATH})
     64SET(CMAKE_LOG_OUTPUT_DIRECTORY     ${CMAKE_BINARY_DIR}/${DEFAULT_LOG_PATH})
     65
     66# Set the extension of the dynamic modules
     67SET(ORXONOX_MODULE_EXTENSION ".module")
     68
     69# Sets where to find the external libraries like OgreMain.dll at runtime
     70# On Unix you should not have to change this at all.
     71# This only applies to development runs in the build tree
     72SET(RUNTIME_LIBRARY_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
     73
     74# Take care of some CMake 2.6.0 leftovers
     75MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
     76
     77# This sets where to look for CMake modules (e.g. "Find*.cmake" files)
    4078SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
     79
     80# Set Debug build to default when not having multi-config generator like msvc
     81IF(NOT CMAKE_CONFIGURATION_TYPES)
     82  IF(NOT CMAKE_BUILD_TYPE)
     83    SET(CMAKE_BUILD_TYPE Debug CACHE STRING
     84        "Build types are: Debug, Release, MinSizeRel, RelWithDebInfo" FORCE)
     85  ENDIF()
     86  MARK_AS_ADVANCED(CLEAR CMAKE_BUILD_TYPE)
     87
     88  MESSAGE(STATUS "*** Build type is ${CMAKE_BUILD_TYPE} ***")
     89ELSE()
     90  IF(CMAKE_BUILD_TYPE)
     91    SET(CMAKE_BUILD_TYPE CACHE STRING FORCE)
     92  ENDIF()
     93  MARK_AS_ADVANCED(CMAKE_BUILD_TYPE)
     94ENDIF()
     95
     96# Enable expensive optimisations: use this for a binary release build
     97OPTION(ORXONOX_RELEASE "Enable when building restributable releases" FALSE)
     98
     99########### Subfolders and Subscripts ###########
    41100
    42101# Library finding
     
    44103
    45104# General build and compiler options and configurations
    46 INCLUDE(BuildConfig)
     105INCLUDE(CompilerConfig)
    47106
    48 # Configure media directory location and installation
    49 INCLUDE(Media)
     107# Configure installation paths and options
     108INCLUDE(InstallConfig)
     109
     110# Configure data directory location and installation
     111ADD_SUBDIRECTORY(data)
    50112
    51113# Create the actual project
     
    55117ADD_SUBDIRECTORY(bin)
    56118
    57 # Last but not least: Try to make doxygen target
     119# Last but not least: Try to make a doc target with Doxygen
    58120ADD_SUBDIRECTORY(doc)
  • code/trunk/bin/CMakeLists.txt

    r3196 r5695  
    4545  SEt(_default_subdir) # No default subdir
    4646ENDIF()
    47 STRING(REPLACE "/" "\\" ORXONOX_RUNTIME_LIBRARY_DIRECTORY_WINDOWS ${ORXONOX_RUNTIME_LIBRARY_DIRECTORY})
     47STRING(REPLACE "/" "\\" RUNTIME_LIBRARY_DIRECTORY_WINDOWS ${RUNTIME_LIBRARY_DIRECTORY})
    4848FOREACH(_subdir ${_subdirs})
    4949  GET_FILENAME_COMPONENT(CURRENT_RUNTIME_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_subdir} ABSOLUTE)
     
    6969# Make a symlink to be able to run from the root directory when installing copyable on Unix
    7070IF(UNIX AND INSTALL_COPYABLE)
    71   INSTAll(CODE "EXECUTE_PROCESS(COMMAND ln -sf ${ORXONOX_RUNTIME_INSTALL_PATH}/${ORXONOX_EXECUTABLE_NAME} ${CMAKE_INSTALL_PREFIX}/orxonox)")
     71  INSTAll(CODE "EXECUTE_PROCESS(COMMAND ln -sf ${RUNTIME_INSTALL_DIRECTORY}/${ORXONOX_EXECUTABLE_NAME} ${CMAKE_INSTALL_PREFIX}/orxonox)")
    7272ENDIF()
  • code/trunk/bin/client1.bat.in

    r3068 r5695  
    11title @PROJECT_NAME@
    2 path @ORXONOX_RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
     2path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
    33@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@ --client --writingPathSuffix client1
    44pause
  • code/trunk/bin/client2.bat.in

    r3068 r5695  
    11title @PROJECT_NAME@
    2 path @ORXONOX_RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
     2path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
    33@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@ --client --writingPathSuffix client2
    44pause
  • code/trunk/bin/dedicated.bat.in

    r3068 r5695  
    11title @PROJECT_NAME@
    2 path @ORXONOX_RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
     2path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
    33@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@ --dedicated --writingPathSuffix dedicated
    44pause
  • code/trunk/bin/run.bat.in

    r3068 r5695  
    11title @PROJECT_NAME@
    2 path @ORXONOX_RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
     2path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
    33@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@
    44pause
  • code/trunk/bin/server.bat.in

    r3068 r5695  
    11title @PROJECT_NAME@
    2 path @ORXONOX_RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
     2path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
    33@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@ --server --writingPathSuffix server
    44pause
  • code/trunk/bin/standalone.bat.in

    r3068 r5695  
    11title @PROJECT_NAME@
    2 path @ORXONOX_RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
     2path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
    33@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@ --standalone --writingPathSuffix standalone
    44pause
  • code/trunk/cmake/CheckOGREPlugins.cmake

    r2710 r5695  
    3232 #    OGRE_PLUGINS_RELEASE        Names of the release plugins without ext.
    3333 #  Note:
    34  #    You must not specify render systems as input, but the ones found will be
    35  #    present in the output variables.
     34 #    You must not specify render systems as input. That will be taken care of
     35 #    automatically.
    3636 #
    3737
  • code/trunk/cmake/GenerateToluaBindings.cmake

    r3368 r5695  
    3030 #    TOLUA_PARSER_SOURCE - Lua file with the parser source code
    3131 #    TOLUA_PARSER_DEPENDENCIES - All the dependent lua files
    32  #    ORXONOX_RUNTIME_LIBRARY_DIRECTORY - Working directory
     32 #    RUNTIME_LIBRARY_DIRECTORY - Working directory
    3333 #
    3434
     
    7474    DEPENDS           ${TOLUA_PARSER_DEPENDENCIES}
    7575    IMPLICIT_DEPENDS  ${_implicit_dependencies}
    76     WORKING_DIRECTORY ${ORXONOX_RUNTIME_LIBRARY_DIRECTORY}
     76    WORKING_DIRECTORY ${RUNTIME_LIBRARY_DIRECTORY}
    7777    COMMENT "Generating tolua bind files for package ${_tolua_package}"
    7878  )
  • code/trunk/cmake/InstallConfig.cmake

    r5694 r5695  
    4343SET(LIBRARY_INSTALL_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${DEFAULT_LIBRARY_PATH})
    4444SET(ARCHIVE_INSTALL_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${DEFAULT_ARCHIVE_PATH})
     45SET(MODULE_INSTALL_DIRECTORY  ${CMAKE_INSTALL_PREFIX}/${DEFAULT_MODULE_PATH})
    4546SET(DOC_INSTALL_DIRECTORY     ${CMAKE_INSTALL_PREFIX}/${DEFAULT_DOC_PATH})
    4647SET(DATA_INSTALL_DIRECTORY    ${CMAKE_INSTALL_PREFIX}/${DEFAULT_DATA_PATH})
     
    5455    SET(LIBRARY_INSTALL_DIRECTORY ${CMAKE_INSTALL_PREFIX}/lib/orxonox)
    5556    SET(ARCHIVE_INSTALL_DIRECTORY ${CMAKE_INSTALL_PREFIX}/lib/orxonox/static)
     57    SET(MODULE_INSTALL_DIRECTORY  ${CMAKE_INSTALL_PREFIX}/lib/orxonox/modules)
    5658    SET(DOC_INSTALL_DIRECTORY     ${CMAKE_INSTALL_PREFIX}/share/doc/orxonox)
    5759    SET(DATA_INSTALL_DIRECTORY    ${CMAKE_INSTALL_PREFIX}/share/orxonox)
     
    6769# When building, don't use the install RPATH already
    6870# (but later on when installing)
    69 SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) 
     71SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
    7072
    7173# The RPATH to be used when installing
  • code/trunk/cmake/LibraryConfig.cmake

    r3304 r5695  
    3131# Prevent CMake from finding libraries in the installation folder on Windows.
    3232# There might already be an installation from another compiler
    33 IF(DEPENDENCY_PACKAGE_ENABLE)
     33IF(WIN32)
    3434  LIST(REMOVE_ITEM CMAKE_SYSTEM_PREFIX_PATH  "${CMAKE_INSTALL_PREFIX}")
    3535  LIST(REMOVE_ITEM CMAKE_SYSTEM_LIBRARY_PATH "${CMAKE_INSTALL_PREFIX}/bin")
     
    7272
    7373# User script
    74 SET(USER_SCRIPT_LIBRARY_CONFIG "" CACHE FILEPATH
     74SET(LIBRARY_CONFIG_USER_SCRIPT "" CACHE FILEPATH
    7575    "Specify a CMake script if you wish to write your own library path config.
    76      See LibraryConfigTardis.cmake or LibraryConfigMinGW.cmake for examples.")
    77 IF(USER_SCRIPT_LIBRARY_CONFIG)
    78   IF(EXISTS ${CMAKE_MODULE_PATH}/${USER_SCRIPT_LIBRARY_CONFIG}.cmake)
    79     INCLUDE(${USER_SCRIPT_LIBRARY_CONFIG})
    80   ELSEIF(EXISTS ${USER_SCRIPT_LIBRARY_CONFIG})
    81     INCLUDE(${USER_SCRIPT_LIBRARY_CONFIG})
    82   ELSEIF(EXISTS ${CMAKE_MODULE_PATH}/${USER_SCRIPT_LIBRARY_CONFIG})
    83     INCLUDE(${CMAKE_MODULE_PATH}/${USER_SCRIPT_LIBRARY_CONFIG})
    84   ENDIF()
    85 ENDIF(USER_SCRIPT_LIBRARY_CONFIG)
     76     See LibraryConfigTardis.cmake for an example.")
     77IF(LIBRARY_CONFIG_USER_SCRIPT)
     78  IF(EXISTS ${CMAKE_MODULE_PATH}/${LIBRARY_CONFIG_USER_SCRIPT})
     79    INCLUDE(${CMAKE_MODULE_PATH}/${LIBRARY_CONFIG_USER_SCRIPT})
     80  ENDIF()
     81ENDIF(LIBRARY_CONFIG_USER_SCRIPT)
    8682
    8783
     
    8985# Performs the search and sets the variables    #
    9086
    91 FIND_PACKAGE(OGRE  1.4 EXACT REQUIRED)
     87FIND_PACKAGE(OGRE  1.4       REQUIRED)
    9288FIND_PACKAGE(ENet  1.1       REQUIRED)
    9389FIND_PACKAGE(Ogg             REQUIRED)
     
    185181  ENDIF()
    186182ENDIF(WIN32)
     183
     184
     185################# OGRE Plugins ##################
     186
     187# More plugins: Plugin_BSPSceneManager, Plugin_OctreeSceneManager
     188SET(OGRE_PLUGINS_INT Plugin_ParticleFX)
     189IF(WIN32)
     190  # CG program manager is probably DirectX related (not available under unix)
     191  LIST(APPEND OGRE_PLUGINS_INT Plugin_CgProgramManager)
     192ENDIF(WIN32)
     193SET(OGRE_PLUGINS ${OGRE_PLUGINS_INT} CACHE STRING
     194   "Specify which OGRE plugins to load. Existance check is performed.")
     195
     196# Check the plugins and determine the plugin folder
     197# You can give a hint by setting the environment variable ENV{OGRE_PLUGIN_DIR}
     198INCLUDE(CheckOGREPlugins)
     199CHECK_OGRE_PLUGINS(${OGRE_PLUGINS})
     200
  • code/trunk/cmake/PackageConfig.cmake

    r3370 r5695  
    1 # General package configuration. Merely sets the include paths.
    2 # Library files are treated separately.
     1 #
     2 #             ORXONOX - the hottest 3D action shooter ever to exist
     3 #                             > www.orxonox.net <
     4 #
     5 #        This program is free software; you can redistribute it and/or
     6 #         modify it under the terms of the GNU General Public License
     7 #        as published by the Free Software Foundation; either version 2
     8 #            of the License, or (at your option) any later version.
     9 #
     10 #       This program is distributed in the hope that it will be useful,
     11 #        but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 #        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 #                 GNU General Public License for more details.
     14 #
     15 #   You should have received a copy of the GNU General Public License along
     16 #      with this program; if not, write to the Free Software Foundation,
     17 #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
     18 #
     19 #
     20 #  Author:
     21 #    Reto Grieder
     22 #  Description:
     23 #    General package configuration. Merely sets the include paths.
     24 #    Library files are treated separately.
     25 #
    326
    427# Check package version info
     
    2851ENDIF()
    2952
    30 MESSAGE(STATUS "Using library package for the dependencies.")
     53IF(NOT _INTERNAL_PACKAGE_MESSAGE)
     54  MESSAGE(STATUS "Using library package for the dependencies.")
     55  SET(_INTERNAL_PACKAGE_MESSAGE 1 CACHE INTERNAL "Do not edit!" FORCE)
     56ENDIF()
    3157
    3258# Include paths and other special treatments
  • code/trunk/cmake/PackageConfigMSVC.cmake

    r3370 r5695  
    4747
    4848  # Also the directory with the runtime libraries
    49   SET(ORXONOX_RUNTIME_LIBRARY_DIRECTORY ${DEP_BINARY_DIR})
     49  SET(RUNTIME_LIBRARY_DIRECTORY ${DEP_BINARY_DIR})
    5050
    5151  # Sets the library path for the FIND_LIBRARY
  • code/trunk/cmake/PackageConfigMinGW.cmake

    r3196 r5695  
    4040
    4141  # Also the directory with the runtime libraries
    42   SET(ORXONOX_RUNTIME_LIBRARY_DIRECTORY ${DEP_BINARY_DIR})
     42  SET(RUNTIME_LIBRARY_DIRECTORY ${DEP_BINARY_DIR})
    4343
    4444  # Sets the library path for the FIND_LIBRARY
  • code/trunk/cmake/ParseMacroArguments.cmake

    r3196 r5695  
    3636
    3737MACRO(PARSE_MACRO_ARGUMENTS _switches _list_names)
     38
     39  # Using LIST(FIND ...) speeds up the process
     40  SET(_keywords ${_switches} ${_list_names})
     41
    3842  # Parse all the arguments and set the corresponding variable
    3943  # If the option is just a switch, set the variable to its name for later use
    4044  FOREACH(_arg ${ARGN})
    41     SET(_arg_found FALSE)
    4245
    43     # Switches
    44     FOREACH(_switch ${_switches})
    45       IF(${_switch} STREQUAL ${_arg})
    46         SET(_arg_${_switch} ${_switch})
    47         SET(_arg_found TRUE)
    48         # Avoid interpreting arguments after this one as options args for the previous one
    49         SET(_storage_var)
    50         BREAK()
    51       ENDIF()
    52     ENDFOREACH(_switch)
     46    # Is the argument a keyword?
     47    LIST(FIND _keywords ${_arg} _keyword_index)
     48    IF(NOT _keyword_index EQUAL -1)
    5349
    54     # Input options
    55     IF(NOT _arg_found)
    56       FOREACH(_list_name ${_list_names})
    57         IF(${_list_name} STREQUAL ${_arg})
    58           SET(_storage_var _arg_${_list_name})
    59           SET(_arg_found TRUE)
     50      # Another optimisation
     51      SET(_arg_found FALSE)
     52      # Switches
     53      FOREACH(_switch ${_switches})
     54        IF(${_switch} STREQUAL ${_arg})
     55          SET(_arg_${_switch} ${_switch})
     56          SET(_arg_found TRUE)
     57          # Avoid interpreting arguments after this one as options args for the previous one
     58          SET(_storage_var)
    6059          BREAK()
    6160        ENDIF()
    62       ENDFOREACH(_list_name)
    63     ENDIF(NOT _arg_found)
     61      ENDFOREACH(_switch)
    6462
    65     # Arguments of an input option (like source files for SOURCE_FILES)
    66     IF(NOT _arg_found)
     63      # Input options
     64      IF(NOT _arg_found)
     65        FOREACH(_list_name ${_list_names})
     66          IF(${_list_name} STREQUAL ${_arg})
     67            SET(_storage_var _arg_${_list_name})
     68            BREAK()
     69          ENDIF()
     70        ENDFOREACH(_list_name)
     71      ENDIF(NOT _arg_found)
     72
     73    ELSE()
     74
     75      # Arguments of an input option (like source files for SOURCE_FILES)
    6776      IF(_storage_var)
    6877        # Store in variable define above in the foreach loop
     
    7180        MESSAGE(FATAL_ERROR "ORXONOX_ADD_${_target_type} was given a non compliant argument: ${_arg}")
    7281      ENDIF(_storage_var)
    73     ENDIF(NOT _arg_found)
     82
     83    ENDIF()
    7484
    7585  ENDFOREACH(_arg)
  • code/trunk/cmake/TargetUtilities.cmake

    r5693 r5695  
    5858 #
    5959
     60INCLUDE(CMakeDependentOption)
    6061INCLUDE(CapitaliseName)
    6162INCLUDE(GenerateToluaBindings)
     
    118119
    119120  # First part (pre target) of precompiled header files
    120   IF(PCH_COMPILER_SUPPORT AND PCH_ENABLE AND _arg_PCH_FILE)
     121  IF(PCH_COMPILER_SUPPORT AND _arg_PCH_FILE)
    121122    # Provide convenient option to control PCH
    122123    STRING(TOUPPER "${_target_name}" _target_name_upper)
     
    126127      SET(PCH_DEFAULT TRUE)
    127128    ENDIF()
    128     OPTION(PCH_ENABLE_${_target_name_upper} "Enable using precompiled header files for library ${_target_name}." ${PCH_DEFAULT})
     129    CMAKE_DEPENDENT_OPTION(PCH_ENABLE_${_target_name_upper}
     130      "Enable using precompiled header files for library ${_target_name}." ${PCH_DEFAULT} PCH_ENABLE OFF)
    129131
    130132    IF(PCH_ENABLE_${_target_name_upper})
     
    203205    IF(_arg_MODULE)
    204206      INSTALL(TARGETS ${_target_name}
    205         RUNTIME DESTINATION ${ORXONOX_MODULE_INSTALL_PATH}
    206         LIBRARY DESTINATION ${ORXONOX_MODULE_INSTALL_PATH}
     207        RUNTIME DESTINATION ${MODULE_INSTALL_DIRECTORY}
     208        LIBRARY DESTINATION ${MODULE_INSTALL_DIRECTORY}
    207209      )
    208210    ELSE()
    209211      INSTALL(TARGETS ${_target_name}
    210         RUNTIME DESTINATION ${ORXONOX_RUNTIME_INSTALL_PATH}
    211         LIBRARY DESTINATION ${ORXONOX_LIBRARY_INSTALL_PATH}
     212        RUNTIME DESTINATION ${RUNTIME_INSTALL_DIRECTORY}
     213        LIBRARY DESTINATION ${LIBRARY_INSTALL_DIRECTORY}
    212214      )
    213215    ENDIF()
     
    217219
    218220
    219 # Creates a helper file with name <name_of_the_library>.module
     221# Creates a helper file with name <name_of_the_library>${ORXONOX_MODULE_EXTENSION}
    220222# This helps finding dynamically loadable modules at runtime
    221223
     
    235237      INSTALL(
    236238        FILES ${_module_filename}
    237         DESTINATION ${ORXONOX_MODULE_INSTALL_PATH}
     239        DESTINATION ${MODULE_INSTALL_DIRECTORY}
    238240        CONFIGURATIONS ${_config}
    239241      )
     
    246248    INSTALL(
    247249      FILES ${_module_filename}
    248       DESTINATION ${ORXONOX_MODULE_INSTALL_PATH}
     250      DESTINATION ${MODULE_INSTALL_DIRECTORY}
    249251    )
    250252  ENDIF()
  • code/trunk/doc/api/CMakeLists.txt

    r3196 r5695  
    7676  INSTALL(
    7777    FILES ${DOXY_CONFIG} ${CMAKE_CURRENT_BINARY_DIR}/doxy.log
    78     DESTINATION ${ORXONOX_DOC_INSTALL_PATH}/api
    79     OPTIONAL
     78    DESTINATION ${DOC_INSTALL_DIRECTORY}/api OPTIONAL
    8079  )
    8180  # Install command always needs the directory
     
    8584  INSTALL(
    8685    DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
    87     DESTINATION ${ORXONOX_DOC_INSTALL_PATH}/api
     86    DESTINATION ${DOC_INSTALL_DIRECTORY}/api
    8887  )
    8988ENDIF(DOXYGEN_FOUND)
  • code/trunk/src/CMakeLists.txt

    r3368 r5695  
    1717 #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    1818 #
     19 #
     20 #  Author:
     21 #    Reto Grieder
     22 #  Description:
     23 #    Configures the compilers and sets build options.
     24 #
    1925
    20 ################ Various Options ################
    21 
    22 # various macro includes
     26# Required macros and functions
    2327INCLUDE(FlagUtilities)
    2428INCLUDE(TargetUtilities)
    2529
     30# Configure the two headers and set some options
     31INCLUDE(OrxonoxConfig.cmake)
     32
     33################ Library Defines ################
     34
     35# Disable Boost auto linking completely
     36ADD_COMPILER_FLAGS("-DBOOST_ALL_NO_LIB")
     37
     38# If no defines are specified, these libs get linked statically
     39ADD_COMPILER_FLAGS("-DBOOST_ALL_DYN_LINK" WIN32 LINK_BOOST_DYNAMIC)
     40ADD_COMPILER_FLAGS("-DENET_DLL"           WIN32 LINK_ENET_DYNAMIC)
     41ADD_COMPILER_FLAGS("-DLUA_BUILD_AS_DLL"   WIN32 LINK_LUA_DYNAMIC)
     42ADD_COMPILER_FLAGS("-DOIS_DYNAMIC_LIB")
     43ADD_COMPILER_FLAGS("-DZLIB_DLL"           WIN32 LINK_ZLIB_DYNAMIC)
     44# If no defines are specified, these libs get linked dynamically
     45ADD_COMPILER_FLAGS("-DCEGUI_STATIC"       WIN32 NOT LINK_CEGUI_DYNAMIC)
     46ADD_COMPILER_FLAGS("-DOGRE_STATIC_LIB"    WIN32 NOT LINK_OGRE_DYNAMIC)
     47ADD_COMPILER_FLAGS("-DSTATIC_BUILD"       WIN32 NOT LINK_TCL_DYNAMIC)
     48
    2649# Use TinyXML++
    2750ADD_COMPILER_FLAGS("-DTIXML_USE_TICPP")
    28 # OIS dynamic linking requires macro definition, at least for Windows
    29 ADD_COMPILER_FLAGS("-DOIS_DYNAMIC_LIB")
    30 
    31 ################ OrxonoxConfig.h ################
    32 
    33 # Check endianness
    34 INCLUDE(TestBigEndian)
    35 TEST_BIG_ENDIAN(ORXONOX_BIG_ENDIAN)
    36 IF(NOT ORXONOX_BIG_ENDIAN)
    37   SET(ORXONOX_LITTLE_ENDIAN TRUE)
    38 ENDIF()
    39 
    40 # 32/64 bit system check
    41 IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
    42   SET(ORXONOX_ARCH_64 TRUE)
    43 ELSE()
    44   SET(ORXONOX_ARCH_32 TRUE)
    45 ENDIF()
    46 
    47 # Platforms
    48 SET(ORXONOX_PLATFORM_WINDOWS ${WIN32})
    49 SET(ORXONOX_PLATFORM_APPLE ${APPLE})
    50 SET(ORXONOX_PLATFORM_UNIX ${UNIX})
    51 IF(UNIX AND NOT APPLE)
    52   SET(ORXONOX_PLATFORM_LINUX TRUE)
    53 ENDIF()
    54 
    55 # Check __forceinline
    56 IF(MSVC)
    57   INCLUDE(CheckCXXSourceCompiles)
    58   SET(_source "int main() { return 0; } __forceinline void test() { return; }")
    59   CHECK_CXX_SOURCE_COMPILES("${_source}" HAVE_FORCEINLINE)
    60 ENDIF(MSVC)
    61 
    62 # Check ciso646 include (literal operators)
    63 INCLUDE(CheckIncludeFileCXX)
    64 CHECK_INCLUDE_FILE_CXX(iso646.h HAVE_ISO646_H)
    65 
    66 # XCode and Visual Studio support multiple configurations. In order to tell the
    67 # which one we have to define the macros separately for each configuration
    68 ADD_COMPILER_FLAGS("-DCMAKE_BUILD_TYPE=Debug"          Debug)
    69 ADD_COMPILER_FLAGS("-DCMAKE_BUILD_TYPE=Release"        Release)
    70 ADD_COMPILER_FLAGS("-DCMAKE_BUILD_TYPE=RelWithDebInfo" RelWithDebInfo)
    71 ADD_COMPILER_FLAGS("-DCMAKE_BUILD_TYPE=MinSizeRel"     MinSizeRel)
    72 
    73 SET(GENERATED_FILE_COMMENT
    74    "DO NOT EDIT THIS FILE! <br>
    75     It has been automatically generated by CMake from OrxonoxConfig.h.in")
    76 # Copy and configure OrxonoxConfig which gets included in every file
    77 CONFIGURE_FILE(OrxonoxConfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/OrxonoxConfig.h)
    78 # This file only gets included by very few classes to avoid a large recompilation
    79 CONFIGURE_FILE(SpecialConfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/SpecialConfig.h)
    80 
    81 SET(ORXONOX_CONFIG_FILES
    82   ${CMAKE_CURRENT_BINARY_DIR}/OrxonoxConfig.h
    83   ${CMAKE_CURRENT_SOURCE_DIR}/OrxonoxConfig.h.in
    84   ${CMAKE_CURRENT_BINARY_DIR}/SpecialConfig.h
    85   ${CMAKE_CURRENT_SOURCE_DIR}/SpecialConfig.h.in
    86 )
    8751
    8852############## Include Directories ##############
  • code/trunk/src/OrxonoxConfig.h.in

    r3196 r5695  
    198198}
    199199
     200// Import general purpose smart pointers
     201namespace boost
     202{
     203    template<class T> class scoped_ptr;
     204    template<class T> class shared_ptr;
     205    template<class T> class weak_ptr;
     206    template<class T> class intrusive_ptr;
     207    template<class T> class shared_array;
     208    template<class T> class scoped_array;
     209}
     210namespace orxonox
     211{
     212    using boost::scoped_ptr;
     213    using boost::shared_ptr;
     214    using boost::weak_ptr;
     215    using boost::intrusive_ptr;
     216    using boost::shared_array;
     217    using boost::scoped_array;
     218}
     219
    200220#endif /* _OrxonoxConfig_H__ */
  • code/trunk/src/SpecialConfig.h.in

    r5693 r5695  
    7070
    7171// Handle default ConfigValues
    72 namespace orxonox
     72namespace orxonox { namespace specialConfig
    7373{
     74    // DEFAULT RELATIVE PATHS (might not be used at all)
     75    const char defaultRuntimePath[] = "@DEFAULT_RUNTIME_PATH@";
     76    const char defaultLibraryPath[] = "@DEFAULT_LIBRARY_PATH@";
     77    const char defaultArchivePath[] = "@DEFAULT_ARCHIVE_PATH@";
     78    const char defaultModulePath[]  = "@DEFAULT_MODULE_PATH@";
     79    const char defaultDocPath[]     = "@DEFAULT_DOC_PATH@";
     80    const char defaultDataPath[]    = "@DEFAULT_DATA_PATH@";
     81    const char defaultConfigPath[]  = "@DEFAULT_CONFIG_PATH@";
     82    const char defaultLogPath[]     = "@DEFAULT_LOG_PATH@";
     83
     84#ifndef INSTALL_COPYABLE
    7485    // INSTALLATION PATHS
    75     const char ORXONOX_RUNTIME_INSTALL_PATH[] = "@ORXONOX_RUNTIME_INSTALL_PATH@";
    76     const char ORXONOX_MODULE_INSTALL_PATH[]  = "@ORXONOX_MODULE_INSTALL_PATH@";
    77     const char ORXONOX_MEDIA_INSTALL_PATH[]   = "@ORXONOX_MEDIA_INSTALL_PATH@";
    78     /* Config and Log path might be relative because they could be user and therefore runtime dependent */
    79     const char ORXONOX_CONFIG_INSTALL_PATH[]  = "@ORXONOX_CONFIG_INSTALL_PATH@";
    80     const char ORXONOX_LOG_INSTALL_PATH[]     = "@ORXONOX_LOG_INSTALL_PATH@";
     86    const char dataInstallDirectory[]       = "@DATA_INSTALL_DIRECTORY@";
     87    const char moduleInstallDirectory[]     = "@MODULE_INSTALL_DIRECTORY@";
     88#endif
    8189
    8290    // DEVELOPMENT RUN PATHS
    83     const char ORXONOX_MEDIA_DEV_PATH[]       = "@CMAKE_MEDIA_OUTPUT_DIRECTORY@";
     91    const char dataDevDirectory[]           = "@DATA_DIRECTORY@";
     92    const char externalDataDevDirectory[]   = "@EXTERNAL_DATA_DIRECTORY@";
    8493#ifdef CMAKE_CONFIGURATION_TYPES
    85     const char ORXONOX_MODULE_DEV_PATH[]      = "@CMAKE_MODULE_OUTPUT_DIRECTORY@/" BOOST_PP_STRINGIZE(CMAKE_BUILD_TYPE);
    86     const char ORXONOX_CONFIG_DEV_PATH[]      = "@CMAKE_CONFIG_OUTPUT_DIRECTORY@/" BOOST_PP_STRINGIZE(CMAKE_BUILD_TYPE);
    87     const char ORXONOX_LOG_DEV_PATH[]         = "@CMAKE_LOG_OUTPUT_DIRECTORY@/"    BOOST_PP_STRINGIZE(CMAKE_BUILD_TYPE);
     94    const char moduleDevDirectory[]         = "@CMAKE_MODULE_OUTPUT_DIRECTORY@/" BOOST_PP_STRINGIZE(CMAKE_BUILD_TYPE);
     95    const char configDevDirectory[]         = "@CMAKE_CONFIG_OUTPUT_DIRECTORY@/" BOOST_PP_STRINGIZE(CMAKE_BUILD_TYPE);
     96    const char logDevDirectory[]            = "@CMAKE_LOG_OUTPUT_DIRECTORY@/"    BOOST_PP_STRINGIZE(CMAKE_BUILD_TYPE);
    8897#else
    89     const char ORXONOX_MODULE_DEV_PATH[]      = "@CMAKE_MODULE_OUTPUT_DIRECTORY@";
    90     const char ORXONOX_CONFIG_DEV_PATH[]      = "@CMAKE_CONFIG_OUTPUT_DIRECTORY@";
    91     const char ORXONOX_LOG_DEV_PATH[]         = "@CMAKE_LOG_OUTPUT_DIRECTORY@";
     98    const char moduleDevDirectory[]         = "@CMAKE_MODULE_OUTPUT_DIRECTORY@";
     99    const char configDevDirectory[]         = "@CMAKE_CONFIG_OUTPUT_DIRECTORY@";
     100    const char logDevDirectory[]            = "@CMAKE_LOG_OUTPUT_DIRECTORY@";
    92101#endif
     102
    93103#ifdef DEPENDENCY_PACKAGE_ENABLE
    94     const char ORXONOX_DEP_LIB_PATH[]        = "@DEP_LIBRARY_DIR@";
     104    const char dependencyLibraryDirectory[] = "@DEP_LIBRARY_DIR@";
    95105#endif
    96106
    97107    // Module extension
    98     const char ORXONOX_MODULE_EXTENSION[]    = "@ORXONOX_MODULE_EXTENSION@";
     108    const char moduleExtension[] = "@ORXONOX_MODULE_EXTENSION@";
    99109
    100110    // OGRE PLUGINS
    101111#ifdef NDEBUG
    102     const char ORXONOX_OGRE_PLUGINS[] = "@OGRE_PLUGINS_RELEASE@";
     112    const char ogrePlugins[] = "@OGRE_PLUGINS_RELEASE@";
    103113#  ifdef DEPENDENCY_PACKAGE_ENABLE
    104     const char ORXONOX_OGRE_PLUGINS_FOLDER[] = ".";
     114    const char ogrePluginsDirectory[] = ".";
    105115#  else
    106     const char ORXONOX_OGRE_PLUGINS_FOLDER[] = "@OGRE_PLUGINS_FOLDER_RELEASE@";
     116    const char ogrePluginsDirectory[] = "@OGRE_PLUGINS_FOLDER_RELEASE@";
    107117#  endif
    108118#else
    109     const char ORXONOX_OGRE_PLUGINS[] = "@OGRE_PLUGINS_DEBUG@";
     119    const char ogrePlugins[] = "@OGRE_PLUGINS_DEBUG@";
    110120#  ifdef DEPENDENCY_PACKAGE_ENABLE
    111     const char ORXONOX_OGRE_PLUGINS_FOLDER[] = ".";
     121    const char ogrePluginsDirectory[] = ".";
    112122#  else
    113     const char ORXONOX_OGRE_PLUGINS_FOLDER[] = "@OGRE_PLUGINS_FOLDER_DEBUG@";
     123    const char ogrePluginsDirectory[] = "@OGRE_PLUGINS_FOLDER_DEBUG@";
    114124#  endif
    115125#endif
    116 }
     126} }
    117127
    118128/**
  • code/trunk/src/ceguilua/CMakeLists.txt

    r3196 r5695  
    6363                                CEGUI.pkg
    6464  DEPENDS              ${TOLUA_PARSER_DEPENDENCIES}
    65   WORKING_DIRECTORY    ${ORXONOX_RUNTIME_LIBRARY_DIRECTORY}
     65  WORKING_DIRECTORY    ${RUNTIME_LIBRARY_DIRECTORY}
    6666  COMMENT "Generating tolua bind files for package CEGUILua"
    6767)
  • code/trunk/src/core/CMakeLists.txt

    r5693 r5695  
    3232  GUIManager.cc
    3333  Language.cc
    34   LuaBind.cc
     34  LuaState.cc
     35  MemoryArchive.cc
    3536  ObjectListBase.cc
    3637  OrxonoxClass.cc
     38  Resource.cc
    3739  WindowEventListener.cc
    3840
     
    7779  TOLUA_FILES
    7880    CommandExecutor.h
    79     LuaBind.h
     81    Loader.h
     82    LuaState.h
    8083  DEFINE_SYMBOL
    8184    "CORE_SHARED_BUILD"
  • code/trunk/src/core/Clock.h

    r3370 r5695  
    2121 *
    2222 *   Author:
    23  *      Fabian 'x3n' Landau
     23 *      Reto Grieder
    2424 *   Co-authors:
    25  *      Reto Grieder
     25 *      ...
    2626 *
    2727 */
  • code/trunk/src/core/ConfigFileManager.cc

    r3370 r5695  
    4040namespace orxonox
    4141{
    42     const char* const DEFAULT_CONFIG_FILE = "default.ini";
    43 
    44     ConfigFileManager* ConfigFileManager::singletonPtr_s = 0;
    45 
    4642    SetConsoleCommandShortcutExtern(config).argumentCompleter(0, autocompletion::configvalueclasses()).argumentCompleter(1, autocompletion::configvalues()).argumentCompleter(2, autocompletion::configvalue());
    4743    SetConsoleCommandShortcutExtern(tconfig).argumentCompleter(0, autocompletion::configvalueclasses()).argumentCompleter(1, autocompletion::configvalues()).argumentCompleter(2, autocompletion::configvalue());
     
    229225        if (!boost::filesystem::exists(filepath))
    230226        {
    231             // Try to get default one from the media folder
    232             boost::filesystem::path defaultFilepath(Core::getMediaPath() / "defaultConfig" / this->filename_);
     227            // Try to get default one from the data folder
     228            boost::filesystem::path defaultFilepath(Core::getDataPath() / "defaultConfig" / this->filename_);
    233229            if (boost::filesystem::exists(defaultFilepath))
    234230            {
     
    339335    void ConfigFile::save() const
    340336    {
    341         boost::filesystem::path filepath(Core::getConfigPath() / this->filename_);
    342 
    343337        std::ofstream file;
    344         file.open(filepath.string().c_str(), std::fstream::out);
     338        file.open((Core::getConfigPathString() + filename_).c_str(), std::fstream::out);
    345339        file.setf(std::ios::fixed, std::ios::floatfield);
    346340        file.precision(6);
     
    479473    ///////////////////////
    480474
     475    ConfigFileManager* ConfigFileManager::singletonPtr_s = 0;
     476
     477    std::string ConfigFileManager::DEFAULT_CONFIG_FILE = "default.ini";
     478
    481479    ConfigFileManager::ConfigFileManager()
    482480         : mininmalFreeType_(ConfigFileType::numberOfReservedTypes)
  • code/trunk/src/core/ConfigFileManager.h

    r3370 r5695  
    307307            void updateConfigValues(ConfigFileType type);
    308308
     309            static std::string DEFAULT_CONFIG_FILE;
     310
    309311        private:
    310312            ConfigFileManager(const ConfigFileManager&);
  • code/trunk/src/core/ConfigValueContainer.h

    r3301 r5695  
    3131    @brief Definition of the ConfigValueContainer class.
    3232
    33     The ConfigValueContainer class contains all needed informations about a configurable variable:
     33    The ConfigValueContainer class contains all needed information about a configurable variable:
    3434     - the name of the variable
    3535     - the name of the class the variable belongs to
     
    7979
    8080
    81     //! The ConfigValuecontainer contains all needed informations about a configurable variable.
     81    //! The ConfigValuecontainer contains all needed information about a configurable variable.
    8282    /**
    83         The ConfigValueContainer class contains all needed informations about a configurable variable:
     83        The ConfigValueContainer class contains all needed information about a configurable variable:
    8484         - the name of the variable
    8585         - the name of the class the variable belongs to
  • code/trunk/src/core/Core.cc

    r5693 r5695  
    4242#include <boost/version.hpp>
    4343#include <boost/filesystem.hpp>
    44 #include <OgreRenderWindow.h>
    4544
    4645#ifdef ORXONOX_PLATFORM_WINDOWS
     
    7675#include "Identifier.h"
    7776#include "Language.h"
    78 #include "LuaBind.h"
     77#include "LuaState.h"
    7978#include "Shell.h"
    8079#include "TclBind.h"
     
    9493    Core* Core::singletonPtr_s  = 0;
    9594
    96     SetCommandLineArgument(mediaPath, "").information("Path to the media/data files");
     95    SetCommandLineArgument(externalDataPath, "").information("Path to the external data files");
    9796    SetCommandLineOnlyArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");
    9897    SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file");
     
    119118            this->setConfigValues();
    120119
    121             // Possible media path override by the command line
    122             if (!CommandLine::getArgument("mediaPath")->hasDefaultValue())
    123                 tsetMediaPath(CommandLine::getValue("mediaPath"));
     120            // External data directory only exists for dev runs
     121            if (Core::isDevelopmentRun())
     122            {
     123                // Possible data path override by the command line
     124                if (!CommandLine::getArgument("externalDataPath")->hasDefaultValue())
     125                    tsetExternalDataPath(CommandLine::getValue("externalDataPath"));
     126            }
    124127        }
    125128
     
    154157                .description("If true, all random actions are different each time you start the game")
    155158                .callback(this, &CoreConfiguration::initializeRandomNumberGenerator);
    156 
    157             // Only show this config value for development builds
    158             if (Core::isDevelopmentRun())
    159             {
    160                 SetConfigValue(mediaPathString_, mediaPath_.string())
    161                     .description("Relative path to the game data.")
    162                     .callback(this, &CoreConfiguration::mediaPathChanged);
    163             }
    164159        }
    165160
     
    192187
    193188        /**
    194         @brief
    195             Callback function if the media path has changed.
    196         */
    197         void mediaPathChanged()
    198         {
    199             mediaPath_ = boost::filesystem::path(this->mediaPathString_);
    200         }
    201 
    202         /**
    203189            @brief Sets the language in the config-file back to the default.
    204190        */
     
    210196        /**
    211197        @brief
    212             Temporary sets the media path
     198            Temporary sets the data path
    213199        @param path
    214             The new media path
     200            The new data path
    215201        */
    216         void tsetMediaPath(const std::string& path)
    217         {
    218             if (Core::isDevelopmentRun())
    219             {
    220                 ModifyConfigValue(mediaPathString_, tset, path);
    221             }
    222             else
    223             {
    224                 // Manual 'config' value without the file entry
    225                 mediaPathString_ = path;
    226                 this->mediaPathChanged();
    227             }
     202        void tsetExternalDataPath(const std::string& path)
     203        {
     204            dataPath_ = boost::filesystem::path(path);
    228205        }
    229206
     
    245222        std::string language_;                          //!< The language
    246223        bool bInitializeRandomNumberGenerator_;         //!< If true, srand(time(0)) is called
    247         std::string mediaPathString_;                   //!< Path to the data/media file folder as string
    248224
    249225        //! Path to the parent directory of the ones above if program was installed with relativ pahts
     
    251227        boost::filesystem::path executablePath_;        //!< Path to the executable
    252228        boost::filesystem::path modulePath_;            //!< Path to the modules
    253         boost::filesystem::path mediaPath_;             //!< Path to the media file folder
     229        boost::filesystem::path dataPath_;              //!< Path to the data file folder
     230        boost::filesystem::path externalDataPath_;      //!< Path to the external data file folder
    254231        boost::filesystem::path configPath_;            //!< Path to the config file folder
    255232        boost::filesystem::path logPath_;               //!< Path to the log file folder
     
    276253        {
    277254            // We search for helper files with the following extension
    278             std::string moduleextension = ORXONOX_MODULE_EXTENSION;
     255            std::string moduleextension = specialConfig::moduleExtension;
    279256            size_t moduleextensionlength = moduleextension.size();
    280257
     
    364341        this->languageInstance_.reset(new Language());
    365342
     343        // creates the class hierarchy for all classes with factories
     344        Factory::createClassHierarchy();
     345
    366346        // Do this soon after the ConfigFileManager has been created to open up the
    367347        // possibility to configure everything below here
    368348        this->configuration_->initialise();
    369349
    370         // Create the lua interface
    371         this->luaBind_.reset(new LuaBind());
     350        // Load OGRE excluding the renderer and the render window
     351        this->graphicsManager_.reset(new GraphicsManager(false));
    372352
    373353        // initialise Tcl
    374         this->tclBind_.reset(new TclBind(Core::getMediaPathString()));
     354        this->tclBind_.reset(new TclBind(Core::getDataPathString()));
    375355        this->tclThreadManager_.reset(new TclThreadManager(tclBind_->getTclInterpreter()));
    376356
    377357        // create a shell
    378358        this->shell_.reset(new Shell());
    379 
    380         // creates the class hierarchy for all classes with factories
    381         Factory::createClassHierarchy();
    382359    }
    383360
    384361    /**
    385362    @brief
    386         All destruction code is handled by scoped_ptrs and SimpleScopeGuards.
     363        All destruction code is handled by scoped_ptrs and ScopeGuards.
    387364    */
    388365    Core::~Core()
     
    392369    void Core::loadGraphics()
    393370    {
    394         if (bGraphicsLoaded_)
    395             return;
    396 
    397         // Load OGRE including the render window
    398         scoped_ptr<GraphicsManager> graphicsManager(new GraphicsManager());
    399 
    400         // The render window width and height are used to set up the mouse movement.
    401         size_t windowHnd = 0;
    402         graphicsManager->getRenderWindow()->getCustomAttribute("WINDOW", &windowHnd);
     371        // Any exception should trigger this, even in upgradeToGraphics (see its remarks)
     372        Loki::ScopeGuard unloader = Loki::MakeObjGuard(*this, &Core::unloadGraphics);
     373
     374        // Upgrade OGRE to receive a render window
     375        graphicsManager_->upgradeToGraphics();
    403376
    404377        // Calls the InputManager which sets up the input devices.
    405         scoped_ptr<InputManager> inputManager(new InputManager(windowHnd));
     378        inputManager_.reset(new InputManager());
    406379
    407380        // load the CEGUI interface
    408         guiManager_.reset(new GUIManager(graphicsManager->getRenderWindow()));
    409 
    410         // Dismiss scoped pointers
    411         graphicsManager_.swap(graphicsManager);
    412         inputManager_.swap(inputManager);
     381        guiManager_.reset(new GUIManager(graphicsManager_->getRenderWindow(),
     382            inputManager_->getMousePosition(), graphicsManager_->isFullScreen()));
     383
     384        unloader.Dismiss();
    413385
    414386        bGraphicsLoaded_ = true;
     
    417389    void Core::unloadGraphics()
    418390    {
    419         if (!bGraphicsLoaded_)
    420             return;
    421 
    422391        this->guiManager_.reset();;
    423392        this->inputManager_.reset();;
    424393        this->graphicsManager_.reset();
     394
     395        // Load Ogre::Root again, but without the render system
     396        try
     397            { this->graphicsManager_.reset(new GraphicsManager(false)); }
     398        catch (...)
     399        {
     400            COUT(0) << "An exception occurred during 'new GraphicsManager' while "
     401                    << "another exception was being handled. This will lead to undefined behaviour!" << std::endl
     402                    << "Terminating the program." << std::endl;
     403            abort();
     404        }
    425405
    426406        bGraphicsLoaded_ = false;
     
    485465    }
    486466
    487     /*static*/ void Core::tsetMediaPath(const std::string& path)
    488     {
    489         getInstance().configuration_->tsetMediaPath(path);
    490     }
    491 
    492     /*static*/ const boost::filesystem::path& Core::getMediaPath()
    493     {
    494         return getInstance().configuration_->mediaPath_;
    495     }
    496     /*static*/ std::string Core::getMediaPathString()
    497     {
    498         return getInstance().configuration_->mediaPath_.string() + '/';
     467    /*static*/ void Core::tsetExternalDataPath(const std::string& path)
     468    {
     469        getInstance().configuration_->tsetExternalDataPath(path);
     470    }
     471
     472    /*static*/ const boost::filesystem::path& Core::getDataPath()
     473    {
     474        return getInstance().configuration_->dataPath_;
     475    }
     476    /*static*/ std::string Core::getDataPathString()
     477    {
     478        return getInstance().configuration_->dataPath_.string() + '/';
     479    }
     480
     481    /*static*/ const boost::filesystem::path& Core::getExternalDataPath()
     482    {
     483        return getInstance().configuration_->externalDataPath_;
     484    }
     485    /*static*/ std::string Core::getExternalDataPathString()
     486    {
     487        return getInstance().configuration_->externalDataPath_.string() + '/';
    499488    }
    500489
     
    638627            COUT(1) << "Running from the build tree." << std::endl;
    639628            Core::bDevRun_ = true;
    640             configuration_->modulePath_ = ORXONOX_MODULE_DEV_PATH;
     629            configuration_->modulePath_ = specialConfig::moduleDevDirectory;
    641630        }
    642631        else
     
    646635
    647636            // Also set the root path
    648             boost::filesystem::path relativeExecutablePath(ORXONOX_RUNTIME_INSTALL_PATH);
     637            boost::filesystem::path relativeExecutablePath(specialConfig::defaultRuntimePath);
    649638            configuration_->rootPath_ = configuration_->executablePath_;
    650639            while (!boost::filesystem::equivalent(configuration_->rootPath_ / relativeExecutablePath, configuration_->executablePath_)
     
    655644
    656645            // Module path is fixed as well
    657             configuration_->modulePath_ = configuration_->rootPath_ / ORXONOX_MODULE_INSTALL_PATH;
     646            configuration_->modulePath_ = configuration_->rootPath_ / specialConfig::defaultModulePath;
    658647
    659648#else
     
    661650            // There is no root path, so don't set it at all
    662651            // Module path is fixed as well
    663             configuration_->modulePath_ = ORXONOX_MODULE_INSTALL_PATH;
     652            configuration_->modulePath_ = specialConfig::moduleInstallDirectory;
    664653
    665654#endif
     
    677666        if (Core::isDevelopmentRun())
    678667        {
    679             configuration_->mediaPath_  = ORXONOX_MEDIA_DEV_PATH;
    680             configuration_->configPath_ = ORXONOX_CONFIG_DEV_PATH;
    681             configuration_->logPath_    = ORXONOX_LOG_DEV_PATH;
     668            configuration_->dataPath_  = specialConfig::dataDevDirectory;
     669            configuration_->externalDataPath_ = specialConfig::externalDataDevDirectory;
     670            configuration_->configPath_ = specialConfig::configDevDirectory;
     671            configuration_->logPath_    = specialConfig::logDevDirectory;
    682672        }
    683673        else
     
    687677
    688678            // Using paths relative to the install prefix, complete them
    689             configuration_->mediaPath_  = configuration_->rootPath_ / ORXONOX_MEDIA_INSTALL_PATH;
    690             configuration_->configPath_ = configuration_->rootPath_ / ORXONOX_CONFIG_INSTALL_PATH;
    691             configuration_->logPath_    = configuration_->rootPath_ / ORXONOX_LOG_INSTALL_PATH;
     679            configuration_->dataPath_   = configuration_->rootPath_ / specialConfig::defaultDataPath;
     680            configuration_->configPath_ = configuration_->rootPath_ / specialConfig::defaultConfigPath;
     681            configuration_->logPath_    = configuration_->rootPath_ / specialConfig::defaultLogPath;
    692682
    693683#else
    694684
    695             configuration_->mediaPath_  = ORXONOX_MEDIA_INSTALL_PATH;
     685            configuration_->dataPath_  = specialConfig::dataInstallDirectory;
    696686
    697687            // Get user directory
     
    706696            userDataPath /= ".orxonox";
    707697
    708             configuration_->configPath_ = userDataPath / ORXONOX_CONFIG_INSTALL_PATH;
    709             configuration_->logPath_    = userDataPath / ORXONOX_LOG_INSTALL_PATH;
     698            configuration_->configPath_ = userDataPath / specialConfig::defaultConfigPath;
     699            configuration_->logPath_    = userDataPath / specialConfig::defaultLogPath;
    710700
    711701#endif
     
    741731    }
    742732
    743     bool Core::preUpdate(const Clock& time) throw()
    744     {
    745         std::string exceptionMessage;
    746         try
    747         {
    748             if (this->bGraphicsLoaded_)
    749             {
    750                 // process input events
    751                 this->inputManager_->update(time);
    752                 // process gui events
    753                 this->guiManager_->update(time);
    754             }
    755             // process thread commands
    756             this->tclThreadManager_->update(time);
    757         }
    758         catch (const std::exception& ex)
    759         { exceptionMessage = ex.what(); }
    760         catch (...)
    761         { exceptionMessage = "Unknown exception"; }
    762         if (!exceptionMessage.empty())
    763         {
    764             COUT(0) << "An exception occurred in the Core preUpdate: " << exceptionMessage << std::endl;
    765             COUT(0) << "This should really never happen! Closing the program." << std::endl;
    766             return false;
    767         }
    768         return true;
    769     }
    770 
    771     bool Core::postUpdate(const Clock& time) throw()
    772     {
    773         std::string exceptionMessage;
    774         try
    775         {
    776             if (this->bGraphicsLoaded_)
    777             {
    778                 // Render (doesn't throw)
    779                 this->graphicsManager_->update(time);
    780             }
    781         }
    782         catch (const std::exception& ex)
    783         { exceptionMessage = ex.what(); }
    784         catch (...)
    785         { exceptionMessage = "Unknown exception"; }
    786         if (!exceptionMessage.empty())
    787         {
    788             COUT(0) << "An exception occurred in the Core postUpdate: " << exceptionMessage << std::endl;
    789             COUT(0) << "This should really never happen! Closing the program." << std::endl;
    790             return false;
    791         }
    792         return true;
     733    void Core::preUpdate(const Clock& time)
     734    {
     735        if (this->bGraphicsLoaded_)
     736        {
     737            // process input events
     738            this->inputManager_->update(time);
     739            // process gui events
     740            this->guiManager_->update(time);
     741        }
     742        // process thread commands
     743        this->tclThreadManager_->update(time);
     744    }
     745
     746    void Core::postUpdate(const Clock& time)
     747    {
     748        if (this->bGraphicsLoaded_)
     749        {
     750            // Render (doesn't throw)
     751            this->graphicsManager_->update(time);
     752        }
    793753    }
    794754}
  • code/trunk/src/core/Core.h

    r5693 r5695  
    5151{
    5252    class CoreConfiguration;
    53     using boost::scoped_ptr;
    5453
    5554    /**
     
    5756        The Core class is a singleton used to configure the program basics.
    5857    @details
    59         The class provides information about the media, config and log path.
     58        The class provides information about the data, config and log path.
    6059        It determines those by the use of platform specific functions.
    6160    @remark
     
    6665        typedef Loki::ScopeGuardImpl0<void (*)()> SimpleScopeGuard;
    6766        friend class Singleton<Core>;
     67        friend class Game;
    6868
    6969        public:
     
    8080            void setConfigValues();
    8181
    82             bool preUpdate(const Clock& time) throw();
    83             bool postUpdate(const Clock& time) throw();
    84 
    85             void loadGraphics();
    86             void unloadGraphics();
    87 
    8882            static int   getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
    8983            static void  setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
     
    9185            static void  resetLanguage();
    9286
    93             static void tsetMediaPath(const std::string& path);
    94             //! Returns the path to the config files as boost::filesystem::path
    95             static const boost::filesystem::path& getMediaPath();
     87            static void tsetExternalDataPath(const std::string& path);
     88            //! Returns the path to the data files as boost::filesystem::path
     89            static const boost::filesystem::path& getDataPath();
     90            //! Returns the path to the external data files as boost::filesystem::path
     91            static const boost::filesystem::path& getExternalDataPath();
    9692            //! Returns the path to the config files as boost::filesystem::path
    9793            static const boost::filesystem::path& getConfigPath();
     
    10197            static const boost::filesystem::path& getRootPath();
    10298            //! Returns the path to the data files as std::string
    103             static std::string getMediaPathString();
     99            static std::string getDataPathString();
     100            //! Returns the path to the external data files as std::string
     101            static std::string getExternalDataPathString();
    104102            //! Returns the path to the config files as std::string
    105103            static std::string getConfigPathString();
     
    113111        private:
    114112            Core(const Core&); //!< Don't use (undefined symbol)
     113
     114            void preUpdate(const Clock& time);
     115            void postUpdate(const Clock& time);
     116
     117            void loadGraphics();
     118            void unloadGraphics();
    115119
    116120            void setFixedPaths();
     
    126130            scoped_ptr<Language>          languageInstance_;
    127131            scoped_ptr<CoreConfiguration> configuration_;
    128             scoped_ptr<LuaBind>           luaBind_;
    129132            scoped_ptr<TclBind>           tclBind_;
    130133            scoped_ptr<TclThreadManager>  tclThreadManager_;
  • code/trunk/src/core/CorePrereqs.h

    r5693 r5695  
    135135    class LanguageEntry;
    136136    class Loader;
    137     class LuaBind;
     137    class LuaState;
     138    class MemoryArchive;
     139    class MemoryArchiveFactory;
    138140    class MetaObjectList;
    139141    class MetaObjectListElement;
     
    150152    class OgreWindowEventListener;
    151153    class OrxonoxClass;
     154    struct ResourceInfo;
    152155    class Shell;
    153156    class ShellListener;
     
    225228}
    226229
     230// Ogre
     231namespace Ogre
     232{
     233    class DataStream;
     234    template <class T> class SharedPtr;
     235    typedef SharedPtr<DataStream> DataStreamPtr;
     236}
     237namespace orxonox
     238{
     239    // Import the Ogre::DataStream
     240    using Ogre::DataStream;
     241    using Ogre::DataStreamPtr;
     242}
     243
    227244// CEGUI
    228245namespace CEGUI
  • code/trunk/src/core/DynLibManager.h

    r5693 r5695  
    3434
    3535#include "CorePrereqs.h"
     36
     37#include <map>
     38#include <string>
    3639#include "util/Singleton.h"
    3740
  • code/trunk/src/core/GUIManager.cc

    r3370 r5695  
    2727 *
    2828 */
    29 
    30 /**
    31 @file
    32 @brief
    33     Implementation of the GUIManager class.
    34 */
    3529
    3630#include "GUIManager.h"
     
    4337#include <CEGUIExceptions.h>
    4438#include <CEGUIInputEvent.h>
     39#include <CEGUIMouseCursor.h>
    4540#include <CEGUIResourceProvider.h>
    4641#include <CEGUISystem.h>
     
    5954#include "Core.h"
    6055#include "Clock.h"
    61 #include "LuaBind.h"
     56#include "LuaState.h"
     57#include "Resource.h"
    6258
    6359namespace orxonox
     
    10197    @return true if success, otherwise false
    10298    */
    103     GUIManager::GUIManager(Ogre::RenderWindow* renderWindow)
     99    GUIManager::GUIManager(Ogre::RenderWindow* renderWindow, const std::pair<int, int>& mousePosition, bool bFullScreen)
    104100        : renderWindow_(renderWindow)
    105101        , resourceProvider_(0)
     
    109105        COUT(3) << "Initialising CEGUI." << std::endl;
    110106
    111         try
    112         {
    113             // Note: No SceneManager specified yet
    114             guiRenderer_.reset(new OgreCEGUIRenderer(renderWindow_, Ogre::RENDER_QUEUE_OVERLAY, false, 3000));
    115             resourceProvider_ = guiRenderer_->createResourceProvider();
    116             resourceProvider_->setDefaultResourceGroup("GUI");
    117 
    118             // setup scripting
    119             scriptModule_.reset(new LuaScriptModule());
    120             luaState_ = scriptModule_->getLuaState();
    121 
    122             // Create our own logger to specify the filepath
    123             std::auto_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
    124             ceguiLogger->setLogFilename(Core::getLogPathString() + "cegui.log");
    125             // set the log level according to ours (translate by subtracting 1)
    126             ceguiLogger->setLoggingLevel(
    127                 static_cast<LoggingLevel>(Core::getSoftDebugLevel(OutputHandler::LD_Logfile) - 1));
    128             this->ceguiLogger_ = ceguiLogger.release();
    129 
    130             // create the CEGUI system singleton
    131             guiSystem_.reset(new System(guiRenderer_.get(), resourceProvider_, 0, scriptModule_.get()));
    132 
    133             // do this after 'new CEGUI::Sytem' because that creates the lua state in the first place
    134             LuaBind::getInstance().openToluaInterfaces(this->luaState_);
    135 
    136             // initialise the basic lua code
    137             this->loadLuaCode();
    138         }
    139         catch (CEGUI::Exception& ex)
    140         {
    141 #if CEGUI_VERSION_MAJOR == 0 && CEGUI_VERSION_MINOR < 6
    142             throw GeneralException(ex.getMessage().c_str());
    143 #else
    144             throw GeneralException(ex.getMessage().c_str(), ex.getLine(),
    145                 ex.getFileName().c_str(), ex.getName().c_str());
    146 #endif
    147         }
    148     }
    149 
    150     /**
    151     @brief
    152         Destructor of the GUIManager
    153 
     107        // Note: No SceneManager specified yet
     108        guiRenderer_.reset(new OgreCEGUIRenderer(renderWindow_, Ogre::RENDER_QUEUE_OVERLAY, false, 3000));
     109        resourceProvider_ = guiRenderer_->createResourceProvider();
     110        resourceProvider_->setDefaultResourceGroup("GUI");
     111
     112        // setup scripting
     113        luaState_.reset(new LuaState());
     114        scriptModule_.reset(new LuaScriptModule(luaState_->getInternalLuaState()));
     115
     116        // Create our own logger to specify the filepath
     117        std::auto_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
     118        ceguiLogger->setLogFilename(Core::getLogPathString() + "cegui.log");
     119        // set the log level according to ours (translate by subtracting 1)
     120        ceguiLogger->setLoggingLevel(
     121            static_cast<LoggingLevel>(Core::getSoftDebugLevel(OutputHandler::LD_Logfile) - 1));
     122        this->ceguiLogger_ = ceguiLogger.release();
     123
     124        // create the CEGUI system singleton
     125        guiSystem_.reset(new System(guiRenderer_.get(), resourceProvider_, 0, scriptModule_.get()));
     126
     127        // Initialise the basic lua code
     128        rootFileInfo_ = Resource::getInfo("InitialiseGUI.lua", "GUI");
     129        this->luaState_->doFile("InitialiseGUI.lua", "GUI", false);
     130
     131        // Align CEGUI mouse with OIS mouse
     132        guiSystem_->injectMousePosition(mousePosition.first, mousePosition.second);
     133
     134        // Hide the mouse cursor unless playing in fullscreen mode
     135        if (!bFullScreen)
     136            CEGUI::MouseCursor::getSingleton().hide();
     137    }
     138
     139    /**
     140    @brief
    154141        Basically shuts down CEGUI (member smart pointers) but first unloads our Tolua modules.
    155142    */
    156143    GUIManager::~GUIManager()
    157144    {
    158         // destroy our own tolua interfaces
    159         LuaBind::getInstance().closeToluaInterfaces(this->luaState_);
    160     }
    161 
    162     /**
    163     @brief
    164         Calls main Lua script
    165     @todo
    166         This function calls the main Lua script for our GUI.
    167 
    168         Additionally we set the datapath variable in Lua. This is needed so Lua can access the data used for the GUI.
    169     */
    170     void GUIManager::loadLuaCode()
    171     {
    172         // set datapath for GUI data
    173         lua_pushfstring(this->scriptModule_->getLuaState(), Core::getMediaPathString().c_str());
    174         lua_setglobal(this->scriptModule_->getLuaState(), "datapath");
    175         // call main Lua script
    176         this->scriptModule_->executeScriptFile("loadGUI_3.lua", "GUI");
    177145    }
    178146
     
    221189    void GUIManager::executeCode(const std::string& str)
    222190    {
    223         try
    224         {
    225             this->scriptModule_->executeString(str);
    226         }
    227         catch (const CEGUI::Exception& ex)
    228         {
    229             COUT(2) << "CEGUI Error: \"" << ex.getMessage() << "\" while executing code \"" << str << "\"" << std::endl;
    230         }
    231         catch (...)
    232         {
    233             COUT(2) << "Couldn't execute GUI related Lua code due to unknown reasons." << std::endl;
    234         }
     191        this->luaState_->doString(str, rootFileInfo_);
    235192    }
    236193
     
    246203    void GUIManager::showGUI(const std::string& name)
    247204    {
    248         this->executeCode(std::string("showGUI(\"") + name + "\")");
     205        this->luaState_->doString("showGUI(\"" + name + "\")", rootFileInfo_);
    249206    }
    250207
     
    305262    void GUIManager::mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize)
    306263    {
    307         guiSystem_->injectMouseMove(static_cast<float>(rel.x), static_cast<float>(rel.y));
     264        guiSystem_->injectMousePosition(static_cast<float>(abs.x), static_cast<float>(abs.y));
    308265    }
    309266    void GUIManager::mouseScrolled(int abs, int rel)
  • code/trunk/src/core/GUIManager.h

    r5693 r5695  
    2828 */
    2929
    30 /**
    31 @file
    32 @brief
    33     Declaration of the GUIManager class.
    34 */
    35 
    3630#ifndef _GUIManager_H__
    3731#define _GUIManager_H__
     
    4337#include <CEGUIForwardRefs.h>
    4438#include <boost/scoped_ptr.hpp>
     39#include <boost/shared_ptr.hpp>
    4540
    4641#include "util/OgreForwardRefs.h"
     
    6762        friend class Singleton<GUIManager>;
    6863    public:
    69         GUIManager(Ogre::RenderWindow* renderWindow);
     64        GUIManager(Ogre::RenderWindow* renderWindow, const std::pair<int, int>& mousePosition, bool bFullScreen);
    7065        ~GUIManager();
    7166
     
    8782        GUIManager(const GUIManager& instance); //!< private and undefined copy c'tor (this is a singleton class)
    8883
    89         void loadLuaCode();
    90 
    9184        // keyHandler functions
    9285        void keyPressed (const KeyEvent& evt);
     
    9992        void mouseScrolled (int abs, int rel);
    10093
    101         boost::scoped_ptr<CEGUI::OgreCEGUIRenderer> guiRenderer_;       //!< CEGUI's interface to the Ogre Engine
    102         boost::scoped_ptr<CEGUI::LuaScriptModule>   scriptModule_;      //!< CEGUI's script module to use Lua
    103         boost::scoped_ptr<CEGUI::System>            guiSystem_;         //!< CEGUI's main system
    104         Ogre::RenderWindow*                         renderWindow_;      //!< Ogre's render window to give CEGUI access to it
    105         CEGUI::ResourceProvider*                    resourceProvider_;  //!< CEGUI's resource provider
    106         CEGUI::Logger*                              ceguiLogger_;       //!< CEGUI's logger to be able to log CEGUI errors in our log
    107         lua_State*                                  luaState_;          //!< Lua state, access point to the Lua engine
    108         std::map<std::string, PlayerInfo*>          players_;           //!< Stores the player (owner) for each gui
     94        scoped_ptr<CEGUI::OgreCEGUIRenderer> guiRenderer_;      //!< CEGUI's interface to the Ogre Engine
     95        scoped_ptr<LuaState>                 luaState_;         //!< LuaState, access point to the Lua engine
     96        scoped_ptr<CEGUI::LuaScriptModule>   scriptModule_;     //!< CEGUI's script module to use Lua
     97        scoped_ptr<CEGUI::System>            guiSystem_;        //!< CEGUI's main system
     98        shared_ptr<ResourceInfo>             rootFileInfo_;     //!< Resource information about the root script
     99        Ogre::RenderWindow*                  renderWindow_;     //!< Ogre's render window to give CEGUI access to it
     100        CEGUI::ResourceProvider*             resourceProvider_; //!< CEGUI's resource provider
     101        CEGUI::Logger*                       ceguiLogger_;      //!< CEGUI's logger to be able to log CEGUI errors in our log
     102        std::map<std::string, PlayerInfo*>   players_;          //!< Stores the player (owner) for each gui
    109103
    110         static GUIManager*                          singletonPtr_s;     //!< Singleton reference to GUIManager
     104        static GUIManager*                   singletonPtr_s;    //!< Singleton reference to GUIManager
    111105
    112106    };
  • code/trunk/src/core/Game.cc

    r5693 r5695  
    3737#include <exception>
    3838#include <boost/weak_ptr.hpp>
     39#include <CEGUIExceptions.h>
    3940
    4041#include "util/Debug.h"
     
    5455namespace orxonox
    5556{
    56     using boost::shared_ptr;
    57     using boost::weak_ptr;
    58 
    5957    static void stop_game()
    6058        { Game::getInstance().stop(); }
     
    202200
    203201            // Core preUpdate (doesn't throw)
    204             if (!this->core_->preUpdate(*this->gameClock_))
    205             {
     202            try
     203                { this->core_->preUpdate(*this->gameClock_); }
     204            catch (...)
     205            {
     206                COUT(0) << "An exception occurred in the Core preUpdate: " << Game::getExceptionMessage() << std::endl;
     207                COUT(0) << "This should really never happen! Closing the program." << std::endl;
    206208                this->stop();
    207209                break;
     
    212214
    213215            // Core postUpdate (doesn't throw)
    214             if (!this->core_->postUpdate(*this->gameClock_))
    215             {
     216            try
     217                { this->core_->postUpdate(*this->gameClock_); }
     218            catch (...)
     219            {
     220            COUT(0) << "An exception occurred in the Core postUpdate: " << Game::getExceptionMessage() << std::endl;
     221            COUT(0) << "This should really never happen! Closing the program." << std::endl;
    216222                this->stop();
    217223                break;
     
    246252                    this->loadState(requestedStateNode->name_);
    247253                }
    248                 catch (const std::exception& ex)
     254                catch (...)
    249255                {
    250                     COUT(1) << "Error: Loading GameState '" << requestedStateNode->name_ << "' failed: " << ex.what() << std::endl;
     256                    COUT(1) << "Error: Loading GameState '" << requestedStateNode->name_ << "' failed: " << Game::getExceptionMessage() << std::endl;
    251257                    // All scheduled operations have now been rendered inert --> flush them and issue a warning
    252258                    if (this->requestedStateNodes_.size() > 1)
    253                         COUT(1) << "All " << this->requestedStateNodes_.size() - 1 << " scheduled transitions have been ignored." << std::endl;
     259                        COUT(4) << "All " << this->requestedStateNodes_.size() - 1 << " scheduled transitions have been ignored." << std::endl;
    254260                    this->requestedStateNodes_.clear();
    255261                    break;
     
    267273            it != this->loadedStates_.end(); ++it)
    268274        {
    269             std::string exceptionMessage;
    270275            try
    271276            {
    272277                // Add tick time for most of the states
    273                 uint64_t timeBeforeTick;
     278                uint64_t timeBeforeTick = 0;
    274279                if ((*it)->getInfo().bIgnoreTickTime)
    275280                    timeBeforeTick = this->gameClock_->getRealMicroseconds();
     
    278283                    this->subtractTickTime(static_cast<int32_t>(this->gameClock_->getRealMicroseconds() - timeBeforeTick));
    279284            }
    280             catch (const std::exception& ex)
    281             { exceptionMessage = ex.what(); }
    282285            catch (...)
    283             { exceptionMessage = "Unknown exception"; }
    284             if (!exceptionMessage.empty())
    285             {
    286                 COUT(1) << "An exception occurred while updating '" << (*it)->getName() << "': " << exceptionMessage << std::endl;
     286            {
     287                COUT(1) << "An exception occurred while updating '" << (*it)->getName() << "': " << Game::getExceptionMessage() << std::endl;
    287288                COUT(1) << "This should really never happen!" << std::endl;
    288289                COUT(1) << "Unloading all GameStates depending on the one that crashed." << std::endl;
     
    590591            state->deactivate();
    591592        }
     593        catch (...)
     594        {
     595            COUT(2) << "Warning: Unloading GameState '" << name << "' threw an exception: " << Game::getExceptionMessage() << std::endl;
     596            COUT(2) << "         There might be potential resource leaks involved! To avoid this, improve exception-safety." << std::endl;
     597        }
     598        // Check if graphics is still required
     599        if (!bAbort_)
     600        {
     601            bool graphicsRequired = false;
     602            for (unsigned i = 0; i < loadedStates_.size(); ++i)
     603                graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
     604            if (!graphicsRequired)
     605                this->unloadGraphics();
     606        }
     607        this->bChangingState_ = false;
     608    }
     609
     610    /*static*/ std::string Game::getExceptionMessage()
     611    {
     612        std::string exceptionMessage;
     613        try
     614        {
     615            // rethrow
     616            throw;
     617        }
    592618        catch (const std::exception& ex)
    593619        {
    594             COUT(2) << "Warning: Unloading GameState '" << name << "' threw an exception: " << ex.what() << std::endl;
    595             COUT(2) << "         There might be potential resource leaks involved! To avoid this, improve exception-safety." << std::endl;
    596         }
    597         // Check if graphics is still required
    598         bool graphicsRequired = false;
    599         for (unsigned i = 0; i < loadedStates_.size(); ++i)
    600             graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
    601         if (!graphicsRequired)
    602             this->unloadGraphics();
    603         this->bChangingState_ = false;
     620            return ex.what();
     621        }
     622        catch (const CEGUI::Exception& ex)
     623        {
     624#if CEGUI_VERSION_MAJOR == 0 && CEGUI_VERSION_MINOR < 6
     625            return GeneralException(ex.getMessage().c_str()).getDescription();
     626#else
     627            return GeneralException(ex.getMessage().c_str(), ex.getLine(),
     628                ex.getFileName().c_str(), ex.getName().c_str()).getDescription();
     629#endif
     630        }
     631        catch (...)
     632        {
     633            return "Unknown exception";
     634        }
    604635    }
    605636
  • code/trunk/src/core/Game.h

    r5693 r5695  
    6262{
    6363    class GameConfiguration;
    64     using boost::scoped_ptr;
    65     using boost::shared_ptr;
    6664
    6765    //! Helper object required before GameStates are being constructed
     
    8583        typedef std::vector<shared_ptr<GameState> > GameStateVector;
    8684        typedef std::map<std::string, shared_ptr<GameState> > GameStateMap;
    87         typedef boost::shared_ptr<GameStateTreeNode> GameStateTreeNodePtr;
     85        typedef shared_ptr<GameStateTreeNode> GameStateTreeNodePtr;
    8886
    8987    public:
     
    157155        // ScopeGuard helper function
    158156        void resetChangingState() { this->bChangingState_ = false; }
     157        /**
     158        @brief
     159            Retrieves information from an exception caught with "..."
     160        @remarks
     161            Never ever call this function without an exception in the stack!
     162        */
     163        static std::string getExceptionMessage();
    159164
    160165        scoped_ptr<Clock>                  gameClock_;
  • code/trunk/src/core/GraphicsManager.cc

    r3370 r5695  
    2828 */
    2929
    30 /**
    31 @file
    32 @brief
    33     Implementation of an partial interface to Ogre.
    34 */
    35 
    3630#include "GraphicsManager.h"
    3731
    3832#include <fstream>
    39 #include <memory>
     33#include <sstream>
    4034#include <boost/filesystem.hpp>
    41 #include <boost/shared_ptr.hpp>
    42 
    43 #include <OgreCompositorManager.h>
    44 #include <OgreConfigFile.h>
     35#include <boost/shared_array.hpp>
     36
     37#include <OgreArchiveFactory.h>
     38#include <OgreArchiveManager.h>
    4539#include <OgreFrameListener.h>
    4640#include <OgreRoot.h>
    4741#include <OgreLogManager.h>
    48 #include <OgreException.h>
    4942#include <OgreRenderWindow.h>
    5043#include <OgreRenderSystem.h>
     44#include <OgreResourceGroupManager.h>
    5145#include <OgreTextureManager.h>
    5246#include <OgreViewport.h>
     
    6458#include "Game.h"
    6559#include "GameMode.h"
     60#include "Loader.h"
     61#include "MemoryArchive.h"
    6662#include "WindowEventListener.h"
     63#include "XMLFile.h"
    6764
    6865namespace orxonox
    6966{
    70     using boost::shared_ptr;
    71 
    7267    class OgreWindowEventListener : public Ogre::WindowEventListener
    7368    {
     
    8984        Non-initialising constructor.
    9085    */
    91     GraphicsManager::GraphicsManager()
    92         : ogreRoot_(0)
    93         , ogreLogger_(0)
     86    GraphicsManager::GraphicsManager(bool bLoadRenderer)
     87        : ogreWindowEventListener_(new OgreWindowEventListener())
     88#if OGRE_VERSION < 0x010600
     89        , memoryArchiveFactory_(new MemoryArchiveFactory())
     90#endif
    9491        , renderWindow_(0)
    9592        , viewport_(0)
    96         , ogreWindowEventListener_(new OgreWindowEventListener())
    9793    {
    9894        RegisterObject(GraphicsManager);
     
    10096        this->setConfigValues();
    10197
    102         // Ogre setup procedure
    103         setupOgre();
    104 
    105         try
    106         {
    107             // load all the required plugins for Ogre
    108             loadOgrePlugins();
    109             // read resource declaration file
    110             this->declareResources();
    111             // Reads ogre config and creates the render window
    112             this->loadRenderer();
    113 
    114             // TODO: Spread this
    115             this->initialiseResources();
    116 
    117             // add console commands
    118             FunctorMember<GraphicsManager>* functor1 = createFunctor(&GraphicsManager::printScreen);
    119             functor1->setObject(this);
    120             ccPrintScreen_ = createConsoleCommand(functor1, "printScreen");
    121             CommandExecutor::addConsoleCommandShortcut(ccPrintScreen_);
    122         }
    123         catch (...)
    124         {
    125             // clean up
    126             delete this->ogreRoot_;
    127             delete this->ogreLogger_;
    128             delete this->ogreWindowEventListener_;
    129             throw;
     98        // Ogre setup procedure (creating Ogre::Root)
     99        this->loadOgreRoot();
     100        // load all the required plugins for Ogre
     101        this->loadOgrePlugins();
     102
     103        // At first, add the root paths of the data directories as resource locations
     104        Ogre::ResourceGroupManager::getSingleton().addResourceLocation(Core::getDataPathString(), "FileSystem", "dataRoot", false);
     105        // Load resources
     106        resources_.reset(new XMLFile("resources.oxr", "dataRoot"));
     107        resources_->setLuaSupport(false);
     108        Loader::open(resources_.get());
     109
     110        // Only for development runs
     111        if (Core::isDevelopmentRun())
     112        {
     113            Ogre::ResourceGroupManager::getSingleton().addResourceLocation(Core::getExternalDataPathString(), "FileSystem", "externalDataRoot", false);
     114            extResources_.reset(new XMLFile("resources.oxr", "externalDataRoot"));
     115            extResources_->setLuaSupport(false);
     116            Loader::open(extResources_.get());
     117        }
     118
     119        if (bLoadRenderer)
     120        {
     121            // Reads the ogre config and creates the render window
     122            this->upgradeToGraphics();
    130123        }
    131124    }
     
    133126    /**
    134127    @brief
    135         Destroys all the Ogre related objects
     128        Destruction is done by the member scoped_ptrs.
    136129    */
    137130    GraphicsManager::~GraphicsManager()
    138131    {
    139 /*
    140         delete this->ccPrintScreen_;
    141 */
    142 
    143         // unload all compositors (this is only necessary because we don't yet destroy all resources!)
    144         Ogre::CompositorManager::getSingleton().removeAll();
    145 
    146         // Delete OGRE main control organ
    147         delete this->ogreRoot_;
    148 
    149         // delete the logManager (since we have created it in the first place).
    150         delete this->ogreLogger_;
    151 
    152         delete this->ogreWindowEventListener_;
     132        Ogre::WindowEventUtilities::removeWindowEventListener(renderWindow_, ogreWindowEventListener_.get());
     133        // TODO: Destroy the console command
    153134    }
    154135
    155136    void GraphicsManager::setConfigValues()
    156137    {
    157         SetConfigValue(resourceFile_,    "resources.cfg")
    158             .description("Location of the resources file in the data path.");
    159138        SetConfigValue(ogreConfigFile_,  "ogre.cfg")
    160139            .description("Location of the Ogre config file");
    161         SetConfigValue(ogrePluginsFolder_, ORXONOX_OGRE_PLUGINS_FOLDER)
     140        SetConfigValue(ogrePluginsDirectory_, specialConfig::ogrePluginsDirectory)
    162141            .description("Folder where the Ogre plugins are located.");
    163         SetConfigValue(ogrePlugins_, ORXONOX_OGRE_PLUGINS)
     142        SetConfigValue(ogrePlugins_, specialConfig::ogrePlugins)
    164143            .description("Comma separated list of all plugins to load.");
    165144        SetConfigValue(ogreLogFile_,     "ogre.log")
     
    173152    }
    174153
     154    /**
     155    @brief
     156        Loads the renderer and creates the render window if not yet done so.
     157    @remarks
     158        This operation is irreversible without recreating the GraphicsManager!
     159        So if it throws you HAVE to recreate the GraphicsManager!!!
     160        It therefore offers almost no exception safety.
     161    */
     162    void GraphicsManager::upgradeToGraphics()
     163    {
     164        if (renderWindow_ != NULL)
     165            return;
     166
     167        this->loadRenderer();
     168
     169#if OGRE_VERSION < 0x010600
     170        // WORKAROUND: There is an incompatibility for particle scripts when trying
     171        // to support both Ogre 1.4 and 1.6. The hacky solution is to create
     172        // scripts for the 1.6 version and then remove the inserted "particle_system"
     173        // keyword. But we need to supply these new scripts as well, which is why
     174        // there is an extra Ogre::Archive dealing with in the memory.
     175        using namespace Ogre;
     176        ArchiveManager::getSingleton().addArchiveFactory(memoryArchiveFactory_.get());
     177        const StringVector& groups = ResourceGroupManager::getSingleton().getResourceGroups();
     178        // Travers all groups
     179        for (StringVector::const_iterator itGroup = groups.begin(); itGroup != groups.end(); ++itGroup)
     180        {
     181            FileInfoListPtr files = ResourceGroupManager::getSingleton().findResourceFileInfo(*itGroup, "*.particle");
     182            for (FileInfoList::const_iterator itFile = files->begin(); itFile != files->end(); ++itFile)
     183            {
     184                // open file
     185                Ogre::DataStreamPtr input = ResourceGroupManager::getSingleton().openResource(itFile->filename, *itGroup, false);
     186                std::stringstream output;
     187                // Parse file and replace "particle_system" with nothing
     188                while (!input->eof())
     189                {
     190                    std::string line = input->getLine();
     191                    size_t pos = line.find("particle_system");
     192                    if (pos != std::string::npos)
     193                    {
     194                        // 15 is the length of "particle_system"
     195                        line.replace(pos, 15, "");
     196                    }
     197                    output << line << std::endl;
     198                }
     199                // Add file to the memory archive
     200                shared_array<char> data(new char[output.str().size()]);
     201                // Debug optimisations
     202                const std::string outputStr = output.str();
     203                char* rawData = data.get();
     204                for (unsigned i = 0; i < outputStr.size(); ++i)
     205                    rawData[i] = outputStr[i];
     206                MemoryArchive::addFile("particle_scripts_ogre_1.4_" + *itGroup, itFile->filename, data, output.str().size());
     207            }
     208            if (!files->empty())
     209            {
     210                // Declare the files, but using a new group
     211                ResourceGroupManager::getSingleton().addResourceLocation("particle_scripts_ogre_1.4_" + *itGroup,
     212                    "Memory", "particle_scripts_ogre_1.4_" + *itGroup);
     213            }
     214        }
     215#endif
     216
     217        // Initialise all resources (do this AFTER the renderer has been loaded!)
     218        // Note: You can only do this once! Ogre will check whether a resource group has
     219        // already been initialised. If you need to load resources later, you will have to
     220        // choose another resource group.
     221        Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
     222    }
     223
     224    /**
     225    @brief
     226        Creates the Ogre Root object and sets up the ogre log.
     227    */
     228    void GraphicsManager::loadOgreRoot()
     229    {
     230        COUT(3) << "Setting up Ogre..." << std::endl;
     231
     232        if (ogreConfigFile_ == "")
     233        {
     234            COUT(2) << "Warning: Ogre config file set to \"\". Defaulting to config.cfg" << std::endl;
     235            ModifyConfigValue(ogreConfigFile_, tset, "config.cfg");
     236        }
     237        if (ogreLogFile_ == "")
     238        {
     239            COUT(2) << "Warning: Ogre log file set to \"\". Defaulting to ogre.log" << std::endl;
     240            ModifyConfigValue(ogreLogFile_, tset, "ogre.log");
     241        }
     242
     243        boost::filesystem::path ogreConfigFilepath(Core::getConfigPath() / this->ogreConfigFile_);
     244        boost::filesystem::path ogreLogFilepath(Core::getLogPath() / this->ogreLogFile_);
     245
     246        // create a new logManager
     247        // Ogre::Root will detect that we've already created a Log
     248        ogreLogger_.reset(new Ogre::LogManager());
     249        COUT(4) << "Ogre LogManager created" << std::endl;
     250
     251        // create our own log that we can listen to
     252        Ogre::Log *myLog;
     253        myLog = ogreLogger_->createLog(ogreLogFilepath.string(), true, false, false);
     254        COUT(4) << "Ogre Log created" << std::endl;
     255
     256        myLog->setLogDetail(Ogre::LL_BOREME);
     257        myLog->addListener(this);
     258
     259        COUT(4) << "Creating Ogre Root..." << std::endl;
     260
     261        // check for config file existence because Ogre displays (caught) exceptions if not
     262        if (!boost::filesystem::exists(ogreConfigFilepath))
     263        {
     264            // create a zero sized file
     265            std::ofstream creator;
     266            creator.open(ogreConfigFilepath.string().c_str());
     267            creator.close();
     268        }
     269
     270        // Leave plugins file empty. We're going to do that part manually later
     271        ogreRoot_.reset(new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string()));
     272
     273        COUT(3) << "Ogre set up done." << std::endl;
     274    }
     275
     276    void GraphicsManager::loadOgrePlugins()
     277    {
     278        // just to make sure the next statement doesn't segfault
     279        if (ogrePluginsDirectory_ == "")
     280            ogrePluginsDirectory_ = ".";
     281
     282        boost::filesystem::path folder(ogrePluginsDirectory_);
     283        // Do some SubString magic to get the comma separated list of plugins
     284        SubString plugins(ogrePlugins_, ",", " ", false, '\\', false, '"', false, '(', ')', false, '\0');
     285        // Use backslash paths on Windows! file_string() already does that though.
     286        for (unsigned int i = 0; i < plugins.size(); ++i)
     287            ogreRoot_->loadPlugin((folder / plugins[i]).file_string());
     288    }
     289
     290    void GraphicsManager::loadRenderer()
     291    {
     292        CCOUT(4) << "Configuring Renderer" << std::endl;
     293
     294        if (!ogreRoot_->restoreConfig())
     295            if (!ogreRoot_->showConfigDialog())
     296                ThrowException(InitialisationFailed, "OGRE graphics configuration dialogue failed.");
     297
     298        CCOUT(4) << "Creating render window" << std::endl;
     299
     300        this->renderWindow_ = ogreRoot_->initialise(true, "Orxonox");
     301        // Propagate the size of the new winodw
     302        this->ogreWindowEventListener_->windowResized(renderWindow_);
     303
     304        Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, ogreWindowEventListener_.get());
     305
     306        // create a full screen default viewport
     307        // Note: This may throw when adding a viewport with an existing z-order!
     308        //       But in our case we only have one viewport for now anyway, therefore
     309        //       no ScopeGuards or anything to handle exceptions.
     310        this->viewport_ = this->renderWindow_->addViewport(0, 0);
     311
     312        Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(0);
     313
     314        // add console commands
     315        FunctorMember<GraphicsManager>* functor1 = createFunctor(&GraphicsManager::printScreen);
     316        ccPrintScreen_ = createConsoleCommand(functor1->setObject(this), "printScreen");
     317        CommandExecutor::addConsoleCommandShortcut(ccPrintScreen_);
     318    }
     319
    175320    void GraphicsManager::update(const Clock& time)
    176321    {
     
    207352    {
    208353        this->viewport_->setCamera(camera);
    209     }
    210 
    211     /**
    212     @brief
    213         Creates the Ogre Root object and sets up the ogre log.
    214     */
    215     void GraphicsManager::setupOgre()
    216     {
    217         COUT(3) << "Setting up Ogre..." << std::endl;
    218 
    219         if (ogreConfigFile_ == "")
    220         {
    221             COUT(2) << "Warning: Ogre config file set to \"\". Defaulting to config.cfg" << std::endl;
    222             ModifyConfigValue(ogreConfigFile_, tset, "config.cfg");
    223         }
    224         if (ogreLogFile_ == "")
    225         {
    226             COUT(2) << "Warning: Ogre log file set to \"\". Defaulting to ogre.log" << std::endl;
    227             ModifyConfigValue(ogreLogFile_, tset, "ogre.log");
    228         }
    229 
    230         boost::filesystem::path ogreConfigFilepath(Core::getConfigPath() / this->ogreConfigFile_);
    231         boost::filesystem::path ogreLogFilepath(Core::getLogPath() / this->ogreLogFile_);
    232 
    233         // create a new logManager
    234         // Ogre::Root will detect that we've already created a Log
    235         std::auto_ptr<Ogre::LogManager> logger(new Ogre::LogManager());
    236         COUT(4) << "Ogre LogManager created" << std::endl;
    237 
    238         // create our own log that we can listen to
    239         Ogre::Log *myLog;
    240         myLog = logger->createLog(ogreLogFilepath.string(), true, false, false);
    241         COUT(4) << "Ogre Log created" << std::endl;
    242 
    243         myLog->setLogDetail(Ogre::LL_BOREME);
    244         myLog->addListener(this);
    245 
    246         COUT(4) << "Creating Ogre Root..." << std::endl;
    247 
    248         // check for config file existence because Ogre displays (caught) exceptions if not
    249         if (!boost::filesystem::exists(ogreConfigFilepath))
    250         {
    251             // create a zero sized file
    252             std::ofstream creator;
    253             creator.open(ogreConfigFilepath.string().c_str());
    254             creator.close();
    255         }
    256 
    257         // Leave plugins file empty. We're going to do that part manually later
    258         ogreRoot_ = new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string());
    259         // In case that new Root failed the logger gets destroyed because of the std::auto_ptr
    260         ogreLogger_ = logger.release();
    261 
    262         COUT(3) << "Ogre set up done." << std::endl;
    263     }
    264 
    265     void GraphicsManager::loadOgrePlugins()
    266     {
    267         // just to make sure the next statement doesn't segfault
    268         if (ogrePluginsFolder_ == "")
    269             ogrePluginsFolder_ = ".";
    270 
    271         boost::filesystem::path folder(ogrePluginsFolder_);
    272         // Do some SubString magic to get the comma separated list of plugins
    273         SubString plugins(ogrePlugins_, ",", " ", false, '\\', false, '"', false, '(', ')', false, '\0');
    274         // Use backslash paths on Windows! file_string() already does that though.
    275         for (unsigned int i = 0; i < plugins.size(); ++i)
    276             ogreRoot_->loadPlugin((folder / plugins[i]).file_string());
    277     }
    278 
    279     void GraphicsManager::declareResources()
    280     {
    281         CCOUT(4) << "Declaring Resources" << std::endl;
    282         //TODO: Specify layout of data file and maybe use xml-loader
    283         //TODO: Work with ressource groups (should be generated by a special loader)
    284 
    285         if (resourceFile_ == "")
    286         {
    287             COUT(2) << "Warning: Ogre resource file set to \"\". Defaulting to resources.cfg" << std::endl;
    288             ModifyConfigValue(resourceFile_, tset, "resources.cfg");
    289         }
    290 
    291         // Load resource paths from data file using configfile ressource type
    292         Ogre::ConfigFile cf;
    293         try
    294         {
    295             cf.load((Core::getMediaPath() / resourceFile_).string());
    296         }
    297         catch (...)
    298         {
    299             //COUT(1) << ex.getFullDescription() << std::endl;
    300             COUT(0) << "Have you forgotten to set the data path in orxnox.ini?" << std::endl;
    301             throw;
    302         }
    303 
    304         // Go through all sections & settings in the file
    305         Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
    306 
    307         std::string secName, typeName, archName;
    308         while (seci.hasMoreElements())
    309         {
    310             try
    311             {
    312                 secName = seci.peekNextKey();
    313                 Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
    314                 Ogre::ConfigFile::SettingsMultiMap::iterator i;
    315                 for (i = settings->begin(); i != settings->end(); ++i)
    316                 {
    317                     typeName = i->first; // for instance "FileSystem" or "Zip"
    318                     archName = i->second; // name (and location) of archive
    319 
    320                     Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
    321                         (Core::getMediaPath() / archName).string(), typeName, secName);
    322                 }
    323             }
    324             catch (Ogre::Exception& ex)
    325             {
    326                 COUT(1) << ex.getFullDescription() << std::endl;
    327             }
    328         }
    329     }
    330 
    331     void GraphicsManager::loadRenderer()
    332     {
    333         CCOUT(4) << "Configuring Renderer" << std::endl;
    334 
    335         if (!ogreRoot_->restoreConfig())
    336             if (!ogreRoot_->showConfigDialog())
    337                 ThrowException(InitialisationFailed, "OGRE graphics configuration dialogue failed.");
    338 
    339         CCOUT(4) << "Creating render window" << std::endl;
    340 
    341         this->renderWindow_ = ogreRoot_->initialise(true, "Orxonox");
    342         this->ogreWindowEventListener_->windowResized(renderWindow_);
    343 
    344         Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, ogreWindowEventListener_);
    345 
    346         Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(0);
    347 
    348         // create a full screen default viewport
    349         this->viewport_ = this->renderWindow_->addViewport(0, 0);
    350     }
    351 
    352     void GraphicsManager::initialiseResources()
    353     {
    354         CCOUT(4) << "Initialising resources" << std::endl;
    355         //TODO: Do NOT load all the groups, why are we doing that? And do we really do that? initialise != load...
    356         //try
    357         //{
    358             Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
    359             /*Ogre::StringVector str = Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
    360             for (unsigned int i = 0; i < str.size(); i++)
    361             {
    362             Ogre::ResourceGroupManager::getSingleton().loadResourceGroup(str[i]);
    363             }*/
    364         //}
    365         //catch (...)
    366         //{
    367         //    CCOUT(2) << "Error: There was a serious error when initialising the resources." << std::endl;
    368         //    throw;
    369         //}
    370354    }
    371355
     
    406390    }
    407391
     392    size_t GraphicsManager::getRenderWindowHandle()
     393    {
     394        size_t windowHnd = 0;
     395        renderWindow_->getCustomAttribute("WINDOW", &windowHnd);
     396        return windowHnd;
     397    }
     398
     399    bool GraphicsManager::isFullScreen() const
     400    {
     401        Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions();
     402        if (options.find("Full Screen") != options.end())
     403        {
     404            if (options["Full Screen"].currentValue == "Yes")
     405                return true;
     406            else
     407                return false;
     408        }
     409        else
     410        {
     411            COUT(0) << "Could not find 'Full Screen' render system option. Fix This!!!" << std::endl;
     412            return false;
     413        }
     414    }
     415
    408416    void GraphicsManager::printScreen()
    409417    {
  • code/trunk/src/core/GraphicsManager.h

    r3370 r5695  
    4242#include <string>
    4343#include <OgreLog.h>
     44#include <boost/scoped_ptr.hpp>
     45#include <boost/shared_ptr.hpp>
     46
    4447#include "util/Singleton.h"
    4548#include "OrxonoxClass.h"
     
    5558        friend class Singleton<GraphicsManager>;
    5659    public:
    57         GraphicsManager();
     60        GraphicsManager(bool bLoadRenderer = true);
    5861        ~GraphicsManager();
    5962
     
    6265        void update(const Clock& time);
    6366
    64         inline Ogre::Viewport* getViewport()
    65             { return this->viewport_; }
    66         inline Ogre::RenderWindow* getRenderWindow()
    67             { return this->renderWindow_; }
     67        Ogre::Viewport* getViewport()         { return this->viewport_; }
     68        Ogre::RenderWindow* getRenderWindow() { return this->renderWindow_; }
     69        size_t getRenderWindowHandle();
     70        bool isFullScreen() const;
     71
     72        void upgradeToGraphics();
     73        bool rendererLoaded() const { return renderWindow_ != NULL; }
    6874
    6975        void setCamera(Ogre::Camera* camera);
     
    7379
    7480        // OGRE initialisation
    75         void setupOgre();
     81        void loadOgreRoot();
    7682        void loadOgrePlugins();
    77         void declareResources();
    7883        void loadRenderer();
    79         void initialiseResources();
    8084
    8185        // event from Ogre::LogListener
     
    8690        void printScreen();
    8791
    88     private:
    89         Ogre::Root*         ogreRoot_;                 //!< Ogre's root
    90         Ogre::LogManager*   ogreLogger_;
     92        scoped_ptr<OgreWindowEventListener> ogreWindowEventListener_; //!< Pimpl to hide OgreWindowUtilities.h
     93#if OGRE_VERSION < 0x010600
     94        scoped_ptr<MemoryArchiveFactory>    memoryArchiveFactory_;    //!< Stores the modified particle scripts
     95#endif
     96        scoped_ptr<Ogre::LogManager>        ogreLogger_;
     97        scoped_ptr<Ogre::Root>              ogreRoot_;                //!< Ogre's root
    9198        Ogre::RenderWindow* renderWindow_;             //!< the one and only render window
    9299        Ogre::Viewport*     viewport_;                 //!< default full size viewport
    93         OgreWindowEventListener* ogreWindowEventListener_; //!< Pimpl to hide OgreWindowUtilities.h
     100
     101        // XML files for the resources
     102        shared_ptr<XMLFile> resources_;                //!< XML with resource locations
     103        shared_ptr<XMLFile> extResources_;             //!< XML with resource locations in the external path (only for dev runs)
    94104
    95105        // config values
    96         std::string         resourceFile_;             //!< resources file name
    97106        std::string         ogreConfigFile_;           //!< ogre config file name
    98         std::string         ogrePluginsFolder_;        //!< Folder where the Ogre plugins are located
     107        std::string         ogrePluginsDirectory_;     //!< Directory where the Ogre plugins are located
    99108        std::string         ogrePlugins_;              //!< Comma separated list of all plugins to load
    100109        std::string         ogreLogFile_;              //!< log file name for Ogre log messages
  • code/trunk/src/core/Identifier.cc

    r3325 r5695  
    138138        if (!this->bCreatedOneObject_ && Identifier::isCreatingHierarchy())
    139139        {
    140             // If no: We have to store the informations and initialize the Identifier
     140            // If no: We have to store the information and initialize the Identifier
    141141            COUT(4) << "*** ClassIdentifier: Register Class in " << this->getName() << "-Singleton -> Initialize Singleton." << std::endl;
    142142            if (bRootClass)
  • code/trunk/src/core/Identifier.h

    r3370 r5695  
    3131    @brief Definition of the Identifier, ClassIdentifier and SubclassIdentifier classes, implementation of the ClassIdentifier and SubclassIdentifier classes.
    3232
    33     The Identifier contains all needed informations about the class it belongs to:
     33    The Identifier contains all needed information about the class it belongs to:
    3434     - the name
    3535     - a list with all objects
     
    7373    // ###       Identifier        ###
    7474    // ###############################
    75     //! The Identifier is used to identify the class of an object and to store informations about the class.
    76     /**
    77         The Identifier contains all needed informations about the class it belongs to:
     75    //! The Identifier is used to identify the class of an object and to store information about the class.
     76    /**
     77        The Identifier contains all needed information about the class it belongs to:
    7878         - the name
    7979         - a list with all objects
     
    335335    /**
    336336        ClassIdentifier is a Singleton, which means that only one object of a given type T exists.
    337         This makes it possible to store informations about a class, sharing them with all
     337        This makes it possible to store information about a class, sharing them with all
    338338        objects of that class without defining static variables in every class.
    339339
  • code/trunk/src/core/Loader.cc

    r3370 r5695  
    2929#include "Loader.h"
    3030
     31#include <sstream>
    3132#include <tinyxml/ticpp.h>
     33#include <boost/scoped_ptr.hpp>
    3234
    3335#include "util/Debug.h"
    3436#include "util/Exception.h"
     37#include "util/StringUtils.h"
    3538#include "BaseObject.h"
    3639#include "Iterator.h"
    3740#include "ObjectList.h"
    38 #include "LuaBind.h"
     41#include "LuaState.h"
    3942#include "Namespace.h"
     43#include "Resource.h"
    4044#include "XMLFile.h"
    4145
     
    118122        Loader::currentMask_s = file->getMask() * mask;
    119123
    120         // let Lua work this out:
    121         LuaBind& lua = LuaBind::getInstance();
    122         lua.clearLuaOutput();
    123         lua.loadFile(file->getFilename(), true);
    124         lua.run();
     124        std::string xmlInput;
     125        if (file->getLuaSupport())
     126        {
     127            // Use the LuaState to replace the XML tags (calls our function)
     128            scoped_ptr<LuaState> luaState(new LuaState());
     129            luaState->setIncludeParser(&Loader::replaceLuaTags);
     130            luaState->includeFile(file->getFilename(), file->getResourceGroup(), false);
     131            xmlInput = luaState->getOutput().str();
     132        }
     133        else
     134        {
     135            shared_ptr<ResourceInfo> info = Resource::getInfo(file->getFilename(), file->getResourceGroup());
     136            if (info == NULL)
     137            {
     138                COUT(1) << "Error: Could not find XML file '" << file->getFilename() << "'." << std::endl;
     139                return false;
     140            }
     141            xmlInput = Resource::open(file->getFilename(), file->getResourceGroup())->getAsString();
     142        }
    125143
    126144        try
     
    129147            COUT(3) << "Mask: " << Loader::currentMask_s << std::endl;
    130148
    131             //ticpp::Document xmlfile(file->getFilename());
    132             //xmlfile.LoadFile();
    133             //ticpp::Element myelement(*Script::getFileString());
    134             ticpp::Document xmlfile;
    135             //xmlfile.ToDocument();
    136             xmlfile.Parse(lua.getLuaOutput(), true);
     149            ticpp::Document xmlfile(file->getFilename());
     150            xmlfile.Parse(xmlInput, true);
    137151
    138152            ticpp::Element rootElement;
     
    208222        return Loader::load(file, mask);
    209223    }
     224
     225    std::string Loader::replaceLuaTags(const std::string& text)
     226    {
     227        // chreate map with all Lua tags
     228        std::map<size_t, bool> luaTags;
     229        {
     230            size_t pos = 0;
     231            while ((pos = text.find("<?lua", pos)) != std::string::npos)
     232                luaTags[pos++] = true;
     233        }
     234        {
     235            size_t pos = 0;
     236            while ((pos = text.find("?>", pos)) != std::string::npos)
     237                luaTags[pos++] = false;
     238        }
     239
     240        // erase all tags from the map that are between two quotes
     241        {
     242            std::map<size_t, bool>::iterator it = luaTags.begin();
     243            std::map<size_t, bool>::iterator it2 = it;
     244            bool bBetweenQuotes = false;
     245            size_t pos = 0;
     246            while ((pos = getNextQuote(text, pos)) != std::string::npos)
     247            {
     248                while ((it != luaTags.end()) && (it->first < pos))
     249                {
     250                    if (bBetweenQuotes)
     251                    {
     252                        it2++;
     253                        if(it->second && !(it2->second) && it2->first < pos)
     254                            it = ++it2;
     255                        else
     256                            luaTags.erase(it++);
     257                    }
     258                    else
     259                        ++it;
     260                }
     261                bBetweenQuotes = !bBetweenQuotes;
     262                pos++;
     263            }
     264        }
     265
     266        // check whether on every opening <?lua tag a closing ?> tag follows
     267        {
     268            bool expectedValue = true;
     269            for (std::map<size_t, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
     270            {
     271                if (it->second == expectedValue)
     272                    expectedValue = !expectedValue;
     273                else
     274                {
     275                    expectedValue = false;
     276                    break;
     277                }
     278            }
     279            if (!expectedValue)
     280            {
     281                COUT(2) << "Warning: Error in level file" << std::endl;
     282                // todo: errorhandling
     283                return "";
     284            }
     285        }
     286
     287        // Use a stringstream object to speed up the parsing
     288        std::ostringstream output;
     289
     290        // cut the original string into pieces and put them together with print() instead of lua tags
     291        {
     292            std::map<size_t, bool>::iterator it = luaTags.begin();
     293            bool bInPrintFunction = true;
     294            size_t start = 0;
     295            size_t end = 0;
     296
     297            do
     298            {
     299                if (it != luaTags.end())
     300                    end = (*(it++)).first;
     301                else
     302                    end = std::string::npos;
     303
     304                unsigned int equalSignCounter = 0;
     305
     306                if (bInPrintFunction)
     307                {
     308                    // count ['='[ and ]'='] and replace tags with print([[ and ]])
     309                    std::string temp = text.substr(start, end - start);
     310                    {
     311                    size_t pos = 0;
     312                    while ((pos = temp.find('[', pos)) != std::string::npos)
     313                    {
     314                        unsigned int tempCounter = 1;
     315                        size_t tempPos = pos++;
     316                        while(temp[++tempPos] == '=')
     317                        {
     318                            tempCounter++;
     319                        }
     320                        if(temp[tempPos] != '[')
     321                        {
     322                            tempCounter = 0;
     323                        }
     324                        else if(tempCounter == 0)
     325                        {
     326                            tempCounter = 1;
     327                        }
     328                        if (tempCounter > equalSignCounter)
     329                            equalSignCounter = tempCounter;
     330                        }
     331                    }
     332                    {
     333                        size_t pos = 0;
     334                        while ((pos = temp.find(']', pos)) != std::string::npos)
     335                        {
     336                            unsigned int tempCounter = 1;
     337                            size_t tempPos = pos++;
     338                            while(temp[++tempPos] == '=')
     339                            {
     340                                tempCounter++;
     341                            }
     342                            if(temp[tempPos] != ']')
     343                            {
     344                                tempCounter = 0;
     345                            }
     346                            else if(tempCounter == 0)
     347                            {
     348                                tempCounter = 1;
     349                            }
     350                            if (tempCounter > equalSignCounter)
     351                                equalSignCounter = tempCounter;
     352                        }
     353                    }
     354                    std::string equalSigns = "";
     355                    for(unsigned int i = 0; i < equalSignCounter; i++)
     356                    {
     357                        equalSigns += "=";
     358                    }
     359                    output << "print([" + equalSigns + "[" + temp + "]" + equalSigns +"])";
     360                    start = end + 5;
     361                }
     362                else
     363                {
     364                    output << text.substr(start, end - start);
     365                    start = end + 2;
     366                }
     367
     368                bInPrintFunction = !bInPrintFunction;
     369            }
     370            while (end != std::string::npos);
     371        }
     372
     373        return output.str();
     374    }
    210375}
  • code/trunk/src/core/Loader.h

    r3370 r5695  
    5555            static bool reload(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask());
    5656
     57            static std::string replaceLuaTags(const std::string& text);
     58
    5759            static ClassTreeMask currentMask_s;
    5860
  • code/trunk/src/core/TclBind.cc

    r3370 r5695  
    127127#ifdef DEPENDENCY_PACKAGE_ENABLE
    128128        if (Core::isDevelopmentRun())
    129             return (std::string(ORXONOX_DEP_LIB_PATH) + "/tcl");
     129            return (std::string(specialConfig::dependencyLibraryDirectory) + "/tcl");
    130130        else
    131131            return (Core::getRootPathString() + "lib/tcl");
  • code/trunk/src/core/TclThreadManager.cc

    r3370 r5695  
    5757
    5858    /**
    59         @brief A struct containing all informations about a Tcl-interpreter
     59        @brief A struct containing all information about a Tcl-interpreter
    6060    */
    6161    struct TclInterpreterBundle
  • code/trunk/src/core/XMLFile.h

    r3196 r5695  
    4040    {
    4141        public:
    42             XMLFile(const std::string& filename) : filename_(filename) {}
    43             XMLFile(const std::string& filename, const ClassTreeMask& mask) : filename_(filename), mask_(mask) {};
     42            XMLFile(const std::string& filename, const std::string& resourceGroup = "General")
     43                : filename_(filename)
     44                , group_(resourceGroup)
     45                , bLuaSupport_(true)
     46            { }
     47            XMLFile(const ClassTreeMask& mask, const std::string& filename, const std::string& resourceGroup = "General")
     48                : filename_(filename)
     49                , group_(resourceGroup)
     50                , mask_(mask)
     51                , bLuaSupport_(true)
     52            { }
     53
     54            void setLuaSupport(bool val) { bLuaSupport_ = val; }
    4455
    4556            const std::string& getFilename() const { return this->filename_; }
     57            const std::string& getResourceGroup() const { return this->group_; }
    4658            const ClassTreeMask& getMask() const { return this->mask_; }
     59            bool getLuaSupport() const { return this->bLuaSupport_; }
    4760
    4861        private:
    4962            std::string filename_;
     63            std::string group_;
    5064            ClassTreeMask mask_;
     65            bool bLuaSupport_; // Default is true
    5166    };
    5267}
  • code/trunk/src/core/input/Button.cc

    r3327 r5695  
    5959        nCommands_[1]=0;
    6060        nCommands_[2]=0;
    61         this->configContainer_ = 0;
    6261    }
    6362
  • code/trunk/src/core/input/InputManager.cc

    r3370 r5695  
    4141#include <boost/foreach.hpp>
    4242
     43#include "util/Convert.h"
    4344#include "util/Exception.h"
    4445#include "util/ScopeGuard.h"
     
    4950#include "core/CommandLine.h"
    5051#include "core/Functor.h"
     52#include "core/GraphicsManager.h"
    5153
    5254#include "InputBuffer.h"
     
    8284    // ##########                                        ##########
    8385    // ############################################################
    84     InputManager::InputManager(size_t windowHnd)
     86    InputManager::InputManager()
    8587        : internalState_(Bad)
    8688        , oisInputManager_(0)
    8789        , devices_(2)
    88         , windowHnd_(0)
     90        , bExclusiveMouse_(false)
    8991        , emptyState_(0)
    9092        , keyDetector_(0)
     
    9799        this->setConfigValues();
    98100
    99         this->loadDevices(windowHnd);
     101        this->loadDevices();
    100102
    101103        // Lowest priority empty InputState
     
    147149        Creates the OIS::InputMananger, the keyboard, the mouse and
    148150        the joys ticks. If either of the first two fail, this method throws an exception.
    149     @param windowHnd
    150         The window handle of the render window
    151151    @param windowWidth
    152152        The width of the render window
     
    154154        The height of the render window
    155155    */
    156     void InputManager::loadDevices(size_t windowHnd)
    157     {
    158         CCOUT(3) << "Loading input devices..." << std::endl;
     156    void InputManager::loadDevices()
     157    {
     158        CCOUT(4) << "Loading input devices..." << std::endl;
    159159
    160160        // When loading the devices they should not already be loaded
     
    164164        assert(devices_.size() == InputDeviceEnumerator::FirstJoyStick);
    165165
    166         // store handle internally so we can reload OIS
    167         windowHnd_ = windowHnd;
    168 
     166        // Fill parameter list
    169167        OIS::ParamList paramList;
    170         std::ostringstream windowHndStr;
    171 
    172         // Fill parameter list
    173         windowHndStr << static_cast<unsigned int>(windowHnd);
    174         paramList.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
     168        size_t windowHnd = GraphicsManager::getInstance().getRenderWindowHandle();
     169        paramList.insert(std::make_pair("WINDOW", multi_cast<std::string>(windowHnd)));
    175170#if defined(ORXONOX_PLATFORM_WINDOWS)
    176         //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
    177         //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND")));
    178         //paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
    179         //paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));
     171        paramList.insert(std::make_pair("w32_keyboard", "DISCL_NONEXCLUSIVE"));
     172        paramList.insert(std::make_pair("w32_keyboard", "DISCL_FOREGROUND"));
     173        paramList.insert(std::make_pair("w32_mouse", "DISCL_FOREGROUND"));
     174        if (bExclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
     175        {
     176            // Disable Windows key plus special keys (like play, stop, next, etc.)
     177            paramList.insert(std::make_pair("w32_keyboard", "DISCL_NOWINKEY"));
     178            paramList.insert(std::make_pair("w32_mouse", "DISCL_EXCLUSIVE"));
     179        }
     180        else
     181            paramList.insert(std::make_pair("w32_mouse", "DISCL_NONEXCLUSIVE"));
    180182#elif defined(ORXONOX_PLATFORM_LINUX)
    181         paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
    182         paramList.insert(std::make_pair(std::string("x11_mouse_grab"), "true"));
    183         paramList.insert(std::make_pair(std::string("x11_mouse_hide"), "true"));
    184         bool kbNoGrab;
    185         CommandLine::getValue("keyboard_no_grab", &kbNoGrab);
    186         if (kbNoGrab)
    187             paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
     183        // Enabling this is probably a bad idea, but whenever orxonox crashes, the setting stays on
     184        // Trouble might be that the Pressed event occurs a bit too often...
     185        paramList.insert(std::make_pair("XAutoRepeatOn", "true"));
     186
     187        if (bExclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
     188        {
     189            if (CommandLine::getValue("keyboard_no_grab").getBool())
     190                paramList.insert(std::make_pair("x11_keyboard_grab", "false"));
     191            else
     192                paramList.insert(std::make_pair("x11_keyboard_grab", "true"));
     193            paramList.insert(std::make_pair("x11_mouse_grab",  "true"));
     194            paramList.insert(std::make_pair("x11_mouse_hide", "true"));
     195        }
    188196        else
    189             paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("true")));
     197        {
     198            paramList.insert(std::make_pair("x11_keyboard_grab", "false"));
     199            paramList.insert(std::make_pair("x11_mouse_grab",  "false"));
     200            paramList.insert(std::make_pair("x11_mouse_hide", "false"));
     201        }
    190202#endif
    191203
     
    212224        }
    213225
    214         // TODO: Remove the two parameters
    215226        this->loadMouse();
    216227        this->loadJoySticks();
     
    219230        this->updateActiveStates();
    220231
    221         CCOUT(3) << "Input devices loaded." << std::endl;
     232        CCOUT(4) << "Input devices loaded." << std::endl;
    222233    }
    223234
     
    275286    InputManager::~InputManager()
    276287    {
    277         CCOUT(4) << "Destroying..." << std::endl;
     288        CCOUT(3) << "Destroying..." << std::endl;
    278289
    279290        // Destroy calibrator helper handler and state
     
    293304            this->destroyDevices();
    294305
    295         CCOUT(4) << "Destruction complete." << std::endl;
     306        CCOUT(3) << "Destruction complete." << std::endl;
    296307    }
    297308
     
    304315    void InputManager::destroyDevices()
    305316    {
    306         CCOUT(3) << "Destroying devices..." << std::endl;
     317        CCOUT(4) << "Destroying devices..." << std::endl;
    307318
    308319        BOOST_FOREACH(InputDevice*& device, devices_)
     
    336347
    337348        internalState_ |= Bad;
    338         CCOUT(3) << "Destroyed devices." << std::endl;
     349        CCOUT(4) << "Destroyed devices." << std::endl;
    339350    }
    340351
     
    365376
    366377        this->destroyDevices();
    367         this->loadDevices(windowHnd_);
     378        this->loadDevices();
    368379
    369380        internalState_ &= ~Bad;
    370381        internalState_ &= ~ReloadRequest;
    371         CCOUT(3) << "Reloading complete." << std::endl;
     382        CCOUT(4) << "Reloading complete." << std::endl;
    372383    }
    373384
     
    481492    void InputManager::updateActiveStates()
    482493    {
     494        assert((internalState_ & InputManager::Ticking) == 0);
    483495        // temporary resize
    484496        for (unsigned int i = 0; i < devices_.size(); ++i)
     
    512524        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
    513525            activeStatesTicked_.push_back(*it);
     526
     527        // Check whether we have to change the mouse mode
     528        std::vector<InputState*>& mouseStates = devices_[InputDeviceEnumerator::Mouse]->getStateListRef();
     529        if (mouseStates.empty() && bExclusiveMouse_ ||
     530            !mouseStates.empty() && mouseStates.front()->getIsExclusiveMouse() != bExclusiveMouse_)
     531        {
     532            bExclusiveMouse_ = !bExclusiveMouse_;
     533            if (!GraphicsManager::getInstance().isFullScreen())
     534                this->reloadInternal();
     535        }
    514536    }
    515537
     
    556578    }
    557579
    558     // ############################################################
    559     // #####                    Iput States                   #####
     580    std::pair<int, int> InputManager::getMousePosition() const
     581    {
     582        Mouse* mouse = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse]);
     583        if (mouse != NULL)
     584        {
     585            const OIS::MouseState state = mouse->getOISDevice()->getMouseState();
     586            return std::make_pair(state.X.abs, state.Y.abs);
     587        }
     588        else
     589            return std::make_pair(0, 0);
     590    }
     591
     592    // ############################################################
     593    // #####                    Input States                  #####
    560594    // ##########                                        ##########
    561595    // ############################################################
  • code/trunk/src/core/input/InputManager.h

    r3370 r5695  
    8484            the constructor fails with an std::exception.
    8585        */
    86         InputManager(size_t windowHnd);
     86        InputManager();
    8787        //! Destroys all devices AND all input states!
    8888        ~InputManager();
     
    167167            { return devices_.size() - InputDeviceEnumerator::FirstJoyStick; }
    168168        //! Returns a pointer to the OIS InputManager. Only you if you know what you're doing!
    169         OIS::InputManager* getOISInputManager()
    170             { return this->oisInputManager_; }
     169        OIS::InputManager* getOISInputManager() { return this->oisInputManager_; }
     170        std::pair<int, int> getMousePosition() const;
    171171
    172172    private: // functions
     
    175175
    176176        // Intenal methods
    177         void loadDevices(size_t windowHnd);
     177        void loadDevices();
    178178        void loadMouse();
    179179        void loadJoySticks();
     
    193193        OIS::InputManager*                  oisInputManager_;      //!< OIS input manager
    194194        std::vector<InputDevice*>           devices_;              //!< List of all input devices (keyboard, mouse, joy sticks)
    195         // TODO: Get this from the GraphicsManager during reload
    196         size_t                              windowHnd_;            //!< Render window handle (used to reload the InputManager)
     195        bool                                bExclusiveMouse_;      //!< Currently applied mouse mode
    197196
    198197        // some internally handled states and handlers
  • code/trunk/src/core/input/InputState.cc

    r3327 r5695  
    3737        , bAlwaysGetsInput_(bAlwaysGetsInput)
    3838        , bTransparent_(bTransparent)
     39        , bExclusiveMouse_(true)
    3940        , bExpired_(true)
    4041        , handlers_(2)
  • code/trunk/src/core/input/InputState.h

    r3327 r5695  
    7575          not influence ony other InputState at all.
    7676
    77         Priorities
    78         **********
     77    @par Priorities
    7978        Every InputState has a priority when on the stack, but mostly this
    8079        priority is dynamic (InputStatePriority::Dynamic) which means that a state
     
    8382        a high priority (InputStatePriority::HighPriority). These 'special' ones
    8483        are used for features like the KeyDetector or the console. Use with care!
     84
     85    @par Exclusive/Non-Exclusive mouse Mode
     86        You can select a specific mouse mode that tells whether the application
     87        should have exclusive accessto it or not.
     88        When in non-exclusive mode, you can move the mouse out of the window
     89        like with any other normal window (only for windowed mode!).
     90        The setting is dictated by the topmost InputState that gets mouse events.
    8591    */
    8692    class _CoreExport InputState : public JoyStickQuantityListener
     
    114120        void setHandler        (InputHandler* handler);
    115121
     122        void setIsExclusiveMouse(bool value) { bExclusiveMouse_ = value; this->bExpired_ = true; }
     123        bool getIsExclusiveMouse() const { return bExclusiveMouse_; }
     124
    116125        //! Returns the name of the state (which is unique!)
    117126        const std::string& getName() const { return name_; }
     
    165174        const bool                  bAlwaysGetsInput_;      //!< See class declaration for explanation
    166175        const bool                  bTransparent_;          //!< See class declaration for explanation
     176        bool                        bExclusiveMouse_;       //!< See class declaration for explanation
    167177        int                         priority_;              //!< Current priority (might change)
    168178        bool                        bExpired_;              //!< See hasExpired()
  • code/trunk/src/core/input/KeyBinder.cc

    r3327 r5695  
    5555        mousePosition_[0] = 0;
    5656        mousePosition_[1] = 0;
    57 
    58         joyStickButtons_.reserve(1000);
    59         joyStickAxes_.reserve(1000);
    6057
    6158        RegisterRootObject(KeyBinder);
     
    167164            {
    168165                for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; ++i)
    169                     joyStickButtons_[iDev][i].readConfigValue(this->configFile_);
     166                    (*joyStickButtons_[iDev])[i].readConfigValue(this->configFile_);
    170167                for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; ++i)
    171                     joyStickAxes_[iDev][i].readConfigValue(this->configFile_);
     168                    (*joyStickAxes_[iDev])[i].readConfigValue(this->configFile_);
    172169            }
    173170        }
     
    179176    void KeyBinder::initialiseJoyStickBindings()
    180177    {
     178        while (joyStickAxes_.size() < joySticks_.size())
     179            joyStickAxes_.push_back(shared_ptr<JoyStickAxisVector>(new JoyStickAxisVector()));
     180        while (joyStickButtons_.size() < joySticks_.size())
     181            joyStickButtons_.push_back(shared_ptr<JoyStickButtonVector>(new JoyStickButtonVector()));
     182        // For the case the new size is smaller
    181183        this->joyStickAxes_.resize(joySticks_.size());
    182184        this->joyStickButtons_.resize(joySticks_.size());
     
    189191            for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; i++)
    190192            {
    191                 joyStickButtons_[iDev][i].name_ = JoyStickButtonCode::ByString[i];
    192                 joyStickButtons_[iDev][i].paramCommandBuffer_ = &paramCommandBuffer_;
    193                 joyStickButtons_[iDev][i].groupName_ = "JoyStickButtons_" + deviceName;
     193                (*joyStickButtons_[iDev])[i].name_ = JoyStickButtonCode::ByString[i];
     194                (*joyStickButtons_[iDev])[i].paramCommandBuffer_ = &paramCommandBuffer_;
     195                (*joyStickButtons_[iDev])[i].groupName_ = "JoyStickButtons_" + deviceName;
    194196            }
    195197            // joy stick axes
    196198            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
    197199            {
    198                 joyStickAxes_[iDev][i].name_ = JoyStickAxisCode::ByString[i / 2];
     200                (*joyStickAxes_[iDev])[i].name_ = JoyStickAxisCode::ByString[i / 2];
    199201                if (i & 1)
    200                     joyStickAxes_[iDev][i].name_ += "Pos";
     202                    (*joyStickAxes_[iDev])[i].name_ += "Pos";
    201203                else
    202                     joyStickAxes_[iDev][i].name_ += "Neg";
    203                 joyStickAxes_[iDev][i].paramCommandBuffer_ = &paramCommandBuffer_;
    204                 joyStickAxes_[iDev][i].groupName_ = "JoyStickAxes_" + deviceName;
     204                    (*joyStickAxes_[iDev])[i].name_ += "Neg";
     205                (*joyStickAxes_[iDev])[i].paramCommandBuffer_ = &paramCommandBuffer_;
     206                (*joyStickAxes_[iDev])[i].groupName_ = "JoyStickAxes_" + deviceName;
    205207            }
    206208        }
     
    226228        {
    227229            for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; i++)
    228                 allButtons_[joyStickButtons_[iDev][i].groupName_ + "." + joyStickButtons_[iDev][i].name_] = &(joyStickButtons_[iDev][i]);
     230                allButtons_[(*joyStickButtons_[iDev])[i].groupName_ + "." + (*joyStickButtons_[iDev])[i].name_] = &((*joyStickButtons_[iDev])[i]);
    229231            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
    230232            {
    231                 allButtons_[joyStickAxes_[iDev][i].groupName_ + "." + joyStickAxes_[iDev][i].name_] = &(joyStickAxes_[iDev][i]);
    232                 allHalfAxes_.push_back(&(joyStickAxes_[iDev][i]));
     233                allButtons_[(*joyStickAxes_[iDev])[i].groupName_ + "." + (*joyStickAxes_[iDev])[i].name_] = &((*joyStickAxes_[iDev])[i]);
     234                allHalfAxes_.push_back(&((*joyStickAxes_[iDev])[i]));
    233235            }
    234236        }
     
    303305            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
    304306            {
    305                 joyStickAxes_[iDev][i].absVal_ = 0.0f;
    306                 joyStickAxes_[iDev][i].relVal_ = 0.0f;
     307                (*joyStickAxes_[iDev])[i].absVal_ = 0.0f;
     308                (*joyStickAxes_[iDev])[i].relVal_ = 0.0f;
    307309            }
    308310        }
     
    366368        for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
    367369        {
    368             tickHalfAxis(joyStickAxes_[joyStick][i]);
     370            tickHalfAxis((*joyStickAxes_[joyStick])[i]);
    369371        }
    370372    }
     
    481483    {
    482484        int i = axisID * 2;
    483         JoyStickAxisVector& axis = joyStickAxes_[device];
     485        JoyStickAxisVector& axis = *joyStickAxes_[device];
    484486        if (value < 0)
    485487        {
  • code/trunk/src/core/input/KeyBinder.h

    r3327 r5695  
    4141#include <string>
    4242#include <vector>
     43#include <boost/shared_ptr.hpp>
    4344
    4445#include "InputHandler.h"
     
    115116        };
    116117        //! Actual key bindings for joy stick buttons
    117         std::vector<JoyStickButtonVector> joyStickButtons_;
     118        std::vector<shared_ptr<JoyStickButtonVector> > joyStickButtons_;
    118119        //! Helper class to use something like std:vector<HalfAxis[48]>
    119120        struct JoyStickAxisVector
     
    123124        };
    124125        //! Actual key bindings for joy stick axes (and sliders)
    125         std::vector<JoyStickAxisVector> joyStickAxes_;
     126        std::vector<shared_ptr<JoyStickAxisVector> > joyStickAxes_;
    126127
    127128        //! Pointer map with all Buttons, including half axes
     
    191192
    192193    inline void KeyBinder::buttonPressed (unsigned int device, JoyStickButtonCode::ByEnum button)
    193     { joyStickButtons_[device][button].execute(KeybindMode::OnPress); }
     194    { (*joyStickButtons_[device])[button].execute(KeybindMode::OnPress); }
    194195
    195196    inline void KeyBinder::buttonReleased(unsigned int device, JoyStickButtonCode::ByEnum button)
    196     { joyStickButtons_[device][button].execute(KeybindMode::OnRelease); }
     197    { (*joyStickButtons_[device])[button].execute(KeybindMode::OnRelease); }
    197198
    198199    inline void KeyBinder::buttonHeld    (unsigned int device, JoyStickButtonCode::ByEnum button)
    199     { joyStickButtons_[device][button].execute(KeybindMode::OnHold); }
     200    { (*joyStickButtons_[device])[button].execute(KeybindMode::OnHold); }
    200201
    201202    inline void KeyBinder::allDevicesUpdated(float dt)
  • code/trunk/src/core/input/KeyDetector.cc

    r3327 r5695  
    7070    {
    7171        KeyBinder::JoyStickQuantityChanged(joyStickList);
    72         setCallbackCommand(callbackCommand_);
     72        if (!callbackCommand_.empty())
     73            setCallbackCommand(callbackCommand_);
    7374    }
    7475}
  • code/trunk/src/network/CMakeLists.txt

    r3304 r5695  
    3535  TrafficControl.cc
    3636)
     37
     38SET_SOURCE_FILES(NETWORK_HDR_FILES
     39  ChatListener.h
     40  Client.h
     41  ClientConnection.h
     42  ClientConnectionListener.h
     43  ClientInformation.h
     44  Connection.h
     45  FunctionCallManager.h
     46  GamestateClient.h
     47  GamestateHandler.h
     48  GamestateManager.h
     49  Host.h
     50  NetworkFunction.h
     51  NetworkPrecompiledHeaders.h
     52  NetworkPrereqs.h
     53  Server.h
     54  ServerConnection.h
     55  TrafficControl.h
     56)
     57
    3758ADD_SUBDIRECTORY(packet)
    3859ADD_SUBDIRECTORY(synchronisable)
    3960
    4061ORXONOX_ADD_LIBRARY(network
    41   FIND_HEADER_FILES
    4262  DEFINE_SYMBOL
    4363    "NETWORK_SHARED_BUILD"
     
    5171    core
    5272  SOURCE_FILES
    53     ${NETWORK_SRC_FILES}
     73    ${NETWORK_SRC_FILES} ${NETWORK_HDR_FILES}
    5474)
  • code/trunk/src/network/ClientInformation.h

    r3304 r5695  
    4949
    5050  /**
    51   * This class implements a list for client informations
     51  * This class implements a list for client information
    5252  * @author Oliver Scheuss
    5353  */
  • code/trunk/src/network/TODO

    • Property svn:mergeinfo deleted
  • code/trunk/src/network/packet/CMakeLists.txt

    r3084 r5695  
    11ADD_SOURCE_FILES(NETWORK_SRC_FILES
    2   Packet.cc
    32  Acknowledgement.cc
    43  Chat.cc
     
    87  FunctionCalls.cc
    98  Gamestate.cc
     9  Packet.cc
    1010  Welcome.cc
    1111)
     12
     13ADD_SOURCE_FILES(NETWORK_HDR_FILES
     14  Acknowledgement.h
     15  Chat.cc
     16  Chat.h
     17  ClassID.h
     18  DeleteObjects.h
     19  FunctionCalls.h
     20  FunctionIDs.h
     21  Gamestate.h
     22  Packet.h
     23  Welcome.h
     24)
  • code/trunk/src/network/synchronisable/CMakeLists.txt

    r2710 r5695  
    55  SynchronisableVariable.cc
    66)
     7
     8ADD_SOURCE_FILES(NETWORK_HDR_FILES
     9  NetworkCallback.h
     10  NetworkCallbackManager.h
     11  Synchronisable.h
     12  SynchronisableVariable.h
     13)
  • code/trunk/src/ois/OISEffect.cpp

    r1505 r5695  
    2929//Perhaps a case of a crazy extreme optimizer :/ (moved to header)
    3030//const unsigned int Effect::OIS_INFINITE = 0xFFFFFFFF;
     31
     32//------------------------------------------------------------------------------//
     33static const char* pszEForceString[] =
     34  { "UnknownForce",
     35    "ConstantForce",
     36    "RampForce",
     37    "PeriodicForce",
     38    "ConditionalForce",
     39    "CustomForce" };
     40
     41const char* Effect::getForceTypeName(Effect::EForce eValue)
     42{
     43  return (eValue >= 0 && eValue < _ForcesNumber) ? pszEForceString[eValue] : "<Bad force type>";
     44}
     45
     46static const char* pszETypeString[] =
     47  { "Unknown",
     48    "Constant",
     49    "Ramp",
     50    "Square", "Triangle", "Sine", "SawToothUp", "SawToothDown",
     51    "Friction", "Damper", "Inertia", "Spring",
     52    "Custom" };
     53
     54const char* Effect::getEffectTypeName(Effect::EType eValue)
     55{
     56  return (eValue >= 0 && eValue < _TypesNumber) ? pszETypeString[eValue] : "<Bad effect type>";
     57}
     58
     59static const char* pszEDirectionString[] =
     60  { "NorthWest", "North", "NorthEast", "East", "SouthEast", "South", "SouthWest", "West"};
     61
     62const char* Effect::getDirectionName(Effect::EDirection eValue)
     63{
     64  return (eValue >= 0 && eValue < _DirectionsNumber) ? pszEDirectionString[eValue] : "<Bad direction>";
     65}
    3166
    3267//------------------------------------------------------------------------------//
  • code/trunk/src/ois/OISEffect.h

    r1505 r5695  
    6060                        PeriodicForce,
    6161                        ConditionalForce,
    62                         CustomForce
     62                        CustomForce,
     63                        _ForcesNumber // Always keep in last position.
    6364                };
     65
     66                static const char* getForceTypeName(EForce eValue);
    6467
    6568                //! Type of effect
     
    7982                        Inertia,     //ConditionalForce
    8083                        Spring,      //ConditionalForce
    81                         Custom       //CustomForce
     84                        Custom,      //CustomForce
     85                        _TypesNumber // Always keep in last position.
    8286                };
     87
     88                static const char* getEffectTypeName(EType eValue);
    8389
    8490                //! Direction of the Force
     
    9298                        South,
    9399                        SouthWest,
    94                         West
     100                        West,
     101                        _DirectionsNumber // Always keep in last position.
    95102                };
     103
     104                static const char* getDirectionName(EDirection eValue);
    96105
    97106                /**
     
    168177                An optional envelope to be applied to the start/end of an effect. If any of
    169178                these values are nonzero, then the envelope will be used in setting up the
    170                 effect. Not currently utilised.. But, will be soon.
     179                effect.
    171180        */
    172181        class _OISExport Envelope : public ForceEffect
     
    178187  #pragma warning (disable : 4800)
    179188#endif
    180                 bool isUsed() { return attackLength | attackLevel | fadeLength | fadeLevel; }
     189                bool isUsed() const { return attackLength | attackLevel | fadeLength | fadeLevel; }
    181190#if defined(OIS_MSVC_COMPILER)
    182191  #pragma warning (pop)
    183192#endif
    184193
    185                 unsigned short attackLength;
     194                // Duration of the attack (microseconds)
     195                unsigned int attackLength;
     196
     197                // Absolute level at the beginning of the attack (0 to 10K)
     198                // (automatically signed when necessary by FF core according to effect level sign)
    186199                unsigned short attackLevel;
    187                 unsigned short fadeLength;
     200
     201                // Duration of fade (microseconds)
     202                unsigned int fadeLength;
     203
     204                // Absolute level at the end of fade (0 to 10K)
     205                // (automatically signed when necessary by FF core according to effect level sign)
    188206                unsigned short fadeLevel;
    189207        };
     
    211229                RampEffect() : startLevel(0), endLevel(0) {}
    212230
    213         class Envelope envelope; //Optional envolope
     231        class Envelope envelope; //Optional envelope
    214232                signed short startLevel;  //-10K to +10k
    215233                signed short endLevel;    //-10K to +10k
  • code/trunk/src/ois/OISForceFeedback.cpp

    r1505 r5695  
    2727
    2828//-------------------------------------------------------------//
    29 void ForceFeedback::_addEffectTypes( Effect::EForce force, Effect::EType type )
     29ForceFeedback::ForceFeedback() : mSetGainSupport(false), mSetAutoCenterSupport(false)
    3030{
    31         if( force == Effect::UnknownForce || type == Effect::Unknown )
    32                 OIS_EXCEPT( E_General, "Unknown Force||Type was added too effect list..." );
    33 
    34         mSupportedEffects[force] = type;
    3531}
    3632
    3733//-------------------------------------------------------------//
    38 const ForceFeedback::SupportedEffectList&
    39                                                 ForceFeedback::getSupportedEffects() const
     34void ForceFeedback::_addEffectTypes( Effect::EForce force, Effect::EType type )
     35{
     36        if( force <= Effect::UnknownForce || force >= Effect::_ForcesNumber
     37                || type <= Effect::Unknown || type >= Effect::_TypesNumber )
     38                OIS_EXCEPT( E_General, "Can't add unknown effect Force/Type to the supported list" );
     39
     40        mSupportedEffects.insert(std::pair<Effect::EForce, Effect::EType>(force, type));
     41}
     42
     43//-------------------------------------------------------------//
     44void ForceFeedback::_setGainSupport( bool on )
     45{
     46        mSetGainSupport = on;
     47}
     48
     49//-------------------------------------------------------------//
     50void ForceFeedback::_setAutoCenterSupport( bool on )
     51{
     52        mSetAutoCenterSupport = on;
     53}
     54
     55//-------------------------------------------------------------//
     56const ForceFeedback::SupportedEffectList& ForceFeedback::getSupportedEffects() const
    4057{
    4158        return mSupportedEffects;
    4259}
     60
     61//-------------------------------------------------------------//
     62bool ForceFeedback::supportsEffect(Effect::EForce force, Effect::EType type) const
     63{
     64    const std::pair<SupportedEffectList::const_iterator, SupportedEffectList::const_iterator>
     65            iterRange = mSupportedEffects.equal_range(force);
     66        SupportedEffectList::const_iterator iter;
     67        for (iter = iterRange.first; iter != iterRange.second; iter++)
     68        {
     69          if ((*iter).second == type)
     70                return true;
     71        }
     72
     73        return false;
     74}
  • code/trunk/src/ois/OISForceFeedback.h

    r1505 r5695  
    3636        {
    3737        public:
    38                 ForceFeedback() {}
     38                ForceFeedback();
    3939                virtual ~ForceFeedback() {}
    4040
     
    4444                        Individual effects have gain levels; however, this affects all
    4545                        effects at once.
     46                        Note: If the device does not support master gain setting, nothing is done
    4647                @param level
    4748                        A value between 0.0 and 1.0 represent the percentage of gain. 1.0
     
    5657                        the joystick back to center. DirectInput only has an on/off setting,
    5758                        whereas linux has levels.. Though, we go with DI's on/off mode only
     59                        Note: If the device does not support auto-centering, nothing is done
    5860                @param auto_on
    5961                        true to turn auto centering on, false to turn off.
     
    8789        virtual short getFFAxesNumber() = 0;
    8890
    89                 typedef std::map<Effect::EForce, Effect::EType> SupportedEffectList;
     91                /**
     92                @remarks
     93                        Get the current load (%, in [0, 100] of the FF device memory
     94                */
     95                virtual unsigned short getFFMemoryLoad() = 0;
     96
     97                typedef std::multimap<Effect::EForce, Effect::EType> SupportedEffectList;
    9098                /**
    9199                @remarks
     
    94102                const SupportedEffectList& getSupportedEffects() const;
    95103
     104                /**
     105                @remarks
     106                        Tell if a given force / effect type pair is supported
     107                */
     108                bool supportsEffect(Effect::EForce force, Effect::EType type) const;
     109
    96110                void _addEffectTypes( Effect::EForce force, Effect::EType type );
     111                void _setGainSupport( bool on );
     112                void _setAutoCenterSupport( bool on );
    97113
    98114        protected:
    99115                SupportedEffectList mSupportedEffects;
     116                bool mSetGainSupport;
     117                bool mSetAutoCenterSupport;
    100118        };
    101119}
  • code/trunk/src/ois/OISJoyStick.h

    r1505 r5695  
    3232
    3333        //! POV / HAT Joystick component
    34         class _OISExport Pov : Component
     34        class _OISExport Pov : public Component
    3535        {
    3636        public:
     
    5151
    5252        //! A sliding axis - only used in Win32 Right Now
    53         class _OISExport Slider : Component
     53        class _OISExport Slider : public Component
    5454        {
    5555        public:
  • code/trunk/src/ois/OISPrereqs.h

    r1505 r5695  
    167167        {
    168168        public:
    169                 Button() {}
    170                 Button(bool bPushed) : Component(OIS_Button), pushed(bPushed) {};
     169                Button() : Component(OIS_Button), pushed(false) {}
     170                Button(bool bPushed) : Component(OIS_Button), pushed(bPushed) {}
    171171                //! true if pushed, false otherwise
    172172                bool pushed;
  • code/trunk/src/ois/changes_orxonox.diff

    r2710 r5695  
     1--- linux/EventHelpers.cpp      (revision 5668)
     2+++ linux/EventHelpers.cpp      (working copy)
     3@@ -35,6 +35,20 @@
     4 # include <iostream>
     5 #endif
     6 
     7+// Fixes for missing macros in input.h
     8+#ifndef FF_EFFECT_MIN
     9+#define FF_EFFECT_MIN FF_RUMBLE
     10+#endif
     11+#ifndef FF_EFFECT_MAX
     12+#define FF_EFFECT_MAX FF_RAMP
     13+#endif
     14+#ifndef FF_WAVEFORM_MIN
     15+#define FF_WAVEFORM_MIN FF_SQUARE
     16+#endif
     17+#ifndef FF_WAVEFORM_MAX
     18+#define FF_WAVEFORM_MAX FF_CUSTOM
     19+#endif
     20+
     21 using namespace std;
     22 using namespace OIS;
     23 
     24
  • code/trunk/src/ois/linux/EventHelpers.cpp

    r1505 r5695  
    3434#ifdef OIS_LINUX_JOY_DEBUG
    3535# include <iostream>
    36   using namespace std;
    37 #endif
    38 
     36#endif
     37
     38// Fixes for missing macros in input.h
     39#ifndef FF_EFFECT_MIN
     40#define FF_EFFECT_MIN FF_RUMBLE
     41#endif
     42#ifndef FF_EFFECT_MAX
     43#define FF_EFFECT_MAX FF_RAMP
     44#endif
     45#ifndef FF_WAVEFORM_MIN
     46#define FF_WAVEFORM_MIN FF_SQUARE
     47#endif
     48#ifndef FF_WAVEFORM_MAX
     49#define FF_WAVEFORM_MAX FF_CUSTOM
     50#endif
     51
     52using namespace std;
    3953using namespace OIS;
    4054
     
    4256{
    4357public:
    44         std::vector<int> buttons, relAxes, absAxes, hats;
     58        vector<int> buttons, relAxes, absAxes, hats;
    4559};
    4660
    47 bool inline isBitSet(unsigned long bits[], unsigned int bit)
    48 {
    49         return (bits[bit/(sizeof(long)*8)] >> ((bit)%(sizeof(long)*8))) & 1;
    50 }
     61bool inline isBitSet(unsigned char bits[], unsigned int bit)
     62{
     63  return (bits[(bit)/(sizeof(unsigned char)*8)] >> ((bit)%(sizeof(unsigned char)*8))) & 1;
     64}
     65
    5166//-----------------------------------------------------------------------------//
    5267DeviceComponentInfo getComponentInfo( int deviceID )
    5368{
    54         unsigned long info[2][((KEY_MAX-1)/(sizeof(long)*8)) +1];
    55         memset( info, 0, sizeof(info) );
     69        unsigned char ev_bits[1 + EV_MAX/8/sizeof(unsigned char)];
     70        memset( ev_bits, 0, sizeof(ev_bits) );
     71
     72        //Read "all" (hence 0) components of the device
     73#ifdef OIS_LINUX_JOY_DEBUG
     74        cout << "EventUtils::getComponentInfo(" << deviceID
     75                 << ") : Reading device events features" << endl;
     76#endif
     77        if (ioctl(deviceID, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1)
     78                OIS_EXCEPT( E_General, "Could not read device events features");
    5679
    5780        DeviceComponentInfo components;
    58 
    59         //Read "all" (hence 0) components of the device - read into first entry
    60         ioctl(deviceID, EVIOCGBIT(0, EV_MAX), info[0]);
    6181
    6282        for (int i = 0; i < EV_MAX; i++)
    6383        {
    64                 if( isBitSet(info[0], i) )
     84                if( isBitSet(ev_bits, i) )
    6585                {
    66                         memset( info[1], 0, sizeof(info) / 2 );
    67                         ioctl(deviceID, EVIOCGBIT(i, KEY_MAX), info[1]);
    68                         for (int j = 0; j < KEY_MAX; j++)
     86                    // Absolute axis.
     87                    if(i == EV_ABS)
    6988                        {
    70                                 if( isBitSet(info[1], j) )
     89                            unsigned char abs_bits[1 + ABS_MAX/8/sizeof(unsigned char)];
     90                            memset( abs_bits, 0, sizeof(abs_bits) );
     91
     92#ifdef OIS_LINUX_JOY_DEBUG
     93                                cout << "EventUtils::getComponentInfo(" << deviceID
     94                                         << ") : Reading device absolute axis features" << endl;
     95#endif
     96
     97                                if (ioctl(deviceID, EVIOCGBIT(i, sizeof(abs_bits)), abs_bits) == -1)
     98                                    OIS_EXCEPT( E_General, "Could not read device absolute axis features");
     99
     100                                for (int j = 0; j < ABS_MAX; j++)
    71101                                {
    72                                         if(i == EV_ABS)
     102                                    if( isBitSet(abs_bits, j) )
    73103                                        {
    74104                                                //input_absinfo abInfo;
     
    89119                                                }
    90120                                        }
    91                                         else if(i == EV_REL)
     121                                }
     122                        }
     123                        else if(i == EV_REL)
     124                        {
     125                            unsigned char rel_bits[1 + REL_MAX/8/sizeof(unsigned char)];
     126                                memset( rel_bits, 0, sizeof(rel_bits) );
     127                               
     128#ifdef OIS_LINUX_JOY_DEBUG
     129                                cout << "EventUtils::getComponentInfo(" << deviceID
     130                                         << ") : Reading device relative axis features" << endl;
     131#endif
     132
     133                                if (ioctl(deviceID, EVIOCGBIT(i, sizeof(rel_bits)), rel_bits) == -1)
     134                                    OIS_EXCEPT( E_General, "Could not read device relative axis features");
     135                               
     136                                for (int j = 0; j < REL_MAX; j++)
     137                                {
     138                                    if( isBitSet(rel_bits, j) )
    92139                                        {
    93                                                 components.relAxes.push_back(j);
     140                                            components.relAxes.push_back(j);
    94141                                        }
    95                                         else if(i == EV_KEY)
     142                                }
     143                        }
     144                        else if(i == EV_KEY)
     145                        {
     146                            unsigned char key_bits[1 + KEY_MAX/8/sizeof(unsigned char)];
     147                                memset( key_bits, 0, sizeof(key_bits) );
     148                               
     149#ifdef OIS_LINUX_JOY_DEBUG
     150                                cout << "EventUtils::getComponentInfo(" << deviceID
     151                                         << ") : Reading device buttons features" << endl;
     152#endif
     153
     154                                if (ioctl(deviceID, EVIOCGBIT(i, sizeof(key_bits)), key_bits) == -1)
     155                                    OIS_EXCEPT( E_General, "Could not read device buttons features");
     156                               
     157                                for (int j = 0; j < KEY_MAX; j++)
     158                                {
     159                                    if( isBitSet(key_bits, j) )
    96160                                        {
    97                                                 components.buttons.push_back(j);
     161                                            components.buttons.push_back(j);
    98162                                        }
    99163                                }
     
    108172bool EventUtils::isJoyStick( int deviceID, JoyStickInfo &js )
    109173{
    110         if( deviceID == -1 ) OIS_EXCEPT( E_General, "Error with File Descriptor" );
     174        if( deviceID == -1 )
     175                OIS_EXCEPT( E_General, "Error with File Descriptor" );
    111176
    112177        DeviceComponentInfo info = getComponentInfo( deviceID );
     
    117182
    118183        #ifdef OIS_LINUX_JOY_DEBUG
    119           cout << "\n\nDisplaying ButtonMapping Status:";
     184        cout << endl << "Displaying ButtonMapping Status:" << endl;
    120185        #endif
    121         for(std::vector<int>::iterator i = info.buttons.begin(), e = info.buttons.end(); i != e; ++i )
     186        for(vector<int>::iterator i = info.buttons.begin(), e = info.buttons.end(); i != e; ++i )
    122187        {
    123188                //Check to ensure we find at least one joy only button
    124                 if( (*i >= BTN_JOYSTICK && *i <= BTN_THUMBR) || (*i >= BTN_WHEEL && *i <= BTN_GEAR_UP ) )
     189                if( (*i >= BTN_JOYSTICK && *i < BTN_GAMEPAD) 
     190                        || (*i >= BTN_GAMEPAD && *i < BTN_DIGI)
     191                        || (*i >= BTN_WHEEL && *i < KEY_OK) )
    125192                        joyButtonFound = true;
    126193
     
    128195
    129196                #ifdef OIS_LINUX_JOY_DEBUG
    130                   cout << "\nButton Mapping ID (hex): " << hex << *i << " OIS Button Num: " << dec << (buttons-1);
     197                  cout << "Button Mapping ID (hex): " << hex << *i
     198                           << " OIS Button Num: " << dec << buttons-1 << endl;
    131199                #endif
    132200        }
     201        #ifdef OIS_LINUX_JOY_DEBUG
     202        cout << endl;
     203        #endif
    133204
    134205        //Joy Buttons found, so it must be a joystick or pad
     
    140211                js.axes = info.relAxes.size() + info.absAxes.size();
    141212                js.hats = info.hats.size();
     213                #ifdef OIS_LINUX_JOY_DEBUG
     214                  cout << endl << "Device name:" << js.vendor << endl;
     215                  cout << "Device unique Id:" << getUniqueId(deviceID) << endl;
     216                  cout << "Device physical location:" << getPhysicalLocation(deviceID) << endl;
     217                #endif
    142218
    143219                //Map the Axes
    144220                #ifdef OIS_LINUX_JOY_DEBUG
    145                   cout << "\n\nDisplaying AxisMapping Status:";
     221                  cout << endl << "Displaying AxisMapping Status:" << endl;
    146222                #endif
    147223                int axes = 0;
    148                 for(std::vector<int>::iterator i = info.absAxes.begin(), e = info.absAxes.end(); i != e; ++i )
     224                for(vector<int>::iterator i = info.absAxes.begin(), e = info.absAxes.end(); i != e; ++i )
    149225                {
    150226                        js.axis_map[*i] = axes;
    151227
     228#ifdef OIS_LINUX_JOY_DEBUG
     229                        cout << "EventUtils::isJoyStick(" << deviceID
     230                                          << ") : Reading device absolute axis #" << *i << " features" << endl;
     231#endif
     232
    152233                        input_absinfo absinfo;
    153                         ioctl(deviceID, EVIOCGABS(*i), &absinfo);
     234                        if (ioctl(deviceID, EVIOCGABS(*i), &absinfo) == -1)
     235                                OIS_EXCEPT( E_General, "Could not read device absolute axis features");
    154236                        js.axis_range[axes] = Range(absinfo.minimum, absinfo.maximum);
    155237
    156238                        #ifdef OIS_LINUX_JOY_DEBUG
    157                           cout << "\nAxis Mapping ID (hex): " << hex << *i << " OIS Axis Num: " << dec << axes;
     239                          cout << "Axis Mapping ID (hex): " << hex << *i
     240                                   << " OIS Axis Num: " << dec << axes << endl;
    158241                        #endif
    159242
     
    166249
    167250//-----------------------------------------------------------------------------//
    168 std::string EventUtils::getName( int deviceID )
    169 {
     251string EventUtils::getName( int deviceID )
     252{
     253#ifdef OIS_LINUX_JOY_DEBUG
     254        cout << "EventUtils::getName(" << deviceID
     255                 << ") : Reading device name" << endl;
     256#endif
     257
    170258        char name[OIS_DEVICE_NAME];
    171         ioctl(deviceID, EVIOCGNAME(OIS_DEVICE_NAME), name);
    172         return std::string(name);
     259        if (ioctl(deviceID, EVIOCGNAME(OIS_DEVICE_NAME), name) == -1)
     260                OIS_EXCEPT( E_General, "Could not read device name");
     261        return string(name);
     262}
     263
     264//-----------------------------------------------------------------------------//
     265string EventUtils::getUniqueId( int deviceID )
     266{
     267#ifdef OIS_LINUX_JOY_DEBUG
     268        cout << "EventUtils::getUniqueId(" << deviceID
     269                 << ") : Reading device unique Id" << endl;
     270#endif
     271
     272#define OIS_DEVICE_UNIQUE_ID 128
     273        char uId[OIS_DEVICE_UNIQUE_ID];
     274        if (ioctl(deviceID, EVIOCGUNIQ(OIS_DEVICE_UNIQUE_ID), uId) == -1)
     275                OIS_EXCEPT( E_General, "Could not read device unique Id");
     276        return string(uId);
     277}
     278
     279//-----------------------------------------------------------------------------//
     280string EventUtils::getPhysicalLocation( int deviceID )
     281{
     282#ifdef OIS_LINUX_JOY_DEBUG
     283        cout << "EventUtils::getPhysicalLocation(" << deviceID
     284                 << ") : Reading device physical location" << endl;
     285#endif
     286
     287#define OIS_DEVICE_PHYSICAL_LOCATION 128
     288        char physLoc[OIS_DEVICE_PHYSICAL_LOCATION];
     289        if (ioctl(deviceID, EVIOCGPHYS(OIS_DEVICE_PHYSICAL_LOCATION), physLoc) == -1)
     290                OIS_EXCEPT( E_General, "Could not read device physical location");
     291        return string(physLoc);
    173292}
    174293
     
    177296{
    178297        //Linux Event to OIS Event Mappings
    179         std::map<int, Effect::EType> typeMap;
     298        map<int, Effect::EType> typeMap;
    180299        typeMap[FF_CONSTANT] = Effect::Constant;
    181300        typeMap[FF_RAMP]     = Effect::Ramp;
     
    191310        typeMap[FF_CUSTOM]   = Effect::Custom;
    192311
    193         std::map<int, Effect::EForce> forceMap;
     312        map<int, Effect::EForce> forceMap;
    194313        forceMap[FF_CONSTANT] = Effect::ConstantForce;
    195         forceMap[FF_RAMP] = Effect::RampForce;
    196         forceMap[FF_PERIODIC] = Effect::PeriodicForce;
    197         forceMap[FF_CUSTOM] = Effect::CustomForce;
     314        forceMap[FF_RAMP]     = Effect::RampForce;
     315        forceMap[FF_SPRING]   = Effect::ConditionalForce;
     316        forceMap[FF_FRICTION] = Effect::ConditionalForce;
     317        forceMap[FF_SQUARE]   = Effect::PeriodicForce;
     318        forceMap[FF_TRIANGLE] = Effect::PeriodicForce;
     319        forceMap[FF_SINE]     = Effect::PeriodicForce;
     320        forceMap[FF_SAW_UP]   = Effect::PeriodicForce;
     321        forceMap[FF_SAW_DOWN] = Effect::PeriodicForce;
     322        forceMap[FF_DAMPER]   = Effect::ConditionalForce;
     323        forceMap[FF_INERTIA]  = Effect::ConditionalForce;
     324        forceMap[FF_CUSTOM]   = Effect::CustomForce;
    198325
    199326        //Remove any previously existing memory and create fresh
    200327        removeForceFeedback( ff );
    201         *ff = new LinuxForceFeedback();
    202 
    203         unsigned long info[4] = {0,0,0,0};
    204         unsigned long subinfo[4]= {0,0,0,0};
    205 
    206         //Read overall force feedback components of the device
    207         ioctl(deviceID, EVIOCGBIT(EV_FF, sizeof(long)*4), info);
     328        *ff = new LinuxForceFeedback(deviceID);
     329
     330        //Read overall force feedback features
     331        unsigned char ff_bits[1 + FF_MAX/8/sizeof(unsigned char)];
     332        memset(ff_bits, 0, sizeof(ff_bits));
     333
     334#ifdef OIS_LINUX_JOY_DEBUG
     335        cout << "EventUtils::enumerateForceFeedback(" << deviceID
     336                 << ") : Reading device force feedback features" << endl;
     337#endif
     338
     339        if (ioctl(deviceID, EVIOCGBIT(EV_FF, sizeof(ff_bits)), ff_bits) == -1)
     340                OIS_EXCEPT( E_General, "Could not read device force feedback features");
     341
     342
     343    #ifdef OIS_LINUX_JOY_DEBUG
     344        cout << "FF bits: " << hex;
     345        for (int i = 0; i < sizeof(ff_bits); i++)
     346                cout << (int)ff_bits[i];
     347        cout << endl << dec;
     348    #endif
    208349
    209350        //FF Axes
    210         //if( isBitSet(info, ABS_X) ) //X Axis
    211         //if( isBitSet(info, ABS_Y) ) //Y Axis
    212         //if( isBitSet(info, ABS_WHEEL) ) //Wheel
     351        //if( isBitSet(ff_bits, ABS_X) ) //X Axis
     352        //if( isBitSet(ff_bits, ABS_Y) ) //Y Axis
     353        //if( isBitSet(ff_bits, ABS_WHEEL) ) //Wheel
    213354
    214355        //FF Effects
    215         for( int effect = ABS_WHEEL+1; effect < FF_MAX; effect++ )
     356        for( int effect = FF_EFFECT_MIN; effect <= FF_WAVEFORM_MAX; effect++ )
    216357        {
    217                 if(isBitSet(info, effect))
     358                // The RUMBLE force type is ignored, as periodic force one is more powerfull.
     359                // The PERIODIC force type is processed later, for each associated periodic effect type.
     360                if (effect == FF_RUMBLE || effect == FF_PERIODIC)
     361                        continue;
     362
     363                if(isBitSet(ff_bits, effect))
    218364                {
    219                         //std::cout << "\tEffect Type: " << effect << std::endl;
    220                         memset(subinfo, 0, sizeof(subinfo));
    221                         //Read any info about this supported effect
    222                         ioctl(deviceID, EVIOCGBIT(effect, sizeof(long)*4), subinfo);
    223                         for( int force = 0; force < FF_MAX; force++ )
    224                         {
    225                                 if(isBitSet(subinfo, force))
    226                                         (*ff)->_addEffectTypes( forceMap[force], typeMap[effect] );
    227                         }
     365                        #ifdef OIS_LINUX_JOY_DEBUG
     366                    cout << "  Effect Type: " << Effect::getEffectTypeName(typeMap[effect]) << endl;
     367                        #endif
     368
     369                        (*ff)->_addEffectTypes( forceMap[effect], typeMap[effect] );
    228370                }
    229371        }
     372
     373        //FF device properties
     374        if (isBitSet(ff_bits, FF_GAIN))
     375                (*ff)->_setGainSupport(true);
     376               
     377        if (isBitSet(ff_bits, FF_AUTOCENTER))
     378                (*ff)->_setAutoCenterSupport(true);
    230379
    231380        //Check to see if any effects were added, else destroy the pointer
  • code/trunk/src/ois/linux/EventHelpers.h

    r1505 r5695  
    4343
    4444                static std::string getName( int deviceID );
     45                static std::string getUniqueId( int deviceID );
     46                static std::string getPhysicalLocation( int deviceID );
    4547        };
    4648}
  • code/trunk/src/ois/linux/LinuxForceFeedback.cpp

    r1505 r5695  
    2424#include "OISException.h"
    2525
     26#include <cstdlib>
     27#include <errno.h>
     28#include <memory.h>
     29
    2630using namespace OIS;
    2731
    28 //--------------------------------------------------------------//
    29 LinuxForceFeedback::LinuxForceFeedback()
    30 {
    31 }
     32// 0 = No trace; 1 = Important traces; 2 = Debug traces
     33#define OIS_LINUX_JOYFF_DEBUG 1
     34
     35#ifdef OIS_LINUX_JOYFF_DEBUG
     36# include <iostream>
     37  using namespace std;
     38#endif
     39
     40//--------------------------------------------------------------//
     41LinuxForceFeedback::LinuxForceFeedback(int deviceID) :
     42        ForceFeedback(), mJoyStick(deviceID)
     43{
     44}
     45
    3246//--------------------------------------------------------------//
    3347LinuxForceFeedback::~LinuxForceFeedback()
    3448{
    35 }
    36 
    37 //--------------------------------------------------------------//
    38 void LinuxForceFeedback::setMasterGain(float)
    39 {
    40 }
    41 
    42 //--------------------------------------------------------------//
    43 void LinuxForceFeedback::setAutoCenterMode(bool)
    44 {
    45 }
    46 
    47 //--------------------------------------------------------------//
    48 void LinuxForceFeedback::upload( const Effect* /*effect*/ )
    49 {
    50 }
    51 
    52 //--------------------------------------------------------------//
    53 void LinuxForceFeedback::modify( const Effect* /*effect*/ )
    54 {
    55 }
    56 
    57 //--------------------------------------------------------------//
    58 void LinuxForceFeedback::remove( const Effect* /*effect*/ )
    59 {
    60 }
    61 
     49        // Unload all effects.
     50        for(EffectList::iterator i = mEffectList.begin(); i != mEffectList.end(); ++i )
     51        {
     52                struct ff_effect *linEffect = i->second;
     53                if( linEffect )
     54                        _unload(linEffect->id);
     55        }
     56
     57        mEffectList.clear();
     58}
     59
     60//--------------------------------------------------------------//
     61unsigned short LinuxForceFeedback::getFFMemoryLoad()
     62{
     63        int nEffects = -1;
     64        if (ioctl(mJoyStick, EVIOCGEFFECTS, &nEffects) == -1)
     65                OIS_EXCEPT(E_General, "Unknown error reading max number of uploaded effects.");
     66#if (OIS_LINUX_JOYFF_DEBUG > 1)
     67        cout << "LinuxForceFeedback("<< mJoyStick 
     68                 << ") : Read device max number of uploaded effects : " << nEffects << endl;
     69#endif
     70
     71        return (unsigned short int)(nEffects > 0 ? 100.0*mEffectList.size()/nEffects : 100);
     72}
     73
     74//--------------------------------------------------------------//
     75void LinuxForceFeedback::setMasterGain(float value)
     76{
     77        if (!mSetGainSupport)
     78        {
     79#if (OIS_LINUX_JOYFF_DEBUG > 0)
     80                cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting master gain "
     81                         << "is not supported by the device" << endl;
     82#endif
     83                return;
     84        }
     85
     86        struct input_event event;
     87
     88        memset(&event, 0, sizeof(event));
     89        event.type = EV_FF;
     90        event.code = FF_GAIN;
     91        if (value < 0.0)
     92                value = 0.0;
     93        else if (value > 1.0)
     94                value = 1.0;
     95        event.value = (__s32)(value * 0xFFFFUL);
     96
     97#if (OIS_LINUX_JOYFF_DEBUG > 0)
     98        cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting master gain to "
     99                 << value << " => " << event.value << endl;
     100#endif
     101
     102        if (write(mJoyStick, &event, sizeof(event)) != sizeof(event)) {
     103                OIS_EXCEPT(E_General, "Unknown error changing master gain.");
     104        }
     105}
     106
     107//--------------------------------------------------------------//
     108void LinuxForceFeedback::setAutoCenterMode(bool enabled)
     109{
     110        if (!mSetAutoCenterSupport)
     111        {
     112#if (OIS_LINUX_JOYFF_DEBUG > 0)
     113                cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting auto-center mode "
     114                         << "is not supported by the device" << endl;
     115#endif
     116                return;
     117        }
     118
     119        struct input_event event;
     120
     121        memset(&event, 0, sizeof(event));
     122        event.type = EV_FF;
     123        event.code = FF_AUTOCENTER;
     124        event.value = (__s32)(enabled*0xFFFFFFFFUL);
     125
     126#if (OIS_LINUX_JOYFF_DEBUG > 0)
     127        cout << "LinuxForceFeedback("<< mJoyStick << ") : Toggling auto-center to "
     128                 << enabled << " => 0x" << hex << event.value << dec << endl;
     129#endif
     130
     131        if (write(mJoyStick, &event, sizeof(event)) != sizeof(event)) {
     132                OIS_EXCEPT(E_General, "Unknown error toggling auto-center.");
     133        }
     134}
     135
     136//--------------------------------------------------------------//
     137void LinuxForceFeedback::upload( const Effect* effect )
     138{
     139        switch( effect->force )
     140        {
     141                case OIS::Effect::ConstantForce:
     142                        _updateConstantEffect(effect); 
     143                        break;
     144                case OIS::Effect::ConditionalForce:
     145                        _updateConditionalEffect(effect);
     146                        break;
     147                case OIS::Effect::PeriodicForce:
     148                        _updatePeriodicEffect(effect);
     149                        break;
     150                case OIS::Effect::RampForce:
     151                        _updateRampEffect(effect);     
     152                        break;
     153                case OIS::Effect::CustomForce:
     154                        //_updateCustomEffect(effect);
     155                        //break;
     156                default:
     157                        OIS_EXCEPT(E_NotImplemented, "Requested force not implemented yet, sorry!");
     158                        break;
     159        }
     160}
     161
     162//--------------------------------------------------------------//
     163void LinuxForceFeedback::modify( const Effect* effect )
     164{
     165        upload(effect);
     166}
     167
     168//--------------------------------------------------------------//
     169void LinuxForceFeedback::remove( const Effect* effect )
     170{
     171        //Get the effect - if it exists
     172        EffectList::iterator i = mEffectList.find(effect->_handle);
     173        if( i != mEffectList.end() )
     174        {
     175                struct ff_effect *linEffect = i->second;
     176                if( linEffect )
     177                {
     178                        _stop(effect->_handle);
     179
     180                        _unload(effect->_handle);
     181
     182                        free(linEffect);
     183
     184                        mEffectList.erase(i);
     185                }
     186                else
     187                        mEffectList.erase(i);
     188        }
     189}
     190
     191//--------------------------------------------------------------//
     192// To Signed16/Unsigned15 safe conversions
     193#define MaxUnsigned15Value 0x7FFF
     194#define toUnsigned15(value) \
     195        (__u16)((value) < 0 ? 0 : ((value) > MaxUnsigned15Value ? MaxUnsigned15Value : (value)))
     196
     197#define MaxSigned16Value  0x7FFF
     198#define MinSigned16Value -0x7FFF
     199#define toSigned16(value) \
     200  (__s16)((value) < MinSigned16Value ? MinSigned16Value : ((value) > MaxSigned16Value ? MaxSigned16Value : (value)))
     201
     202// OIS to Linux duration
     203#define LinuxInfiniteDuration 0xFFFF
     204#define OISDurationUnitMS 1000 // OIS duration unit (microseconds), expressed in milliseconds (theLinux duration unit)
     205
     206// linux/input.h : All duration values are expressed in ms. Values above 32767 ms (0x7fff)
     207//                 should not be used and have unspecified results.
     208#define LinuxDuration(oisDuration) ((oisDuration) == Effect::OIS_INFINITE ? LinuxInfiniteDuration \
     209                                                                        : toUnsigned15((oisDuration)/OISDurationUnitMS))
     210
     211
     212// OIS to Linux levels
     213#define OISMaxLevel 10000
     214#define LinuxMaxLevel 0x7FFF
     215
     216// linux/input.h : Valid range for the attack and fade levels is 0x0000 - 0x7fff
     217#define LinuxPositiveLevel(oisLevel) toUnsigned15(LinuxMaxLevel*(long)(oisLevel)/OISMaxLevel)
     218
     219#define LinuxSignedLevel(oisLevel) toSigned16(LinuxMaxLevel*(long)(oisLevel)/OISMaxLevel)
     220
     221
     222//--------------------------------------------------------------//
     223void LinuxForceFeedback::_setCommonProperties(struct ff_effect *event,
     224                                                                                          struct ff_envelope *ffenvelope,
     225                                                                                          const Effect* effect, const Envelope *envelope )
     226{
     227        memset(event, 0, sizeof(struct ff_effect));
     228
     229        if (envelope && ffenvelope && envelope->isUsed()) {
     230                ffenvelope->attack_length = LinuxDuration(envelope->attackLength);
     231                ffenvelope->attack_level = LinuxPositiveLevel(envelope->attackLevel);
     232                ffenvelope->fade_length = LinuxDuration(envelope->fadeLength);
     233                ffenvelope->fade_level = LinuxPositiveLevel(envelope->fadeLevel);
     234        }
     235       
     236#if (OIS_LINUX_JOYFF_DEBUG > 1)
     237        cout << endl;
     238        if (envelope && ffenvelope)
     239        {
     240                cout << "  Enveloppe :" << endl
     241                         << "    AttackLen : " << envelope->attackLength
     242                         << " => " << ffenvelope->attack_length << endl
     243                         << "    AttackLvl : " << envelope->attackLevel
     244                         << " => " << ffenvelope->attack_level << endl
     245                         << "    FadeLen   : " << envelope->fadeLength
     246                         << " => " << ffenvelope->fade_length << endl
     247                         << "    FadeLvl   : " << envelope->fadeLevel
     248                         << " => " << ffenvelope->fade_level << endl;
     249        }
     250#endif
     251       
     252        event->direction = (__u16)(1 + (effect->direction*45.0+135.0)*0xFFFFUL/360.0);
     253
     254#if (OIS_LINUX_JOYFF_DEBUG > 1)
     255        cout << "  Direction : " << Effect::getDirectionName(effect->direction)
     256                 << " => 0x" << hex << event->direction << dec << endl;
     257#endif
     258
     259        // TODO trigger_button 0 vs. -1
     260        event->trigger.button = effect->trigger_button; // < 0 ? 0 : effect->trigger_button;
     261        event->trigger.interval = LinuxDuration(effect->trigger_interval);
     262
     263#if (OIS_LINUX_JOYFF_DEBUG > 1)
     264        cout << "  Trigger :" << endl
     265                 << "    Button   : " << effect->trigger_button
     266                 << " => " << event->trigger.button << endl
     267                 << "    Interval : " << effect->trigger_interval
     268                 << " => " << event->trigger.interval << endl;
     269#endif
     270
     271        event->replay.length = LinuxDuration(effect->replay_length);
     272        event->replay.delay = LinuxDuration(effect->replay_delay);
     273
     274#if (OIS_LINUX_JOYFF_DEBUG > 1)
     275        cout << "  Replay :" << endl
     276                 << "    Length : " << effect->replay_length
     277                 << " => " << event->replay.length << endl
     278                 << "    Delay  : " << effect->replay_delay
     279                 << " => " << event->replay.delay << endl;
     280#endif
     281}
     282
     283//--------------------------------------------------------------//
     284void LinuxForceFeedback::_updateConstantEffect( const Effect* eff )
     285{
     286        struct ff_effect event;
     287
     288        ConstantEffect *effect = static_cast<ConstantEffect*>(eff->getForceEffect());
     289
     290        _setCommonProperties(&event, &event.u.constant.envelope, eff, &effect->envelope);
     291
     292        event.type = FF_CONSTANT;
     293        event.id = -1;
     294
     295        event.u.constant.level = LinuxSignedLevel(effect->level);
     296
     297#if (OIS_LINUX_JOYFF_DEBUG > 1)
     298        cout << "  Level : " << effect->level
     299                 << " => " << event.u.constant.level << endl;
     300#endif
     301
     302        _upload(&event, eff);
     303}
     304
     305//--------------------------------------------------------------//
     306void LinuxForceFeedback::_updateRampEffect( const Effect* eff )
     307{
     308        struct ff_effect event;
     309
     310        RampEffect *effect = static_cast<RampEffect*>(eff->getForceEffect());
     311
     312        _setCommonProperties(&event, &event.u.constant.envelope, eff, &effect->envelope);
     313
     314        event.type = FF_RAMP;
     315        event.id = -1;
     316
     317        event.u.ramp.start_level = LinuxSignedLevel(effect->startLevel);
     318        event.u.ramp.end_level = LinuxSignedLevel(effect->endLevel);
     319
     320#if (OIS_LINUX_JOYFF_DEBUG > 1)
     321        cout << "  StartLevel : " << effect->startLevel
     322                 << " => " << event.u.ramp.start_level << endl
     323                 << "  EndLevel   : " << effect->endLevel
     324                 << " => " << event.u.ramp.end_level << endl;
     325#endif
     326
     327        _upload(&event, eff);
     328}
     329
     330//--------------------------------------------------------------//
     331void LinuxForceFeedback::_updatePeriodicEffect( const Effect* eff )
     332{
     333        struct ff_effect event;
     334
     335        PeriodicEffect *effect = static_cast<PeriodicEffect*>(eff->getForceEffect());
     336
     337        _setCommonProperties(&event, &event.u.periodic.envelope, eff, &effect->envelope);
     338
     339        event.type = FF_PERIODIC;
     340        event.id = -1;
     341
     342        switch( eff->type )
     343        {
     344                case OIS::Effect::Square:
     345                        event.u.periodic.waveform = FF_SQUARE;
     346                        break;
     347                case OIS::Effect::Triangle:
     348                        event.u.periodic.waveform = FF_TRIANGLE;
     349                        break;
     350                case OIS::Effect::Sine:
     351                        event.u.periodic.waveform = FF_SINE;
     352                        break;
     353                case OIS::Effect::SawToothUp:
     354                        event.u.periodic.waveform = FF_SAW_UP;
     355                        break;
     356                case OIS::Effect::SawToothDown:
     357                        event.u.periodic.waveform = FF_SAW_DOWN;
     358                        break;
     359                // Note: No support for Custom periodic force effect for the moment
     360                //case OIS::Effect::Custom:
     361                        //event.u.periodic.waveform = FF_CUSTOM;
     362                        //break;
     363                default:
     364                        OIS_EXCEPT(E_General, "No such available effect for Periodic force!");
     365                        break;
     366        }
     367
     368        event.u.periodic.period    = LinuxDuration(effect->period);
     369        event.u.periodic.magnitude = LinuxPositiveLevel(effect->magnitude);
     370        event.u.periodic.offset    = LinuxPositiveLevel(effect->offset);
     371        event.u.periodic.phase     = (__u16)(effect->phase*event.u.periodic.period/36000.0); // ?????
     372
     373        // Note: No support for Custom periodic force effect for the moment
     374        event.u.periodic.custom_len = 0;
     375        event.u.periodic.custom_data = 0;
     376
     377#if (OIS_LINUX_JOYFF_DEBUG > 1)
     378        cout << "  Magnitude : " << effect->magnitude
     379                 << " => " << event.u.periodic.magnitude << endl
     380                 << "  Period    : " << effect->period
     381                 << " => " << event.u.periodic.period  << endl
     382                 << "  Offset    : " << effect->offset
     383                 << " => " << event.u.periodic.offset << endl
     384                 << "  Phase     : " << effect->phase
     385                 << " => " << event.u.periodic.phase << endl;
     386#endif
     387
     388        _upload(&event, eff);
     389}
     390
     391//--------------------------------------------------------------//
     392void LinuxForceFeedback::_updateConditionalEffect( const Effect* eff )
     393{
     394        struct ff_effect event;
     395
     396        ConditionalEffect *effect = static_cast<ConditionalEffect*>(eff->getForceEffect());
     397
     398        _setCommonProperties(&event, NULL, eff, NULL);
     399
     400        switch( eff->type )
     401        {
     402                case OIS::Effect::Friction:
     403                        event.type = FF_FRICTION;
     404                        break;
     405                case OIS::Effect::Damper:
     406                        event.type = FF_DAMPER;
     407                        break;
     408                case OIS::Effect::Inertia:
     409                        event.type = FF_INERTIA;
     410                        break;
     411                case OIS::Effect::Spring:
     412                        event.type = FF_SPRING;
     413                        break;
     414                default:
     415                        OIS_EXCEPT(E_General, "No such available effect for Conditional force!");
     416                        break;
     417        }
     418
     419        event.id = -1;
     420
     421        event.u.condition[0].right_saturation = LinuxSignedLevel(effect->rightSaturation);
     422        event.u.condition[0].left_saturation  = LinuxSignedLevel(effect->leftSaturation);
     423        event.u.condition[0].right_coeff      = LinuxSignedLevel(effect->rightCoeff);
     424        event.u.condition[0].left_coeff       = LinuxSignedLevel(effect->leftCoeff);
     425        event.u.condition[0].deadband         = LinuxPositiveLevel(effect->deadband);// Unit ??
     426        event.u.condition[0].center           = LinuxSignedLevel(effect->center); // Unit ?? TODO ?
     427
     428        // TODO support for second condition
     429        event.u.condition[1] = event.u.condition[0];
     430
     431#if (OIS_LINUX_JOYFF_DEBUG > 1)
     432        cout << "  Condition[0] : " << endl
     433                 << "    RightSaturation  : " << effect->rightSaturation
     434                 << " => " << event.u.condition[0].right_saturation << endl
     435                 << "    LeftSaturation   : " << effect->leftSaturation
     436                 << " => " << event.u.condition[0]. left_saturation << endl
     437                 << "    RightCoefficient : " << effect->rightCoeff
     438                 << " => " << event.u.condition[0].right_coeff << endl
     439                 << "    LeftCoefficient : " << effect->leftCoeff
     440                 << " => " << event.u.condition[0].left_coeff << endl
     441                 << "    DeadBand        : " << effect->deadband
     442                 << " => " << event.u.condition[0].deadband  << endl
     443                 << "    Center          : " << effect->center
     444                 << " => " << event.u.condition[0].center << endl;
     445        cout << "  Condition[1] : Not implemented" << endl;
     446#endif
     447        _upload(&event, eff);
     448}
     449
     450//--------------------------------------------------------------//
     451void LinuxForceFeedback::_upload( struct ff_effect* ffeffect, const Effect* effect)
     452{
     453        struct ff_effect *linEffect = 0;
     454
     455        //Get the effect - if it exists
     456        EffectList::iterator i = mEffectList.find(effect->_handle);
     457        //It has been created already
     458        if( i != mEffectList.end() )
     459                linEffect = i->second;
     460
     461        if( linEffect == 0 )
     462        {
     463#if (OIS_LINUX_JOYFF_DEBUG > 1)
     464                cout << endl << "LinuxForceFeedback("<< mJoyStick << ") : Adding new effect : "
     465                         << Effect::getEffectTypeName(effect->type) << endl;
     466#endif
     467
     468                //This effect has not yet been created, so create it in the device
     469                if (ioctl(mJoyStick, EVIOCSFF, ffeffect) == -1) {
     470                        // TODO device full check
     471                        // OIS_EXCEPT(E_DeviceFull, "Remove an effect before adding more!");
     472                        OIS_EXCEPT(E_General, "Unknown error creating effect (may be the device is full)->..");
     473                }
     474
     475                // Save returned effect handle
     476                effect->_handle = ffeffect->id;
     477
     478                // Save a copy of the uploaded effect for later simple modifications
     479                linEffect = (struct ff_effect *)calloc(1, sizeof(struct ff_effect));
     480                memcpy(linEffect, ffeffect, sizeof(struct ff_effect));
     481
     482                mEffectList[effect->_handle] = linEffect;
     483
     484                // Start playing the effect.
     485                _start(effect->_handle);
     486        }
     487        else
     488        {
     489#if (OIS_LINUX_JOYFF_DEBUG > 1)
     490                cout << endl << "LinuxForceFeedback("<< mJoyStick << ") : Replacing effect : "
     491                         << Effect::getEffectTypeName(effect->type) << endl;
     492#endif
     493
     494                // Keep same id/handle, as this is just an update in the device.
     495                ffeffect->id = effect->_handle;
     496
     497                // Update effect in the device.
     498                if (ioctl(mJoyStick, EVIOCSFF, ffeffect) == -1) {
     499                        OIS_EXCEPT(E_General, "Unknown error updating an effect->..");
     500                }
     501
     502                // Update local linEffect for next time.
     503                memcpy(linEffect, ffeffect, sizeof(struct ff_effect));
     504        }
     505
     506#if (OIS_LINUX_JOYFF_DEBUG > 1)
     507        cout << "LinuxForceFeedback("<< mJoyStick
     508                 << ") : Effect handle : " << effect->_handle << endl;
     509#endif
     510}
     511
     512//--------------------------------------------------------------//
     513void LinuxForceFeedback::_stop( int handle) {
     514        struct input_event stop;
     515
     516        stop.type = EV_FF;
     517        stop.code = handle;
     518        stop.value = 0;
     519
     520#if (OIS_LINUX_JOYFF_DEBUG > 1)
     521        cout << endl << "LinuxForceFeedback("<< mJoyStick
     522                 << ") : Stopping effect with handle " << handle << endl;
     523#endif
     524
     525        if (write(mJoyStick, &stop, sizeof(stop)) != sizeof(stop)) {
     526                OIS_EXCEPT(E_General, "Unknown error stopping effect->..");
     527        }
     528}
     529
     530//--------------------------------------------------------------//
     531void LinuxForceFeedback::_start( int handle) {
     532        struct input_event play;
     533
     534        play.type = EV_FF;
     535        play.code = handle;
     536        play.value = 1; // Play once.
     537
     538#if (OIS_LINUX_JOYFF_DEBUG > 1)
     539        cout << endl << "LinuxForceFeedback("<< mJoyStick
     540                 << ") : Starting effect with handle " << handle << endl;
     541#endif
     542
     543        if (write(mJoyStick, &play, sizeof(play)) != sizeof(play)) {
     544                OIS_EXCEPT(E_General, "Unknown error playing effect->..");
     545        }
     546}
     547
     548//--------------------------------------------------------------//
     549void LinuxForceFeedback::_unload( int handle)
     550{
     551#if (OIS_LINUX_JOYFF_DEBUG > 1)
     552        cout << endl << "LinuxForceFeedback("<< mJoyStick
     553                 << ") : Removing effect with handle " << handle << endl;
     554#endif
     555
     556        if (ioctl(mJoyStick, EVIOCRMFF, handle) == -1) {
     557                OIS_EXCEPT(E_General, "Unknown error removing effect->..");
     558        }
     559}
  • code/trunk/src/ois/linux/LinuxForceFeedback.h

    r1505 r5695  
    2626#include "linux/LinuxPrereqs.h"
    2727#include "OISForceFeedback.h"
     28#include <linux/input.h>
    2829
    2930namespace OIS
     
    3233        {
    3334        public:
    34                 LinuxForceFeedback();
     35                LinuxForceFeedback(int deviceID);
    3536                ~LinuxForceFeedback();
    3637
     
    5051                void remove( const Effect* effect );
    5152
    52                 /** FF is not yet implemented fully on Linux.. just retun 0 for now. todo, xxx */
    53                 short int getFFAxesNumber() { return 0; }
     53                /** FF is not yet implemented fully on Linux.. just return -1 for now. todo, xxx */
     54                short int getFFAxesNumber() { return -1; }
     55
     56                /** @copydoc ForceFeedback::getFFMemoryLoad */
     57                unsigned short getFFMemoryLoad();
     58
     59        protected:
     60
     61                //Sets the common properties to all effects
     62                void _setCommonProperties(struct ff_effect *event, struct ff_envelope *ffenvelope,
     63                                                                  const Effect* effect, const Envelope *envelope );
     64
     65                //Specific Effect Settings
     66                void _updateConstantEffect( const Effect* effect );
     67                void _updateRampEffect( const Effect* effect );
     68                void _updatePeriodicEffect( const Effect* effect );
     69                void _updateConditionalEffect( const Effect* effect );
     70                //void _updateCustomEffect( const Effect* effect );
     71
     72                void _upload( struct ff_effect* ffeffect, const Effect* effect);
     73                void _stop( int handle);
     74                void _start( int handle);
     75                void _unload( int handle);
     76
     77                // Map of currently uploaded effects (handle => effect)
     78                typedef std::map<int, struct ff_effect *> EffectList;
     79                EffectList mEffectList;
     80
     81                // Joystick device (file) descriptor.
     82                int mJoyStick;
    5483        };
    5584}
  • code/trunk/src/ois/linux/LinuxJoyStickEvents.cpp

    r1505 r5695  
    3737
    3838#include <sstream>
     39# include <iostream>
     40using namespace std;
    3941
    4042using namespace OIS;
    4143
    4244//#define OIS_LINUX_JOY_DEBUG
    43 
    44 #ifdef OIS_LINUX_JOY_DEBUG
    45 # include <iostream>
    46   using namespace std;
    47 #endif
    4845
    4946//-------------------------------------------------------------------//
     
    114111
    115112                        #ifdef OIS_LINUX_JOY_DEBUG
    116                           std::cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << std::endl;
     113                          cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << endl;
    117114                        #endif
    118115
     
    132129                        break;
    133130                }
    134                 case EV_ABS:  //Absoulte Axis
     131
     132                case EV_ABS:  //Absolute Axis
    135133                {
    136134                        //A Stick (BrakeDefine is the highest possible Axis)
     
    138136                        {
    139137                                int axis = mAxisMap[js[i].code];
    140                                 assert( axis < 32 && "Too many axes, not supported. Report this to OIS forums!" );
    141                                
     138                                assert( axis < 32 && "Too many axes (Max supported is 32). Report this to OIS forums!" );
     139
    142140                                axisMoved[axis] = true;
    143141
     
    190188                        break;
    191189                }
    192                 //Relative Axes (Do any joysticks actually have a relative axis?)
    193                 case EV_REL:
     190
     191               
     192                case EV_REL: //Relative Axes (Do any joystick actually have a relative axis?)
     193#ifdef OIS_LINUX_JOY_DEBUG
     194                    cout << "\nWarning: Relatives axes not supported yet" << endl;
     195#endif
     196                        break;
    194197                default: break;
    195198                }
     
    243246        for(int i = 0; i < 64; ++i )
    244247        {
    245                 std::stringstream s;
     248                stringstream s;
    246249                s << "/dev/input/event" << i;
    247                 int fd = open( s.str().c_str(), O_RDONLY |O_NONBLOCK );
     250                int fd = open( s.str().c_str(), O_RDWR |O_NONBLOCK );
    248251                if(fd == -1)
    249252                        continue;
    250                
     253
    251254        #ifdef OIS_LINUX_JOY_DEBUG
    252           std::cout << "\nOpening " << s.str() << "...";
     255                  cout << "Opening " << s.str() << "..." << endl;
    253256        #endif
    254257                try
     
    259262                                joys.push_back(js);
    260263                #ifdef OIS_LINUX_JOY_DEBUG
    261                   std::cout << "\n__Joystick added to list";
     264                  cout << "=> Joystick added to list." << endl;
    262265                #endif
    263266                        }
     
    265268                        {
    266269                #ifdef OIS_LINUX_JOY_DEBUG
    267                   std::cout << "\n__Not a joystick!!";
     270                  cout << "=> Not a joystick." << endl;
    268271                #endif
    269272                                close(fd);
     
    273276                {
    274277            #ifdef OIS_LINUX_JOY_DEBUG
    275               std::cout << "\nException caught!!";
     278              cout << "Exception caught!!" << endl;
    276279            #endif
    277280                        close(fd);
  • code/trunk/src/ois/win32/Win32ForceFeedback.cpp

    r1505 r5695  
    2525#include <Math.h>
    2626
    27 #if defined (_DEBUG)
     27// 0 = No trace; 1 = Important traces; 2 = Debug traces
     28#define OIS_WIN32_JOYFF_DEBUG 1
     29
     30#if (defined (_DEBUG) || defined(OIS_WIN32_JOYFF_DEBUG))
     31  #include <iostream>
    2832  #include <sstream>
     33  using namespace std;
    2934#endif
    3035
     
    3237
    3338//--------------------------------------------------------------//
    34 Win32ForceFeedback::Win32ForceFeedback(IDirectInputDevice8* joy) :
    35         mHandles(0), mJoyStick(joy)
    36 {
     39Win32ForceFeedback::Win32ForceFeedback(IDirectInputDevice8* pDIJoy, const DIDEVCAPS* pDIJoyCaps) :
     40  mHandles(0), mJoyStick(pDIJoy), mFFAxes(0), mpDIJoyCaps(pDIJoyCaps)
     41{
     42#if (OIS_WIN32_JOYFF_DEBUG > 0)
     43  cout << "FFSamplePeriod      : " << mpDIJoyCaps->dwFFSamplePeriod << " mu-s, "
     44           << "FFMinTimeResolution : " << mpDIJoyCaps->dwFFMinTimeResolution << " mu-s,"
     45           << "" << endl;
     46#endif
    3747}
    3848
     
    4555                LPDIRECTINPUTEFFECT dxEffect = i->second;
    4656                if( dxEffect )
     57                {
    4758                        dxEffect->Unload();
     59                        dxEffect->Release();
     60                }
    4861        }
    4962
    5063        mEffectList.clear();
     64}
     65
     66//--------------------------------------------------------------//
     67short Win32ForceFeedback::getFFAxesNumber()
     68{
     69        return mFFAxes;
     70}
     71
     72//--------------------------------------------------------------//
     73unsigned short Win32ForceFeedback::getFFMemoryLoad()
     74{
     75    DIPROPDWORD dipdw;  // DIPROPDWORD contains a DIPROPHEADER structure.
     76        dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
     77        dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
     78        dipdw.diph.dwObj        = 0; // device property
     79        dipdw.diph.dwHow        = DIPH_DEVICE;
     80        dipdw.dwData            = 0; // In case of any error.
     81
     82        const HRESULT hr = mJoyStick->GetProperty(DIPROP_FFLOAD, &dipdw.diph);
     83        if(FAILED(hr))
     84        {
     85            if (hr == DIERR_NOTEXCLUSIVEACQUIRED)
     86                    OIS_EXCEPT(E_General, "Can't query FF memory load as device was not acquired in exclusive mode");
     87                else
     88                    OIS_EXCEPT(E_General, "Unknown error querying FF memory load ->..");
     89        }
     90
     91        return (unsigned short)dipdw.dwData;
    5192}
    5293
     
    86127                        //have been unlaoded
    87128                        if( SUCCEEDED(dxEffect->Unload()) )
     129                        {
     130                            dxEffect->Release();
    88131                                mEffectList.erase(i);
     132                        }
    89133                }
    90134                else
     
    111155        DIPropGain.dwData            = gain_level;
    112156
    113         mJoyStick->SetProperty(DIPROP_FFGAIN, &DIPropGain.diph);
     157#if (OIS_WIN32_JOYFF_DEBUG > 0)
     158        cout << "Win32ForceFeedback("<< mJoyStick << ") : Setting master gain to "
     159                 << level << " => " << DIPropGain.dwData << endl;
     160#endif
     161
     162        const HRESULT hr = mJoyStick->SetProperty(DIPROP_FFGAIN, &DIPropGain.diph);
     163
     164#if defined (_DEBUG)
     165        if(FAILED(hr))
     166            cout << "Failed to change master gain" << endl;
     167#endif
    114168}
    115169
     
    117171void Win32ForceFeedback::setAutoCenterMode( bool auto_on )
    118172{
    119         //DI Property DIPROPAUTOCENTER_OFF = 0, 1 is on
    120173        DIPROPDWORD DIPropAutoCenter;
    121174        DIPropAutoCenter.diph.dwSize       = sizeof(DIPropAutoCenter);
     
    123176        DIPropAutoCenter.diph.dwObj        = 0;
    124177        DIPropAutoCenter.diph.dwHow        = DIPH_DEVICE;
    125         DIPropAutoCenter.dwData            = auto_on;
    126 
    127         //hr =
    128         mJoyStick->SetProperty(DIPROP_AUTOCENTER, &DIPropAutoCenter.diph);
     178        DIPropAutoCenter.dwData            = (auto_on ? DIPROPAUTOCENTER_ON : DIPROPAUTOCENTER_OFF);
     179
     180#if (OIS_WIN32_JOYFF_DEBUG > 0)
     181        cout << "Win32ForceFeedback("<< mJoyStick << ") : Setting auto-center mode to "
     182                 << auto_on << " => " << DIPropAutoCenter.dwData << endl;
     183#endif
     184
     185        const HRESULT hr = mJoyStick->SetProperty(DIPROP_AUTOCENTER, &DIPropAutoCenter.diph);
     186
     187#if defined (_DEBUG)
     188        if(FAILED(hr))
     189            cout << "Failed to change auto-center mode" << endl;
     190#endif
    129191}
    130192
     
    132194void Win32ForceFeedback::_updateConstantEffect( const Effect* effect )
    133195{
     196        ConstantEffect *eff = static_cast<ConstantEffect*>(effect->getForceEffect());
     197
    134198        DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
    135199        LONG            rglDirection[2] = { 0, 0 };
     200        DIENVELOPE      diEnvelope;
    136201        DICONSTANTFORCE cf;
    137202        DIEFFECT        diEffect;
     
    139204        //Currently only support 1 axis
    140205        //if( effect->getNumAxes() == 1 )
    141         cf.lMagnitude = static_cast<ConstantEffect*>(effect->getForceEffect())->level;
    142 
    143         _setCommonProperties(&diEffect, rgdwAxes, rglDirection, sizeof(DICONSTANTFORCE), &cf, effect);
     206        cf.lMagnitude = eff->level;
     207
     208#if (OIS_WIN32_JOYFF_DEBUG > 1)
     209        cout << "  Level : " << eff->level
     210                 << " => " << cf.lMagnitude << endl;
     211#endif
     212
     213        _setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DICONSTANTFORCE), &cf, effect, &eff->envelope);
    144214        _upload(GUID_ConstantForce, &diEffect, effect);
    145215}
     
    148218void Win32ForceFeedback::_updateRampEffect( const Effect* effect )
    149219{
     220        RampEffect *eff = static_cast<RampEffect*>(effect->getForceEffect());
     221
    150222        DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
    151223        LONG            rglDirection[2] = { 0, 0 };
     224        DIENVELOPE      diEnvelope;
    152225        DIRAMPFORCE     rf;
    153226        DIEFFECT        diEffect;
    154227
    155228        //Currently only support 1 axis
    156         rf.lStart = static_cast<RampEffect*>(effect->getForceEffect())->startLevel;
    157         rf.lEnd = static_cast<RampEffect*>(effect->getForceEffect())->endLevel;
    158 
    159         _setCommonProperties(&diEffect, rgdwAxes, rglDirection, sizeof(DIRAMPFORCE), &rf, effect);
     229        rf.lStart = eff->startLevel;
     230        rf.lEnd = eff->endLevel;
     231
     232        _setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DIRAMPFORCE), &rf, effect, &eff->envelope );
    160233        _upload(GUID_RampForce, &diEffect, effect);
    161234}
     
    164237void Win32ForceFeedback::_updatePeriodicEffect( const Effect* effect )
    165238{
     239        PeriodicEffect *eff = static_cast<PeriodicEffect*>(effect->getForceEffect());
     240
    166241        DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
    167242        LONG            rglDirection[2] = { 0, 0 };
     243        DIENVELOPE      diEnvelope;
    168244        DIPERIODIC      pf;
    169245        DIEFFECT        diEffect;
    170246
    171247        //Currently only support 1 axis
    172         pf.dwMagnitude = static_cast<PeriodicEffect*>(effect->getForceEffect())->magnitude;
    173         pf.lOffset = static_cast<PeriodicEffect*>(effect->getForceEffect())->offset;
    174         pf.dwPhase = static_cast<PeriodicEffect*>(effect->getForceEffect())->phase;
    175         pf.dwPeriod = static_cast<PeriodicEffect*>(effect->getForceEffect())->period;
    176 
    177         _setCommonProperties(&diEffect, rgdwAxes, rglDirection, sizeof(DIPERIODIC), &pf, effect);
     248        pf.dwMagnitude = eff->magnitude;
     249        pf.lOffset = eff->offset;
     250        pf.dwPhase = eff->phase;
     251        pf.dwPeriod = eff->period;
     252
     253        _setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DIPERIODIC), &pf, effect, &eff->envelope );
    178254
    179255        switch( effect->type )
     
    191267void Win32ForceFeedback::_updateConditionalEffect( const Effect* effect )
    192268{
     269        ConditionalEffect *eff = static_cast<ConditionalEffect*>(effect->getForceEffect());
     270
    193271        DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
    194272        LONG            rglDirection[2] = { 0, 0 };
     273        DIENVELOPE      diEnvelope;
    195274        DICONDITION     cf;
    196275        DIEFFECT        diEffect;
    197276
    198         cf.lOffset = static_cast<ConditionalEffect*>(effect->getForceEffect())->deadband;
    199         cf.lPositiveCoefficient = static_cast<ConditionalEffect*>(effect->getForceEffect())->rightCoeff;
    200         cf.lNegativeCoefficient = static_cast<ConditionalEffect*>(effect->getForceEffect())->leftCoeff;
    201         cf.dwPositiveSaturation = static_cast<ConditionalEffect*>(effect->getForceEffect())->rightSaturation;
    202         cf.dwNegativeSaturation = static_cast<ConditionalEffect*>(effect->getForceEffect())->leftSaturation;
    203         cf.lDeadBand = static_cast<ConditionalEffect*>(effect->getForceEffect())->deadband;
    204 
    205         _setCommonProperties(&diEffect, rgdwAxes, rglDirection, sizeof(DICONDITION), &cf, effect);
     277        cf.lOffset = eff->deadband;
     278        cf.lPositiveCoefficient = eff->rightCoeff;
     279        cf.lNegativeCoefficient = eff->leftCoeff;
     280        cf.dwPositiveSaturation = eff->rightSaturation;
     281        cf.dwNegativeSaturation = eff->leftSaturation;
     282        cf.lDeadBand = eff->deadband;
     283
     284        _setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DICONDITION), &cf, effect, 0 );
    206285
    207286        switch( effect->type )
     
    218297void Win32ForceFeedback::_updateCustomEffect( const Effect* /*effect*/ )
    219298{
     299    //CustomEffect *eff = static_cast<CustomEffect*>(effect->getForceEffect());
     300    //
    220301        //DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
    221302        //LONG            rglDirection[2] = { 0, 0 };
     303        //DIENVELOPE      diEnvelope;
    222304        //DICUSTOMFORCE cf;
    223305        //DIEFFECT        diEffect;
     
    226308        //cf.cSamples = 0;
    227309        //cf.rglForceData = 0;
    228         //_setCommonProperties(&diEffect, rgdwAxes, rglDirection, sizeof(DICUSTOMFORCE), &cf, effect);
     310        //_setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DICUSTOMFORCE), &cf, effect, &eff->envelope);
    229311        //_upload(GUID_CustomForce, &diEffect, effect);
    230312}
     
    233315void Win32ForceFeedback::_setCommonProperties(
    234316                DIEFFECT* diEffect, DWORD* rgdwAxes,
    235                 LONG* rglDirection, DWORD struct_size,
    236                 LPVOID struct_type, const Effect* effect )
     317                LONG* rglDirection, DIENVELOPE* diEnvelope, DWORD struct_size,
     318                LPVOID struct_type, const Effect* effect, const Envelope* envelope )
    237319{
    238320        ZeroMemory(diEffect, sizeof(DIEFFECT));
     
    240322        diEffect->dwSize                  = sizeof(DIEFFECT);
    241323        diEffect->dwFlags                 = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
     324        diEffect->dwGain                  = DI_FFNOMINALMAX;
     325
     326        diEffect->dwTriggerButton         = DIEB_NOTRIGGER; // effect->trigger_button; // TODO: Conversion
     327        diEffect->dwTriggerRepeatInterval = effect->trigger_interval;
     328
     329#if (OIS_WIN32_JOYFF_DEBUG > 1)
     330        cout << "  Trigger :" << endl
     331                 << "    Button   : " << effect->trigger_button
     332                 << " => " << diEffect->dwTriggerButton << endl
     333                 << "    Interval : " << effect->trigger_interval
     334                 << " => " << diEffect->dwTriggerRepeatInterval << endl;
     335#endif
     336
     337        diEffect->cAxes                   = 1; // effect->getNumAxes();
     338        diEffect->rgdwAxes                = rgdwAxes;
     339
     340        diEffect->rglDirection            = rglDirection; // TODO: conversion from effect->direction
     341
     342#if (OIS_WIN32_JOYFF_DEBUG > 1)
     343        cout << "  Direction : " << Effect::getDirectionName(effect->direction)
     344                 << " => {";
     345        for (int iDir=0; iDir < (int)diEffect->cAxes; iDir++)
     346          cout << " " << diEffect->rglDirection[iDir];
     347        cout << "}" << endl;
     348#endif
     349
     350        if (diEnvelope && envelope && envelope->isUsed())
     351        {
     352            diEnvelope->dwSize = sizeof(DIENVELOPE);
     353            diEnvelope->dwAttackLevel = envelope->attackLevel;
     354            diEnvelope->dwAttackTime  = envelope->attackLength;
     355            diEnvelope->dwFadeLevel   = envelope->fadeLevel;
     356            diEnvelope->dwFadeTime    = envelope->fadeLength;
     357            diEffect->lpEnvelope = diEnvelope;
     358        }
     359        else
     360            diEffect->lpEnvelope = 0;
     361
     362#if (OIS_WIN32_JOYFF_DEBUG > 1)
     363        if (diEnvelope && envelope && envelope->isUsed())
     364        {
     365                cout << "  Enveloppe :" << endl
     366                         << "    AttackLen : " << envelope->attackLength
     367                         << " => " << diEnvelope->dwAttackTime << endl
     368                         << "    AttackLvl : " << envelope->attackLevel
     369                         << " => " << diEnvelope->dwAttackLevel << endl
     370                         << "    FadeLen   : " << envelope->fadeLength
     371                         << " => " << diEnvelope->dwFadeTime << endl
     372                         << "    FadeLvl   : " << envelope->fadeLevel
     373                         << " => " << diEnvelope->dwFadeLevel << endl;
     374        }
     375#endif
     376
     377        diEffect->dwSamplePeriod          = 0;
    242378        diEffect->dwDuration              = effect->replay_length;
    243         diEffect->dwSamplePeriod          = 0;
    244         diEffect->dwGain                  = DI_FFNOMINALMAX;
    245         diEffect->dwTriggerButton         = DIEB_NOTRIGGER;
    246         diEffect->dwTriggerRepeatInterval = 0;
    247         diEffect->cAxes                   = effect->getNumAxes();
    248         diEffect->rgdwAxes                = rgdwAxes;
    249         diEffect->rglDirection            = rglDirection;
    250         diEffect->lpEnvelope              = 0;
     379        diEffect->dwStartDelay            = effect->replay_delay;
     380
     381#if (OIS_WIN32_JOYFF_DEBUG > 1)
     382        cout << "  Replay :" << endl
     383                 << "    Length : " << effect->replay_length
     384                 << " => " << diEffect->dwDuration << endl
     385                 << "    Delay  : " << effect->replay_delay
     386                 << " => " << diEffect->dwStartDelay << endl;
     387#endif
     388
    251389        diEffect->cbTypeSpecificParams    = struct_size;
    252390        diEffect->lpvTypeSpecificParams   = struct_type;
    253         diEffect->dwStartDelay            = effect->replay_delay;
    254391}
    255392
     
    295432void Win32ForceFeedback::_addEffectSupport( LPCDIEFFECTINFO pdei )
    296433{
    297         //Determine what the effect is and how it corresponds to our OIS's Enums
    298         //We could save the GUIDs too, however, we will just use the predefined
    299         //ones later
     434#if (OIS_WIN32_JOYFF_DEBUG > 0)
     435    // Dump some usefull information about the effect type.
     436    cout << "Adding support for '" << pdei->tszName << "' effect type" << endl;
     437        cout << "  Supported static params: ";
     438        if (pdei->dwStaticParams & DIEP_AXES) cout << " Axes";
     439        if (pdei->dwStaticParams & DIEP_DIRECTION) cout << " Direction";
     440        if (pdei->dwStaticParams & DIEP_DURATION) cout << " Duration";
     441        if (pdei->dwStaticParams & DIEP_ENVELOPE) cout << " Envelope";
     442        if (pdei->dwStaticParams & DIEP_GAIN) cout << " Gain";
     443        if (pdei->dwStaticParams & DIEP_SAMPLEPERIOD) cout << " SamplePeriod";
     444        if (pdei->dwStaticParams & DIEP_STARTDELAY) cout << " StartDelay";
     445        if (pdei->dwStaticParams & DIEP_TRIGGERBUTTON) cout << " TriggerButton";
     446        if (pdei->dwStaticParams & DIEP_TRIGGERREPEATINTERVAL) cout << " TriggerRepeatInterval";
     447        if (pdei->dwStaticParams & DIEP_TYPESPECIFICPARAMS) cout << " TypeSpecificParams";
     448        cout << endl;
     449        cout << "  Supported dynamic params: ";
     450        if (pdei->dwDynamicParams & DIEP_AXES) cout << " Axes";
     451        if (pdei->dwDynamicParams & DIEP_DIRECTION) cout << " Direction";
     452        if (pdei->dwDynamicParams & DIEP_DURATION) cout << " Duration";
     453        if (pdei->dwDynamicParams & DIEP_ENVELOPE) cout << " Envelope";
     454        if (pdei->dwDynamicParams & DIEP_GAIN) cout << " Gain";
     455        if (pdei->dwDynamicParams & DIEP_SAMPLEPERIOD) cout << " SamplePeriod";
     456        if (pdei->dwDynamicParams & DIEP_STARTDELAY) cout << " StartDelay";
     457        if (pdei->dwDynamicParams & DIEP_TRIGGERBUTTON) cout << " TriggerButton";
     458        if (pdei->dwDynamicParams & DIEP_TRIGGERREPEATINTERVAL) cout << " TriggerRepeatInterval";
     459        if (pdei->dwDynamicParams & DIEP_TYPESPECIFICPARAMS) cout << " TypeSpecificParams";
     460        cout << endl;
     461        cout << "  More details about supported parameters support: ";
     462        if (pdei->dwEffType & DIEFT_STARTDELAY) cout << " StartDelay";
     463        if (pdei->dwEffType & DIEFT_FFATTACK) cout << " Attack";
     464        if (pdei->dwEffType & DIEFT_FFFADE) cout << " Fade";
     465        if (pdei->dwEffType & DIEFT_DEADBAND) cout << " DeadBand";
     466        if (pdei->dwEffType & DIEFT_SATURATION) cout << " Saturation";
     467        if (pdei->dwEffType & DIEFT_POSNEGSATURATION) cout << " PosNegaturation";
     468        if (pdei->dwEffType & DIEFT_POSNEGCOEFFICIENTS) cout << " PosNegCoefficients";
     469        if (pdei->dwEffType & DIEFT_HARDWARE) cout << " HardwareSpecific";
     470        cout << endl;
     471#endif
     472
     473    Effect::EForce eForce;
     474        switch (DIEFT_GETTYPE(pdei->dwEffType))
     475        {
     476            case DIEFT_CONSTANTFORCE:
     477                    eForce = Effect::ConstantForce;
     478                        break;
     479            case DIEFT_RAMPFORCE:
     480                    eForce = Effect::RampForce;
     481                        break;
     482            case DIEFT_PERIODIC:
     483                    eForce = Effect::PeriodicForce;
     484                        break;
     485            case DIEFT_CONDITION:
     486                    eForce = Effect::ConditionalForce;
     487                        break;
     488            case DIEFT_CUSTOMFORCE:
     489                    eForce = Effect::CustomForce;
     490                        break;
     491            default:
     492                    eForce = Effect::UnknownForce;
     493#if defined (_DEBUG)
     494                        cout << "Win32ForceFeedback: DirectInput8 Effect type support not implemented: "
     495                                 << "DIEFT_GETTYPE="<< (int)DIEFT_GETTYPE(pdei->dwEffType) << endl;
     496#endif
     497                        return;
     498        }
     499
     500        //Determine what the effect type is and how it corresponds to our OIS's Enums
     501        //We could save the GUIDs too, however, we will just use the predefined ones later
    300502        if( pdei->guid == GUID_ConstantForce )
    301                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Constant );
     503                _addEffectTypes(eForce, Effect::Constant );
    302504        else if( pdei->guid == GUID_Triangle )
    303                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Triangle );
     505                _addEffectTypes(eForce, Effect::Triangle );
    304506        else if( pdei->guid == GUID_Spring )
    305                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Spring );
     507                _addEffectTypes(eForce, Effect::Spring );
    306508        else if( pdei->guid == GUID_Friction )
    307                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Friction );
     509                _addEffectTypes(eForce, Effect::Friction );
    308510        else if( pdei->guid == GUID_Square )
    309                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Square );
     511                _addEffectTypes(eForce, Effect::Square );
    310512        else if( pdei->guid == GUID_Sine )
    311                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Sine );
     513                _addEffectTypes(eForce, Effect::Sine );
    312514        else if( pdei->guid == GUID_SawtoothUp )
    313                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::SawToothUp );
     515                _addEffectTypes(eForce, Effect::SawToothUp );
    314516        else if( pdei->guid == GUID_SawtoothDown )
    315                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::SawToothDown );
     517                _addEffectTypes(eForce, Effect::SawToothDown );
    316518        else if( pdei->guid == GUID_Damper )
    317                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Damper );
     519                _addEffectTypes(eForce, Effect::Damper );
    318520        else if( pdei->guid == GUID_Inertia )
    319                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Inertia );
     521                _addEffectTypes(eForce, Effect::Inertia );
    320522        else if( pdei->guid == GUID_CustomForce )
    321                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Custom );
     523                _addEffectTypes(eForce, Effect::Custom );
    322524        else if( pdei->guid == GUID_RampForce )
    323                 _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Ramp );
     525                _addEffectTypes(eForce, Effect::Ramp );
     526
    324527#if defined (_DEBUG)
    325528        //Only care about this for Debugging Purposes
     
    333536#endif
    334537}
     538
     539//--------------------------------------------------------------//
     540void Win32ForceFeedback::_addFFAxis()
     541{
     542        mFFAxes++;
     543}
  • code/trunk/src/ois/win32/Win32ForceFeedback.h

    r1505 r5695  
    3434                Win32ForceFeedback() {}
    3535        public:
    36                 Win32ForceFeedback(IDirectInputDevice8* joy);
     36                Win32ForceFeedback(IDirectInputDevice8* pDIJoy, const DIDEVCAPS* pDIJoyCaps);
    3737                ~Win32ForceFeedback();
    3838
     
    5252                void setAutoCenterMode( bool auto_on );
    5353
    54                 /** @copydoc ForceFeedback::getFFAxesNumber
    55                         xxx todo - Actually return correct number
    56                 */
    57                 short getFFAxesNumber() {return 1;}
     54                /** @copydoc ForceFeedback::getFFAxesNumber */
     55                short getFFAxesNumber();
     56
     57                /** @copydoc ForceFeedback::getFFMemoryLoad */
     58                unsigned short getFFMemoryLoad();
    5859
    5960                /**
     
    6465                void _addEffectSupport( LPCDIEFFECTINFO pdei );
    6566
     67                /**
     68                        @remarks
     69                        Internal use.. Used during axis enumeration to get number of FF axes
     70                        support effects.
     71                */
     72                void _addFFAxis();
     73
    6674        protected:
     75
    6776                //Specific Effect Settings
    6877                void _updateConstantEffect( const Effect* effect );
     
    7180                void _updateConditionalEffect( const Effect* effect );
    7281                void _updateCustomEffect( const Effect* effect );
     82
    7383                //Sets the common properties to all effects
    7484                void _setCommonProperties( DIEFFECT* diEffect, DWORD* rgdwAxes,
    75                                                                         LONG* rglDirection, DWORD struct_size,
    76                                                                         LPVOID struct_type, const Effect* effect );
     85                                                                        LONG* rglDirection, DIENVELOPE* diEnvelope, DWORD struct_size,
     86                                                                        LPVOID struct_type, const Effect* effect, const Envelope* envelope );
    7787                //Actually do the upload
    7888                void _upload( GUID, DIEFFECT*, const Effect* );
    7989
     90                // Map of currently uploaded effects (handle => effect)
    8091                typedef std::map<int,LPDIRECTINPUTEFFECT> EffectList;
    8192                EffectList mEffectList;
    82                 //Simple unique handle creation - allows for upto 2+ million effects
     93
     94                //Simple unique handle creation - allows for upto 2+ billion effects
    8395                //during the lifetime of application. Hopefully, that is enough.
    8496                int mHandles;
    8597
     98                // Joystick device descriptor.
    8699                IDirectInputDevice8* mJoyStick;
     100               
     101                // Joystick capabilities.
     102                const DIDEVCAPS* mpDIJoyCaps;
     103
     104                // Number of axis supporting FF.
     105                short mFFAxes;
    87106        };
    88107}
  • code/trunk/src/ois/win32/Win32InputManager.cpp

    r1505 r5695  
    7575        hInst = GetModuleHandle(0);
    7676
    77         //Create the device
     77        //Create the input system
    7878        hr = DirectInput8Create( hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&mDirectInput, NULL );
    7979    if (FAILED(hr))     
     
    8282        //Ok, now we have DirectInput, parse whatever extra settings were sent to us
    8383        _parseConfigSettings( paramList );
     84
     85        // Enumerate devices ...
    8486        _enumerateDevices();
    8587}
     
    116118{
    117119        //Enumerate all attached devices
    118         mDirectInput->EnumDevices(NULL, _DIEnumKbdCallback, this, DIEDFL_ATTACHEDONLY);
    119 }
    120 
    121 //--------------------------------------------------------------------------------//
    122 BOOL CALLBACK Win32InputManager::_DIEnumKbdCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
     120        mDirectInput->EnumDevices(NULL , _DIEnumDevCallback, this, DIEDFL_ATTACHEDONLY);
     121}
     122
     123//--------------------------------------------------------------------------------//
     124BOOL CALLBACK Win32InputManager::_DIEnumDevCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
    123125{
    124126        Win32InputManager *_this_ = static_cast<Win32InputManager*>(pvRef);
     127
     128        // Register only game devices (keyboard and mouse are managed differently).
    125129        if( GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_JOYSTICK ||
    126130                GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_GAMEPAD ||
  • code/trunk/src/ois/win32/Win32InputManager.h

    r1505 r5695  
    8181
    8282                //! Used during device enumeration
    83                 static BOOL CALLBACK _DIEnumKbdCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef);
     83                static BOOL CALLBACK _DIEnumDevCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef);
    8484
    8585                //! Keep a list of all joysticks enumerated, but not in use
  • code/trunk/src/ois/win32/Win32JoyStick.cpp

    r1505 r5695  
    8282        mState.mAxes.clear();
    8383
    84         delete ff_device;
    85         ff_device = 0;
    86 
     84        if (ff_device)
     85        {
     86                delete ff_device;
     87                ff_device = 0;
     88        }
     89
     90        // Create direct input joystick device.
     91        if(FAILED(mDirectInput->CreateDevice(deviceGuid, &mJoyStick, NULL)))
     92                OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!");
     93
     94        // Set DIJoystick2 data format.
     95        if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2)))
     96                OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!");
     97
     98        // Set cooperative level as specified when creating input manager.
     99        HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
     100        if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting)))
     101                OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!");
     102
     103        // Set buffer size.
    87104        DIPROPDWORD dipdw;
    88 
    89105        dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
    90106        dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
     
    93109        dipdw.dwData            = JOYSTICK_DX_BUFFERSIZE;
    94110
    95         if(FAILED(mDirectInput->CreateDevice(deviceGuid, &mJoyStick, NULL)))
    96                 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!");
    97 
    98         if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2)))
    99                 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!");
    100 
    101         HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
    102 
    103         if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting)))
    104                 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!");
    105 
    106111        if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) )
    107                 OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set buffer size property" );
    108 
    109         //Enumerate all axes/buttons/sliders/etc before aquiring
     112                OIS_EXCEPT( E_General, "Win32JoyStick::_initialize >> Failed to set buffer size property" );
     113
     114        // Enumerate all axes/buttons/sliders/force feedback/etc before aquiring
    110115        _enumerate();
    111116
     
    118123void Win32JoyStick::_enumerate()
    119124{
    120         //We can check force feedback here too
    121         DIDEVCAPS  DIJoyCaps;
    122         DIJoyCaps.dwSize = sizeof(DIDEVCAPS);
    123         mJoyStick->GetCapabilities(&DIJoyCaps);
    124 
    125         mPOVs = (short)DIJoyCaps.dwPOVs;
    126 
    127         mState.mButtons.resize(DIJoyCaps.dwButtons);
    128         mState.mAxes.resize(DIJoyCaps.dwAxes);
     125        // Get joystick capabilities.
     126        mDIJoyCaps.dwSize = sizeof(DIDEVCAPS);
     127        if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) )
     128                OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" );
     129
     130        // => Number of POVs
     131        mPOVs = (short)mDIJoyCaps.dwPOVs;
     132
     133        // => Number of buttons and axes.
     134        mState.mButtons.resize(mDIJoyCaps.dwButtons);
     135        mState.mAxes.resize(mDIJoyCaps.dwAxes);
     136
     137        // Enumerate all Force Feedback effects (if any)
     138        mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
    129139
    130140        //Reset the axis mapping enumeration value
    131141        _AxisNumber = 0;
    132142
    133         //Enumerate Force Feedback (if any)
    134         mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
    135 
    136         //Enumerate and set axis constraints (and check FF Axes)
     143        // Enumerate and set axis constraints (and check FF Axes)
    137144        mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS);
    138145}
     
    181188                OIS_EXCEPT( E_General, "Win32JoyStick::_DIEnumDeviceObjectsCallback >> Failed to set min/max range property" );
    182189
    183         //Check if FF Axes
     190        //Check if FF Axes, and if so, increment counter
    184191        if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 )
    185192        {
    186193                if( _this->ff_device )
    187194                {
    188                         //todo - increment force feedback axis count
     195                        _this->ff_device->_addFFAxis();
    189196                }
    190197        }
    191198
     199        //Force the flags for gain and auto-center support to true,
     200        //as DInput has no API to query the device for these capabilities
     201        //(the only way to know is to try them ...)
     202        if( _this->ff_device )
     203        {
     204            _this->ff_device->_setGainSupport(true);
     205            _this->ff_device->_setAutoCenterSupport(true);
     206        }
     207
    192208        return DIENUM_CONTINUE;
    193209}
     
    198214        Win32JoyStick* _this = (Win32JoyStick*)pvRef;
    199215
    200         //Create the FF class after we know there is at least one effect type
     216        //Create the FF instance only after we know there is at least one effect type
    201217        if( _this->ff_device == 0 )
    202                 _this->ff_device = new Win32ForceFeedback(_this->mJoyStick);
     218          _this->ff_device = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps);
    203219
    204220        _this->ff_device->_addEffectSupport( pdei );
  • code/trunk/src/ois/win32/Win32JoyStick.h

    r1505 r5695  
    6060                IDirectInput8* mDirectInput;
    6161                IDirectInputDevice8* mJoyStick;
     62                DIDEVCAPS mDIJoyCaps;
     63
    6264                DWORD coopSetting;
    6365                GUID deviceGuid;
  • code/trunk/src/ois/win32/Win32KeyBoard.cpp

    r1505 r5695  
    238238                return 0;
    239239
    240         unsigned char buff[3] = {0,0,0};
    241         int ascii = ToAsciiEx(vk, kc, keyState, (LPWORD) buff, 0, layout);
    242         //WCHAR wide[3];
    243         //int ascii = ToUnicodeEx(vk, kc, keyState, wide, 3, 0, layout);
     240        WCHAR buff[3] = {0};
     241        int ascii = ToUnicodeEx(vk, kc, keyState, buff, 3, 0, layout);
     242
    244243        if(ascii == 1 && deadKey != '\0' )
    245244        {
  • code/trunk/src/orxonox/LevelManager.cc

    r3370 r5695  
    3030
    3131#include <map>
    32 #include <boost/filesystem.hpp>
     32#include <OgreResourceGroupManager.h>
    3333
    3434#include "core/CommandLine.h"
     
    135135        availableLevels_.clear();
    136136
    137         boost::filesystem::directory_iterator file(Core::getMediaPathString() + "levels");
    138         boost::filesystem::directory_iterator end;
     137        availableLevels_ = *Ogre::ResourceGroupManager::getSingleton().findResourceNames(
     138            Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "*.oxw");
    139139
    140         while (file != end)
    141         {
    142             if (!boost::filesystem::is_directory(*file) && file->string()[file->string().length()-1] != '~')
     140        for (std::vector<std::string>::iterator it = availableLevels_.begin(); it != availableLevels_.end();)
     141            if (it->find("old/") == 0)
     142                it = availableLevels_.erase(it);
     143            else
    143144            {
    144                 std::string filename = file->path().leaf();
    145                 if (filename.length() > 4)
    146                     availableLevels_.push_back(filename.substr(0,filename.length()-4));
     145                size_t pos = it->find(".oxw");
     146                *it = it->substr(0, pos);
     147                ++it;
    147148            }
    148             ++file;
    149         }
    150149    }
    151150}
  • code/trunk/src/orxonox/Main.cc

    r5693 r5695  
    4040#include "core/CommandLine.h"
    4141#include "core/Game.h"
     42#include "core/LuaState.h"
     43#include "ToluaBindOrxonox.h"
    4244#include "Main.h"
    4345
     
    4850SetCommandLineSwitch(dedicated).information("Start in dedicated server mode");
    4951SetCommandLineSwitch(standalone).information("Start in standalone mode");
     52
     53DeclareToluaInterface(Orxonox);
    5054
    5155namespace orxonox
  • code/trunk/src/orxonox/gamestates/GSDedicated.cc

    r3370 r5695  
    2828
    2929#include "GSDedicated.h"
     30
     31#include <iomanip>
     32#include <iostream>
     33#include <boost/bind.hpp>
    3034
    3135#include "util/Debug.h"
     
    3741#include "core/GameMode.h"
    3842#include "network/Server.h"
    39 
    40 #include <iostream>
    41 #include <iomanip>
    42 #include <boost/bind.hpp>
    4343
    4444#ifdef ORXONOX_PLATFORM_UNIX
  • code/trunk/src/orxonox/gamestates/GSGraphics.cc

    r5693 r5695  
    9696        // load debug overlay
    9797        COUT(3) << "Loading Debug Overlay..." << std::endl;
    98         this->debugOverlay_ = new XMLFile(Core::getMediaPathString() + "overlay/debug.oxo");
     98        this->debugOverlay_ = new XMLFile("debug.oxo");
    9999        Loader::open(debugOverlay_);
    100100
  • code/trunk/src/orxonox/gamestates/GSLevel.cc

    r5693 r5695  
    2929
    3030#include "GSLevel.h"
     31
     32#include <OgreCompositorManager.h>
    3133
    3234#include "core/input/InputManager.h"
     
    166168*/
    167169
     170        if (GameMode::showsGraphics())
     171        {
     172            // unload all compositors (this is only necessary because we don't yet destroy all resources!)
     173            Ogre::CompositorManager::getSingleton().removeAll();
     174        }
    168175
    169176        // this call will delete every BaseObject!
     
    229236        // call the loader
    230237        COUT(0) << "Loading level..." << std::endl;
    231         startFile_s = new XMLFile(Core::getMediaPathString() + "levels" + '/' + LevelManager::getInstance().getDefaultLevel());
     238        startFile_s = new XMLFile(LevelManager::getInstance().getDefaultLevel());
    232239        Loader::open(startFile_s);
    233240    }
  • code/trunk/src/orxonox/gamestates/GSMainMenu.cc

    r3370 r5695  
    5252        inputState_->setHandler(GUIManager::getInstancePtr());
    5353        inputState_->setJoyStickHandler(&InputHandler::EMPTY);
     54        inputState_->setIsExclusiveMouse(false);
    5455
    5556        // create an empty Scene
     
    7071    {
    7172        // show main menu
    72         GUIManager::getInstance().showGUI("mainmenu_4");
     73        GUIManager::getInstance().showGUI("MainMenu");
    7374        GUIManager::getInstance().setCamera(this->camera_);
    7475        GraphicsManager::getInstance().setCamera(this->camera_);
  • code/trunk/src/orxonox/gamestates/GSRoot.cc

    r5693 r5695  
    3333#include "core/Game.h"
    3434#include "core/GameMode.h"
    35 #include "core/LuaBind.h"
    3635#include "network/NetworkFunction.h"
    37 #include "ToluaBindCore.h"
    38 #include "ToluaBindOrxonox.h"
    3936#include "tools/Timer.h"
    4037#include "tools/interfaces/TimeFactorListener.h"
     
    5451        this->ccSetTimeFactor_ = 0;
    5552        this->ccPause_ = 0;
    56 
    57         // Tell LuaBind about all tolua interfaces
    58         LuaBind::getInstance().addToluaInterface(&tolua_Core_open, "Core");
    59         LuaBind::getInstance().addToluaInterface(&tolua_Orxonox_open, "Orxonox");
    6053    }
    6154
     
    8679        }
    8780
    88         // create the global LevelManager
     81        // create the LevelManager
    8982        this->levelManager_ = new LevelManager();
    9083    }
  • code/trunk/src/orxonox/objects/Level.cc

    r3325 r5695  
    5353        this->registerVariables();
    5454        this->xmlfilename_ = this->getFilename();
    55 
    56         if (this->xmlfilename_.length() >= Core::getMediaPathString().length())
    57             this->xmlfilename_ = this->xmlfilename_.substr(Core::getMediaPathString().length());
    5855    }
    5956
     
    10198        mask.include(Class(OverlayGroup)); // HACK to include the ChatOverlay
    10299
    103         this->xmlfile_ = new XMLFile(Core::getMediaPathString() + this->xmlfilename_, mask);
     100        this->xmlfile_ = new XMLFile(mask, this->xmlfilename_);
    104101
    105102        Loader::open(this->xmlfile_);
  • code/trunk/src/orxonox/objects/Script.cc

    r3196 r5695  
    2929#include "Script.h"
    3030
    31 #include <tinyxml/ticpp.h>
    3231#include "core/CoreIncludes.h"
    33 #include "core/LuaBind.h"
     32#include "core/LuaState.h"
     33#include "core/XMLPort.h"
    3434
    3535namespace orxonox
    3636{
    37   CreateFactory(Script);
     37    CreateFactory(Script);
    3838
    39   Script::Script(BaseObject* creator) : BaseObject(creator)
    40   {
    41     RegisterObject(Script);
     39    Script::Script(BaseObject* creator) : BaseObject(creator)
     40    {
     41        RegisterObject(Script);
    4242
    43     code_ = "";
    44   }
     43        // Get a new LuaState
     44        luaState_ = new LuaState();
     45    }
    4546
    46   Script::~Script()
    47   {
    48   }
     47    Script::~Script()
     48    {
     49        if (this->isInitialized())
     50            delete luaState_;
     51    }
    4952
    50   /**
    51   @brief XML loading and saving.
    52   @param xmlelement The XML-element
    53   @param loading Loading (true) or saving (false)
    54    */
    55   void Script::XMLPort(Element& xmlelement, XMLPort::Mode mode)
    56   {
    57     BaseObject::XMLPort(xmlelement, mode);
     53    void Script::XMLPort(Element& xmlelement, XMLPort::Mode mode)
     54    {
     55        BaseObject::XMLPort(xmlelement, mode);
    5856
    59     code_ = xmlelement.GetText(false);
    60   }
     57        XMLPortParam(Script, "code", setCode, getCode, xmlelement, mode);
     58    }
    6159
    62   void Script::execute()
    63   {
    64     LuaBind& lua = LuaBind::getInstance();
    65     lua.loadString(this->code_);
    66     lua.run();
    67   }
     60    void Script::execute()
     61    {
     62        luaState_->doString(code_);
     63    }
    6864}
  • code/trunk/src/orxonox/objects/Script.h

    r3196 r5695  
    3737namespace orxonox
    3838{
    39   class _OrxonoxExport Script : public BaseObject
    40   {
     39    class _OrxonoxExport Script : public BaseObject
     40    {
    4141    public:
    42       Script(BaseObject* creator);
    43       ~Script();
    44       void XMLPort(Element& xmlelement, XMLPort::Mode mode);
    45       void execute();
     42        Script(BaseObject* creator);
     43        ~Script();
     44        void XMLPort(Element& xmlelement, XMLPort::Mode mode);
     45        void execute();
     46
     47        void setCode(const std::string& code) { code_ = code; }
     48        const std::string& getCode() const { return code_; }
    4649
    4750    private:
    48       std::string code_;
    49   };
     51        std::string code_;
     52        LuaState* luaState_;
     53    };
    5054}
    5155
  • code/trunk/src/orxonox/orxonox-main.vcproj.user.in

    r5693 r5695  
    1111                        <DebugSettings
    1212                                WorkingDirectory="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$(OutDir)"
    13                                 Environment="Path=${ORXONOX_RUNTIME_LIBRARY_DIRECTORY}"
     13                                Environment="Path=${RUNTIME_LIBRARY_DIRECTORY}"
    1414                                EnvironmentMerge="true"
    1515                        />
     
    2020                        <DebugSettings
    2121                                WorkingDirectory="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$(OutDir)"
    22                                 Environment="Path=${ORXONOX_RUNTIME_LIBRARY_DIRECTORY}"
     22                                Environment="Path=${RUNTIME_LIBRARY_DIRECTORY}"
    2323                                EnvironmentMerge="true"
    2424                        />
     
    2929                        <DebugSettings
    3030                                WorkingDirectory="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$(OutDir)"
    31                                 Environment="Path=${ORXONOX_RUNTIME_LIBRARY_DIRECTORY}"
     31                                Environment="Path=${RUNTIME_LIBRARY_DIRECTORY}"
    3232                                EnvironmentMerge="true"
    3333                        />
     
    3838                        <DebugSettings
    3939                                WorkingDirectory="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$(OutDir)"
    40                                 Environment="Path=${ORXONOX_RUNTIME_LIBRARY_DIRECTORY}"
     40                                Environment="Path=${RUNTIME_LIBRARY_DIRECTORY}"
    4141                                EnvironmentMerge="true"
    4242                        />
  • code/trunk/src/orxonox/sound/SoundBase.cc

    r3370 r5695  
    3636#include "util/Math.h"
    3737#include "core/Core.h"
     38#include "core/Resource.h"
    3839#include "orxonox/objects/worldentities/WorldEntity.h"
    3940#include "SoundManager.h"
     
    134135    }
    135136
    136     bool SoundBase::loadFile(std::string filename) {
    137         filename = Core::getMediaPathString() + "/audio/" + filename;
    138 
     137    bool SoundBase::loadFile(const std::string& filename) {
    139138        if(!SoundManager::getInstance().isSoundAvailable())
    140139        {
     
    144143
    145144        COUT(3) << "Sound: OpenAL ALUT: loading file " << filename << std::endl;
    146         this->buffer_ = alutCreateBufferFromFile(filename.c_str());
     145        // Get DataStream from the resources
     146        shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(filename);
     147        if (fileInfo == NULL) {
     148            COUT(2) << "Warning: Sound file '" << filename << "' not found" << std::endl;
     149            return false;
     150        }
     151        DataStreamPtr stream = Resource::open(filename);
     152        // Read everything into a temporary buffer
     153        char* buffer = new char[fileInfo->size];
     154        stream->read(buffer, fileInfo->size);
     155
     156        this->buffer_ = alutCreateBufferFromFileImage(buffer, fileInfo->size);
     157        delete[] buffer;
     158
    147159        if(this->buffer_ == AL_NONE) {
    148160            COUT(2) << "Sound: OpenAL ALUT: " << alutGetErrorString(alutGetError()) << std::endl;
  • code/trunk/src/orxonox/sound/SoundBase.h

    r5693 r5695  
    5555        bool isStopped();
    5656
    57         bool loadFile(std::string filename);
     57        bool loadFile(const std::string& filename);
    5858
    5959    private:
  • code/trunk/src/orxonox/tools/CMakeLists.txt

    r5693 r5695  
    55  Mesh.cc
    66  ParticleInterface.cc
     7  ResourceCollection.cc
     8  ResourceLocation.cc
    79  Shader.cc
    810  TextureGenerator.cc
  • code/trunk/src/orxonox/tools/Mesh.cc

    r3280 r5695  
    7171                this->entity_->setCastShadows(this->bCastShadows_);
    7272
     73#if OGRE_VERSION < 0x010600
    7374                this->entity_->setNormaliseNormals(true);
    7475                /*
     
    7980                    I don't know exactly what this means, but I put this here if there will be problems with shaders.
    8081                */
     82#endif
    8183            }
    8284            catch (...)
  • code/trunk/src/orxonox/tools/ResourceCollection.h

    r5694 r5695  
    3030#define _ResourceCollection_H__
    3131
    32 #include "OrxonoxPrereqs.h"
     32#include "tools/ToolsPrereqs.h"
    3333
    3434#include <string>
     
    4040    class ResourceLocation;
    4141
    42     class _OrxonoxExport ResourceCollection : public BaseObject
     42    class _ToolsExport ResourceCollection : public BaseObject
    4343    {
    4444    public:
  • code/trunk/src/orxonox/tools/ResourceLocation.h

    r5694 r5695  
    3030#define _ResourceLocation_H__
    3131
    32 #include "OrxonoxPrereqs.h"
     32#include "tools/ToolsPrereqs.h"
    3333
    3434#include <string>
     
    3737namespace orxonox
    3838{
    39     class _OrxonoxExport ResourceLocation : public BaseObject
     39    class _ToolsExport ResourceLocation : public BaseObject
    4040    {
    4141        // for load/unload
  • code/trunk/src/util/CMakeLists.txt

    r5693 r5695  
    3434)
    3535
     36SET_SOURCE_FILES(UTIL_HDR_FILES
     37  CRC32.h
     38  Clipboard.h
     39  Convert.h
     40  Debug.h
     41  Exception.h
     42  ExprParser.h
     43  Math.h
     44  MathConvert.h
     45  mbool.h
     46  MultiType.h
     47  MultiTypeValue.h
     48  OgreForwardRefs.h
     49  OrxAssert.h
     50  OrxEnum.h
     51  OutputBuffer.h
     52  OutputHandler.h
     53  RefToValue.h
     54  ScopeGuard.h
     55  Serialise.h
     56  SignalHandler.h
     57  Singleton.h
     58  Sleep.h
     59  StringUtils.h
     60  SubString.h
     61  TemplateUtils.h
     62  TypeTraits.h
     63  UTFStringConversions.h
     64  UtilPrereqs.h
     65)
     66
    3667IF(GCC_NO_SYSTEM_HEADER_SUPPORT)
    3768  # Get around displaying a few hundred lines of warning code
     
    4071
    4172ORXONOX_ADD_LIBRARY(util
    42   FIND_HEADER_FILES
    4373  DEFINE_SYMBOL
    4474    "UTIL_SHARED_BUILD"
     
    4676    ${OGRE_LIBRARY}
    4777  SOURCE_FILES
    48     ${UTIL_SRC_FILES}
     78    ${UTIL_SRC_FILES} ${UTIL_HDR_FILES}
    4979)
  • code/trunk/src/util/Debug.h

    r3196 r5695  
    2929/**
    3030    @file
    31     @brief Handles different output-levels of errors, warnings, infos and debug informations.
     31    @brief Handles different output-levels of errors, warnings, infos and debug information.
    3232
    3333    The COUT(level) macro acts like std::cout, but the output is only performed if the given
     
    4545     1: Errors
    4646     2: Warnings
    47      3: Informations
     47     3: Information
    4848     4: Debug information
    4949     5: More debug information
    50      6: Crazy debug informations
     50     6: Crazy debug information
    5151
    5252    @example
Note: See TracChangeset for help on using the changeset viewer.