diff --git a/.hgignore b/.hgignore index ae7f6de31..77768c635 100644 --- a/.hgignore +++ b/.hgignore @@ -147,6 +147,7 @@ external_stlport *.lnk thumbs.db Thumbs.db +.Sync* # build code/nel/build/* diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 926f66e35..0cd9afd54 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -2,7 +2,7 @@ # # NeL # Authors: Nevrax and the NeL Community -# Version: 0.8.0 +# Version: 0.9.0 # # Notes: # * Changing install location: add -DCMAKE_INSTALL_PREFIX:PATH=/my/new/path @@ -41,16 +41,18 @@ INCLUDE(${CMAKE_ROOT}/Modules/Documentation.cmake OPTIONAL) # Force out of source builds. CHECK_OUT_OF_SOURCE() +# Specify Mac OS X deployment target before including Darwin.cmake +IF(NOT CMAKE_OSX_DEPLOYMENT_TARGET) + SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.6") +ENDIF(NOT CMAKE_OSX_DEPLOYMENT_TARGET) + CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(RyzomCore CXX C) SET(NL_VERSION_MAJOR 0) -SET(NL_VERSION_MINOR 8) +SET(NL_VERSION_MINOR 9) SET(NL_VERSION_PATCH 0) SET(NL_VERSION "${NL_VERSION_MAJOR}.${NL_VERSION_MINOR}.${NL_VERSION_PATCH}") -NL_SETUP_BUILD() -NL_SETUP_BUILD_FLAGS() - #----------------------------------------------------------------------------- # Redirect output files SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) @@ -87,6 +89,9 @@ RYZOM_SETUP_PREFIX_PATHS() NL_CONFIGURE_CHECKS() +NL_SETUP_BUILD() +NL_SETUP_BUILD_FLAGS() + #----------------------------------------------------------------------------- #Platform specifics @@ -106,15 +111,18 @@ FIND_PACKAGE(LibXml2 REQUIRED) FIND_PACKAGE(PNG REQUIRED) FIND_PACKAGE(Jpeg) +IF(WITH_STATIC_LIBXML2) + SET(LIBXML2_DEFINITIONS ${LIBXML2_DEFINITIONS} -DLIBXML_STATIC) +ENDIF(WITH_STATIC_LIBXML2) IF(WITH_STATIC) # libxml2 could need winsock2 library - SET(LIBXML2_DEFINITIONS ${LIBXML2_DEFINITIONS} -DLIBXML_STATIC) SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${WINSOCK2_LIB}) - # on Mac OS X libxml2 requieres iconv + # on Mac OS X libxml2 requires iconv and liblzma IF(APPLE) FIND_PACKAGE(Iconv REQUIRED) - SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${ICONV_LIBRARIES}) + FIND_PACKAGE(LibLZMA REQUIRED) + SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${ICONV_LIBRARIES} ${LIBLZMA_LIBRARIES}) INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR}) ENDIF(APPLE) ENDIF(WITH_STATIC) @@ -134,6 +142,10 @@ IF(WITH_NEL) FIND_PACKAGE(CppTest) ENDIF(WITH_NEL_TESTS) + IF(WITH_GUI) + FIND_PACKAGE(Libwww REQUIRED) + ENDIF(WITH_GUI) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/nel/include ${LIBXML2_INCLUDE_DIR}) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS}) ADD_SUBDIRECTORY(nel) @@ -230,7 +242,7 @@ IF(WIN32) "${QT_LIBRARY_DIR}/../bin/QtGuid4.dll" "${QT_LIBRARY_DIR}/../bin/QtXmld4.dll" "${QT_LIBRARY_DIR}/../bin/QtCored4.dll" - DESTINATION bin) + DESTINATION ${NL_BIN_PREFIX}) ENDIF(WITH_QT) ELSE(NOT CMAKE_BUILD_TYPE STREQUAL "Release") IF(WITH_QT) @@ -239,18 +251,18 @@ IF(WIN32) "${QT_LIBRARY_DIR}/../bin/QtGui4.dll" "${QT_LIBRARY_DIR}/../bin/QtXml4.dll" "${QT_LIBRARY_DIR}/../bin/QtCore4.dll" - DESTINATION bin) + DESTINATION ${NL_BIN_PREFIX}) ENDIF(WITH_QT) ENDIF(NOT CMAKE_BUILD_TYPE STREQUAL "Release") # Install CEGUI and its dependencies. IF(WITH_NEL_CEGUI) - INSTALL(FILES "${CEGUI_LIB_DIR}/CEGUIBase.dll" DESTINATION bin) - INSTALL(FILES "${CEGUI_LIB_DIR}/CEGUIDevilImageCodec.dll" DESTINATION bin) - INSTALL(FILES "${CEGUI_LIB_DIR}/CEGUIExpatParser.dll" DESTINATION bin) - INSTALL(FILES "${CEGUI_LIB_DIR}/CEGUIFalagardWRBase.dll" DESTINATION bin) - INSTALL(FILES "${CEGUI_LIB_DIR}/Devil.dll" DESTINATION bin) - INSTALL(FILES "${CEGUI_LIB_DIR}/ILU.dll" DESTINATION bin) + INSTALL(FILES "${CEGUI_LIB_DIR}/CEGUIBase.dll" DESTINATION ${NL_BIN_PREFIX}) + INSTALL(FILES "${CEGUI_LIB_DIR}/CEGUIDevilImageCodec.dll" DESTINATION ${NL_BIN_PREFIX}) + INSTALL(FILES "${CEGUI_LIB_DIR}/CEGUIExpatParser.dll" DESTINATION ${NL_BIN_PREFIX}) + INSTALL(FILES "${CEGUI_LIB_DIR}/CEGUIFalagardWRBase.dll" DESTINATION ${NL_BIN_PREFIX}) + INSTALL(FILES "${CEGUI_LIB_DIR}/Devil.dll" DESTINATION ${NL_BIN_PREFIX}) + INSTALL(FILES "${CEGUI_LIB_DIR}/ILU.dll" DESTINATION ${NL_BIN_PREFIX}) ENDIF(WITH_NEL_CEGUI) # Only the tools require MFC. diff --git a/code/CMakeModules/FindLibwww.cmake b/code/CMakeModules/FindLibwww.cmake index 77140492e..e59d981c7 100644 --- a/code/CMakeModules/FindLibwww.cmake +++ b/code/CMakeModules/FindLibwww.cmake @@ -58,6 +58,7 @@ MACRO(FIND_WWW_LIBRARY MYLIBRARY OPTION) PATHS /usr/local/lib /usr/lib + /usr/lib/x86_64-linux-gnu /usr/local/X11R6/lib /usr/X11R6/lib /sw/lib diff --git a/code/CMakeModules/FindMercurial.cmake b/code/CMakeModules/FindMercurial.cmake index 9c252ad17..a18e50c43 100644 --- a/code/CMakeModules/FindMercurial.cmake +++ b/code/CMakeModules/FindMercurial.cmake @@ -60,7 +60,7 @@ IF(Mercurial_HG_EXECUTABLE) "\\1" Mercurial_VERSION_HG "${Mercurial_VERSION_HG}") MACRO(Mercurial_WC_INFO dir prefix) - EXECUTE_PROCESS(COMMAND ${Mercurial_HG_EXECUTABLE} tip + EXECUTE_PROCESS(COMMAND ${Mercurial_HG_EXECUTABLE} tip --template "{rev};{node};{tags};{author}" WORKING_DIRECTORY ${dir} OUTPUT_VARIABLE ${prefix}_WC_INFO ERROR_VARIABLE Mercurial_hg_info_error @@ -70,18 +70,18 @@ IF(Mercurial_HG_EXECUTABLE) IF(NOT ${Mercurial_hg_info_result} EQUAL 0) MESSAGE(SEND_ERROR "Command \"${Mercurial_HG_EXECUTABLE} tip\" failed with output:\n${Mercurial_hg_info_error}") ELSE(NOT ${Mercurial_hg_info_result} EQUAL 0) - - STRING(REGEX REPLACE "^(.*\n)?Repository Root: ([^\n]+).*" - "\\2" ${prefix}_WC_ROOT "${${prefix}_WC_INFO}") - STRING(REGEX REPLACE "^(.*\n)?changeset: *([0-9]+).*" - "\\2" ${prefix}_WC_REVISION "${${prefix}_WC_INFO}") - STRING(REGEX REPLACE "^(.*\n)?Last Changed Author: ([^\n]+).*" - "\\2" ${prefix}_WC_LAST_CHANGED_AUTHOR "${${prefix}_WC_INFO}") - STRING(REGEX REPLACE "^(.*\n)?Last Changed Rev: ([^\n]+).*" - "\\2" ${prefix}_WC_LAST_CHANGED_REV "${${prefix}_WC_INFO}") - STRING(REGEX REPLACE "^(.*\n)?Last Changed Date: ([^\n]+).*" - "\\2" ${prefix}_WC_LAST_CHANGED_DATE "${${prefix}_WC_INFO}") - + LIST(LENGTH ${prefix}_WC_INFO _COUNT) + IF(_COUNT EQUAL 4) + LIST(GET ${prefix}_WC_INFO 0 ${prefix}_WC_REVISION) + LIST(GET ${prefix}_WC_INFO 1 ${prefix}_WC_CHANGESET) + LIST(GET ${prefix}_WC_INFO 2 ${prefix}_WC_BRANCH) + LIST(GET ${prefix}_WC_INFO 3 ${prefix}_WC_LAST_CHANGED_AUTHOR) + ELSE(_COUNT EQUAL 4) + MESSAGE(STATUS "Bad output from HG") + SET(${prefix}_WC_REVISION "unknown") + SET(${prefix}_WC_CHANGESET "unknown") + SET(${prefix}_WC_BRANCH "unknown") + ENDIF(_COUNT EQUAL 4) ENDIF(NOT ${Mercurial_hg_info_result} EQUAL 0) ENDMACRO(Mercurial_WC_INFO) diff --git a/code/CMakeModules/FindSquish.cmake b/code/CMakeModules/FindSquish.cmake index 04f657485..ad0f7ce80 100644 --- a/code/CMakeModules/FindSquish.cmake +++ b/code/CMakeModules/FindSquish.cmake @@ -12,7 +12,7 @@ IF(SQUISH_LIBRARIES AND SQUISH_INCLUDE_DIR) SET(SQUISH_FIND_QUIETLY TRUE) ENDIF(SQUISH_LIBRARIES AND SQUISH_INCLUDE_DIR) -FIND_PATH(SQUISH_INCLUDE_DIR +FIND_PATH(SQUISH_INCLUDE_DIR squish.h PATHS /usr/local/include @@ -67,6 +67,11 @@ IF(SQUISH_FOUND) IF(NOT SQUISH_FIND_QUIETLY) MESSAGE(STATUS "Found Squish: ${SQUISH_LIBRARIES}") ENDIF(NOT SQUISH_FIND_QUIETLY) + FILE(STRINGS ${SQUISH_INCLUDE_DIR}/squish.h METRIC REGEX "metric = 0") + IF(METRIC) + SET(SQUISH_COMPRESS_HAS_METRIC ON) + SET(SQUISH_DEFINITIONS -DSQUISH_COMPRESS_HAS_METRIC) + ENDIF(METRIC) ELSE(SQUISH_FOUND) IF(NOT SQUISH_FIND_QUIETLY) MESSAGE(STATUS "Warning: Unable to find Squish!") diff --git a/code/CMakeModules/FindWindowsSDK.cmake b/code/CMakeModules/FindWindowsSDK.cmake index 25903be14..9d9b91777 100644 --- a/code/CMakeModules/FindWindowsSDK.cmake +++ b/code/CMakeModules/FindWindowsSDK.cmake @@ -2,47 +2,86 @@ # Find the Windows includes # # WINSDK_INCLUDE_DIR - where to find Windows.h +# WINSDK_INCLUDE_DIRS - where to find all Windows headers +# WINSDK_LIBRARY_DIR - where to find libraries # WINSDK_FOUND - True if Windows SDK found. IF(WINSDK_INCLUDE_DIR) # Already in cache, be silent - SET(WINSDK_FIND_QUIETLY TRUE) + SET(WindowsSDK_FIND_QUIETLY TRUE) ENDIF(WINSDK_INCLUDE_DIR) +# TODO: add the possibility to use a specific Windows SDK + +IF(MSVC11) + GET_FILENAME_COMPONENT(WINSDK8_DIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v8.0;InstallationFolder]" ABSOLUTE CACHE) + GET_FILENAME_COMPONENT(WINSDK8_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v8.0;ProductVersion]" NAME) + + IF(WINSDK8_DIR) + IF(NOT WindowsSDK_FIND_QUIETLY) + MESSAGE(STATUS "Found Windows SDK ${WINSDK8_VERSION} in ${WINSDK8_DIR}") + ENDIF(NOT WindowsSDK_FIND_QUIETLY) + IF(TARGET_ARM) + SET(WINSDK8_SUFFIX "arm") + ELSEIF(TARGET_X64) + SET(WINSDK8_SUFFIX "x64") + ELSEIF(TARGET_X86) + SET(WINSDK8_SUFFIX "x86") + ENDIF(TARGET_ARM) + ENDIF(WINSDK8_DIR) +ENDIF(MSVC11) + GET_FILENAME_COMPONENT(WINSDK71_DIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v7.1;InstallationFolder]" ABSOLUTE CACHE) GET_FILENAME_COMPONENT(WINSDK71_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v7.1;ProductVersion]" NAME) IF(WINSDK71_DIR) - IF(NOT WINSDK_FIND_QUIETLY) + IF(NOT WindowsSDK_FIND_QUIETLY) MESSAGE(STATUS "Found Windows SDK ${WINSDK71_VERSION} in ${WINSDK71_DIR}") - ENDIF(NOT WINSDK_FIND_QUIETLY) + ENDIF(NOT WindowsSDK_FIND_QUIETLY) ENDIF(WINSDK71_DIR) GET_FILENAME_COMPONENT(WINSDKCURRENT_DIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" ABSOLUTE CACHE) GET_FILENAME_COMPONENT(WINSDKCURRENT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentVersion]" NAME) IF(WINSDKCURRENT_DIR) - IF(NOT WINSDK_FIND_QUIETLY) + IF(NOT WindowsSDK_FIND_QUIETLY) MESSAGE(STATUS "Found Windows SDK ${WINSDKCURRENT_VERSION} in ${WINSDKCURRENT_DIR}") - ENDIF(NOT WINSDK_FIND_QUIETLY) + ENDIF(NOT WindowsSDK_FIND_QUIETLY) ENDIF(WINSDKCURRENT_DIR) FIND_PATH(WINSDK_INCLUDE_DIR Windows.h - PATHS + HINTS + ${WINSDK8_DIR}/Include/um ${WINSDK71_DIR}/Include ${WINSDKCURRENT_DIR}/Include ) +FIND_PATH(WINSDK_SHARED_INCLUDE_DIR d3d9.h + HINTS + ${WINSDK8_DIR}/Include/shared + ${WINSDK71_DIR}/Include + ${WINSDKCURRENT_DIR}/Include +) + +FIND_PATH(WINSDK_LIBRARY_DIR ComCtl32.lib + HINTS + ${WINSDK8_DIR}/Lib/win8/um/${WINSDK8_SUFFIX} + ${WINSDK71_DIR}/Lib + ${WINSDKCURRENT_DIR}/Lib +) + FIND_PROGRAM(WINSDK_SIGNTOOL signtool - PATHS + HINTS + ${WINSDK8_DIR}/Bin/x86 ${WINSDK71_DIR}/Bin ${WINSDKCURRENT_DIR}/Bin ) IF(WINSDK_INCLUDE_DIR) SET(WINSDK_FOUND TRUE) + SET(WINSDK_INCLUDE_DIRS ${WINSDK_INCLUDE_DIR} ${WINSDK_SHARED_INCLUDE_DIR}) ELSE(WINSDK_INCLUDE_DIR) - IF(NOT WINSDK_FIND_QUIETLY) + IF(NOT WindowsSDK_FIND_QUIETLY) MESSAGE(STATUS "Warning: Unable to find Windows SDK!") - ENDIF(NOT WINSDK_FIND_QUIETLY) + ENDIF(NOT WindowsSDK_FIND_QUIETLY) ENDIF(WINSDK_INCLUDE_DIR) diff --git a/code/CMakeModules/GetRevision.cmake b/code/CMakeModules/GetRevision.cmake index 52f443d5f..18e997af2 100644 --- a/code/CMakeModules/GetRevision.cmake +++ b/code/CMakeModules/GetRevision.cmake @@ -3,20 +3,24 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3) # ROOT_DIR should be set to root of the repository (where to find the .svn or .hg directory) # SOURCE_DIR should be set to root of your code (where to find CMakeLists.txt) -# Replace spaces by semi-columns -IF(CMAKE_MODULE_PATH) - STRING(REPLACE " " ";" CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}) -ENDIF(CMAKE_MODULE_PATH) +IF(SOURCE_DIR) + # Replace spaces by semi-columns + IF(CMAKE_MODULE_PATH) + STRING(REPLACE " " ";" CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}) + ENDIF(CMAKE_MODULE_PATH) -SET(CMAKE_MODULE_PATH ${SOURCE_DIR}/CMakeModules ${CMAKE_MODULE_PATH}) + SET(CMAKE_MODULE_PATH ${SOURCE_DIR}/CMakeModules ${CMAKE_MODULE_PATH}) -IF(NOT ROOT_DIR AND SOURCE_DIR) - SET(ROOT_DIR ${SOURCE_DIR}) -ENDIF(NOT ROOT_DIR AND SOURCE_DIR) + IF(NOT ROOT_DIR AND SOURCE_DIR) + SET(ROOT_DIR ${SOURCE_DIR}) + ENDIF(NOT ROOT_DIR AND SOURCE_DIR) -IF(NOT SOURCE_DIR AND ROOT_DIR) - SET(SOURCE_DIR ${ROOT_DIR}) -ENDIF(NOT SOURCE_DIR AND ROOT_DIR) + IF(NOT SOURCE_DIR AND ROOT_DIR) + SET(SOURCE_DIR ${ROOT_DIR}) + ENDIF(NOT SOURCE_DIR AND ROOT_DIR) +ELSE(SOURCE_DIR) + SET(ROOT_DIR ${CMAKE_SOURCE_DIR}) +ENDIF(SOURCE_DIR) MACRO(NOW RESULT) IF (WIN32) @@ -53,10 +57,11 @@ IF(EXISTS "${ROOT_DIR}/.hg/") ENDIF(MERCURIAL_FOUND) ENDIF(EXISTS "${ROOT_DIR}/.hg/") -IF(DEFINED REVISION) +IF(SOURCE_DIR AND DEFINED REVISION) IF(EXISTS ${SOURCE_DIR}/revision.h.in) + MESSAGE(STATUS "Revision: ${REVISION}") NOW(BUILD_DATE) CONFIGURE_FILE(${SOURCE_DIR}/revision.h.in revision.h.txt) EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy revision.h.txt revision.h) # copy_if_different ENDIF(EXISTS ${SOURCE_DIR}/revision.h.in) -ENDIF(DEFINED REVISION) +ENDIF(SOURCE_DIR AND DEFINED REVISION) diff --git a/code/CMakeModules/PCHSupport.cmake b/code/CMakeModules/PCHSupport.cmake index 7cd4c6c7d..d444bfa3d 100644 --- a/code/CMakeModules/PCHSupport.cmake +++ b/code/CMakeModules/PCHSupport.cmake @@ -9,231 +9,384 @@ # ADD_NATIVE_PRECOMPILED_HEADER _targetName _inputh _inputcpp IF(MSVC) - SET(PCHSupport_FOUND TRUE) - SET(_PCH_include_prefix "/I") + SET(PCHSupport_FOUND TRUE) + SET(_PCH_include_prefix "/I") ELSE(MSVC) - IF(CMAKE_COMPILER_IS_GNUCXX) - EXEC_PROGRAM(${CMAKE_CXX_COMPILER} - ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion - OUTPUT_VARIABLE gcc_compiler_version) - - IF(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]") - SET(PCHSupport_FOUND TRUE) - ELSE(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]") - IF(gcc_compiler_version MATCHES "3\\.4\\.[0-9]") - SET(PCHSupport_FOUND TRUE) - ENDIF(gcc_compiler_version MATCHES "3\\.4\\.[0-9]") - ENDIF(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]") - ELSE(CMAKE_COMPILER_IS_GNUCXX) - # TODO: make tests for other compilers than GCC - SET(PCHSupport_FOUND TRUE) - ENDIF(CMAKE_COMPILER_IS_GNUCXX) - - SET(_PCH_include_prefix "-I") + IF(CMAKE_COMPILER_IS_GNUCXX) + EXEC_PROGRAM(${CMAKE_CXX_COMPILER} + ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion + OUTPUT_VARIABLE gcc_compiler_version) + + IF(gcc_compiler_version MATCHES "^4\\.1(\\.[0-9]+)?") + SET(PCHSupport_FOUND FALSE) + ELSEIF(gcc_compiler_version MATCHES "^4\\.[0-9]+(\\.[0-9]+)?") + SET(PCHSupport_FOUND TRUE) + ENDIF(gcc_compiler_version MATCHES "^4\\.1(\\.[0-9]+)?") + ELSE(CMAKE_COMPILER_IS_GNUCXX) + # TODO: make tests for other compilers than GCC + SET(PCHSupport_FOUND TRUE) + ENDIF(CMAKE_COMPILER_IS_GNUCXX) + + SET(_PCH_include_prefix "-I") ENDIF(MSVC) -MACRO(_PCH_GET_COMPILE_FLAGS _out_compile_flags) - STRING(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" _flags_var_name) - SET(${_out_compile_flags} ${${_flags_var_name}} ) - - IF(NOT MSVC) - GET_TARGET_PROPERTY(_targetType ${_PCH_current_target} TYPE) - IF(${_targetType} STREQUAL SHARED_LIBRARY OR ${_targetType} STREQUAL MODULE_LIBRARY) - LIST(APPEND ${_out_compile_flags} "-fPIC") - ENDIF(${_targetType} STREQUAL SHARED_LIBRARY OR ${_targetType} STREQUAL MODULE_LIBRARY) - ENDIF(NOT MSVC) - - GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES ) - FOREACH(item ${DIRINC}) - LIST(APPEND ${_out_compile_flags} " ${_PCH_include_prefix}\"${item}\"") - ENDFOREACH(item) - - # Required for CMake 2.6 - SET(GLOBAL_DEFINITIONS "") - GET_DIRECTORY_PROPERTY(DEFINITIONS COMPILE_DEFINITIONS) - FOREACH(item ${DEFINITIONS}) - LIST(APPEND GLOBAL_DEFINITIONS -D${item}) - ENDFOREACH(item) - - GET_DIRECTORY_PROPERTY(_directory_flags DEFINITIONS) - GET_DIRECTORY_PROPERTY(_directory_definitions DIRECTORY ${CMAKE_SOURCE_DIR} DEFINITIONS) - LIST(APPEND ${_out_compile_flags} ${GLOBAL_DEFINITIONS}) - LIST(APPEND ${_out_compile_flags} ${_directory_flags}) - LIST(APPEND ${_out_compile_flags} ${_directory_definitions}) - LIST(APPEND ${_out_compile_flags} ${CMAKE_CXX_FLAGS}) - - # Format definitions - SEPARATE_ARGUMENTS(${_out_compile_flags}) -ENDMACRO(_PCH_GET_COMPILE_FLAGS) - -MACRO(_PCH_GET_PDB_FILENAME out_filename _target) - # determine output directory based on target type - GET_TARGET_PROPERTY(_targetType ${_target} TYPE) - IF(${_targetType} STREQUAL EXECUTABLE) - SET(_targetOutput ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - ELSEIF(${_targetType} STREQUAL STATIC_LIBRARY) - SET(_targetOutput ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) - ELSE(${_targetType} STREQUAL EXECUTABLE) - SET(_targetOutput ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) - ENDIF(${_targetType} STREQUAL EXECUTABLE) - - # determine target postfix - STRING(TOUPPER "${CMAKE_BUILD_TYPE}_POSTFIX" _postfix_var_name) - GET_TARGET_PROPERTY(_targetPostfix ${_target} ${_postfix_var_name}) - IF(${_targetPostfix} MATCHES NOTFOUND) - SET(_targetPostfix "") - ENDIF(${_targetPostfix} MATCHES NOTFOUND) - - SET(${out_filename} "${_targetOutput}/${_target}${_targetPostfix}.pdb") -ENDMACRO(_PCH_GET_PDB_FILENAME) - -MACRO(_PCH_GET_COMPILE_COMMAND out_command _input _inputcpp _output) - IF(CMAKE_CXX_COMPILER_ARG1) - # remove leading space in compiler argument - STRING(REGEX REPLACE "^ +" "" pchsupport_compiler_cxx_arg1 ${CMAKE_CXX_COMPILER_ARG1}) - ELSE(CMAKE_CXX_COMPILER_ARG1) - SET(pchsupport_compiler_cxx_arg1 "") - ENDIF(CMAKE_CXX_COMPILER_ARG1) - - IF(MSVC) - _PCH_GET_PDB_FILENAME(PDB_FILE ${_PCH_current_target}) - SET(${out_command} ${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} /Yc /Fp\"${_output}\" ${_inputcpp} /c /Fd\"${PDB_FILE}\") - ELSE(MSVC) - SET(HEADER_FORMAT "c++-header") - IF(APPLE) - SET(HEADER_FORMAT "objective-${HEADER_FORMAT}") - ENDIF(APPLE) - SET(${out_command} ${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} -x ${HEADER_FORMAT} -o ${_output} -c ${_input}) - ENDIF(MSVC) -ENDMACRO(_PCH_GET_COMPILE_COMMAND) - -MACRO(GET_PRECOMPILED_HEADER_OUTPUT _targetName _input _output) - IF(MSVC) - GET_FILENAME_COMPONENT(_name ${_input} NAME_WE) - SET(_output "${CMAKE_CURRENT_BINARY_DIR}/${_name}.pch") - ELSE(MSVC) - GET_FILENAME_COMPONENT(_name ${_input} NAME) - SET(_output "${CMAKE_CURRENT_BINARY_DIR}/${_name}.gch") - ENDIF(MSVC) -ENDMACRO(GET_PRECOMPILED_HEADER_OUTPUT _targetName _input) - -MACRO(ADD_PRECOMPILED_HEADER_TO_TARGET _targetName _input _pch_output_to_use ) - GET_TARGET_PROPERTY(oldProps ${_targetName} COMPILE_FLAGS) - IF(${oldProps} MATCHES NOTFOUND) - SET(oldProps "") - ENDIF(${oldProps} MATCHES NOTFOUND) - - IF(MSVC) - SET(_target_cflags "${oldProps} /Yu\"${_input}\" /FI\"${_input}\" /Fp\"${_pch_output_to_use}\"") - ELSE(MSVC) - # to do: test whether compiler flags match between target _targetName - # and _pch_output_to_use - FILE(TO_NATIVE_PATH ${_pch_output_to_use} _native_pch_path) - - # for use with distcc and gcc >4.0.1 if preprocessed files are accessible - # on all remote machines set - # PCH_ADDITIONAL_COMPILER_FLAGS to -fpch-preprocess - SET(_target_cflags "${oldProps} ${PCH_ADDITIONAL_COMPILER_FLAGS}-include ${_input} -Winvalid-pch") - ENDIF(MSVC) - - SET_TARGET_PROPERTIES(${_targetName} PROPERTIES COMPILE_FLAGS ${_target_cflags}) - IF(oldProps) - SET_TARGET_PROPERTIES(${_targetName}_pch_dephelp PROPERTIES COMPILE_FLAGS ${oldProps}) - ENDIF(oldProps) - ADD_CUSTOM_TARGET(pch_Generate_${_targetName} DEPENDS ${_pch_output_to_use}) - ADD_DEPENDENCIES(${_targetName} pch_Generate_${_targetName}) +# Set PCH_FLAGS for common flags, PCH_ARCH_XXX_FLAGS for specific archs flags and PCH_ARCHS for archs +MACRO(PCH_SET_COMPILE_FLAGS _target) + SET(PCH_FLAGS) + SET(PCH_ARCHS) + + SET(FLAGS) + LIST(APPEND _FLAGS ${CMAKE_CXX_FLAGS}) + + STRING(TOUPPER "${CMAKE_BUILD_TYPE}" _UPPER_BUILD) + LIST(APPEND _FLAGS " ${CMAKE_CXX_FLAGS_${_UPPER_BUILD}}") + + IF(NOT MSVC) + GET_TARGET_PROPERTY(_targetType ${_target} TYPE) + IF(${_targetType} STREQUAL SHARED_LIBRARY OR ${_targetType} STREQUAL MODULE_LIBRARY) + LIST(APPEND _FLAGS " -fPIC") + ENDIF(${_targetType} STREQUAL SHARED_LIBRARY OR ${_targetType} STREQUAL MODULE_LIBRARY) + ENDIF(NOT MSVC) + + GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES) + FOREACH(item ${DIRINC}) + LIST(APPEND _FLAGS " ${_PCH_include_prefix}\"${item}\"") + ENDFOREACH(item) + + # Required for CMake 2.6 + SET(GLOBAL_DEFINITIONS) + GET_DIRECTORY_PROPERTY(DEFINITIONS COMPILE_DEFINITIONS) + FOREACH(item ${DEFINITIONS}) + LIST(APPEND GLOBAL_DEFINITIONS " -D${item}") + ENDFOREACH(item) + + GET_DIRECTORY_PROPERTY(DEFINITIONS COMPILE_DEFINITIONS_${_UPPER_BUILD}) + FOREACH(item ${DEFINITIONS}) + LIST(APPEND GLOBAL_DEFINITIONS " -D${item}") + ENDFOREACH(item) + + GET_TARGET_PROPERTY(oldProps ${_target} COMPILE_FLAGS) + IF(oldProps) + LIST(APPEND _FLAGS " ${oldProps}") + ENDIF(oldProps) + + GET_TARGET_PROPERTY(oldPropsBuild ${_target} COMPILE_FLAGS_${_UPPER_BUILD}) + IF(oldPropsBuild) + LIST(APPEND _FLAGS " ${oldPropsBuild}") + ENDIF(oldPropsBuild) + + GET_DIRECTORY_PROPERTY(_directory_flags DEFINITIONS) + GET_DIRECTORY_PROPERTY(_directory_definitions DIRECTORY ${CMAKE_SOURCE_DIR} DEFINITIONS) + LIST(APPEND _FLAGS " ${GLOBAL_DEFINITIONS}") + LIST(APPEND _FLAGS " ${_directory_flags}") + LIST(APPEND _FLAGS " ${_directory_definitions}") + + STRING(REGEX REPLACE " +" " " _FLAGS ${_FLAGS}) + + # Format definitions + SEPARATE_ARGUMENTS(_FLAGS) + + IF(CLANG) + # Determining all architectures and get common flags + SET(_ARCH_NEXT) + SET(_XARCH_NEXT) + FOREACH(item ${_FLAGS}) + IF(_ARCH_NEXT) + LIST(FIND PCH_ARCHS ${item} ITEM_FOUND) + IF(ITEM_FOUND EQUAL -1) + LIST(APPEND PCH_ARCHS ${item}) + STRING(TOUPPER "${item}" _UPPER_ARCH) + SET(PCH_ARCH_${_UPPER_ARCH}_FLAGS "-arch" ${item}) + ENDIF(ITEM_FOUND EQUAL -1) + SET(_ARCH_NEXT OFF) + ELSEIF(_XARCH_NEXT) + SET(_XARCH_NEXT OFF) + ELSE(_ARCH_NEXT) + IF(item MATCHES "^-arch") + SET(_ARCH_NEXT ON) + ELSEIF(item MATCHES "^-Xarch_") + STRING(REGEX REPLACE "-Xarch_([a-z0-9_]+)" "\\1" item ${item}) + LIST(FIND PCH_ARCHS ${item} ITEM_FOUND) + IF(ITEM_FOUND EQUAL -1) + LIST(APPEND PCH_ARCHS ${item}) + STRING(TOUPPER "${item}" _UPPER_ARCH) + SET(PCH_ARCH_${_UPPER_ARCH}_FLAGS "-arch" ${item}) + ENDIF(ITEM_FOUND EQUAL -1) + SET(_XARCH_NEXT ON) + ELSE(item MATCHES "^-arch") + LIST(APPEND PCH_FLAGS ${item}) + ENDIF(item MATCHES "^-arch") + ENDIF(_ARCH_NEXT) + ENDFOREACH(item) + + # Get architcture specific flags + SET(_XARCH_NEXT) + FOREACH(item ${_FLAGS}) + IF(_XARCH_NEXT) + STRING(TOUPPER "${_XARCH_NEXT}" _UPPER_XARCH) + LIST(APPEND PCH_ARCH_${_UPPER_XARCH}_FLAGS ${item}) + SET(_XARCH_NEXT OFF) + ELSE(_XARCH_NEXT) + IF(item MATCHES "^-Xarch_") + STRING(SUBSTRING "${item}" 7 -1 _XARCH_NEXT) + ENDIF(item MATCHES "^-Xarch_") + ENDIF(_XARCH_NEXT) + ENDFOREACH(item) + + # Remove duplicated architectures + IF(_ARCHS AND PCH_ARCHS) + LIST(REMOVE_DUPLICATES PCH_ARCHS) + ENDIF(_ARCHS AND PCH_ARCHS) + ELSE(CLANG) + SET(PCH_FLAGS ${_FLAGS}) + ENDIF(CLANG) + + IF(PCH_FLAGS) + LIST(REMOVE_DUPLICATES PCH_FLAGS) + ENDIF(PCH_FLAGS) +ENDMACRO(PCH_SET_COMPILE_FLAGS) + +MACRO(GET_PDB_FILENAME _out_filename _target) + # determine output directory based on target type + GET_TARGET_PROPERTY(_targetType ${_target} TYPE) + IF(${_targetType} STREQUAL EXECUTABLE) + SET(_targetOutput ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + ELSEIF(${_targetType} STREQUAL STATIC_LIBRARY) + SET(_targetOutput ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) + ELSE(${_targetType} STREQUAL EXECUTABLE) + SET(_targetOutput ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + ENDIF(${_targetType} STREQUAL EXECUTABLE) + + # determine target postfix + STRING(TOUPPER "${CMAKE_BUILD_TYPE}_POSTFIX" _postfix_var_name) + GET_TARGET_PROPERTY(_targetPostfix ${_target} ${_postfix_var_name}) + IF(${_targetPostfix} MATCHES NOTFOUND) + SET(_targetPostfix "") + ENDIF(${_targetPostfix} MATCHES NOTFOUND) + + SET(${_out_filename} "${_targetOutput}/${_target}${_targetPostfix}.pdb") +ENDMACRO(GET_PDB_FILENAME) + +MACRO(PCH_SET_COMPILE_COMMAND _inputcpp _compile_FLAGS) + IF(CMAKE_CXX_COMPILER_ARG1) + # remove leading space in compiler argument + STRING(REGEX REPLACE "^ +" "" pchsupport_compiler_cxx_arg1 ${CMAKE_CXX_COMPILER_ARG1}) + ELSE(CMAKE_CXX_COMPILER_ARG1) + SET(pchsupport_compiler_cxx_arg1 "") + ENDIF(CMAKE_CXX_COMPILER_ARG1) + + IF(MSVC) + GET_PDB_FILENAME(PDB_FILE ${_PCH_current_target}) + SET(PCH_COMMAND ${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} /Yc /Fp"${PCH_OUTPUT}" ${_inputcpp} /Fd"${PDB_FILE}" /c /Fo"${PCH_OUTPUT}.obj") + ELSE(MSVC) + SET(HEADER_FORMAT "c++-header") + SET(_FLAGS "") + IF(APPLE) + SET(HEADER_FORMAT "objective-${HEADER_FORMAT}") + SET(_FLAGS -fobjc-abi-version=2 -fobjc-legacy-dispatch) + ENDIF(APPLE) + SET(PCH_COMMAND ${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} ${_FLAGS} -x ${HEADER_FORMAT} -o ${PCH_OUTPUT} -c ${PCH_INPUT}) + ENDIF(MSVC) +ENDMACRO(PCH_SET_COMPILE_COMMAND) + +MACRO(PCH_SET_PRECOMPILED_HEADER_OUTPUT _targetName _input _arch _language) + SET(_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${_targetName}_pch") + + IF(MSVC) + FILE(MAKE_DIRECTORY ${_OUTPUT_DIR}) + GET_FILENAME_COMPONENT(_name ${_input} NAME_WE) + SET(PCH_INPUT ${_input}) + SET(PCH_OUTPUT "${_OUTPUT_DIR}/${_name}.pch") + ELSE(MSVC) + IF(NOT "${_arch}" STREQUAL "") + SET(_OUTPUT_DIR "${_OUTPUT_DIR}_${_arch}") + ENDIF(NOT "${_arch}" STREQUAL "") + + IF(NOT "${_language}" STREQUAL "") + SET(_OUTPUT_DIR "${_OUTPUT_DIR}_${_language}") + ENDIF(NOT "${_language}" STREQUAL "") + + GET_FILENAME_COMPONENT(_name ${_input} NAME) + + # Copy .h to output dir + SET(PCH_INPUT "${_OUTPUT_DIR}/${_name}") + ADD_CUSTOM_COMMAND(OUTPUT ${PCH_INPUT} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_input} ${PCH_INPUT} + DEPENDS ${_input} + COMMENT "[${_targetName}] Update precompiled header - done" + ) + + IF(CLANG) + SET(PCH_EXT "pth") + ELSE(CLANG) + SET(PCH_EXT "gch") + ENDIF(CLANG) + + # For GCC and Clang, PCH needs to be in the same directory as .h + SET(PCH_OUTPUT "${_OUTPUT_DIR}/${_name}.${PCH_EXT}") + ENDIF(MSVC) +ENDMACRO(PCH_SET_PRECOMPILED_HEADER_OUTPUT) + +# Add common flags +MACRO(ADD_PRECOMPILED_HEADER_TO_TARGET _targetName) + GET_TARGET_PROPERTY(oldProps ${_targetName} COMPILE_FLAGS) + + IF(${oldProps} MATCHES NOTFOUND) + SET(oldProps "") + ENDIF(${oldProps} MATCHES NOTFOUND) + + IF(MSVC) + SET(_target_cflags "${oldProps} /Yu\"${PCH_INPUT}\" /FI\"${PCH_INPUT}\" /Fp\"${PCH_OUTPUT}\"") + ELSE(MSVC) + # for use with distcc and gcc >4.0.1 if preprocessed files are accessible + # on all remote machines set + # PCH_ADDITIONAL_COMPILER_FLAGS to -fpch-preprocess + SET(PCH_ADDITIONAL_COMPILER_FLAGS) + LIST(LENGTH PCH_ARCHS PCH_ARCHS_COUNT) + + # If no arch is specified, create common flags + IF(PCH_ARCHS_COUNT LESS 2) + SET(PCH_ADDITIONAL_COMPILER_FLAGS "-include ${PCH_INPUT} ${PCH_ADDITIONAL_COMPILER_FLAGS}") + ENDIF(PCH_ARCHS_COUNT LESS 2) + + IF(APPLE) + SET(PCH_ADDITIONAL_COMPILER_FLAGS "-fobjc-abi-version=2 -fobjc-legacy-dispatch -x objective-c++ ${PCH_ADDITIONAL_COMPILER_FLAGS}") + ENDIF(APPLE) + + IF(WITH_PCH_DEBUG) + SET(PCH_ADDITIONAL_COMPILER_FLAGS "-H ${PCH_ADDITIONAL_COMPILER_FLAGS}") + ENDIF(WITH_PCH_DEBUG) + + SET(_target_cflags "${oldProps} ${PCH_ADDITIONAL_COMPILER_FLAGS} -Winvalid-pch") + ENDIF(MSVC) + + SET_TARGET_PROPERTIES(${_targetName} PROPERTIES COMPILE_FLAGS ${_target_cflags}) ENDMACRO(ADD_PRECOMPILED_HEADER_TO_TARGET) -MACRO(ADD_PRECOMPILED_HEADER _targetName _inputh _inputcpp) +# Add specific flags for an arch +MACRO(ADD_PRECOMPILED_HEADER_TO_TARGET_ARCH _targetName _arch) + LIST(LENGTH PCH_ARCHS PCH_ARCHS_COUNT) + + IF(PCH_ARCHS_COUNT GREATER 1) + GET_TARGET_PROPERTY(_FLAGS ${_targetName} COMPILE_FLAGS) + + IF(${_FLAGS} MATCHES NOTFOUND) + SET(_FLAGS "") + ENDIF(${_FLAGS} MATCHES NOTFOUND) + + SET(_FLAGS "${_FLAGS} -Xarch_${_arch} -include${PCH_INPUT}") - SET(_PCH_current_target ${_targetName}) + SET_TARGET_PROPERTIES(${_targetName} PROPERTIES COMPILE_FLAGS ${_FLAGS}) + ENDIF(PCH_ARCHS_COUNT GREATER 1) +ENDMACRO(ADD_PRECOMPILED_HEADER_TO_TARGET_ARCH) - IF(NOT CMAKE_BUILD_TYPE) - MESSAGE(FATAL_ERROR - "This is the ADD_PRECOMPILED_HEADER macro. " - "You must set CMAKE_BUILD_TYPE!" - ) - ENDIF(NOT CMAKE_BUILD_TYPE) +MACRO(PCH_CREATE_TARGET _targetName _targetNamePCH) + ADD_CUSTOM_COMMAND(OUTPUT ${PCH_OUTPUT} COMMAND ${PCH_COMMAND} COMMENT "Generating ${_targetNamePCH}" DEPENDS ${PCH_INPUT}) + ADD_CUSTOM_TARGET(${_targetNamePCH} DEPENDS ${PCH_INPUT} ${PCH_OUTPUT}) + ADD_DEPENDENCIES(${_targetName} ${_targetNamePCH}) +ENDMACRO(PCH_CREATE_TARGET _targetName _inputh _inputcpp) - GET_PRECOMPILED_HEADER_OUTPUT( ${_targetName} ${_inputh} _output) +MACRO(ADD_PRECOMPILED_HEADER _targetName _inputh _inputcpp) + SET(_PCH_current_target ${_targetName}) + + IF(NOT CMAKE_BUILD_TYPE) + MESSAGE(FATAL_ERROR + "This is the ADD_PRECOMPILED_HEADER macro. " + "You must set CMAKE_BUILD_TYPE!" + ) + ENDIF(NOT CMAKE_BUILD_TYPE) - GET_TARGET_PROPERTY(_targetType ${_PCH_current_target} TYPE) + PCH_SET_COMPILE_FLAGS(${_targetName}) - # always build static library because it doesn't need linking - ADD_LIBRARY(${_targetName}_pch_dephelp STATIC ${_inputcpp}) + IF(PCH_ARCHS) + SET(PCH_OUTPUTS) + FOREACH(_ARCH ${PCH_ARCHS}) + STRING(TOUPPER "${_ARCH}" _UPPER_ARCH) - _PCH_GET_COMPILE_FLAGS(_compile_FLAGS) + PCH_SET_PRECOMPILED_HEADER_OUTPUT(${_targetName} ${_inputh} ${_ARCH} "") + LIST(APPEND PCH_OUTPUTS ${PCH_OUTPUT}) - SET_SOURCE_FILES_PROPERTIES(${_inputh} PROPERTIES GENERATED 1) + PCH_SET_COMPILE_COMMAND(${_inputcpp} "${PCH_ARCH_${_UPPER_ARCH}_FLAGS};${PCH_FLAGS}") + PCH_CREATE_TARGET(${_targetName} ${_targetName}_pch_${_ARCH}) - _PCH_GET_COMPILE_COMMAND(_command ${_inputh} ${_inputcpp} ${_output}) + ADD_PRECOMPILED_HEADER_TO_TARGET_ARCH(${_targetName} ${_ARCH}) + ENDFOREACH(_ARCH) + ELSE(PCH_ARCHS) + PCH_SET_PRECOMPILED_HEADER_OUTPUT(${_targetName} ${_inputh} "" "") + LIST(APPEND PCH_OUTPUTS ${PCH_OUTPUT}) - ADD_CUSTOM_COMMAND( - OUTPUT ${_output} - COMMAND ${_command} - DEPENDS ${_inputh} ${_targetName}_pch_dephelp - ) + PCH_SET_COMPILE_COMMAND(${_inputcpp} "${PCH_FLAGS}") + PCH_CREATE_TARGET(${_targetName} ${_targetName}_pch) + ENDIF(PCH_ARCHS) - ADD_PRECOMPILED_HEADER_TO_TARGET(${_targetName} ${_inputh} ${_output}) + ADD_PRECOMPILED_HEADER_TO_TARGET(${_targetName}) + + SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PCH_OUTPUTS}") ENDMACRO(ADD_PRECOMPILED_HEADER) # Macro to move PCH creation file to the front of files list +# or remove .cpp from library/executable to avoid warning MACRO(FIX_PRECOMPILED_HEADER _files _pch) - # Remove .cpp creating PCH from the list - LIST(REMOVE_ITEM ${_files} ${_pch}) - # Prepend .cpp creating PCH to the list - LIST(INSERT ${_files} 0 ${_pch}) + # Remove .cpp creating PCH from the list + LIST(REMOVE_ITEM ${_files} ${_pch}) + IF(MSVC) + # Prepend .cpp creating PCH to the list + LIST(INSERT ${_files} 0 ${_pch}) + ENDIF(MSVC) ENDMACRO(FIX_PRECOMPILED_HEADER) MACRO(ADD_NATIVE_PRECOMPILED_HEADER _targetName _inputh _inputcpp) - SET(PCH_METHOD 0) - - # 0 => creating a new target for PCH, works for all makefiles - # 1 => setting PCH for VC++ project, works for VC++ projects - # 2 => setting PCH for XCode project, works for XCode projects - IF(CMAKE_GENERATOR MATCHES "Visual Studio") - SET(PCH_METHOD 1) - ELSEIF(CMAKE_GENERATOR MATCHES "NMake Makefiles" AND MFC_FOUND AND CMAKE_MFC_FLAG) - # To fix a bug with MFC - # Don't forget to use FIX_PRECOMPILED_HEADER before creating the target -# SET(PCH_METHOD 1) - ELSEIF(CMAKE_GENERATOR MATCHES "Xcode") - SET(PCH_METHOD 2) - ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio") - - IF(PCH_METHOD EQUAL 1) - # Auto include the precompile (useful for moc processing, since the use of - # precompiled is specified at the target level - # and I don't want to specifiy /F- for each moc/res/ui generated files (using Qt) - - GET_TARGET_PROPERTY(oldProps ${_targetName} COMPILE_FLAGS) - IF(${oldProps} MATCHES NOTFOUND) - SET(oldProps "") - ENDIF(${oldProps} MATCHES NOTFOUND) - - SET(newProperties "${oldProps} /Yu\"${_inputh}\" /FI\"${_inputh}\"") - SET_TARGET_PROPERTIES(${_targetName} PROPERTIES COMPILE_FLAGS "${newProperties}") - - #also inlude ${oldProps} to have the same compile options - SET_SOURCE_FILES_PROPERTIES(${_inputcpp} PROPERTIES COMPILE_FLAGS "${oldProps} /Yc\"${_inputh}\"") - ELSEIF(PCH_METHOD EQUAL 2) - # For Xcode, cmake needs my patch to process - # GCC_PREFIX_HEADER and GCC_PRECOMPILE_PREFIX_HEADER as target properties - - GET_TARGET_PROPERTY(oldProps ${_targetName} COMPILE_FLAGS) - IF(${oldProps} MATCHES NOTFOUND) - SET(oldProps "") - ENDIF(${oldProps} MATCHES NOTFOUND) - - # When buiding out of the tree, precompiled may not be located - # Use full path instead. - GET_FILENAME_COMPONENT(fullPath ${_inputh} ABSOLUTE) - - SET_TARGET_PROPERTIES(${_targetName} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${fullPath}") - SET_TARGET_PROPERTIES(${_targetName} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") - ELSE(PCH_METHOD EQUAL 1) - #Fallback to the "old" precompiled suppport - ADD_PRECOMPILED_HEADER(${_targetName} ${_inputh} ${_inputcpp}) - ENDIF(PCH_METHOD EQUAL 1) - + IF(NOT PCHSupport_FOUND) + MESSAGE(STATUS "PCH disabled because compiler doesn't support them") + RETURN() + ENDIF(NOT PCHSupport_FOUND) + + # 0 => creating a new target for PCH, works for all makefiles + # 1 => setting PCH for VC++ project, works for VC++ projects + # 2 => setting PCH for XCode project, works for XCode projects + IF(CMAKE_GENERATOR MATCHES "Visual Studio") + SET(PCH_METHOD 1) + ELSEIF(CMAKE_GENERATOR MATCHES "NMake Makefiles" AND MFC_FOUND AND CMAKE_MFC_FLAG) + # To fix a bug with MFC + # Don't forget to use FIX_PRECOMPILED_HEADER before creating the target +# SET(PCH_METHOD 1) + ELSEIF(CMAKE_GENERATOR MATCHES "Xcode") + SET(PCH_METHOD 2) + ELSE(CMAKE_GENERATOR MATCHES "Visual Studio") + SET(PCH_METHOD 0) + ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio") + + IF(PCH_METHOD EQUAL 1) + # Auto include the precompile (useful for moc processing, since the use of + # precompiled is specified at the target level + # and I don't want to specifiy /F- for each moc/res/ui generated files (using Qt) + + GET_TARGET_PROPERTY(oldProps ${_targetName} COMPILE_FLAGS) + IF(${oldProps} MATCHES NOTFOUND) + SET(oldProps "") + ENDIF(${oldProps} MATCHES NOTFOUND) + + SET(newProperties "${oldProps} /Yu\"${_inputh}\" /FI\"${_inputh}\"") + SET_TARGET_PROPERTIES(${_targetName} PROPERTIES COMPILE_FLAGS "${newProperties}") + + #also inlude ${oldProps} to have the same compile options + SET_SOURCE_FILES_PROPERTIES(${_inputcpp} PROPERTIES COMPILE_FLAGS "${oldProps} /Yc\"${_inputh}\"") + ELSEIF(PCH_METHOD EQUAL 2) + # For Xcode, cmake needs my patch to process + # GCC_PREFIX_HEADER and GCC_PRECOMPILE_PREFIX_HEADER as target properties + + # When buiding out of the tree, precompiled may not be located + # Use full path instead. + GET_FILENAME_COMPONENT(fullPath ${_inputh} ABSOLUTE) + + SET_TARGET_PROPERTIES(${_targetName} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${fullPath}") + SET_TARGET_PROPERTIES(${_targetName} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") + ELSE(PCH_METHOD EQUAL 1) + #Fallback to the "old" precompiled suppport + ADD_PRECOMPILED_HEADER(${_targetName} ${_inputh} ${_inputcpp}) + ENDIF(PCH_METHOD EQUAL 1) + + IF(TARGET ${_targetName}_static) + ADD_NATIVE_PRECOMPILED_HEADER(${_targetName}_static ${_inputh} ${_inputcpp}) + ENDIF(TARGET ${_targetName}_static) ENDMACRO(ADD_NATIVE_PRECOMPILED_HEADER) diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index 84b817752..4308d0b44 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -13,11 +13,7 @@ ENDIF(NOT CMAKE_BUILD_TYPE) MACRO(NL_GEN_PC name) IF(NOT WIN32 AND WITH_INSTALL_LIBRARIES) CONFIGURE_FILE(${name}.in "${CMAKE_CURRENT_BINARY_DIR}/${name}") - IF(CMAKE_LIBRARY_ARCHITECTURE) - INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/${name}" DESTINATION lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig) - ELSE(CMAKE_LIBRARY_ARCHITECTURE) - INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/${name}" DESTINATION lib/pkgconfig) - ENDIF(CMAKE_LIBRARY_ARCHITECTURE) + INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/${name}" DESTINATION ${NL_LIB_PREFIX}/pkgconfig) ENDIF(NOT WIN32 AND WITH_INSTALL_LIBRARIES) ENDMACRO(NL_GEN_PC) @@ -26,25 +22,52 @@ ENDMACRO(NL_GEN_PC) ### MACRO(NL_GEN_REVISION_H) IF(EXISTS ${CMAKE_SOURCE_DIR}/revision.h.in) - INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}) - ADD_DEFINITIONS(-DHAVE_REVISION_H) - SET(HAVE_REVISION_H ON) - - # a custom target that is always built - ADD_CUSTOM_TARGET(revision ALL - DEPENDS ${CMAKE_BINARY_DIR}/revision.h) - - # creates revision.h using cmake script - ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_BINARY_DIR}/revision.h - COMMAND ${CMAKE_COMMAND} - -DSOURCE_DIR=${CMAKE_SOURCE_DIR} - -DROOT_DIR=${CMAKE_SOURCE_DIR}/.. - -P ${CMAKE_SOURCE_DIR}/CMakeModules/GetRevision.cmake) - - # revision.h is a generated file - SET_SOURCE_FILES_PROPERTIES(${CMAKE_BINARY_DIR}/revision.h - PROPERTIES GENERATED TRUE - HEADER_FILE_ONLY TRUE) + SET(TOOL_FOUND OFF) + + IF(EXISTS "${CMAKE_SOURCE_DIR}/../.svn/") + FIND_PACKAGE(Subversion) + + IF(SUBVERSION_FOUND) + SET(TOOL_FOUND ON) + ENDIF(SUBVERSION_FOUND) + ENDIF(EXISTS "${CMAKE_SOURCE_DIR}/../.svn/") + + IF(EXISTS "${CMAKE_SOURCE_DIR}/../.hg/") + FIND_PACKAGE(Mercurial) + + IF(MERCURIAL_FOUND) + SET(TOOL_FOUND ON) + ENDIF(MERCURIAL_FOUND) + ENDIF(EXISTS "${CMAKE_SOURCE_DIR}/../.hg/") + + # if already generated + IF(EXISTS ${CMAKE_SOURCE_DIR}/revision.h) + # copy it + MESSAGE(STATUS "Copying provided revision.h...") + FILE(COPY ${CMAKE_SOURCE_DIR}/revision.h DESTINATION ${CMAKE_BINARY_DIR}) + SET(HAVE_REVISION_H ON) + ENDIF(EXISTS ${CMAKE_SOURCE_DIR}/revision.h) + + IF(TOOL_FOUND) + # a custom target that is always built + ADD_CUSTOM_TARGET(revision ALL + COMMAND ${CMAKE_COMMAND} + -DSOURCE_DIR=${CMAKE_SOURCE_DIR} + -DROOT_DIR=${CMAKE_SOURCE_DIR}/.. + -DCMAKE_MODULE_PATH=${CMAKE_SOURCE_DIR}/CMakeModules + -P ${CMAKE_SOURCE_DIR}/CMakeModules/GetRevision.cmake) + + # revision.h is a generated file + SET_SOURCE_FILES_PROPERTIES(${CMAKE_BINARY_DIR}/revision.h + PROPERTIES GENERATED TRUE + HEADER_FILE_ONLY TRUE) + SET(HAVE_REVISION_H ON) + ENDIF(TOOL_FOUND) + + IF(HAVE_REVISION_H) + INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}) + ADD_DEFINITIONS(-DHAVE_REVISION_H) + ENDIF(HAVE_REVISION_H) ENDIF(EXISTS ${CMAKE_SOURCE_DIR}/revision.h.in) ENDMACRO(NL_GEN_REVISION_H) @@ -76,6 +99,11 @@ ENDMACRO(NL_TARGET_DRIVER) # Argument: ### MACRO(NL_DEFAULT_PROPS name label) + IF(HAVE_REVISION_H) + # explicitly say that the target depends on revision.h + ADD_DEPENDENCIES(${name} revision) + ENDIF(HAVE_REVISION_H) + # Note: This is just a workaround for a CMake bug generating VS10 files with a colon in the project name. # CMake Bug ID: http://www.cmake.org/Bug/view.php?id=11819 STRING(REGEX REPLACE "\\:" " -" proj_label ${label}) @@ -219,6 +247,11 @@ MACRO(NL_SETUP_DEFAULT_OPTIONS) ELSE(WIN32) OPTION(WITH_STATIC "With static libraries." OFF) ENDIF(WIN32) + IF (WITH_STATIC) + OPTION(WITH_STATIC_LIBXML2 "With static libxml2" ON ) + ELSE(WITH_STATIC) + OPTION(WITH_STATIC_LIBXML2 "With static libxml2" OFF) + ENDIF(WITH_STATIC) OPTION(WITH_STATIC_DRIVERS "With static drivers." OFF) IF(WIN32) OPTION(WITH_EXTERNAL "With provided external." ON ) @@ -243,16 +276,7 @@ MACRO(NL_SETUP_DEFAULT_OPTIONS) ### # Optional support ### - - # Check if CMake is launched from a Debian packaging script - SET(DEB_HOST_GNU_CPU $ENV{DEB_HOST_GNU_CPU}) - - # Don't strip if generating a .deb - IF(DEB_HOST_GNU_CPU) - OPTION(WITH_SYMBOLS "Keep debug symbols in binaries" ON ) - ELSE(DEB_HOST_GNU_CPU) - OPTION(WITH_SYMBOLS "Keep debug symbols in binaries" OFF) - ENDIF(DEB_HOST_GNU_CPU) + OPTION(WITH_SYMBOLS "Keep debug symbols in binaries" OFF) IF(WIN32) OPTION(WITH_STLPORT "With STLport support." ON ) @@ -274,6 +298,7 @@ MACRO(NL_SETUP_NEL_DEFAULT_OPTIONS) ### OPTION(WITH_NET "Build NLNET" ON ) OPTION(WITH_3D "Build NL3D" ON ) + OPTION(WITH_GUI "Build GUI" ON ) OPTION(WITH_PACS "Build NLPACS" ON ) OPTION(WITH_GEORGES "Build NLGEORGES" ON ) OPTION(WITH_LIGO "Build NLLIGO" ON ) @@ -332,6 +357,11 @@ MACRO(NL_SETUP_SNOWBALLS_DEFAULT_OPTIONS) OPTION(WITH_SNOWBALLS_SERVER "Build Snowballs Services" ON ) ENDMACRO(NL_SETUP_SNOWBALLS_DEFAULT_OPTIONS) +MACRO(ADD_PLATFORM_FLAGS _FLAGS) + SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} ${_FLAGS}") + SET(PLATFORM_CXXFLAGS "${PLATFORM_CXXFLAGS} ${_FLAGS}") +ENDMACRO(ADD_PLATFORM_FLAGS) + MACRO(NL_SETUP_BUILD) #----------------------------------------------------------------------------- @@ -364,9 +394,6 @@ MACRO(NL_SETUP_BUILD) ENDIF(HOST_CPU MATCHES "amd64") # Determine target CPU - IF(NOT TARGET_CPU) - SET(TARGET_CPU $ENV{DEB_HOST_GNU_CPU}) - ENDIF(NOT TARGET_CPU) # If not specified, use the same CPU as host IF(NOT TARGET_CPU) @@ -379,9 +406,6 @@ MACRO(NL_SETUP_BUILD) SET(TARGET_CPU "x86") ENDIF(TARGET_CPU MATCHES "amd64") - # DEB_HOST_ARCH_ENDIAN is 'little' or 'big' - # DEB_HOST_ARCH_BITS is '32' or '64' - IF(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") SET(CLANG ON) MESSAGE(STATUS "Using Clang compiler") @@ -393,7 +417,7 @@ MACRO(NL_SETUP_BUILD) ENDIF(CMAKE_GENERATOR MATCHES "Xcode") # If target and host CPU are the same - IF("${HOST_CPU}" STREQUAL "${TARGET_CPU}") + IF("${HOST_CPU}" STREQUAL "${TARGET_CPU}" AND NOT CMAKE_CROSSCOMPILING) # x86-compatible CPU IF(HOST_CPU MATCHES "x86") IF(NOT CMAKE_SIZEOF_VOID_P) @@ -414,75 +438,145 @@ MACRO(NL_SETUP_BUILD) MESSAGE(STATUS "Unknown architecture: ${HOST_CPU}") ENDIF(HOST_CPU MATCHES "x86") # TODO: add checks for PPC - ELSE("${HOST_CPU}" STREQUAL "${TARGET_CPU}") + ELSE("${HOST_CPU}" STREQUAL "${TARGET_CPU}" AND NOT CMAKE_CROSSCOMPILING) MESSAGE(STATUS "Compiling on ${HOST_CPU} for ${TARGET_CPU}") - ENDIF("${HOST_CPU}" STREQUAL "${TARGET_CPU}") - - IF(TARGET_CPU STREQUAL "x86_64") - SET(TARGET_X64 1) - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -DHAVE_X86_64") - ELSEIF(TARGET_CPU STREQUAL "x86") - SET(TARGET_X86 1) - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -DHAVE_X86") - ELSEIF(TARGET_CPU STREQUAL "arm") - SET(TARGET_ARM 1) - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -DHAVE_ARM") - ENDIF(TARGET_CPU STREQUAL "x86_64") + ENDIF("${HOST_CPU}" STREQUAL "${TARGET_CPU}" AND NOT CMAKE_CROSSCOMPILING) + + # Use values from environment variables + SET(PLATFORM_CFLAGS "$ENV{CFLAGS} $ENV{CPPFLAGS} ${PLATFORM_CFLAGS}") + SET(PLATFORM_CXXFLAGS "$ENV{CXXFLAGS} $ENV{CPPFLAGS} ${PLATFORM_CXXFLAGS}") + SET(PLATFORM_LINKFLAGS "$ENV{LDFLAGS} ${PLATFORM_LINKFLAGS}") + + # Remove -g and -O flag because we are managing them ourself + STRING(REPLACE "-g" "" PLATFORM_CFLAGS ${PLATFORM_CFLAGS}) + STRING(REPLACE "-g" "" PLATFORM_CXXFLAGS ${PLATFORM_CXXFLAGS}) + STRING(REGEX REPLACE "-O[0-9s]" "" PLATFORM_CFLAGS ${PLATFORM_CFLAGS}) + STRING(REGEX REPLACE "-O[0-9s]" "" PLATFORM_CXXFLAGS ${PLATFORM_CXXFLAGS}) + + # Strip spaces + STRING(STRIP ${PLATFORM_CFLAGS} PLATFORM_CFLAGS) + STRING(STRIP ${PLATFORM_CXXFLAGS} PLATFORM_CXXFLAGS) + STRING(STRIP ${PLATFORM_LINKFLAGS} PLATFORM_LINKFLAGS) + + IF(NOT CMAKE_OSX_ARCHITECTURES) + IF(TARGET_CPU STREQUAL "x86_64") + SET(TARGET_X64 1) + SET(TARGET_X86 1) + ELSEIF(TARGET_CPU STREQUAL "x86") + SET(TARGET_X86 1) + ELSEIF(TARGET_CPU STREQUAL "armv7s") + SET(TARGET_ARM 1) + SET(TARGET_ARMV7S 1) + ELSEIF(TARGET_CPU STREQUAL "armv7") + SET(TARGET_ARM 1) + SET(TARGET_ARMV7 1) + ELSEIF(TARGET_CPU STREQUAL "armv6") + SET(TARGET_ARM 1) + SET(TARGET_ARMV6 1) + ELSEIF(TARGET_CPU STREQUAL "armv5") + SET(TARGET_ARM 1) + SET(TARGET_ARMV5 1) + ELSEIF(TARGET_CPU STREQUAL "arm") + SET(TARGET_ARM 1) + ELSEIF(TARGET_CPU STREQUAL "mips") + SET(TARGET_MIPS 1) + ENDIF(TARGET_CPU STREQUAL "x86_64") + + IF(TARGET_ARM) + IF(TARGET_ARMV7S) + ADD_PLATFORM_FLAGS("-DHAVE_ARMV7S") + ENDIF(TARGET_ARMV7S) + + IF(TARGET_ARMV7) + ADD_PLATFORM_FLAGS("-DHAVE_ARMV7") + ENDIF(TARGET_ARMV7) + + IF(TARGET_ARMV6) + ADD_PLATFORM_FLAGS("-HAVE_ARMV6") + ENDIF(TARGET_ARMV6) + + ADD_PLATFORM_FLAGS("-DHAVE_ARM") + ENDIF(TARGET_ARM) - # Fix library paths suffixes for Debian MultiArch - SET(DEBIAN_MULTIARCH $ENV{DEB_HOST_MULTIARCH}) + IF(TARGET_X86) + ADD_PLATFORM_FLAGS("-DHAVE_X86") + ENDIF(TARGET_X86) + + IF(TARGET_X64) + ADD_PLATFORM_FLAGS("-DHAVE_X64 -DHAVE_X86_64") + ENDIF(TARGET_X64) - IF(DEBIAN_MULTIARCH) - SET(CMAKE_LIBRARY_ARCHITECTURE ${DEBIAN_MULTIARCH}) - ENDIF(DEBIAN_MULTIARCH) + IF(TARGET_MIPS) + ADD_PLATFORM_FLAGS("-DHAVE_MIPS") + ENDIF(TARGET_MIPS) + ENDIF(NOT CMAKE_OSX_ARCHITECTURES) - IF(CMAKE_LIBRARY_ARCHITECTURE) - SET(CMAKE_LIBRARY_PATH /lib/${CMAKE_LIBRARY_ARCHITECTURE} /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} ${CMAKE_LIBRARY_PATH}) + # Fix library paths suffixes for Debian MultiArch + IF(LIBRARY_ARCHITECTURE) + SET(CMAKE_LIBRARY_PATH /lib/${LIBRARY_ARCHITECTURE} /usr/lib/${LIBRARY_ARCHITECTURE} ${CMAKE_LIBRARY_PATH}) IF(TARGET_X64) SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /lib64 /usr/lib64) - ENDIF(TARGET_X64) - IF(TARGET_X86) + ELSEIF(TARGET_X86) SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /lib32 /usr/lib32) - ENDIF(TARGET_X86) - ENDIF(CMAKE_LIBRARY_ARCHITECTURE) + ENDIF(TARGET_X64) + ENDIF(LIBRARY_ARCHITECTURE) + + IF(APPLE AND NOT IOS) + SET(CMAKE_INCLUDE_PATH /opt/local/include ${CMAKE_INCLUDE_PATH}) + SET(CMAKE_LIBRARY_PATH /opt/local/lib ${CMAKE_LIBRARY_PATH}) + ENDIF(APPLE AND NOT IOS) + + IF(WITH_LOGGING) + ADD_PLATFORM_FLAGS("-DENABLE_LOGS") + ENDIF(WITH_LOGGING) IF(MSVC) - IF(MSVC10) + IF(MSVC_VERSION EQUAL "1700" AND NOT MSVC11) + SET(MSVC11 ON) + ENDIF(MSVC_VERSION EQUAL "1700" AND NOT MSVC11) + + IF(MSVC11) + ADD_PLATFORM_FLAGS("/Gy- /MP") # /Ox is working with VC++ 2010, but custom optimizations don't exist - SET(SPEED_OPTIMIZATIONS "/Ox /GF /GS-") + SET(RELEASE_CFLAGS "/Ox /GF /GS- ${RELEASE_CFLAGS}") # without inlining it's unusable, use custom optimizations again - SET(MIN_OPTIMIZATIONS "/Od /Ob1") + SET(DEBUG_CFLAGS "/Od /Ob1 /GF- ${DEBUG_CFLAGS}") + ELSEIF(MSVC10) + ADD_PLATFORM_FLAGS("/Gy- /MP") + # /Ox is working with VC++ 2010, but custom optimizations don't exist + SET(RELEASE_CFLAGS "/Ox /GF /GS- ${RELEASE_CFLAGS}") + # without inlining it's unusable, use custom optimizations again + SET(DEBUG_CFLAGS "/Od /Ob1 /GF- ${DEBUG_CFLAGS}") ELSEIF(MSVC90) + ADD_PLATFORM_FLAGS("/Gy- /MP") # don't use a /O[012x] flag if you want custom optimizations - SET(SPEED_OPTIMIZATIONS "/Ob2 /Oi /Ot /Oy /GT /GF /GS-") + SET(RELEASE_CFLAGS "/Ob2 /Oi /Ot /Oy /GT /GF /GS- ${RELEASE_CFLAGS}") # without inlining it's unusable, use custom optimizations again - SET(MIN_OPTIMIZATIONS "/Ob1") + SET(DEBUG_CFLAGS "/Ob1 /GF- ${DEBUG_CFLAGS}") ELSEIF(MSVC80) + ADD_PLATFORM_FLAGS("/Gy- /Wp64") # don't use a /O[012x] flag if you want custom optimizations - SET(SPEED_OPTIMIZATIONS "/Ox /GF /GS-") + SET(RELEASE_CFLAGS "/Ox /GF /GS- ${RELEASE_CFLAGS}") # without inlining it's unusable, use custom optimizations again - SET(MIN_OPTIMIZATIONS "/Od /Ob1") - ELSE(MSVC10) + SET(DEBUG_CFLAGS "/Od /Ob1 ${DEBUG_CFLAGS}") + ELSE(MSVC11) MESSAGE(FATAL_ERROR "Can't determine compiler version ${MSVC_VERSION}") - ENDIF(MSVC10) + ENDIF(MSVC11) - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /DWIN32 /D_WINDOWS /W3 /Zm1000 /MP /Gy-") - - # Common link flags - SET(PLATFORM_LINKFLAGS "") + ADD_PLATFORM_FLAGS("/D_CRT_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /DWIN32 /D_WINDOWS /Zm1000 /wd4250") IF(TARGET_X64) # Fix a bug with Intellisense - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} /D_WIN64") + ADD_PLATFORM_FLAGS("/D_WIN64") # Fix a compilation error for some big C++ files - SET(MIN_OPTIMIZATIONS "${MIN_OPTIMIZATIONS} /bigobj") + SET(RELEASE_CFLAGS "${RELEASE_CFLAGS} /bigobj") ELSE(TARGET_X64) # Allows 32 bits applications to use 3 GB of RAM SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /LARGEADDRESSAWARE") ENDIF(TARGET_X64) # Exceptions are only set for C++ - SET(PLATFORM_CXXFLAGS "${PLATFORM_CFLAGS} /EHa") + SET(PLATFORM_CXXFLAGS "${PLATFORM_CXXFLAGS} /EHa") IF(WITH_SYMBOLS) SET(NL_RELEASE_CFLAGS "/Zi ${NL_RELEASE_CFLAGS}") @@ -491,88 +585,292 @@ MACRO(NL_SETUP_BUILD) SET(NL_RELEASE_LINKFLAGS "/RELEASE ${NL_RELEASE_LINKFLAGS}") ENDIF(WITH_SYMBOLS) - SET(NL_DEBUG_CFLAGS "/Zi /MDd /RTC1 /D_DEBUG ${MIN_OPTIMIZATIONS} ${NL_DEBUG_CFLAGS}") - SET(NL_RELEASE_CFLAGS "/MD /DNDEBUG ${SPEED_OPTIMIZATIONS} ${NL_RELEASE_CFLAGS}") + SET(NL_DEBUG_CFLAGS "/Zi /MDd /RTC1 /D_DEBUG ${DEBUG_CFLAGS} ${NL_DEBUG_CFLAGS}") + SET(NL_RELEASE_CFLAGS "/MD /DNDEBUG ${RELEASE_CFLAGS} ${NL_RELEASE_CFLAGS}") SET(NL_DEBUG_LINKFLAGS "/DEBUG /OPT:NOREF /OPT:NOICF /NODEFAULTLIB:msvcrt /INCREMENTAL:YES ${NL_DEBUG_LINKFLAGS}") SET(NL_RELEASE_LINKFLAGS "/OPT:REF /OPT:ICF /INCREMENTAL:NO ${NL_RELEASE_LINKFLAGS}") + + IF(WITH_WARNINGS) + SET(DEBUG_CFLAGS "/W4 ${DEBUG_CFLAGS}") + ELSE(WITH_WARNINGS) + SET(DEBUG_CFLAGS "/W3 ${DEBUG_CFLAGS}") + ENDIF(WITH_WARNINGS) ELSE(MSVC) IF(WIN32) - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -DWIN32 -D_WIN32") + ADD_PLATFORM_FLAGS("-DWIN32 -D_WIN32") + + IF(CLANG) + ADD_PLATFORM_FLAGS("-nobuiltininc") + ENDIF(CLANG) ENDIF(WIN32) IF(APPLE) - IF(TARGET_CPU STREQUAL "x86") - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -arch i386") - ENDIF(TARGET_CPU STREQUAL "x86") - - IF(TARGET_CPU STREQUAL "x86_64") - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -arch x86_64") - ENDIF(TARGET_CPU STREQUAL "x86_64") + IF(NOT XCODE) + IF(CMAKE_OSX_ARCHITECTURES) + SET(TARGETS_COUNT 0) + SET(_ARCHS) + FOREACH(_ARCH ${CMAKE_OSX_ARCHITECTURES}) + IF(_ARCH STREQUAL "i386") + SET(_ARCHS "${_ARCHS} i386") + SET(TARGET_X86 1) + MATH(EXPR TARGETS_COUNT "${TARGETS_COUNT}+1") + ELSEIF(_ARCH STREQUAL "x86_64") + SET(_ARCHS "${_ARCHS} x86_64") + SET(TARGET_X64 1) + MATH(EXPR TARGETS_COUNT "${TARGETS_COUNT}+1") + ELSEIF(_ARCH STREQUAL "armv7s") + SET(_ARCHS "${_ARCHS} armv7s") + SET(TARGET_ARMV7S 1) + SET(TARGET_ARM 1) + MATH(EXPR TARGETS_COUNT "${TARGETS_COUNT}+1") + ELSEIF(_ARCH STREQUAL "armv7") + SET(_ARCHS "${_ARCHS} armv7") + SET(TARGET_ARMV7 1) + SET(TARGET_ARM 1) + MATH(EXPR TARGETS_COUNT "${TARGETS_COUNT}+1") + ELSEIF(_ARCH STREQUAL "armv6") + SET(_ARCHS "${_ARCHS} armv6") + SET(TARGET_ARMV6 1) + SET(TARGET_ARM 1) + MATH(EXPR TARGETS_COUNT "${TARGETS_COUNT}+1") + ELSEIF(_ARCH STREQUAL "mips") + SET(_ARCHS "${_ARCHS} mips") + SET(TARGET_MIPS 1) + MATH(EXPR TARGETS_COUNT "${TARGETS_COUNT}+1") + ELSE(_ARCH STREQUAL "i386") + SET(_ARCHS "${_ARCHS} unknwon(${_ARCH})") + ENDIF(_ARCH STREQUAL "i386") + ENDFOREACH(_ARCH) + MESSAGE(STATUS "Compiling under Mac OS X for ${TARGETS_COUNT} architectures: ${_ARCHS}") + ELSE(CMAKE_OSX_ARCHITECTURES) + SET(TARGETS_COUNT 0) + ENDIF(CMAKE_OSX_ARCHITECTURES) + + IF(TARGETS_COUNT EQUAL 1) + IF(TARGET_ARM) + IF(TARGET_ARMV7S) + ADD_PLATFORM_FLAGS("-arch armv7s -DHAVE_ARMV7S") + ENDIF(TARGET_ARMV7S) + + IF(TARGET_ARMV7) + ADD_PLATFORM_FLAGS("-arch armv7 -DHAVE_ARMV7") + ENDIF(TARGET_ARMV7) + + IF(TARGET_ARMV6) + ADD_PLATFORM_FLAGS("-arch armv6 -DHAVE_ARMV6") + ENDIF(TARGET_ARMV6) + + IF(TARGET_ARMV5) + ADD_PLATFORM_FLAGS("-arch armv5 -DHAVE_ARMV5") + ENDIF(TARGET_ARMV5) + + ADD_PLATFORM_FLAGS("-mthumb -DHAVE_ARM") + ENDIF(TARGET_ARM) + + IF(TARGET_X64) + ADD_PLATFORM_FLAGS("-arch x86_64 -DHAVE_X64 -DHAVE_X86_64 -DHAVE_X86") + ELSEIF(TARGET_X86) + ADD_PLATFORM_FLAGS("-arch i386 -DHAVE_X86") + ENDIF(TARGET_X64) + + IF(TARGET_MIPS) + ADD_PLATFORM_FLAGS("-arch mips -DHAVE_MIPS") + ENDIF(TARGET_MIPS) + ELSEIF(TARGETS_COUNT EQUAL 0) + # Not using CMAKE_OSX_ARCHITECTURES, HAVE_XXX already defined before + IF(TARGET_ARM) + IF(TARGET_ARMV7S) + ADD_PLATFORM_FLAGS("-arch armv7s") + ENDIF(TARGET_ARMV7S) + + IF(TARGET_ARMV7) + ADD_PLATFORM_FLAGS("-arch armv7") + ENDIF(TARGET_ARMV7) + + IF(TARGET_ARMV6) + ADD_PLATFORM_FLAGS("-arch armv6") + ENDIF(TARGET_ARMV6) + + IF(TARGET_ARMV5) + ADD_PLATFORM_FLAGS("-arch armv5") + ENDIF(TARGET_ARMV5) + + ADD_PLATFORM_FLAGS("-mthumb") + ENDIF(TARGET_ARM) + + IF(TARGET_X64) + ADD_PLATFORM_FLAGS("-arch x86_64") + ELSEIF(TARGET_X86) + ADD_PLATFORM_FLAGS("-arch i386") + ENDIF(TARGET_X64) + + IF(TARGET_MIPS) + ADD_PLATFORM_FLAGS("-arch mips") + ENDIF(TARGET_MIPS) + ELSE(TARGETS_COUNT EQUAL 1) + IF(TARGET_ARMV6) + ADD_PLATFORM_FLAGS("-Xarch_armv6 -mthumb -Xarch_armv6 -DHAVE_ARM -Xarch_armv6 -DHAVE_ARMV6") + ENDIF(TARGET_ARMV6) + + IF(TARGET_ARMV7) + ADD_PLATFORM_FLAGS("-Xarch_armv7 -mthumb -Xarch_armv7 -DHAVE_ARM -Xarch_armv7 -DHAVE_ARMV7") + ENDIF(TARGET_ARMV7) + + IF(TARGET_X86) + ADD_PLATFORM_FLAGS("-Xarch_i386 -DHAVE_X86") + ENDIF(TARGET_X86) + + IF(TARGET_X64) + ADD_PLATFORM_FLAGS("-Xarch_x86_64 -DHAVE_X64 -Xarch_x86_64 -DHAVE_X86_64") + ENDIF(TARGET_X64) + + IF(TARGET_MIPS) + ADD_PLATFORM_FLAGS("-Xarch_mips -DHAVE_MIPS") + ENDIF(TARGET_MIPS) + ENDIF(TARGETS_COUNT EQUAL 1) + + IF(IOS) + SET(CMAKE_OSX_SYSROOT "" CACHE PATH "" FORCE) + + IF(IOS_VERSION) + PARSE_VERSION_STRING(${IOS_VERSION} IOS_VERSION_MAJOR IOS_VERSION_MINOR IOS_VERSION_PATCH) + CONVERT_VERSION_NUMBER(${IOS_VERSION_MAJOR} ${IOS_VERSION_MINOR} ${IOS_VERSION_PATCH} IOS_VERSION_NUMBER) + + ADD_PLATFORM_FLAGS("-D__IPHONE_OS_VERSION_MIN_REQUIRED=${IOS_VERSION_NUMBER}") + ENDIF(IOS_VERSION) + + IF(CMAKE_IOS_SYSROOT) + IF(TARGET_ARMV7S) + IF(TARGETS_COUNT GREATER 1) + SET(XARCH "-Xarch_armv7s ") + ENDIF(TARGETS_COUNT GREATER 1) + + ADD_PLATFORM_FLAGS("${XARCH}-isysroot${CMAKE_IOS_SYSROOT}") + ADD_PLATFORM_FLAGS("${XARCH}-miphoneos-version-min=${IOS_VERSION}") + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} ${XARCH}-Wl,-iphoneos_version_min,${IOS_VERSION}") + ENDIF(TARGET_ARMV7S) + + IF(TARGET_ARMV7) + IF(TARGETS_COUNT GREATER 1) + SET(XARCH "-Xarch_armv7 ") + ENDIF(TARGETS_COUNT GREATER 1) + + ADD_PLATFORM_FLAGS("${XARCH}-isysroot${CMAKE_IOS_SYSROOT}") + ADD_PLATFORM_FLAGS("${XARCH}-miphoneos-version-min=${IOS_VERSION}") + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} ${XARCH}-Wl,-iphoneos_version_min,${IOS_VERSION}") + ENDIF(TARGET_ARMV7) + + IF(TARGET_ARMV6) + IF(TARGETS_COUNT GREATER 1) + SET(XARCH "-Xarch_armv6 ") + ENDIF(TARGETS_COUNT GREATER 1) + + ADD_PLATFORM_FLAGS("${XARCH}-isysroot${CMAKE_IOS_SYSROOT}") + ADD_PLATFORM_FLAGS("${XARCH}-miphoneos-version-min=${IOS_VERSION}") + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} ${XARCH}-Wl,-iphoneos_version_min,${IOS_VERSION}") + ENDIF(TARGET_ARMV6) + ENDIF(CMAKE_IOS_SYSROOT) + + IF(CMAKE_IOS_SIMULATOR_SYSROOT AND TARGET_X86) + IF(TARGETS_COUNT GREATER 1) + SET(XARCH "-Xarch_i386 ") + ENDIF(TARGETS_COUNT GREATER 1) + + ADD_PLATFORM_FLAGS("${XARCH}-isysroot${CMAKE_IOS_SIMULATOR_SYSROOT}") + ADD_PLATFORM_FLAGS("${XARCH}-mios-simulator-version-min=${IOS_VERSION}") + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} ${XARCH}-Wl,-macosx_version_min,${CMAKE_OSX_DEPLOYMENT_TARGET}") + ENDIF(CMAKE_IOS_SIMULATOR_SYSROOT AND TARGET_X86) + ELSE(IOS) + IF(CMAKE_OSX_SYSROOT) + ADD_PLATFORM_FLAGS("-isysroot ${CMAKE_OSX_SYSROOT}") + ENDIF(CMAKE_OSX_SYSROOT) + + # Always force -mmacosx-version-min to override environement variable + ADD_PLATFORM_FLAGS("-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,-macosx_version_min,${CMAKE_OSX_DEPLOYMENT_TARGET}") + ENDIF(IOS) + + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,-headerpad_max_install_names") + + IF(HAVE_FLAG_SEARCH_PATHS_FIRST) + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,-search_paths_first") + ENDIF(HAVE_FLAG_SEARCH_PATHS_FIRST) + ENDIF(NOT XCODE) ELSE(APPLE) IF(HOST_CPU STREQUAL "x86_64" AND TARGET_CPU STREQUAL "x86") - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -m32 -march=i686") + ADD_PLATFORM_FLAGS("-m32 -march=i686") ENDIF(HOST_CPU STREQUAL "x86_64" AND TARGET_CPU STREQUAL "x86") IF(HOST_CPU STREQUAL "x86" AND TARGET_CPU STREQUAL "x86_64") - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -m64") + ADD_PLATFORM_FLAGS("-m64") ENDIF(HOST_CPU STREQUAL "x86" AND TARGET_CPU STREQUAL "x86_64") ENDIF(APPLE) - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -D_REENTRANT -pipe -ftemplate-depth-48 -Wall -W -Wpointer-arith -Wsign-compare -Wno-deprecated-declarations -Wno-multichar -Wno-unused -fno-strict-aliasing") - - IF(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -ansi") - ENDIF(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + ADD_PLATFORM_FLAGS("-D_REENTRANT -pipe -fno-strict-aliasing") IF(WITH_COVERAGE) - SET(PLATFORM_CFLAGS "-fprofile-arcs -ftest-coverage ${PLATFORM_CFLAGS}") + ADD_PLATFORM_FLAGS("-fprofile-arcs -ftest-coverage") ENDIF(WITH_COVERAGE) + IF(WITH_WARNINGS) + ADD_PLATFORM_FLAGS("-Wall -W -Wpointer-arith -Wsign-compare -Wno-deprecated-declarations -Wno-multichar -Wno-unused") + IF(CLANG) + ADD_PLATFORM_FLAGS("-std=gnu99") + ELSE(CLANG) + ADD_PLATFORM_FLAGS("-ansi") + ENDIF(CLANG) + ENDIF(WITH_WARNINGS) + + IF(ANDROID) + ADD_PLATFORM_FLAGS("--sysroot=${PLATFORM_ROOT}") + ADD_PLATFORM_FLAGS("-ffunction-sections -funwind-tables") + ADD_PLATFORM_FLAGS("-DANDROID") + ADD_PLATFORM_FLAGS("-Wa,--noexecstack") + + IF(TARGET_ARM) + ADD_PLATFORM_FLAGS("-fpic -fstack-protector") + ADD_PLATFORM_FLAGS("-D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__") + + IF(TARGET_ARMV7) + ADD_PLATFORM_FLAGS("-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16") + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -march=armv7-a -Wl,--fix-cortex-a8") + ELSEIF(TARGET_ARMV5) + ADD_PLATFORM_FLAGS("-march=armv5te -mtune=xscale -msoft-float") + ENDIF(TARGET_ARMV7) + + SET(TARGET_THUMB ON) + IF(TARGET_THUMB) + ADD_PLATFORM_FLAGS("-mthumb -fno-strict-aliasing -finline-limit=64") + SET(DEBUG_CFLAGS "${DEBUG_CFLAGS} -marm") + ELSE(TARGET_THUMB) + ADD_PLATFORM_FLAGS("-funswitch-loops -finline-limit=300") + SET(DEBUG_CFLAGS "${DEBUG_CFLAGS} -fno-strict-aliasing") + SET(RELEASE_CFLAGS "${RELEASE_CFLAGS} -fstrict-aliasing") + ENDIF(TARGET_THUMB) + ELSEIF(TARGET_X86) + # Optimizations for Intel Atom + ADD_PLATFORM_FLAGS("-march=i686 -mtune=atom -mstackrealign -msse3 -mfpmath=sse -m32 -flto -ffast-math -funroll-loops") + ADD_PLATFORM_FLAGS("-fstack-protector -funswitch-loops -finline-limit=300") + SET(RELEASE_CFLAGS "${RELEASE_CFLAGS} -fstrict-aliasing") + SET(DEBUG_CFLAGS "${DEBUG_CFLAGS} -fno-strict-aliasing") + ELSEIF(TARGET_MIPS) + ADD_PLATFORM_FLAGS("-fpic -finline-functions -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -fno-strict-aliasing") + SET(RELEASE_CFLAGS "${RELEASE_CFLAGS} -funswitch-loops -finline-limit=300") + ENDIF(TARGET_ARM) + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now") + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -L${PLATFORM_ROOT}/usr/lib") + ENDIF(ANDROID) + IF(APPLE) - SET(PLATFORM_CFLAGS "-gdwarf-2 ${PLATFORM_CFLAGS}") + ADD_PLATFORM_FLAGS("-gdwarf-2") ENDIF(APPLE) - IF(APPLE AND XCODE) - SET(CMAKE_OSX_SYSROOT "macosx" CACHE PATH "" FORCE) - ELSEIF(APPLE AND NOT XCODE) - IF(NOT CMAKE_OSX_DEPLOYMENT_TARGET) - SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.6") - ENDIF(NOT CMAKE_OSX_DEPLOYMENT_TARGET) - - FOREACH(_SDK ${_CMAKE_OSX_SDKS}) - IF(${_SDK} MATCHES "MacOSX${CMAKE_OSX_DEPLOYMENT_TARGET}\\.sdk") - SET(CMAKE_OSX_SYSROOT ${_SDK} CACHE PATH "" FORCE) - ENDIF(${_SDK} MATCHES "MacOSX${CMAKE_OSX_DEPLOYMENT_TARGET}\\.sdk") - ENDFOREACH(_SDK) - - IF(CMAKE_OSX_SYSROOT) - SET(PLATFORM_CFLAGS "-isysroot ${CMAKE_OSX_SYSROOT} ${PLATFORM_CFLAGS}") - ELSE(CMAKE_OSX_SYSROOT) - MESSAGE(FATAL_ERROR "CMAKE_OSX_SYSROOT can't be determinated") - ENDIF(CMAKE_OSX_SYSROOT) - - IF(CMAKE_OSX_ARCHITECTURES) - FOREACH(_ARCH ${CMAKE_OSX_ARCHITECTURES}) - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -arch ${_ARCH}") - ENDFOREACH(_ARCH) - ENDIF(CMAKE_OSX_ARCHITECTURES) - IF(CMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG) - SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") - ENDIF(CMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG) - - SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,-headerpad_max_install_names") - - IF(HAVE_FLAG_SEARCH_PATHS_FIRST) - SET(PLATFORM_LINKFLAGS "-Wl,-search_paths_first ${PLATFORM_LINKFLAGS}") - ENDIF(HAVE_FLAG_SEARCH_PATHS_FIRST) - ENDIF(APPLE AND XCODE) - # Fix "relocation R_X86_64_32 against.." error on x64 platforms IF(TARGET_X64 AND WITH_STATIC AND NOT WITH_STATIC_DRIVERS) - SET(PLATFORM_CFLAGS "-fPIC ${PLATFORM_CFLAGS}") + ADD_PLATFORM_FLAGS("-fPIC") ENDIF(TARGET_X64 AND WITH_STATIC AND NOT WITH_STATIC_DRIVERS) - SET(PLATFORM_CXXFLAGS ${PLATFORM_CFLAGS}) + SET(PLATFORM_CXXFLAGS "${PLATFORM_CXXFLAGS} -ftemplate-depth-48") IF(NOT APPLE) SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,--no-undefined -Wl,--as-needed") @@ -612,125 +910,146 @@ MACRO(NL_SETUP_BUILD_FLAGS) SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${PLATFORM_LINKFLAGS} ${NL_RELEASE_LINKFLAGS}" CACHE STRING "" FORCE) ENDMACRO(NL_SETUP_BUILD_FLAGS) +# Macro to create x_ABSOLUTE_PREFIX from x_PREFIX +MACRO(NL_MAKE_ABSOLUTE_PREFIX NAME_RELATIVE NAME_ABSOLUTE) + IF(IS_ABSOLUTE "${${NAME_RELATIVE}}") + SET(${NAME_ABSOLUTE} ${${NAME_RELATIVE}}) + ELSE(IS_ABSOLUTE "${${NAME_RELATIVE}}") + IF(WIN32) + SET(${NAME_ABSOLUTE} ${${NAME_RELATIVE}}) + ELSE(WIN32) + SET(${NAME_ABSOLUTE} ${CMAKE_INSTALL_PREFIX}/${${NAME_RELATIVE}}) + ENDIF(WIN32) + ENDIF(IS_ABSOLUTE "${${NAME_RELATIVE}}") +ENDMACRO(NL_MAKE_ABSOLUTE_PREFIX) + MACRO(NL_SETUP_PREFIX_PATHS) ## Allow override of install_prefix/etc path. IF(NOT NL_ETC_PREFIX) IF(WIN32) - SET(NL_ETC_PREFIX "../etc/nel" CACHE PATH "Installation path for configurations") + SET(NL_ETC_PREFIX "." CACHE PATH "Installation path for configurations") ELSE(WIN32) - SET(NL_ETC_PREFIX "${CMAKE_INSTALL_PREFIX}/etc/nel" CACHE PATH "Installation path for configurations") + SET(NL_ETC_PREFIX "etc/nel" CACHE PATH "Installation path for configurations") ENDIF(WIN32) ENDIF(NOT NL_ETC_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(NL_ETC_PREFIX NL_ETC_ABSOLUTE_PREFIX) ## Allow override of install_prefix/share path. IF(NOT NL_SHARE_PREFIX) IF(WIN32) - SET(NL_SHARE_PREFIX "../share/nel" CACHE PATH "Installation path for data.") + SET(NL_SHARE_PREFIX "." CACHE PATH "Installation path for data.") ELSE(WIN32) - SET(NL_SHARE_PREFIX "${CMAKE_INSTALL_PREFIX}/share/nel" CACHE PATH "Installation path for data.") + SET(NL_SHARE_PREFIX "share/nel" CACHE PATH "Installation path for data.") ENDIF(WIN32) ENDIF(NOT NL_SHARE_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(NL_SHARE_PREFIX NL_SHARE_ABSOLUTE_PREFIX) ## Allow override of install_prefix/sbin path. IF(NOT NL_SBIN_PREFIX) IF(WIN32) - SET(NL_SBIN_PREFIX "../sbin" CACHE PATH "Installation path for admin tools and services.") + SET(NL_SBIN_PREFIX "." CACHE PATH "Installation path for admin tools and services.") ELSE(WIN32) - SET(NL_SBIN_PREFIX "${CMAKE_INSTALL_PREFIX}/sbin" CACHE PATH "Installation path for admin tools and services.") + SET(NL_SBIN_PREFIX "sbin" CACHE PATH "Installation path for admin tools and services.") ENDIF(WIN32) ENDIF(NOT NL_SBIN_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(NL_SBIN_PREFIX NL_SBIN_ABSOLUTE_PREFIX) ## Allow override of install_prefix/bin path. IF(NOT NL_BIN_PREFIX) IF(WIN32) - SET(NL_BIN_PREFIX "../bin" CACHE PATH "Installation path for tools and applications.") + SET(NL_BIN_PREFIX "." CACHE PATH "Installation path for tools and applications.") ELSE(WIN32) - SET(NL_BIN_PREFIX "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation path for tools and applications.") + SET(NL_BIN_PREFIX "bin" CACHE PATH "Installation path for tools and applications.") ENDIF(WIN32) ENDIF(NOT NL_BIN_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(NL_BIN_PREFIX NL_BIN_ABSOLUTE_PREFIX) ## Allow override of install_prefix/lib path. IF(NOT NL_LIB_PREFIX) - IF(WIN32) - SET(NL_LIB_PREFIX "../lib" CACHE PATH "Installation path for libraries.") - ELSE(WIN32) - IF(CMAKE_LIBRARY_ARCHITECTURE) - SET(NL_LIB_PREFIX "${CMAKE_INSTALL_PREFIX}/lib/${CMAKE_LIBRARY_ARCHITECTURE}" CACHE PATH "Installation path for libraries.") - ELSE(CMAKE_LIBRARY_ARCHITECTURE) - SET(NL_LIB_PREFIX "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation path for libraries.") - ENDIF(CMAKE_LIBRARY_ARCHITECTURE) - ENDIF(WIN32) + IF(LIBRARY_ARCHITECTURE) + SET(NL_LIB_PREFIX "lib/${LIBRARY_ARCHITECTURE}" CACHE PATH "Installation path for libraries.") + ELSE(LIBRARY_ARCHITECTURE) + SET(NL_LIB_PREFIX "lib" CACHE PATH "Installation path for libraries.") + ENDIF(LIBRARY_ARCHITECTURE) ENDIF(NOT NL_LIB_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(NL_LIB_PREFIX NL_LIB_ABSOLUTE_PREFIX) ## Allow override of install_prefix/lib path. IF(NOT NL_DRIVER_PREFIX) IF(WIN32) - SET(NL_DRIVER_PREFIX "../lib" CACHE PATH "Installation path for drivers.") + SET(NL_DRIVER_PREFIX "." CACHE PATH "Installation path for drivers.") ELSE(WIN32) - IF(CMAKE_LIBRARY_ARCHITECTURE) - SET(NL_DRIVER_PREFIX "${CMAKE_INSTALL_PREFIX}/lib/${CMAKE_LIBRARY_ARCHITECTURE}/nel" CACHE PATH "Installation path for drivers.") - ELSE(CMAKE_LIBRARY_ARCHITECTURE) - SET(NL_DRIVER_PREFIX "${CMAKE_INSTALL_PREFIX}/lib/nel" CACHE PATH "Installation path for drivers.") - ENDIF(CMAKE_LIBRARY_ARCHITECTURE) + IF(LIBRARY_ARCHITECTURE) + SET(NL_DRIVER_PREFIX "lib/${LIBRARY_ARCHITECTURE}/nel" CACHE PATH "Installation path for drivers.") + ELSE(LIBRARY_ARCHITECTURE) + SET(NL_DRIVER_PREFIX "lib/nel" CACHE PATH "Installation path for drivers.") + ENDIF(LIBRARY_ARCHITECTURE) ENDIF(WIN32) ENDIF(NOT NL_DRIVER_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(NL_DRIVER_PREFIX NL_DRIVER_ABSOLUTE_PREFIX) ENDMACRO(NL_SETUP_PREFIX_PATHS) MACRO(RYZOM_SETUP_PREFIX_PATHS) - ## Allow override of install_prefix path. - IF(NOT RYZOM_PREFIX) - IF(WIN32) - SET(RYZOM_PREFIX "." CACHE PATH "Installation path") - ELSE(WIN32) - SET(RYZOM_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE PATH "Installation path") - ENDIF(WIN32) - ENDIF(NOT RYZOM_PREFIX) - ## Allow override of install_prefix/etc path. IF(NOT RYZOM_ETC_PREFIX) IF(WIN32) SET(RYZOM_ETC_PREFIX "." CACHE PATH "Installation path for configurations") ELSE(WIN32) - SET(RYZOM_ETC_PREFIX "${RYZOM_PREFIX}/etc/ryzom" CACHE PATH "Installation path for configurations") + SET(RYZOM_ETC_PREFIX "etc/ryzom" CACHE PATH "Installation path for configurations") ENDIF(WIN32) ENDIF(NOT RYZOM_ETC_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(RYZOM_ETC_PREFIX RYZOM_ETC_ABSOLUTE_PREFIX) ## Allow override of install_prefix/share path. IF(NOT RYZOM_SHARE_PREFIX) IF(WIN32) SET(RYZOM_SHARE_PREFIX "." CACHE PATH "Installation path for data.") ELSE(WIN32) - SET(RYZOM_SHARE_PREFIX "${RYZOM_PREFIX}/share/ryzom" CACHE PATH "Installation path for data.") + SET(RYZOM_SHARE_PREFIX "share/ryzom" CACHE PATH "Installation path for data.") ENDIF(WIN32) ENDIF(NOT RYZOM_SHARE_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(RYZOM_SHARE_PREFIX RYZOM_SHARE_ABSOLUTE_PREFIX) ## Allow override of install_prefix/sbin path. IF(NOT RYZOM_SBIN_PREFIX) IF(WIN32) SET(RYZOM_SBIN_PREFIX "." CACHE PATH "Installation path for admin tools and services.") ELSE(WIN32) - SET(RYZOM_SBIN_PREFIX "${RYZOM_PREFIX}/sbin" CACHE PATH "Installation path for admin tools and services.") + SET(RYZOM_SBIN_PREFIX "sbin" CACHE PATH "Installation path for admin tools and services.") ENDIF(WIN32) ENDIF(NOT RYZOM_SBIN_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(RYZOM_SBIN_PREFIX RYZOM_SBIN_ABSOLUTE_PREFIX) ## Allow override of install_prefix/bin path. IF(NOT RYZOM_BIN_PREFIX) IF(WIN32) SET(RYZOM_BIN_PREFIX "." CACHE PATH "Installation path for tools and applications.") ELSE(WIN32) - SET(RYZOM_BIN_PREFIX "${RYZOM_PREFIX}/bin" CACHE PATH "Installation path for tools.") + SET(RYZOM_BIN_PREFIX "bin" CACHE PATH "Installation path for tools.") ENDIF(WIN32) ENDIF(NOT RYZOM_BIN_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(RYZOM_BIN_PREFIX RYZOM_BIN_ABSOLUTE_PREFIX) + + ## Allow override of install_prefix/lib path. + IF(NOT RYZOM_LIB_PREFIX) + IF(LIBRARY_ARCHITECTURE) + SET(RYZOM_LIB_PREFIX "lib/${LIBRARY_ARCHITECTURE}" CACHE PATH "Installation path for libraries.") + ELSE(LIBRARY_ARCHITECTURE) + SET(RYZOM_LIB_PREFIX "lib" CACHE PATH "Installation path for libraries.") + ENDIF(LIBRARY_ARCHITECTURE) + ENDIF(NOT RYZOM_LIB_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(RYZOM_LIB_PREFIX RYZOM_LIB_ABSOLUTE_PREFIX) ## Allow override of install_prefix/games path. IF(NOT RYZOM_GAMES_PREFIX) IF(WIN32) SET(RYZOM_GAMES_PREFIX "." CACHE PATH "Installation path for tools and applications.") ELSE(WIN32) - SET(RYZOM_GAMES_PREFIX "${RYZOM_PREFIX}/games" CACHE PATH "Installation path for client.") + SET(RYZOM_GAMES_PREFIX "games" CACHE PATH "Installation path for client.") ENDIF(WIN32) ENDIF(NOT RYZOM_GAMES_PREFIX) + NL_MAKE_ABSOLUTE_PREFIX(RYZOM_GAMES_PREFIX RYZOM_GAMES_ABSOLUTE_PREFIX) ENDMACRO(RYZOM_SETUP_PREFIX_PATHS) @@ -742,11 +1061,41 @@ MACRO(SETUP_EXTERNAL) IF(WIN32) FIND_PACKAGE(External REQUIRED) - IF(MSVC10) - IF(NOT MSVC10_REDIST_DIR) + IF(NOT VC_DIR) + SET(VC_DIR $ENV{VC_DIR}) + ENDIF(NOT VC_DIR) + + IF(MSVC11) + IF(NOT MSVC_REDIST_DIR) + # If you have VC++ 2012 Express, put x64/Microsoft.VC110.CRT/*.dll in ${EXTERNAL_PATH}/redist + SET(MSVC_REDIST_DIR "${EXTERNAL_PATH}/redist") + ENDIF(NOT MSVC_REDIST_DIR) + + IF(NOT VC_DIR) + IF(NOT VC_ROOT_DIR) + GET_FILENAME_COMPONENT(VC_ROOT_DIR "[HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\11.0_Config;InstallDir]" ABSOLUTE) + # VC_ROOT_DIR is set to "registry" when a key is not found + IF(VC_ROOT_DIR MATCHES "registry") + GET_FILENAME_COMPONENT(VC_ROOT_DIR "[HKEY_CURRENT_USER\\Software\\Microsoft\\WDExpress\\11.0_Config\\Setup\\VC;InstallDir]" ABSOLUTE) + IF(VC_ROOT_DIR MATCHES "registry") + SET(VS110COMNTOOLS $ENV{VS110COMNTOOLS}) + IF(VS110COMNTOOLS) + FILE(TO_CMAKE_PATH ${VS110COMNTOOLS} VC_ROOT_DIR) + ENDIF(VS110COMNTOOLS) + IF(NOT VC_ROOT_DIR) + MESSAGE(FATAL_ERROR "Unable to find VC++ 2012 directory!") + ENDIF(NOT VC_ROOT_DIR) + ENDIF(VC_ROOT_DIR MATCHES "registry") + ENDIF(VC_ROOT_DIR MATCHES "registry") + ENDIF(NOT VC_ROOT_DIR) + # convert IDE fullpath to VC++ path + STRING(REGEX REPLACE "Common7/.*" "VC" VC_DIR ${VC_ROOT_DIR}) + ENDIF(NOT VC_DIR) + ELSEIF(MSVC10) + IF(NOT MSVC_REDIST_DIR) # If you have VC++ 2010 Express, put x64/Microsoft.VC100.CRT/*.dll in ${EXTERNAL_PATH}/redist - SET(MSVC10_REDIST_DIR "${EXTERNAL_PATH}/redist") - ENDIF(NOT MSVC10_REDIST_DIR) + SET(MSVC_REDIST_DIR "${EXTERNAL_PATH}/redist") + ENDIF(NOT MSVC_REDIST_DIR) IF(NOT VC_DIR) IF(NOT VC_ROOT_DIR) @@ -755,7 +1104,10 @@ MACRO(SETUP_EXTERNAL) IF(VC_ROOT_DIR MATCHES "registry") GET_FILENAME_COMPONENT(VC_ROOT_DIR "[HKEY_CURRENT_USER\\Software\\Microsoft\\VCExpress\\10.0_Config;InstallDir]" ABSOLUTE) IF(VC_ROOT_DIR MATCHES "registry") - FILE(TO_CMAKE_PATH $ENV{VS100COMNTOOLS} VC_ROOT_DIR) + SET(VS100COMNTOOLS $ENV{VS100COMNTOOLS}) + IF(VS100COMNTOOLS) + FILE(TO_CMAKE_PATH ${VS100COMNTOOLS} VC_ROOT_DIR) + ENDIF(VS100COMNTOOLS) IF(NOT VC_ROOT_DIR) MESSAGE(FATAL_ERROR "Unable to find VC++ 2010 directory!") ENDIF(NOT VC_ROOT_DIR) @@ -765,7 +1117,7 @@ MACRO(SETUP_EXTERNAL) # convert IDE fullpath to VC++ path STRING(REGEX REPLACE "Common7/.*" "VC" VC_DIR ${VC_ROOT_DIR}) ENDIF(NOT VC_DIR) - ELSE(MSVC10) + ELSE(MSVC11) IF(NOT VC_DIR) IF(${CMAKE_MAKE_PROGRAM} MATCHES "Common7") # convert IDE fullpath to VC++ path @@ -775,7 +1127,7 @@ MACRO(SETUP_EXTERNAL) STRING(REGEX REPLACE "VC/bin/.+" "VC" VC_DIR ${CMAKE_CXX_COMPILER}) ENDIF(${CMAKE_MAKE_PROGRAM} MATCHES "Common7") ENDIF(NOT VC_DIR) - ENDIF(MSVC10) + ENDIF(MSVC11) ELSE(WIN32) IF(APPLE) IF(WITH_STATIC_EXTERNAL) @@ -800,7 +1152,7 @@ MACRO(SETUP_EXTERNAL) FIND_PACKAGE(WindowsSDK REQUIRED) # use VC++ and Windows SDK include paths - INCLUDE_DIRECTORIES(${VC_INCLUDE_DIR} ${WINSDK_INCLUDE_DIR}) + INCLUDE_DIRECTORIES(${VC_INCLUDE_DIR} ${WINSDK_INCLUDE_DIRS}) ENDIF(MSVC) ENDIF(WITH_STLPORT) ENDMACRO(SETUP_EXTERNAL) diff --git a/code/config.h.cmake b/code/config.h.cmake index 2f2ff8095..d3c9f701d 100644 --- a/code/config.h.cmake +++ b/code/config.h.cmake @@ -43,15 +43,14 @@ #cmakedefine NL_DSOUND_AVAILABLE ${NL_DSOUND_AVAILABLE} #cmakedefine NL_XAUDIO2_AVAILABLE ${NL_XAUDIO2_AVAILABLE} -#cmakedefine NL_BIN_PREFIX "${NL_BIN_PREFIX}" -#cmakedefine NL_ETC_PREFIX "${NL_ETC_PREFIX}" -#cmakedefine NL_SHARE_PREFIX "${NL_SHARE_PREFIX}" -#cmakedefine NL_LIB_PREFIX "${NL_LIB_PREFIX}" -#cmakedefine NL_DRIVER_PREFIX "${NL_DRIVER_PREFIX}" +#cmakedefine NL_BIN_PREFIX "${NL_BIN_ABSOLUTE_PREFIX}" +#cmakedefine NL_ETC_PREFIX "${NL_ETC_ABSOLUTE_PREFIX}" +#cmakedefine NL_SHARE_PREFIX "${NL_SHARE_ABSOLUTE_PREFIX}" +#cmakedefine NL_LIB_PREFIX "${NL_LIB_ABSOLUTE_PREFIX}" +#cmakedefine NL_DRIVER_PREFIX "${NL_DRIVER_ABSOLUTE_PREFIX}" -#cmakedefine RYZOM_PREFIX "${RYZOM_PREFIX}" -#cmakedefine RYZOM_BIN_PREFIX "${RYZOM_BIN_PREFIX}" -#cmakedefine RYZOM_ETC_PREFIX "${RYZOM_ETC_PREFIX}" -#cmakedefine RYZOM_SHARE_PREFIX "${RYZOM_SHARE_PREFIX}" +#cmakedefine RYZOM_BIN_PREFIX "${RYZOM_BIN_ABSOLUTE_PREFIX}" +#cmakedefine RYZOM_ETC_PREFIX "${RYZOM_ETC_ABSOLUTE_PREFIX}" +#cmakedefine RYZOM_SHARE_PREFIX "${RYZOM_SHARE_ABSOLUTE_PREFIX}" #endif // CONFIG_H diff --git a/code/nel/CMakeLists.txt b/code/nel/CMakeLists.txt index 08b4babf0..745278cd7 100644 --- a/code/nel/CMakeLists.txt +++ b/code/nel/CMakeLists.txt @@ -44,8 +44,8 @@ ENDIF(WITH_GTK) IF(WITH_INSTALL_LIBRARIES) IF(UNIX) SET(prefix ${CMAKE_INSTALL_PREFIX}) - SET(exec_prefix ${CMAKE_INSTALL_PREFIX}/bin) - SET(libdir ${CMAKE_INSTALL_PREFIX}/lib) + SET(exec_prefix ${NL_BIN_ABSOLUTE_PREFIX}) + SET(libdir ${NL_LIB_ABSOLUTE_PREFIX}) SET(includedir ${CMAKE_INSTALL_PREFIX}/include) SET(enable_ligo ${WITH_LIGO}) SET(enable_logic ${WITH_LOGIC}) @@ -56,7 +56,7 @@ IF(WITH_INSTALL_LIBRARIES) SET(enable_sound ${WITH_SOUND}) CONFIGURE_FILE(nel-config.in ${CMAKE_CURRENT_BINARY_DIR}/nel-config) - INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/nel-config DESTINATION bin) + INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/nel-config DESTINATION ${NL_BIN_PREFIX}) ENDIF(UNIX) ADD_SUBDIRECTORY(include) diff --git a/code/nel/include/nel/3d/anim_detail_trav.h b/code/nel/include/nel/3d/anim_detail_trav.h index 471ccd52b..7b51afe84 100644 --- a/code/nel/include/nel/3d/anim_detail_trav.h +++ b/code/nel/include/nel/3d/anim_detail_trav.h @@ -71,7 +71,7 @@ public: // For clipTrav. cleared at beginning of CClipTrav::traverse void clearVisibleList(); - // For ClipTrav only. NB: list is cleared at begining of traverse(). NB: only CTransform are supported + // For ClipTrav only. NB: list is cleared at begininng of traverse(). NB: only CTransform are supported void addVisibleModel(CTransform *model) { _VisibleList[_CurrentNumVisibleModels]= model; diff --git a/code/nel/include/nel/3d/camera.h b/code/nel/include/nel/3d/camera.h index 431998f8a..3185dfe7b 100644 --- a/code/nel/include/nel/3d/camera.h +++ b/code/nel/include/nel/3d/camera.h @@ -68,7 +68,7 @@ public: class CCamera : public CTransform { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); diff --git a/code/nel/include/nel/3d/clip_trav.h b/code/nel/include/nel/3d/clip_trav.h index e892ee02e..10dd9dccb 100644 --- a/code/nel/include/nel/3d/clip_trav.h +++ b/code/nel/include/nel/3d/clip_trav.h @@ -93,7 +93,7 @@ public: /// \name Visible List mgt. Those visible models are updated each traverse(). //@{ - // NB: list is cleared at begining of traverse(). + // NB: list is cleared at beginning of traverse(). void addVisibleModel(CTransform *model) { model->_IndexInVisibleList= _CurrentNumVisibleModels; diff --git a/code/nel/include/nel/3d/driver.h b/code/nel/include/nel/3d/driver.h index 630cbcb01..d090d77da 100644 --- a/code/nel/include/nel/3d/driver.h +++ b/code/nel/include/nel/3d/driver.h @@ -293,6 +293,11 @@ public: */ virtual void forceDXTCCompression(bool dxtcComp)=0; + /** if different from 0, enable anisotropic filter on textures. -1 enables max value. + * Default is 0. + */ + virtual void setAnisotropicFilter(sint filter)=0; + /** if !=1, force mostly all the textures (but TextureFonts lightmaps, interfaces etc..) * to be divided by Divisor (2, 4, 8...) * Default is 1. diff --git a/code/nel/include/nel/3d/driver_user.h b/code/nel/include/nel/3d/driver_user.h index a7f6ac7a5..bfe4c1755 100644 --- a/code/nel/include/nel/3d/driver_user.h +++ b/code/nel/include/nel/3d/driver_user.h @@ -471,6 +471,7 @@ public: virtual void delete3dMouseListener (U3dMouseListener *listener); virtual TPolygonMode getPolygonMode (); virtual void forceDXTCCompression(bool dxtcComp); + virtual void setAnisotropicFilter(sint filter); virtual void forceTextureResize(uint divisor); virtual void forceNativeFragmentPrograms(bool nativeOnly); virtual bool setMonitorColorProperties (const CMonitorColorProperties &properties); diff --git a/code/nel/include/nel/3d/landscape_def.h b/code/nel/include/nel/3d/landscape_def.h index 783846d12..c189a428f 100644 --- a/code/nel/include/nel/3d/landscape_def.h +++ b/code/nel/include/nel/3d/landscape_def.h @@ -81,14 +81,14 @@ class IDriver; class CLandscapeGlobals { public: - // LANDSCAPE RENDERING CONTEXT. Landscape must setup it at the begining at refine()/render(). + // LANDSCAPE RENDERING CONTEXT. Landscape must setup it at the beginning at refine()/render(). // The current date of LandScape for refine only. static sint CurrentDate; // The current date of LandScape for render only. static sint CurrentRenderDate; // The center view for refinement. static CVector RefineCenter; - // What is the treshold for tessellation. + // What is the threshold for tessellation. static float RefineThreshold; // Guess. static float OORefineThreshold; @@ -143,7 +143,7 @@ public: static CLandscapeVBAllocator *CurrentTileVBAllocator; - // PATCH GLOBAL INTERFACE. patch must setup them at the begining at refine()/render(). + // PATCH GLOBAL INTERFACE. patch must setup them at the beginning at refine()/render(). // NO!!! REMIND: can't have any patch global, since a propagated split()/updateErrorMetric() // can arise. must use Patch pointer. @@ -158,7 +158,7 @@ public: // *************************************************************************** -// Out of CLandscapeGlobals, because myabe used in __asm{} +// Out of CLandscapeGlobals, because maybe used in __asm{} extern uint NL3D_LandscapeGlobals_PassNTri; extern void *NL3D_LandscapeGlobals_PassTriCurPtr; extern CIndexBuffer::TFormat NL3D_LandscapeGlobals_PassTriFormat; diff --git a/code/nel/include/nel/3d/landscape_model.h b/code/nel/include/nel/3d/landscape_model.h index f9ca071bd..981e3e972 100644 --- a/code/nel/include/nel/3d/landscape_model.h +++ b/code/nel/include/nel/3d/landscape_model.h @@ -42,7 +42,7 @@ const NLMISC::CClassId LandscapeModelId=NLMISC::CClassId(0x5a573b55, 0x6b395829 class CLandscapeModel : public CTransform { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); public: diff --git a/code/nel/include/nel/3d/load_balancing_trav.h b/code/nel/include/nel/3d/load_balancing_trav.h index 37bd69ddd..43d5c95d8 100644 --- a/code/nel/include/nel/3d/load_balancing_trav.h +++ b/code/nel/include/nel/3d/load_balancing_trav.h @@ -165,7 +165,7 @@ public: // For clipTrav. cleared at beginning of CClipTrav::traverse void clearVisibleList(); - // For ClipTrav only. NB: list is cleared at begining of traverse(). + // For ClipTrav only. NB: list is cleared at beginning of traverse(). void addVisibleModel(CTransform *model) { _VisibleList[_CurrentNumVisibleModels]= model; diff --git a/code/nel/include/nel/3d/mesh_base_instance.h b/code/nel/include/nel/3d/mesh_base_instance.h index 4a4091e3c..b045fa414 100644 --- a/code/nel/include/nel/3d/mesh_base_instance.h +++ b/code/nel/include/nel/3d/mesh_base_instance.h @@ -53,7 +53,7 @@ const NLMISC::CClassId MeshBaseInstanceId=NLMISC::CClassId(0xef44331, 0x739f6bc class CMeshBaseInstance : public CTransformShape { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); public: diff --git a/code/nel/include/nel/3d/mesh_instance.h b/code/nel/include/nel/3d/mesh_instance.h index c4018913f..17eb7a97a 100644 --- a/code/nel/include/nel/3d/mesh_instance.h +++ b/code/nel/include/nel/3d/mesh_instance.h @@ -49,7 +49,7 @@ const NLMISC::CClassId MeshInstanceId=NLMISC::CClassId(0x6bfe0a34, 0x23b26dc9); class CMeshInstance : public CMeshBaseInstance { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); public: diff --git a/code/nel/include/nel/3d/mesh_mrm_instance.h b/code/nel/include/nel/3d/mesh_mrm_instance.h index 03fed2d86..4df6b92f0 100644 --- a/code/nel/include/nel/3d/mesh_mrm_instance.h +++ b/code/nel/include/nel/3d/mesh_mrm_instance.h @@ -49,7 +49,7 @@ const NLMISC::CClassId MeshMRMInstanceId=NLMISC::CClassId(0xec608f3, 0x1111c33) class CMeshMRMInstance : public CMeshBaseInstance { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); protected: diff --git a/code/nel/include/nel/3d/mesh_mrm_skinned_instance.h b/code/nel/include/nel/3d/mesh_mrm_skinned_instance.h index 610744a52..71fac9476 100644 --- a/code/nel/include/nel/3d/mesh_mrm_skinned_instance.h +++ b/code/nel/include/nel/3d/mesh_mrm_skinned_instance.h @@ -49,7 +49,7 @@ const NLMISC::CClassId MeshMRMSkinnedInstanceId=NLMISC::CClassId(0x6cfd2619, 0x class CMeshMRMSkinnedInstance : public CMeshBaseInstance { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); protected: diff --git a/code/nel/include/nel/3d/mesh_multi_lod_instance.h b/code/nel/include/nel/3d/mesh_multi_lod_instance.h index 2b249678c..549979438 100644 --- a/code/nel/include/nel/3d/mesh_multi_lod_instance.h +++ b/code/nel/include/nel/3d/mesh_multi_lod_instance.h @@ -61,7 +61,7 @@ public: Lod0Blend = 0x1, }; - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); /// Last Matrix date for Lods diff --git a/code/nel/include/nel/3d/meshvp_per_pixel_light.h b/code/nel/include/nel/3d/meshvp_per_pixel_light.h index bc211a4b6..d7be0f3f9 100644 --- a/code/nel/include/nel/3d/meshvp_per_pixel_light.h +++ b/code/nel/include/nel/3d/meshvp_per_pixel_light.h @@ -29,7 +29,7 @@ namespace NL3D { /** - * This vertex program is used to perform perpixel lighting with meshs. Its ouputs are : + * This vertex program is used to perform perpixel lighting with meshs. Its outputs are : * * Coord Tex 0 : duplicate the tex Coord 0 set from the v.b. * Coord Tex 1 : The light vector in tangent space. diff --git a/code/nel/include/nel/3d/patch.h b/code/nel/include/nel/3d/patch.h index 4b35660d0..c1363953a 100644 --- a/code/nel/include/nel/3d/patch.h +++ b/code/nel/include/nel/3d/patch.h @@ -808,7 +808,7 @@ private: CTessFarVertex BaseFarVertices[4]; - // Local info for CTessFace tiles. CPatch must setup them at the begining at refine()/render(). + // Local info for CTessFace tiles. CPatch must setup them at the beginning at refine()/render(). // For Far Texture coordinates. float Far0UScale, Far0VScale, Far0UBias, Far0VBias; float Far1UScale, Far1VScale, Far1UBias, Far1VBias; diff --git a/code/nel/include/nel/3d/point_light_model.h b/code/nel/include/nel/3d/point_light_model.h index a9da70661..2ca3e46d3 100644 --- a/code/nel/include/nel/3d/point_light_model.h +++ b/code/nel/include/nel/3d/point_light_model.h @@ -55,7 +55,7 @@ const NLMISC::CClassId PointLightModelId=NLMISC::CClassId(0x7e842eba, 0x140b6c6 class CPointLightModel : public CTransform { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); diff --git a/code/nel/include/nel/3d/ps_attrib_maker_bin_op_inline.h b/code/nel/include/nel/3d/ps_attrib_maker_bin_op_inline.h index fa077d0f0..421e059cb 100644 --- a/code/nel/include/nel/3d/ps_attrib_maker_bin_op_inline.h +++ b/code/nel/include/nel/3d/ps_attrib_maker_bin_op_inline.h @@ -128,7 +128,7 @@ inline uint32 CPSAttribMakerBinOp::getMinValue(void) const { uint32 lhs = _Arg[0]->getMinValue(); uint32 rhs = _Arg[1]->getMaxValue(); - return rhs > rhs ? 0 : lhs - rhs; + return lhs > rhs ? 0 : lhs - rhs; } break; default: @@ -153,7 +153,7 @@ inline uint32 CPSAttribMakerBinOp::getMaxValue(void) const { uint32 lhs = _Arg[0]->getMaxValue(); uint32 rhs = _Arg[1]->getMinValue(); - return rhs > rhs ? 0 : lhs - rhs; + return lhs > rhs ? 0 : lhs - rhs; } break; default: diff --git a/code/nel/include/nel/3d/ps_attrib_maker_template.h b/code/nel/include/nel/3d/ps_attrib_maker_template.h index 8d7b68ba2..92953b86f 100644 --- a/code/nel/include/nel/3d/ps_attrib_maker_template.h +++ b/code/nel/include/nel/3d/ps_attrib_maker_template.h @@ -29,7 +29,7 @@ namespace NL3D { /* * In this file, we define several template that helps to create attributes maker such as gradient (of float, int, vector etc) * attributes maker are used in the particle system to generate values, such as size, color etc. see ps_attrib_maker.h - * for more informations + * for more information */ diff --git a/code/nel/include/nel/3d/quad_grid_clip_manager.h b/code/nel/include/nel/3d/quad_grid_clip_manager.h index 7e32c07b3..54d427a8b 100644 --- a/code/nel/include/nel/3d/quad_grid_clip_manager.h +++ b/code/nel/include/nel/3d/quad_grid_clip_manager.h @@ -55,7 +55,7 @@ const NLMISC::CClassId QuadGridClipManagerId=NLMISC::CClassId(0x1ffb079a, 0x6c5 class CQuadGridClipManager : public CTransform { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); public: diff --git a/code/nel/include/nel/3d/render_trav.h b/code/nel/include/nel/3d/render_trav.h index 271165427..6e8d04b32 100644 --- a/code/nel/include/nel/3d/render_trav.h +++ b/code/nel/include/nel/3d/render_trav.h @@ -227,7 +227,7 @@ public: enum {MaxVPLight= 4}; /** reset the lighting setup in the driver (all lights are disabled). - * called at begining of traverse(). Must be called by any model (before and after rendering) + * called at beginning of traverse(). Must be called by any model (before and after rendering) * that wish to use CDriver::setLight() instead of the standard behavior with changeLightSetup() */ void resetLightSetup(); diff --git a/code/nel/include/nel/3d/root_model.h b/code/nel/include/nel/3d/root_model.h index 3faa5b675..d54ad7c20 100644 --- a/code/nel/include/nel/3d/root_model.h +++ b/code/nel/include/nel/3d/root_model.h @@ -39,7 +39,7 @@ const NLMISC::CClassId RootModelId=NLMISC::CClassId(0x25f0505d, 0x75c69f9); class CRootModel : public CTransform { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); diff --git a/code/nel/include/nel/3d/seg_remanence.h b/code/nel/include/nel/3d/seg_remanence.h index dddfa3a61..2e3202a89 100644 --- a/code/nel/include/nel/3d/seg_remanence.h +++ b/code/nel/include/nel/3d/seg_remanence.h @@ -54,7 +54,7 @@ public: CSegRemanence(CSegRemanence &other); CSegRemanence &operator = (CSegRemanence &other); //@} - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); /// to instanciate that model from a scene static CTransform *creator() { return new CSegRemanence; } diff --git a/code/nel/include/nel/3d/skeleton_model.h b/code/nel/include/nel/3d/skeleton_model.h index 196cc680c..ed4f8aadc 100644 --- a/code/nel/include/nel/3d/skeleton_model.h +++ b/code/nel/include/nel/3d/skeleton_model.h @@ -79,7 +79,7 @@ public: /// max number of bones supported in skeleton enum { MaxNumBones = 256 }; - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); public: diff --git a/code/nel/include/nel/3d/transform.h b/code/nel/include/nel/3d/transform.h index cf8d3031f..00e023331 100644 --- a/code/nel/include/nel/3d/transform.h +++ b/code/nel/include/nel/3d/transform.h @@ -90,7 +90,7 @@ const NLMISC::CClassId TransformId=NLMISC::CClassId(0x174750cb, 0xf952024); class CTransform : public ITransformable { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); /// get the scene which has created us @@ -113,7 +113,7 @@ public: /** * Extra init for a model. this method is called by the framework at the very end of CScene::createModel() * Warning! if the model is a CTransformShape, then when initModel() is called, Shape and other related member/setup - * of IShape::createInstance() are not yet done (because createModel() is called at the begining in createInstance()). + * of IShape::createInstance() are not yet done (because createModel() is called at the beginning in createInstance()). * * Because initModel() is called at the very end, deriver could implement anything like creating other models, * but not deleting this model... diff --git a/code/nel/include/nel/3d/transform_shape.h b/code/nel/include/nel/3d/transform_shape.h index 28c5602c3..7bffe971a 100644 --- a/code/nel/include/nel/3d/transform_shape.h +++ b/code/nel/include/nel/3d/transform_shape.h @@ -55,7 +55,7 @@ const NLMISC::CClassId TransformShapeId=NLMISC::CClassId(0x1e6115e6, 0x63502517 class CTransformShape : public CTransform { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); public: diff --git a/code/nel/include/nel/3d/u_driver.h b/code/nel/include/nel/3d/u_driver.h index 9b9eac656..d66a72e47 100644 --- a/code/nel/include/nel/3d/u_driver.h +++ b/code/nel/include/nel/3d/u_driver.h @@ -660,6 +660,11 @@ public: */ virtual void forceDXTCCompression(bool dxtcComp)=0; + /** if different from 0, enable anisotropic filter on textures. -1 enables max value. + * Default is 0. + */ + virtual void setAnisotropicFilter(sint filter)=0; + /** if !=1, force mostly all the textures (but TextureFonts lightmaps, interfaces etc..) * to be divided by Divisor (2, 4, 8...) * Default is 1. diff --git a/code/nel/include/nel/3d/vegetable_blend_layer_model.h b/code/nel/include/nel/3d/vegetable_blend_layer_model.h index ea37a0e4d..1f8840de9 100644 --- a/code/nel/include/nel/3d/vegetable_blend_layer_model.h +++ b/code/nel/include/nel/3d/vegetable_blend_layer_model.h @@ -48,7 +48,7 @@ const NLMISC::CClassId VegetableBlendLayerModelId=NLMISC::CClassId(0x77375163, class CVegetableBlendLayerModel : public CTransform { public: - /// Call at the begining of the program, to register the model + /// Call at the beginning of the program, to register the model static void registerBasic(); public: diff --git a/code/nel/include/nel/3d/vertex_program_parse.h b/code/nel/include/nel/3d/vertex_program_parse.h index 8c7ec7f9b..cd9f414c9 100644 --- a/code/nel/include/nel/3d/vertex_program_parse.h +++ b/code/nel/include/nel/3d/vertex_program_parse.h @@ -188,7 +188,7 @@ public: * \warning: Only syntax is checked. It doesn't check that a register has been initialised before use. * \param src The input text of a vertex program, in OpenGL format. * \param result The result program. - * \param errorOuput If parsing failed, contains the reason + * \param errorOutput If parsing failed, contains the reason * \result true if the parsing succeeded */ bool parse(const char *src, TProgram &result, std::string &errorOutput); diff --git a/code/nel/include/nel/CMakeLists.txt b/code/nel/include/nel/CMakeLists.txt index 874073eb7..b695104ae 100644 --- a/code/nel/include/nel/CMakeLists.txt +++ b/code/nel/include/nel/CMakeLists.txt @@ -4,6 +4,10 @@ IF(WITH_3D) SUBDIRS(3d) ENDIF(WITH_3D) +IF(WITH_GUI) + ADD_SUBDIRECTORY(gui) +ENDIF(WITH_GUI) + IF(WITH_GEORGES) SUBDIRS(georges) ENDIF(WITH_GEORGES) diff --git a/code/nel/include/nel/georges/header.h b/code/nel/include/nel/georges/header.h index 769cc0568..3733f0707 100644 --- a/code/nel/include/nel/georges/header.h +++ b/code/nel/include/nel/georges/header.h @@ -19,6 +19,9 @@ #include "nel/misc/types_nl.h" +// Include from libxml2 +#include + namespace NLGEORGES { diff --git a/code/nel/include/nel/gui/CMakeLists.txt b/code/nel/include/nel/gui/CMakeLists.txt new file mode 100644 index 000000000..cae6dae6f --- /dev/null +++ b/code/nel/include/nel/gui/CMakeLists.txt @@ -0,0 +1,3 @@ +FILE(GLOB HEADERS *.h) + +INSTALL(FILES ${HEADERS} DESTINATION include/nel/gui COMPONENT headers) diff --git a/code/nel/include/nel/gui/action_handler.h b/code/nel/include/nel/gui/action_handler.h new file mode 100644 index 000000000..70c4b386e --- /dev/null +++ b/code/nel/include/nel/gui/action_handler.h @@ -0,0 +1,156 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NL_ACTION_HANDLER_H +#define NL_ACTION_HANDLER_H + +#include "nel/misc/types_nl.h" +#include +#include "nel/misc/types_nl.h" +#include "nel/misc/debug.h" +#include "nel/misc/xml_auto_ptr.h" +#include + +namespace NLGUI +{ + + class CCtrlBase; + + + /** + * interface for action handlers + * \author Nicolas Brigand + * \author Nevrax France + * \date 2002 + */ + class IActionHandler + { + public: + // Execute the answer to the action + // Params has the following form : paramName=theParam|paramName2=theParam2|... + virtual void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) { } + + virtual ~IActionHandler() {} + + static std::string getParam (const std::string &Params, const std::string &ParamName); + + static void getAllParams (const std::string &Params, std::vector< std::pair > &AllParams); + }; + + + /** + interface for action handlers factory + no release in this factory : a handler must be destroyed by the control that created it + */ + class CAHManager + { + public: + typedef std::map< std::string, IActionHandler* > TFactoryMap; + typedef std::map< IActionHandler*, std::string > TNameMap; + + static CAHManager* getInstance() + { + if (_GlobalInstance == NULL) + _GlobalInstance = new CAHManager; + return _GlobalInstance; + } + + /// return pointer to action handler or null if it doesn't exist + IActionHandler *getActionHandler(const std::string &name) const + { + if( name.empty() ) + return NULL; + + TFactoryMap::const_iterator it = FactoryMap.find(name); + if( it == FactoryMap.end() ) + { + nlwarning( "Couldn't find action handler %s", name.c_str() ); + return NULL; + } + else + return it->second; + } + + /// Return the name of the action handler given its pointer + const std::string &getActionHandlerName(IActionHandler *pAH) const + { + TNameMap::const_iterator it = NameMap.find(pAH); + return it != NameMap.end() ? it->second : EmptyName; + } + + /// map of action handler factories + TFactoryMap FactoryMap; + TNameMap NameMap; + std::string EmptyName; + + /// return the Action Handler 'name'. if name is of form 'ah:params', then params are filled (NB: else not changed) + IActionHandler *getAH(const std::string &name, std::string ¶ms); + IActionHandler *getAH(const std::string &name, class CStringShared ¶ms); + + /** common method to parse Action Handler from a xml node + * \param ahId eg: "onclick_l" + * \param paramId eg: "params_l". + * \param params returned parameters. + * NB: if paramId is NULL, empty or does not exist in the xmlNode, then the optional param in ahId (eg: "show:phrase_book") + * is taken + * NB: if none of the optional param in ahId, or the specified param are filled/found, then params is not changed + */ + void parseAH(xmlNodePtr cur, const char *ahId, const char *paramId, IActionHandler *&ahRet, std::string ¶ms); + void parseAH(xmlNodePtr cur, const char *ahId, const char *paramId, IActionHandler *&ahRet, class CStringShared ¶ms); + + /// Get the AH name from ptr + const std::string &getAHName(IActionHandler *pAH){ return getActionHandlerName(pAH); } + + void runActionHandler(const std::string &AHName, CCtrlBase *pCaller, const std::string &Params=std::string("") ); + void runActionHandler(IActionHandler *ah, CCtrlBase *pCaller, const std::string &Params=std::string("") ); + + // Submit a generic event + void submitEvent( const std::string &evt ); + static void setEditorMode( bool b ){ editorMode = b; } + + private: + CAHManager(){} + static CAHManager *_GlobalInstance; + static bool editorMode; + + }; + + /// Ah name must all be lower case + #define REGISTER_ACTION_HANDLER(handler ,name) \ + class handler##Factory : public handler \ + { \ + public: \ + handler##Factory () \ + { \ + nlassert(name!=NULL); \ + const char *c= name; \ + while(*c!='\0') \ + { \ + nlassert(islower(*c) || !isalpha(*c)); \ + c++; \ + } \ + CAHManager *pAHFM = CAHManager::getInstance(); \ + pAHFM->FactoryMap.insert(CAHManager::TFactoryMap::value_type(name,this)); \ + pAHFM->NameMap.insert(CAHManager::TNameMap::value_type(this,name)); \ + }; \ + }; \ + handler##Factory handler##FactoryInstance ; \ + \ + + +} + +#endif //NL_ACTION_HANDLER_H diff --git a/code/nel/include/nel/gui/ctrl_base.h b/code/nel/include/nel/gui/ctrl_base.h new file mode 100644 index 000000000..fe8d5ea60 --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_base.h @@ -0,0 +1,190 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef RZ_CTRL_BASE_H +#define RZ_CTRL_BASE_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/view_base.h" +#include "nel/gui/event_descriptor.h" + +namespace NLGUI +{ + class CCtrlBase : public CViewBase + { + public: + + // Tooltip mode + enum TToolTipParentType + { + TTMouse= 0, // The tooltip is displayed relatively to the mouse when it appears + TTCtrl= 1, // The tooltip is displayed relatively to the ctrl it comes from when it apeears + TTWindow= 2, // The tooltip is displayed relatively to the window where the control lies. + TTSpecialWindow= 3, // The tooltip is displayed relatively to a special user window + + NumToolTipParentRef + }; + + public: + + /// Constructor + CCtrlBase(const TCtorParam ¶m) : CViewBase(param) + { + _ToolTipInstant= true; + _ToolTipParent= TTCtrl; + // see interface.txt for meaning of auto + _ToolTipParentPosRef= Hotspot_TTAuto; + _ToolTipPosRef= Hotspot_TTAuto; + resizer = false; + } + + /// Destructor + virtual ~CCtrlBase(); + + static std::string tooltipParentToString( TToolTipParentType type ); + static TToolTipParentType stringToToolTipParent( const std::string &str ); + + std::string getProperty( const std::string &name ) const; + + void setProperty( const std::string &name, const std::string &value ); + + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + // special parse + virtual bool parse(xmlNodePtr cur, CInterfaceGroup *parentGroup); + + + /// Handle all events (implemented by derived classes) (return true to signal event handled) + virtual bool handleEvent (const NLGUI::CEventDescriptor &event); + + virtual CCtrlBase *getSubCtrl (sint32 /* x */, sint32 /* y */) { return this; } + + /// Debug + virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } + + + /// Get the ContextHelp for this control. Default is to return _ContextHelp + virtual void getContextHelp(ucstring &help) const {help= _ContextHelp;} + /// Get the ContextHelp for this control, with tooltip specific code. Default behaviour is identical to getContextHelp. + virtual void getContextHelpToolTip(ucstring &help) const { getContextHelp(help); } + // Get the name of the context help window. Default to "context_help" + virtual std::string getContextHelpWindowName() const; + /// Get the ContextHelp ActionHandler. If "", noop + const std::string &getContextHelpActionHandler() const {return _OnContextHelp;} + /// Get the ContextHelp ActionHandler Params + const std::string &getContextHelpAHParams() const {return _OnContextHelpParams;} + /// true if both are empty + bool emptyContextHelp() const; + // Should return true if the context help should be displayed instantly + bool wantInstantContextHelp() const { return _ToolTipInstant; } + /// Set true if ToolTip should be displayed instantly + void setInstantContextHelp(bool instant) { _ToolTipInstant = instant;} + + /** If ctrl has a non rectangle shape, perform further test to know + * if control should be taken in account for context help + */ + virtual bool preciseHitTest(sint32 /* x */, sint32 /* y */) const { return true; } + + + /// return the type of anchor for the tooltip of this control + TToolTipParentType getToolTipParent() const { return _ToolTipParent;} + const std::string &getToolTipSpecialParent() const {return _ToolTipSpecialParent.toString();} + /// Set the type of anchor for the tooltip of this control + void setToolTipParent(TToolTipParentType type) { _ToolTipParent = type; } + void setToolTipSpecialParent(const std::string &parent) { _ToolTipSpecialParent = parent; } + /// Get the ToolTip pos references (parent relevant only if getToolTipParent()!=TTMouse) + THotSpot getToolTipParentPosRef() const { return _ToolTipParentPosRef;} + THotSpot getToolTipPosRef() const { return _ToolTipPosRef;} + THotSpot getToolTipParentPosRefAlt() const { return _ToolTipParentPosRefAlt;} + THotSpot getToolTipPosRefAlt() const { return _ToolTipPosRefAlt;} + /// Set the ToolTip pos references (parent relevant only if getToolTipParent()!=TTMouse) + void setToolTipParentPosRef(THotSpot pos) { _ToolTipParentPosRef = pos;} + void setToolTipPosRef(THotSpot pos) { _ToolTipPosRef = pos;} + + /// replace the default contextHelp + ucstring getDefaultContextHelp() const {return _ContextHelp;} + void setDefaultContextHelp(const ucstring &help) {_ContextHelp= help;} + void setOnContextHelp(const std::string &help) {_OnContextHelp= help;} + void setOnContextHelpAHParams(const std::string &p) {_OnContextHelpParams= p;} + + + + // called when this element or a son has been captured + virtual void elementCaptured(CCtrlBase * /* capturedElement */) {} + + virtual bool isCtrl() const { return true; } + + // Made for CtrlResizer to take the precedence over son controls. + virtual uint getDeltaDepth() const { return 0; } + + // true if this ctrl is capturable (true by default, false for tooltip) + virtual bool isCapturable() const {return true;} + + bool isResizer() const{ return resizer; } + + // from CInterfaceElement + virtual void visit(CInterfaceElementVisitor *visitor); + + /** test if virtual desktop change is possible while this element is captured by the mouse + * Useful for resizers + */ + virtual bool canChangeVirtualDesktop() const { return true; } + + // called when keyboard capture has been lost + virtual void onKeyboardCaptureLost() {} + + REFLECT_EXPORT_START(CCtrlBase, CViewBase) + REFLECT_UCSTRING("tooltip", getDefaultContextHelp, setDefaultContextHelp); + REFLECT_EXPORT_END + + // special for mouse over : return true and fill the name of the cursor to display + virtual bool getMouseOverShape(std::string &/* texName */, uint8 &/* rot */, NLMISC::CRGBA &/* col */) { return false; } + + virtual void serial(NLMISC::IStream &f); + + uint32 getDepth( CInterfaceGroup *group ); + + protected: + // This is the ContextHelp filled by default in parse() + ucstring _ContextHelp; + CStringShared _OnContextHelp; + CStringShared _OnContextHelpParams; + CStringShared _ToolTipSpecialParent; + TToolTipParentType _ToolTipParent; + bool _ToolTipInstant : 1; + THotSpot _ToolTipParentPosRef : 6; + THotSpot _ToolTipPosRef : 6; + THotSpot _ToolTipParentPosRefAlt : 6; + THotSpot _ToolTipPosRefAlt : 6; + protected: + void convertTooltipHotSpot(const char *prop, THotSpot &parentHS, THotSpot &childHS); + static std::string TooltipHotSpotToString( THotSpot parent, THotSpot child ); + + void mapAHString( const std::string &key, const std::string &value ); + std::string getAHString( const std::string &key ) const; + + static std::map< std::string, std::map< std::string, std::string > > AHCache; + + bool resizer; + }; + +} + +#endif // RZ_VIEW_BASE_H + +/* End of ctrl_base.h */ diff --git a/code/nel/include/nel/gui/ctrl_base_button.h b/code/nel/include/nel/gui/ctrl_base_button.h new file mode 100644 index 000000000..d4699305f --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_base_button.h @@ -0,0 +1,270 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_CTRL_BASE_BUTTON_H +#define NL_CTRL_BASE_BUTTON_H + +#include "nel/gui/ctrl_base.h" +#include "nel/gui/action_handler.h" + +namespace NLGUI +{ + + // *************************************************************************** + /** + * Base Class For Buttons. + * \author Lionel Berenguier + * \author Nevrax France + * \date 2003 + */ + class CCtrlBaseButton : public CCtrlBase + { + + public: + enum EType { PushButton = 0, ToggleButton, RadioButton, ButtonTypeCount }; + + /// Constructor + CCtrlBaseButton(const TCtorParam ¶m); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + virtual bool parse (xmlNodePtr cur,CInterfaceGroup * parentGroup); + virtual bool handleEvent (const NLGUI::CEventDescriptor& event); + + /// \name Misc + // @{ + void setType (EType t) { _Type = t; } + EType getType() { return _Type; } + std::string getTypeString() const; + void setTypeFromString( const std::string &type ); + + void setClickWhenPushed(bool click) { _ClickWhenPushed = click; } + bool getClickWhenPushed() const { return _ClickWhenPushed; } + + void setPushed (bool state); + bool getPushed () const { return _Pushed; } + + void setFrozen (bool state); + bool getFrozen () const { return _Frozen; } + + // Set half tone mode for the display of frozen buttons. Default is true. + void setFrozenHalfTone(bool enabled); + bool getFrozenHalfTone() const { return _FrozenHalfTone; } + + // if the radio is a radio button, then all radio button are unselected + void unselect(); + // @} + + + /// \name Colors + // @{ + void setColor(NLMISC::CRGBA col) { _ColorNormal = col; } + void setColorPushed(NLMISC::CRGBA col) { _ColorPushed = col; } + void setColorOver(NLMISC::CRGBA col) { _ColorOver = col; } + + NLMISC::CRGBA getColor() const { return _ColorNormal; } + NLMISC::CRGBA getColorPushed() const { return _ColorPushed; } + NLMISC::CRGBA getColorOver() const { return _ColorOver; } + + // Override because mustupdate 3 states + void setModulateGlobalColorAll(bool state); + void setModulateGlobalColorNormal(bool state) {_ModulateGlobalColorNormal= state;} + void setModulateGlobalColorPushed(bool state) {_ModulateGlobalColorPushed= state;} + void setModulateGlobalColorOver(bool state) {_ModulateGlobalColorOver= state;} + + virtual sint32 getAlpha() const { return _ColorNormal.A; } + virtual void setAlpha (sint32 a) { _ColorOver.A = _ColorNormal.A = _ColorPushed.A = (uint8)a; } + + std::string getColorAsString() const + { return NLMISC::toString(_ColorNormal.R) + " " + NLMISC::toString(_ColorNormal.G) + " " + + NLMISC::toString(_ColorNormal.B) + " " + NLMISC::toString(_ColorNormal.A); } + std::string getColorOverAsString() const + { return NLMISC::toString(_ColorOver.R) + " " + NLMISC::toString(_ColorOver.G) + " " + + NLMISC::toString(_ColorOver.B) + " " + NLMISC::toString(_ColorOver.A); } + std::string getColorPushedAsString() const + { return NLMISC::toString(_ColorPushed.R) + " " + NLMISC::toString(_ColorPushed.G) + " " + + NLMISC::toString(_ColorPushed.B) + " " + NLMISC::toString(_ColorPushed.A); } + + void setColorAsString(const std::string &col) { _ColorNormal = convertColor (col.c_str()); } + void setColorOverAsString(const std::string &col) { _ColorOver = convertColor (col.c_str()); } + void setColorPushedAsString(const std::string &col) { _ColorPushed = convertColor (col.c_str()); } + // @} + + ///\name radio button specific + //@{ + /** Initialize radio button reference + * Advanced: + * NB: must call initRBRef() for radio button if button is created without parse(). + * NB: setParent() must be called before (else assert) + */ + void initRBRef(); + //@} + void initRBRefFromRadioButton(CCtrlBaseButton * pBut); + + + /// \name Handlers + // @{ + // Event part + void setActionOnLeftClick (const std::string &actionHandlerName) { _AHOnLeftClickString = actionHandlerName; _AHOnLeftClick = CAHManager::getInstance()->getAH(actionHandlerName, _AHLeftClickParams); } + void setActionOnLeftClickParams(const std::string ¶ms) { _AHOnLeftClickStringParams = params; } + void setActionOnRightClick (const std::string &actionHandlerName) { _AHOnRightClick = CAHManager::getInstance()->getAH(actionHandlerName, _AHRightClickParams); } + void setActionOnClockTick (const std::string &ahName) { _AHOnClockTick = CAHManager::getInstance()->getAH(ahName, _AHClockTickParams); } + void setParamsOnLeftClick (const std::string ¶msHandlerName) { _AHLeftClickParams = paramsHandlerName; } + void setParamsOnRightClick (const std::string ¶msHandlerName) { _AHRightClickParams = paramsHandlerName; } + void setParamsOnClockTick (const std::string &ahParamsName) { _AHClockTickParams = ahParamsName; } + + // get Event part + std::string _getActionOnOver() const{ return CAHManager::getInstance()->getAHName( _AHOnOver ); } + std::string _getActionOnLeftClick() const { return CAHManager::getInstance()->getAHName( _AHOnLeftClick ); } + std::string _getActionOnLeftLongClick() const { return CAHManager::getInstance()->getAHName( _AHOnLeftLongClick ); } + std::string _getActionOnDblLeftClick() const { return CAHManager::getInstance()->getAHName( _AHOnLeftDblClick ); } + std::string _getActionOnRightClick() const { return CAHManager::getInstance()->getAHName( _AHOnRightClick ); } + std::string _getActionOnClockTick() const { return CAHManager::getInstance()->getAHName( _AHOnClockTick ); } + + IActionHandler *getActionOnLeftClick () const { return _AHOnLeftClick; } + IActionHandler *getActionOnRightClick () const { return _AHOnRightClick; } + IActionHandler *getActionOnClockTick () const { return _AHOnClockTick; } + std::string _getParamsOnOver() const{ return _AHOverParams.toString(); } + std::string _getParamsOnLeftClick () const { return _AHLeftClickParams.toString(); } + const std::string &getParamsOnLeftClick () const { return _AHLeftClickParams; } + const std::string &getParamsOnRightClick () const { return _AHRightClickParams; } + const std::string &getParamsOnClockTick () const { return _AHClockTickParams; } + + // run action on left click + void runLeftClickAction(); + + // Context menu accessor/ One for each button + void setListMenuLeft (const std::string &cm) { _ListMenuLeft = cm; } + void setListMenuRight (const std::string &cm) { _ListMenuRight = cm; } + void setListMenuBoth (const std::string &cm) { _ListMenuLeft= _ListMenuRight= cm; } + std::string getListMenuLeft () { return _ListMenuLeft.toString(); } + std::string getListMenuRight () { return _ListMenuRight.toString(); } + // @} + + + + int luaRunLeftClickAction(CLuaState &ls); + REFLECT_EXPORT_START(CCtrlBaseButton, CCtrlBase) + REFLECT_BOOL("pushed", getPushed, setPushed); + REFLECT_STRING("col_normal", getColorAsString, setColorAsString); + REFLECT_STRING("col_over", getColorOverAsString, setColorOverAsString); + REFLECT_STRING("col_pushed", getColorPushedAsString, setColorPushedAsString); + REFLECT_RGBA("col_normal_rgba", getColor, setColor); + REFLECT_RGBA("col_over_rgba", getColorOver, setColorOver); + REFLECT_RGBA("col_pushed_rgba", getColorPushed, setColorPushed); + REFLECT_BOOL("frozen", getFrozen, setFrozen); + REFLECT_BOOL("frozen_half_tone", getFrozenHalfTone, setFrozenHalfTone); + REFLECT_STRING("onclick_l", _getActionOnLeftClick, setActionOnLeftClick); + REFLECT_STRING("params_l", _getParamsOnLeftClick, setParamsOnLeftClick); + REFLECT_LUA_METHOD("runLeftClickAction", luaRunLeftClickAction); + REFLECT_EXPORT_END + + protected: + EType _Type; + + // State + bool _Pushed : 1; + bool _Over : 1; + bool _OverWhenPushed : 1; + bool _Frozen : 1; + bool _FrozenHalfTone : 1; + bool _ClickWhenPushed : 1; + bool _ModulateGlobalColorNormal : 1; + bool _ModulateGlobalColorPushed : 1; + bool _ModulateGlobalColorOver : 1; + bool _LeftLongClickHandled : 1; // Is it already handled ? + bool _LeftDblClickHandled : 1; + + + ///\name radio button specific + //@{ + CCtrlBaseButton *_RBRefBut; // The reference button. If NULL the control do not own the reference + // There is only one radio button per group that own the reference (the first one) + CCtrlBaseButton **_RBRef; // The pointer onto the reference button + //@} + + + // Colors + NLMISC::CRGBA _ColorNormal; + NLMISC::CRGBA _ColorPushed; + NLMISC::CRGBA _ColorOver; + + ///\name Long click specific + //@{ + sint64 _LeftLongClickDate; // Time we left click down + //@} + + // for double click : last date at which last left click occurred + static sint64 _LastLeftClickDate; + static NLMISC::CRefPtr _LastLeftClickButton; + + ///\name Action Handler + //@{ + IActionHandler *_AHOnOver; + CStringShared _AHOverParams; + std::string _AHOnLeftClickString; + std::string _AHOnLeftClickStringParams; + IActionHandler *_AHOnLeftClick; + CStringShared _AHLeftClickParams; + IActionHandler *_AHOnLeftDblClick; + CStringShared _AHLeftDblClickParams; + IActionHandler *_AHOnRightClick; + CStringShared _AHRightClickParams; + IActionHandler *_AHOnClockTick; + CStringShared _AHClockTickParams; + IActionHandler *_AHOnLeftLongClick; + CStringShared _AHLeftLongClickParams; + //@} + CStringShared _ListMenuLeft; + CStringShared _ListMenuRight; + + // get the colors modulated on request + NLMISC::CRGBA getCurrentColorNormal(NLMISC::CRGBA globalColor) const + { + NLMISC::CRGBA rgba = _ColorNormal; + if(_ModulateGlobalColorNormal) + rgba.modulateFromColor(rgba, globalColor); + return rgba; + } + NLMISC::CRGBA getCurrentColorPushed(NLMISC::CRGBA globalColor) const + { + NLMISC::CRGBA rgba = _ColorPushed; + if(_ModulateGlobalColorPushed) + rgba.modulateFromColor(rgba, globalColor); + return rgba; + } + NLMISC::CRGBA getCurrentColorOver(NLMISC::CRGBA globalColor) const + { + NLMISC::CRGBA rgba = _ColorOver; + if(_ModulateGlobalColorOver) + rgba.modulateFromColor(rgba, globalColor); + return rgba; + } + + // call it at draw + void updateOver(bool &lastOver); + virtual void elementCaptured(CCtrlBase *capturedElement); + }; + +} + +#endif // NL_CTRL_BASE_BUTTON_H + +/* End of ctrl_base_button.h */ diff --git a/code/nel/include/nel/gui/ctrl_button.h b/code/nel/include/nel/gui/ctrl_button.h new file mode 100644 index 000000000..02b827329 --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_button.h @@ -0,0 +1,109 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef RZ_CTRL_BUTTON_H +#define RZ_CTRL_BUTTON_H + +#include "nel/gui/ctrl_base_button.h" +#include "nel/gui/view_renderer.h" + +namespace NLGUI +{ + class CEventDescriptor; + + /** + * + * \author Nicolas Brigand + * \author Nevrax France + * \date 2002 + */ + class CCtrlButton : public CCtrlBaseButton + { + public: + DECLARE_UI_CLASS( CCtrlButton ) + + /// Constructor + CCtrlButton(const TCtorParam ¶m) : CCtrlBaseButton(param) + { + _Scale = false; + _Align = 0; + } + + void setAlignFromString( const std::string &s ); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + // Init part + virtual bool parse (xmlNodePtr cur,CInterfaceGroup * parentGroup); + + virtual void updateCoords(); + + virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } + + virtual bool getMouseOverShape(std::string &/* texName */, uint8 &/* rot */, NLMISC::CRGBA &/* col */); + + // Display part + virtual void draw(); + + void setTexture (const std::string&name); + void setTexturePushed (const std::string&name); + void setTextureOver (const std::string&name); + + void fitTexture(); + + std::string getTexture () const; + std::string getTexturePushed () const; + std::string getTextureOver() const; + + bool isTextureValid() const { return _TextureIdNormal != -1; } + + // test if the texture must scale + bool getScale() const { return _Scale; } + void setScale(bool scale) { _Scale = scale; } + + + /// \from CInterfaceElement + sint32 getMaxUsedW() const; + sint32 getMinUsedW() const; + + REFLECT_EXPORT_START(CCtrlButton, CCtrlBaseButton) + REFLECT_STRING("texture", getTexture, setTexture); + REFLECT_STRING("texture_pushed", getTexturePushed, setTexturePushed); + REFLECT_STRING("texture_over", getTextureOver, setTextureOver); + REFLECT_BOOL("scale", getScale, setScale); + REFLECT_EXPORT_END + + protected: + + CViewRenderer::CTextureId _TextureIdNormal; + CViewRenderer::CTextureId _TextureIdPushed; + CViewRenderer::CTextureId _TextureIdOver; + + private: + + bool _Scale; + sint32 _Align; /// 1st bit - Left/Right (0/1) 2nd bit - Bottom/Top (0/1) + }; + +} + +#endif // RZ_CTRL_BUTTON_H + +/* End of ctrl_button.h */ diff --git a/code/nel/include/nel/gui/ctrl_col_pick.h b/code/nel/include/nel/gui/ctrl_col_pick.h new file mode 100644 index 000000000..dd779e837 --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_col_pick.h @@ -0,0 +1,111 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef RZ_CTRL_COL_PICK_H +#define RZ_CTRL_COL_PICK_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/ctrl_base.h" + + +namespace NLGUI +{ + + /** + * Class handling a Color Picker + * \author Matthieu 'TrapII' Besson + * \author Nevrax France + * \date 2003 + */ + class CCtrlColPick : public CCtrlBase + { + + public: + DECLARE_UI_CLASS( CCtrlColPick ) + + CCtrlColPick(const TCtorParam ¶m); + ~CCtrlColPick(); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + virtual bool parse(xmlNodePtr cur, CInterfaceGroup * parentGroup); + + virtual void updateCoords(); + virtual void draw(); + virtual bool handleEvent (const NLGUI::CEventDescriptor &event); + + sint32 getColorR () const { return _ColorSelect.R; } + sint32 getColorG () const { return _ColorSelect.G; } + sint32 getColorB () const { return _ColorSelect.B; } + sint32 getColorA () const { return _ColorSelect.A; } + + void setColorR (sint32 r) { _ColorSelect.R = (uint8)r; } + void setColorG (sint32 g) { _ColorSelect.G = (uint8)g; } + void setColorB (sint32 b) { _ColorSelect.B = (uint8)b; } + void setColorA (sint32 a) { _ColorSelect.A = (uint8)a; } + + + std::string getColor () const; // Get Color Selected + void setColor (const std::string &col); // Set Color Selected + + std::string getColorOver () const; // Get Color Over + void setColorOver (const std::string &col); // Set Color Over + + REFLECT_EXPORT_START(CCtrlColPick, CCtrlBase) + REFLECT_SINT32("r", getColorR, setColorR); + REFLECT_SINT32("g", getColorG, setColorG); + REFLECT_SINT32("b", getColorB, setColorB); + REFLECT_SINT32("a", getColorA, setColorA); + REFLECT_STRING("color", getColor, setColor); + REFLECT_STRING("color_over", getColorOver, setColorOver); + REFLECT_EXPORT_END + + + protected: + + void selectColor (sint32 x, sint32 y); + NLMISC::CRGBA getColor (sint32 x, sint32 y); + + protected: + + bool _MouseDown; + + sint32 _Texture; + + NLMISC::CRGBA _ColorSelect; // Last Color selected + NLMISC::CRGBA _ColorOver; // Color Under Mouse Pointer + + std::string _AHOnChange; + std::string _AHOnChangeParams; + + CInterfaceProperty _ColSelR; + CInterfaceProperty _ColSelG; + CInterfaceProperty _ColSelB; + CInterfaceProperty _ColSelA; + }; + +} + + +#endif // RZ_CTRL_COL_PICK_H + +/* End of ctrl_col_pick.h */ + + diff --git a/code/nel/include/nel/gui/ctrl_draggable.h b/code/nel/include/nel/gui/ctrl_draggable.h new file mode 100644 index 000000000..3f625db1d --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_draggable.h @@ -0,0 +1,64 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef CTRL_DRAGGABLE_H +#define CTRL_DRAGGABLE_H + +#include "nel/gui/ctrl_base.h" + +namespace NLGUI +{ + + class CCtrlDraggable : public CCtrlBase + { + public: + DECLARE_UI_CLASS( CCtrlDraggable ) + + CCtrlDraggable( const TCtorParam ¶m ); + virtual ~CCtrlDraggable(){}; + + static CCtrlDraggable *getDraggedSheet(){ return _LastDraggedSheet; } + bool isDragged() const{ return dragged; } + void setDragged( bool dragged ){ this->dragged = dragged; } + bool isDraggable() const{ return draggable; } + void setDraggable( bool draggable ){ this->draggable = draggable; } + + void abortDragging() + { + dragged = false; + _LastDraggedSheet = NULL; + } + + // Necessary because of reflection, no other purpose + void draw(){} + + REFLECT_EXPORT_START(CCtrlDraggable, CCtrlBase) + REFLECT_BOOL("dragable", isDraggable, setDraggable); + REFLECT_EXPORT_END + + protected: + static void setDraggedSheet( CCtrlDraggable *draggable ){ _LastDraggedSheet = draggable; } + + private: + static CCtrlDraggable *_LastDraggedSheet; + bool dragged; + bool draggable; + }; + +} + +#endif diff --git a/code/nel/include/nel/gui/ctrl_polygon.h b/code/nel/include/nel/gui/ctrl_polygon.h new file mode 100644 index 000000000..cef57dd3c --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_polygon.h @@ -0,0 +1,95 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef RZ_CTRL_POLYGON_H +#define RZ_CTRL_POLYGON_H + +#include "nel/gui/ctrl_base.h" +#include "nel/gui/view_renderer.h" +#include "nel/misc/geom_ext.h" +#include "nel/misc/polygon.h" + +namespace NLMISC +{ + class CVector2f; +} + +namespace NLGUI +{ + + /** Display of an arbitrary polygon in the ui. + * polygons are clipped & batched. + * + * Derives from CCtrlBase in order to provide button / tooltip capability + * + * \author Nicolas Vizerie + * \author Nevrax France + * \date 1/2006 + */ + class CCtrlPolygon : public CCtrlBase + { + public: + DECLARE_UI_CLASS( CCtrlPolygon ) + CCtrlPolygon( const TCtorParam ¶m ); + virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } + virtual void updateCoords(); + virtual void draw(); + /** Change the vertices. This is costly because concav / complex polys are split in a list of triangles + */ + void setVertices(const std::vector &vertices); + const std::vector &getVertices() const { return _Poly.Vertices; } + // test if current position in inside the current (transformed) poly (in window space) + bool contains(const NLMISC::CVector2f &pos) const; + // color + void setColorRGBA(NLMISC::CRGBA col) { _Color = col; } + NLMISC::CRGBA getColorRGBA() const { return _Color; } + // from CViewBase + virtual sint32 getAlpha() const { return (sint32) _Color.A; } + virtual void setAlpha(sint32 a); + /** Change the matrix for this poly. Changing the matrix is usually cheaper than changing + * The vertices because complex poly do not have to be split again + */ + //void setMatrix(const NLMISC::CMatrix &mat); + //const NLMISC::CMatrix &getMatrix() const { return _Matrix; } + // test if last call to 'setVertices' was for a valid poly (e.g one that doesn't overlapp itself) + bool isValid() const { return _Valid; } + virtual bool handleEvent (const NLGUI::CEventDescriptor &event); + + // no capturable by default (just tooltip capability wanted) + virtual bool isCapturable() const { return false; } + private: + NLMISC::CPolygon _Poly; + NLMISC::CPolygon2D _XFormPoly; + //NLMISC::CMatrix _Matrix; + bool _Valid; + bool _Touched; + NLMISC::CRGBA _Color; + std::vector _Tris; + std::vector _RealTris; // clipped tris in screen coordinates + private: + void updateBoudingRect(); + protected: + // TMP TMP : have to solve matrix imprecision for display in map -> do the full computation for now ... + virtual void computeScaledVertex(NLMISC::CVector2f &dest, const NLMISC::CVector2f &src); + public: + void touch(); + }; + +} + + +#endif diff --git a/code/nel/include/nel/gui/ctrl_quad.h b/code/nel/include/nel/gui/ctrl_quad.h new file mode 100644 index 000000000..08c89675e --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_quad.h @@ -0,0 +1,118 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef RZ_CTRL_QUAD_H +#define RZ_CTRL_QUAD_H + +#include "nel/gui/ctrl_base.h" +#include "nel/gui/view_renderer.h" +#include "nel/misc/geom_ext.h" + +namespace NLGUI +{ + + /** Display of an arbitrary textured quad in the UI. The applied texture is filtered. + * Unlike CViewBitmap, the texture is always scaled here, and this ui element coordinates + * are driven by the quad vertices coordinates (see setQuad). + * + * Derives from CCtrlBase for tooltipping support + * + * \author Nicolas Vizerie + * \author Nevrax France + * \date 12/2005 + */ + class CCtrlQuad : public CCtrlBase + { + public: + DECLARE_UI_CLASS( CCtrlQuad ) + + enum TWrapMode { Repeat = 0, Clamp, CustomUVs, WrapModeCount }; + + + CCtrlQuad( const TCtorParam ¶m ); + + // from CInterfaceElement + bool parse(xmlNodePtr cur,CInterfaceGroup *parentGroup); + virtual void updateCoords(); + virtual void draw(); + virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } + + // from CViewBase + virtual sint32 getAlpha() const { return (sint32) _Color.A; } + virtual void setAlpha (sint32 a); + + // texture + void setTexture(const std::string &texName); + std::string getTexture () const; + + // color + void setColorRGBA(NLMISC::CRGBA col) { _Color = col; } + NLMISC::CRGBA getColorRGBA() const { return _Color; } + + /** Set a new quad relative to parent pos + * x,y, w, h & hotspot are updated to fit the bounding rect of the quad + */ + void setQuad(const NLMISC::CQuad &quad); + void setQuad(const NLMISC::CVector &start, const NLMISC::CVector &end, float thickness); + /** Fit the given texture size (no hotspot for now, always centered) + * NB : current texture is not modified. + */ + void setQuad(const std::string &texName, const NLMISC::CVector &pos, float angle = 0.f, float offCenter = 0.f); + void setQuad(const NLMISC::CVector &pos, float radius, float angle = 0.f); + const NLMISC::CQuad &getQuad() const { return _Quad; } + + void setAdditif(bool additif); + bool getAdditif() const { return _Additif; } + + void setFiltered(bool filtered); + bool getFiltered() const { return _Filtered; } + + void setPattern(float umin, float umax, TWrapMode wrapMode); + + /** Set uvs for each corners -> this will change the wrap mode to CustomUVs + * Use setPattern(0.f, 0.f, CCtrlQuad::Repeat) to return to previous behavior + */ + void setCustomUVs(const NLMISC::CUV uvs[4]); + + + // from CCtrlBase, no op by default + virtual bool handleEvent (const NLGUI::CEventDescriptor &event); + + // see if this control contains the given point (in parent coords) + bool contains(const NLMISC::CVector2f &pos) const; + + // no capturable by default (just tooltip capability wanted) + virtual bool isCapturable() const { return false; } + + + private: + NLMISC::CRGBA _Color; + NLMISC::CQuad _Quad; + NLMISC::CQuadUV _RealQuad; // absolute coords + float _ClampedUCorrection; + CViewRenderer::CTextureId _TextureId; /// Accelerator + bool _Additif; + bool _Filtered; + float _UMin; + float _UMax; + TWrapMode _WrapMode; + NLMISC::CUV _CustomUVs[4]; + }; + +} + +#endif diff --git a/code/nel/include/nel/gui/ctrl_scroll.h b/code/nel/include/nel/gui/ctrl_scroll.h new file mode 100644 index 000000000..b01a3bf81 --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_scroll.h @@ -0,0 +1,206 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef RZ_CTRL_SCROLL_H +#define RZ_CTRL_SCROLL_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/ctrl_scroll_base.h" + + +namespace NLGUI +{ + + /** + * Class handling scollbar function + * \author Matthieu 'TrapII' Besson + * \author Nevrax France + * \date 2002 + */ + class CCtrlScroll : public CCtrlScrollBase, public NLMISC::ICDBNode::IPropertyObserver + { + + public: + DECLARE_UI_CLASS( CCtrlScroll ) + CCtrlScroll(const TCtorParam ¶m); + ~CCtrlScroll(); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + virtual bool parse(xmlNodePtr cur, CInterfaceGroup * parentGroup); + + virtual void updateCoords(); + virtual void draw(); + virtual bool handleEvent (const NLGUI::CEventDescriptor &event); + + void setTarget (CInterfaceGroup *pIG); + // Return the delta value the track has moved + sint32 moveTrackX (sint32 dx); + sint32 moveTrackY (sint32 dy); + + /** Move the Target Ofs with a Delta, and recompute TrackPos from this Ofs. + * Useful for finer controled group scrolling when the list is very big (with mouseWheel or scroll buttons) + */ + void moveTargetX (sint32 dx); + void moveTargetY (sint32 dy); + + void setAlign (sint32 nAlign) { _Aligned = nAlign; } + // invert the factor for target + void setInverted(bool invert) { _Inverted = invert; } + + void setTextureBottomOrLeft (const std::string &txName); + void setTextureMiddle (const std::string &txName); + void setTextureTopOrRight (const std::string &txName); + std::string getTextureBottomOrLeft() const; + std::string getTextureMiddle() const; + std::string getTextureTopOrRight() const; + + void setTextureBottomOrLeft (sint32 txid) { _TxIdB = txid; } + void setTextureMiddle (sint32 txid) { _TxIdM = txid; } + void setTextureMiddleTile (uint8 tile) { _TileM = tile; } // 0 - not tiled (1 BL) (2 BR) (3 TL) (4 TR) + void setTextureTopOrRight (sint32 txid) { _TxIdT = txid; } + + // number scroller + sint32 getValue() const { return _IsDBLink ? _DBLink.getSInt32() : _Value; } + // NB: the value is clamped (see setMinMax) and stepped (see setStepValue()) + void setValue(sint32 value); + void setMinMax(sint32 nMin, sint32 nMax) { _Min = nMin; _Max = nMax; } + void setStepValue(uint32 step) { _StepValue= step; } + + void setTrackPos(sint32 pos); + sint32 getTrackPos() const { return _TrackPos; } + sint32 getTrackSize() const { return _TrackSize; } + // dummy set for track size (forlua export) + void setTrackSize(sint32 /* trackSize */) { throw NLMISC::Exception("TrackSize is read-only"); } + + + void setFrozen (bool state); + bool getFrozen () const { return _Frozen; } + + int luaSetTarget(CLuaState &ls); + int luaEnsureVisible(CLuaState &ls); + + // name + void setName(const std::string & val) {_Name = val;} + std::string getName() const {return _Name;} + + // max + void setMax(sint32 max) {_Max = max;} + sint32 getMax() const {return _Max;} + + REFLECT_EXPORT_START(CCtrlScroll, CCtrlScrollBase) + REFLECT_LUA_METHOD("setTarget", luaSetTarget) + REFLECT_LUA_METHOD("ensureVisible", luaEnsureVisible); + REFLECT_SINT32("value", getValue, setValue); + REFLECT_SINT32("trackPos", getTrackPos, setTrackPos); + REFLECT_SINT32("trackSize", getTrackSize, setTrackSize); + REFLECT_STRING("name", getName, setName); + REFLECT_SINT32("max", getMax, setMax); + REFLECT_EXPORT_END + + /** Ensure that a child element be visible into the frame through which + * its parent group is displayed. + * Example : Had we a list of items for which we want some item 'itemPtr' to have its top position + * matching the middle of the list, we would do : + * this->ensureVisible(itemPtr, Hotspot_Tx, Hotspot_Mx); + * + * The scrollbar will be moved accordingly. + */ + void ensureVisible(CInterfaceElement *childElement, THotSpot childHotSpot, THotSpot parentHotSpot); + + + protected: + + CInterfaceProperty _DBLink; // If this is a value scroller we can link it with db + sint32 _Value; // Or we can use a normal value + sint32 _InitialValue; + + sint32 _Min, _Max; + std::string _AHOnScroll; + std::string _AHOnScrollParams; + // + std::string _AHOnScrollEnd; + std::string _AHOnScrollEndParams; + // + // + std::string _AHOnScrollCancel; + std::string _AHOnScrollCancelParams; + + + sint32 _Aligned; // 0-Top 1-Bottom 2-Left 3-Right + + sint32 _TrackDispPos; + sint32 _TrackPos; + sint32 _TrackSize; + sint32 _TrackSizeMin; + + sint32 _MouseDownOffsetX; + sint32 _MouseDownOffsetY; + + sint32 _TxIdB; // Same as Left if Horizontal sb + sint32 _TxIdM; + sint32 _TxIdT; // Same as Right if Horizontal sb + + uint8 _TileM; + + sint32 _LastTargetHReal; + sint32 _LastTargetMaxHReal; + sint32 _LastTargetOfsY; + sint32 _LastTargetWReal; + sint32 _LastTargetMaxWReal; + sint32 _LastTargetOfsX; + + bool _Vertical : 1; // true if vertical track bar + bool _IsDBLink : 1; + bool _ObserverOn : 1; + bool _Inverted : 1; + bool _MouseDown : 1; + bool _CallingAH : 1; + bool _Cancelable : 1; // true if the slider may be cancelled when pressed on the mouse right button + bool _Frozen : 1; + + // For Target Scroller only: the target offset step in pixel. + sint32 _TargetStepX; + sint32 _TargetStepY; + + // For Value Scroller only: indicate the step the scroll bar has. 0 or 1 means no step + uint32 _StepValue; + + // Slider's name + std::string _Name; + + void computeTargetOfsFromPos(); + + // from IPropertyObserver + virtual void update(NLMISC::ICDBNode *node); + + // step the value, and clamp it + void normalizeValue(sint32 &value); + + void runAH(const std::string &name, const std::string ¶ms); + + }; +} + +#endif // RZ_CTRL_SCROLL_H + +/* End of ctrl_scroll.h */ + + diff --git a/code/nel/include/nel/gui/ctrl_scroll_base.h b/code/nel/include/nel/gui/ctrl_scroll_base.h new file mode 100644 index 000000000..38cfd9c09 --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_scroll_base.h @@ -0,0 +1,60 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CTRL_SCROLL_BASE_H +#define CTRL_SCROLL_BASE_H + +#include "nel/gui/ctrl_base.h" + +namespace NLGUI +{ + + class CInterfaceGroup; + + class CCtrlScrollBase : public CCtrlBase + { + public: + DECLARE_UI_CLASS( CCtrlScrollBase ) + + CCtrlScrollBase( const TCtorParam ¶m ); + virtual ~CCtrlScrollBase(); + + virtual void setTarget( CInterfaceGroup *pIG ); + CInterfaceGroup* getTarget(){ return _Target; } + virtual sint32 moveTrackX( sint32 dx ); + virtual sint32 moveTrackY( sint32 dy ); + + /** Move the Target Ofs with a Delta, and recompute TrackPos from this Ofs. + * Useful for finer controled group scrolling when the list is very big (with mouseWheel or scroll buttons) + */ + virtual void moveTargetX( sint32 dx ); + virtual void moveTargetY( sint32 dy ); + + + // Necessary because of reflection, no other purpose + void draw(){} + + protected: + CInterfaceGroup *_Target; // If NULL the scroller is a value scroller + + private: + + }; + +} + +#endif + diff --git a/code/nel/include/nel/gui/ctrl_sheet_selection.h b/code/nel/include/nel/gui/ctrl_sheet_selection.h new file mode 100644 index 000000000..36d1c8336 --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_sheet_selection.h @@ -0,0 +1,83 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef CL_SHEET_CTRL_SELECTION_H +#define CL_SHEET_CTRL_SELECTION_H + +namespace NLGUI +{ + class IActionHandler; + + /** Infos about a selection group + */ + class CSheetSelectionGroup + { + public: + CSheetSelectionGroup(std::string name) : _Name(name), _Active(false), _TextureIndex(-1), _Color(NLMISC::CRGBA::White), _GlobalColorEnabled(true) {} + void setTexture(const std::string &texName); + sint32 getTextureIndex() const { return _TextureIndex; } + sint32 getTextureWidth() const { return _TextureWidth; } + sint32 getTextureHeight() const { return _TextureHeight; } + void setColor(NLMISC::CRGBA color) { _Color = color; } + NLMISC::CRGBA getColor() const { return _Color; } + void setActive(bool active) { _Active = active; } + bool isActive() const { return _Active; } + const std::string &getName() const { return _Name; } + void enableGlobalColor(bool enabled) { _GlobalColorEnabled = enabled; } + bool isGlobalColorEnabled() const { return _GlobalColorEnabled; } + private: + std::string _Name; + bool _Active; + sint32 _TextureIndex; // index for the selection texture + sint32 _TextureWidth; + sint32 _TextureHeight; + NLMISC::CRGBA _Color; // color that modulate the texture of selection + bool _GlobalColorEnabled; + }; + + /** Class to manage selection of sheet. + * Sheet are managed by groups, identified by their ID. + */ + class CCtrlSheetSelection + { + public: + // Add a group, and returns its index, or -1 if already created. + sint addGroup(const std::string &name); + // Get a group by its name (must exist) + CSheetSelectionGroup *getGroup(const std::string &name); + const CSheetSelectionGroup *getGroup(const std::string &name) const; + // Get a group by its index + CSheetSelectionGroup *getGroup(uint index); + const CSheetSelectionGroup *getGroup(uint index) const; + // Get the index of a group from its name, return -1 if not a group + sint getGroupIndex(const std::string &name) const; + // Deactivate all groups + void deactivateAll(); + // delete all groups + void deleteGroups(); + private: + // + typedef std::vector TGroupVect; + typedef std::map TGroupNameToIndex; + private: + TGroupVect _Groups; + TGroupNameToIndex _GroupNameToIndex; + }; + +} + +#endif diff --git a/code/nel/include/nel/gui/ctrl_text_button.h b/code/nel/include/nel/gui/ctrl_text_button.h new file mode 100644 index 000000000..2df1dee5d --- /dev/null +++ b/code/nel/include/nel/gui/ctrl_text_button.h @@ -0,0 +1,171 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_CTRL_TEXT_BUTTON_H +#define NL_CTRL_TEXT_BUTTON_H + +#include "nel/gui/ctrl_base_button.h" +#include "nel/gui/view_renderer.h" + + +namespace NLGUI +{ + class CEventDescriptor; + class CViewText; + + // *************************************************************************** + /** + * Text Button that can be either Push or Toggle button. Localized, auto-resize + * \author Lionel Berenguier + * \author Nevrax France + * \date 2002 + */ + class CCtrlTextButton : public CCtrlBaseButton + { + public: + DECLARE_UI_CLASS( CCtrlTextButton ) + + /// Constructor + CCtrlTextButton(const TCtorParam ¶m); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + // Init part + virtual bool parse (xmlNodePtr cur,CInterfaceGroup * parentGroup); + + virtual void updateCoords(); + + virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } + + // Display part + virtual void draw(); + + // Hide/Show the text also. + virtual void setActive(bool state); + + // Add also our ViewText + virtual void onAddToGroup(); + + + /// \from CInterfaceElement + sint32 getMaxUsedW() const; + sint32 getMinUsedW() const; + + // Special Text Colors accessors + // Colors + NLMISC::CRGBA getTextColorNormal() const {return _TextColorNormal;} + void setTextColorNormal(NLMISC::CRGBA v) {_TextColorNormal= v;} + NLMISC::CRGBA getTextColorPushed() const {return _TextColorPushed;} + void setTextColorPushed(NLMISC::CRGBA v) {_TextColorPushed= v;} + NLMISC::CRGBA getTextColorOver() const {return _TextColorOver;} + void setTextColorOver(NLMISC::CRGBA v) {_TextColorOver= v;} + // Shadow Colors + NLMISC::CRGBA getTextShadowColorNormal() const {return _TextShadowColorNormal;} + void setTextShadowColorNormal(NLMISC::CRGBA v) {_TextShadowColorNormal= v;} + NLMISC::CRGBA getTextShadowColorPushed() const {return _TextShadowColorPushed;} + void setTextShadowColorPushed(NLMISC::CRGBA v) {_TextShadowColorPushed= v;} + NLMISC::CRGBA getTextShadowColorOver() const {return _TextShadowColorOver;} + void setTextShadowColorOver(NLMISC::CRGBA v) {_TextShadowColorOver= v;} + // Global Modulate Colors + bool getTextModulateGlobalColorNormal() const {return _TextModulateGlobalColorNormal;} + void setTextModulateGlobalColorNormal(bool v) {_TextModulateGlobalColorNormal= v;} + bool getTextModulateGlobalColorPushed() const {return _TextModulateGlobalColorPushed;} + void setTextModulateGlobalColorPushed(bool v) {_TextModulateGlobalColorPushed= v;} + bool getTextModulateGlobalColorOver() const {return _TextModulateGlobalColorOver;} + void setTextModulateGlobalColorOver(bool v) {_TextModulateGlobalColorOver= v;} + // Set text (noop if text id) + void setText (const ucstring &text); + ucstring getText () const; + + void setHardText (const std::string &text); + std::string getHardText () const; + + CViewText* getViewText(); + void setViewText(CViewText* text) {_ViewText=text;} + + void setTextX(sint32 x); + sint32 getTextX() const { return _TextX; } + + void setWMargin(sint32 w) { _WMargin = w; } + sint32 getWMargin() const { return _WMargin; } + + sint32 getWMin() const { return _WMin; } + void setWMin( sint32 wmin ) { _WMin = wmin; } + + // Compute Size according to bitmap and Text (Ensure as big as possible button) + sint32 getWMax() const; + + int luaGetViewText(CLuaState &ls); + + REFLECT_EXPORT_START(CCtrlTextButton, CCtrlBaseButton) + REFLECT_UCSTRING("uc_hardtext", getText, setText); + REFLECT_STRING("hardtext", getHardText, setHardText); + REFLECT_SINT32("text_x", getTextX, setTextX) + REFLECT_SINT32("wmargin", getWMargin, setWMargin) + REFLECT_SINT32("wmin", getWMin, setWMin) + REFLECT_LUA_METHOD("getViewText", luaGetViewText) + REFLECT_EXPORT_END + + protected: + + enum {NumTexture= 3}; + + CViewRenderer::CTextureId _TextureIdNormal[NumTexture]; + CViewRenderer::CTextureId _TextureIdPushed[NumTexture]; + CViewRenderer::CTextureId _TextureIdOver[NumTexture]; + + // setup + void setup(); + + private: + + CViewText *_ViewText; + + bool _Setuped; + bool _IsViewTextId; + bool _ForceTextOver; // text is displayed over the "over" texture + // Size of Bitmaps + sint32 _BmpLeftW, _BmpMiddleW, _BmpRightW, _BmpH; + // Value to add to TextW to get button W. + sint32 _WMargin; + // Min W Value + sint32 _WMin; + sint32 _TextY; + sint32 _TextX; + THotSpot _TextPosRef; + THotSpot _TextParentPosRef; + // Special Colors for text + NLMISC::CRGBA _TextColorNormal; + NLMISC::CRGBA _TextColorPushed; + NLMISC::CRGBA _TextColorOver; + NLMISC::CRGBA _TextShadowColorNormal; + NLMISC::CRGBA _TextShadowColorPushed; + NLMISC::CRGBA _TextShadowColorOver; + bool _TextModulateGlobalColorNormal; + bool _TextModulateGlobalColorPushed; + bool _TextModulateGlobalColorOver; + bool _TextHeaderColor; + }; + +} + +#endif // NL_CTRL_TEXT_BUTTON_H + +/* End of ctrl_text_button.h */ diff --git a/code/ryzom/client/src/interface_v3/ctrl_tooltip.h b/code/nel/include/nel/gui/ctrl_tooltip.h similarity index 56% rename from code/ryzom/client/src/interface_v3/ctrl_tooltip.h rename to code/nel/include/nel/gui/ctrl_tooltip.h index da5e17468..a96bbad40 100644 --- a/code/ryzom/client/src/interface_v3/ctrl_tooltip.h +++ b/code/nel/include/nel/gui/ctrl_tooltip.h @@ -19,35 +19,41 @@ #ifndef RZ_CTRL_TOOLTIP_H #define RZ_CTRL_TOOLTIP_H -#include "ctrl_base.h" +#include "nel/gui/ctrl_base.h" #include "nel/3d/u_texture.h" -class CEventDescriptor; -class CInterfaceManager; - -/** - * \author Matthieu 'Mr TRAP' Besson - * \author Nevrax France - * \date 2003 - */ -class CCtrlToolTip : public CCtrlBase +namespace NLGUI { -public: - DECLARE_UI_CLASS(CCtrlToolTip) - /// Constructor - CCtrlToolTip(const TCtorParam ¶m) : CCtrlBase(param) {} + class CEventDescriptor; + + + /** + * \author Matthieu 'Mr TRAP' Besson + * \author Nevrax France + * \date 2003 + */ + class CCtrlToolTip : public CCtrlBase + { + public: + DECLARE_UI_CLASS(CCtrlToolTip) + /// Constructor + CCtrlToolTip(const TCtorParam ¶m) : CCtrlBase(param) {} - virtual bool handleEvent (const CEventDescriptor& eventDesc); - virtual void draw(); - virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup); - // Can do nothing with tooltip (but display it :) ) - virtual bool isCapturable() const {return false;} - virtual void serial(NLMISC::IStream &f); -public: + virtual bool handleEvent (const NLGUI::CEventDescriptor& eventDesc); + virtual void draw(); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup); + // Can do nothing with tooltip (but display it :) ) + virtual bool isCapturable() const {return false;} + virtual void serial(NLMISC::IStream &f); + public: -}; + }; +} + #endif // RZ_CTRL_TOOLTIP_H /* End of ctrl_tooltip.h */ + diff --git a/code/nel/include/nel/gui/db_manager.h b/code/nel/include/nel/gui/db_manager.h new file mode 100644 index 000000000..d5036204d --- /dev/null +++ b/code/nel/include/nel/gui/db_manager.h @@ -0,0 +1,71 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef DBMANAGER_H +#define DBMANAGER_H + +#include "nel/misc/cdb_manager.h" + +namespace NLGUI +{ + + /** + Database Manager + + Provides access to a simple CDB based tree hierarchical data store + */ + class CDBManager : public NLMISC::CCDBManager + { + public: + static CDBManager* getInstance(); + static void release(); + + /** + Retrieves a leaf node from the database. + @param name - name of the data leaf node we are querying. + @param create - when true if a node cannot be found it is created. + */ + NLMISC::CCDBNodeLeaf* getDbProp( const std::string &name, bool create = true ); + + /** + Deletes a node from the database. + @param name - name of the node. + */ + void delDbProp( const std::string &name ); + + /** + Returns a leaf node's content as an sint32 + @param name - name of the leaf node. + */ + sint32 getDbValue32( const std::string &name ); + + /** + Returns the root branch of the database. + */ + NLMISC::CCDBNodeBranch* getDB() const; + + private: + CDBManager(); + ~CDBManager(); + + static CDBManager *instance; + + }; + +} + +#endif diff --git a/code/nel/include/nel/gui/dbgroup_combo_box.h b/code/nel/include/nel/gui/dbgroup_combo_box.h new file mode 100644 index 000000000..75208b1e3 --- /dev/null +++ b/code/nel/include/nel/gui/dbgroup_combo_box.h @@ -0,0 +1,170 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_DBGROUP_COMBO_BOX_H +#define NL_DBGROUP_COMBO_BOX_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/interface_group.h" + +namespace NLGUI +{ + class CCtrlBaseButton; + class CViewText; + class CGroupMenu; + + + // *************************************************************************** + /** + * Widget: ComboBox of text + * \author Lionel Berenguier + * \author Nevrax France + * \date 2002 + */ + class CDBGroupComboBox : public CInterfaceGroup + { + public: + DECLARE_UI_CLASS( CDBGroupComboBox ) + + /// Constructor + CDBGroupComboBox(const TCtorParam ¶m); + ~CDBGroupComboBox(); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + /// CInterfaceGroup Interface + virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup); + virtual void updateCoords (); + virtual void checkCoords (); + + // Combo Texts + void resetTexts(); + void addText(const ucstring &text); + void setText(uint i, const ucstring &text); + void insertText(uint i, const ucstring &text); + const ucstring &getText(uint i) const; + const uint &getTextId(uint i) const; + uint getTextPos(uint nId) const; + const ucstring &getTexture(uint i) const; + void removeText(uint nPos); + uint getNumTexts() const {return (uint)_Texts.size();} + void sortText(); + + // selection + void setSelection(sint32 val); + void setSelectionNoTrigger(sint32 val); + sint32 getSelection() const; + + // selection number + void setSelectionNb(sint32 /* val */){} + sint32 getSelectionNb() const {return (sint32)_Texts.size();} + + // selection text + void setSelectionText(const std::string & val); + std::string getSelectionText() const; + + // view text + void setViewText(const ucstring & text); + ucstring getViewText() const; + + void setTexture(uint i, const ucstring &texture); + + sint32 evalContentWidth() const; + + + int luaAddText(CLuaState &ls); + int luaRemoveSelection(CLuaState &ls); + int luaRemoveText(CLuaState &ls); + int luaRemoveTextByIndex(CLuaState &ls); + int luaResetTexts(CLuaState &ls); + int luaSetText(CLuaState &ls); + int luaInsertText(CLuaState &ls); + int luaGetText(CLuaState &ls); + int luaGetNumTexts(CLuaState &ls); + int luaSetTexture(CLuaState &ls); + + + REFLECT_EXPORT_START(CDBGroupComboBox, CInterfaceGroup) + REFLECT_SINT32("selection", getSelection, setSelection) + REFLECT_LUA_METHOD("addText", luaAddText) + REFLECT_LUA_METHOD("setText", luaSetText) + REFLECT_LUA_METHOD("insertText", luaInsertText) + REFLECT_LUA_METHOD("setTexture", luaSetTexture) + REFLECT_LUA_METHOD("getText", luaGetText) + REFLECT_LUA_METHOD("getNumTexts", luaGetNumTexts) + REFLECT_LUA_METHOD("removeSelection", luaRemoveSelection) + REFLECT_LUA_METHOD("removeText", luaRemoveText) + REFLECT_LUA_METHOD("removeTextByIndex", luaRemoveTextByIndex) + REFLECT_LUA_METHOD("resetTexts", luaResetTexts) + REFLECT_SINT32 ("selectionNb", getSelectionNb, setSelectionNb) + REFLECT_STRING ("selection_text", getSelectionText, setSelectionText) + REFLECT_UCSTRING ("view_text", getViewText, setViewText) + REFLECT_EXPORT_END + + + protected: + friend class CHandlerComboBoxSelectStart; + + bool _LinkedToDB; // if not linked to db, then _NotLinkedToDBSelection is used instead + bool _Setuped; + bool _DirtySelection; + sint32 _CacheSelection; + + // sint32 + CInterfaceProperty _Selection; + sint32 _NotLinkedToDBSelection; + std::vector > _Texts; + std::vector _Textures; + + // Action Handler called on combo click + std::string _AHOnSelectStart; + + // Action handler called when the content is changed + std::string _AHOnChange; + std::string _AHOnChangeParams; + bool _CallingOnChangeActionHandler; // avoid infinite loop here + + + // Children + CViewText *_ViewText; + CCtrlBaseButton *_SelectButton; + + bool _IsExternViewText; + ucstring _ExternViewText; + + + private: + void setup(); + void dirt(); + public: + // private : fill a menu with current content + void fillMenu(CGroupMenu *groupMenu) const; + + + static std::string measureMenu; + static std::string selectMenu; + static std::string selectMenuOut; + }; + +} + +#endif // NL_DBGROUP_COMBO_BOX_H + +/* End of dbgroup_combo_box.h */ diff --git a/code/nel/include/nel/gui/dbgroup_select_number.h b/code/nel/include/nel/gui/dbgroup_select_number.h new file mode 100644 index 000000000..a5ef692ff --- /dev/null +++ b/code/nel/include/nel/gui/dbgroup_select_number.h @@ -0,0 +1,101 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_DBGROUP_SELECT_NUMBER_H +#define NL_DBGROUP_SELECT_NUMBER_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/interface_group.h" + + +namespace NLGUI +{ + class CCtrlBaseButton; + class CViewText; + class CViewBitmap; + + // *************************************************************************** + /** + * Widget to select a number + * \author Lionel Berenguier + * \author Nevrax France + * \date 2002 + */ + class CDBGroupSelectNumber : public CInterfaceGroup + { + public: + DECLARE_UI_CLASS( CDBGroupSelectNumber ) + + /// Constructor + CDBGroupSelectNumber(const TCtorParam ¶m); + ~CDBGroupSelectNumber(); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + /// CInterfaceGroup Interface + virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup); + virtual void updateCoords (); + virtual void checkCoords(); + virtual void draw (); + virtual void clearViews (); + virtual bool handleEvent (const NLGUI::CEventDescriptor &eventDesc); + + // mod interface + void changeValue(sint delta); + + sint32 getMinValue () const { return _MinValue; } + void setMinValue (sint32 m) { _MinValue = m; } + sint32 getMaxValue () const { return _MaxValue; } + void setMaxValue (sint32 m) { _MaxValue = m; } + + sint32 getCurrentValue () const { return _Number.getSInt32(); } + void setCurrentValue (sint32 val) { _Number.setSInt32(val); } + + REFLECT_EXPORT_START(CDBGroupSelectNumber, CInterfaceGroup) + REFLECT_SINT32("min", getMinValue, setMinValue); + REFLECT_SINT32("max", getMaxValue, setMaxValue); + REFLECT_EXPORT_END + + protected: + + // sint32 + CInterfaceProperty _Number; + bool _LoopMode; + sint _MinValue; + sint _MaxValue; + sint _DeltaMultiplier; + + // Children + CViewBitmap *_SlotNumber; + CViewText *_TextNumber; + CCtrlBaseButton *_ButtonUp; + CCtrlBaseButton *_ButtonDown; + + private: + + void setup(); + + }; + +} + +#endif // NL_DBGROUP_SELECT_NUMBER_H + +/* End of dbgroup_select_number.h */ diff --git a/code/nel/include/nel/gui/dbview_bar.h b/code/nel/include/nel/gui/dbview_bar.h new file mode 100644 index 000000000..d4a3de340 --- /dev/null +++ b/code/nel/include/nel/gui/dbview_bar.h @@ -0,0 +1,116 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef RZ_DBVIEW_BAR_H +#define RZ_DBVIEW_BAR_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/view_bitmap.h" + +namespace NLGUI +{ + + /** + * class implementing a bitmap used as the front texture of a progress bar + * the bitmap is drawn from _X to _W * _Range/_RangeMax + * \author Nicolas Brigand + * \author Nevrax France + * \date 2002 + */ + class CDBViewBar : public CViewBitmap + { + public: + enum TViewBar { ViewBar_UltraMini, ViewBar_Mini, ViewBar_Normal, ViewBar_MiniThick }; + public: + DECLARE_UI_CLASS( CDBViewBar ) + + /// Constructor + CDBViewBar(const TCtorParam ¶m) + : CViewBitmap(param), + _Slot(TCtorParam()) + { + _Color= NLMISC::CRGBA::White; + _ValueInt= 0; + _RangeInt = 255; + _ReferenceInt= 0; + _Type = ViewBar_Normal; + } + + void setType (TViewBar vb); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + bool parse(xmlNodePtr cur,CInterfaceGroup * parentGroup); + virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } + virtual void updateCoords (); + virtual void draw (); + + /// Nbs: Values by Int are not used if the Links are setuped + void setValue (sint32 r) { _ValueInt = r; } + void setRange (sint32 r) { _RangeInt = r; } + void setReference (sint32 r) { _ReferenceInt = r; } + sint32 getValue () const { return _ValueInt; } + sint32 getRange () const { return _RangeInt; } + sint32 getReference () const { return _ReferenceInt; } + + void setValueDbLink (const std::string &r); + void setRangeDbLink (const std::string &r); + void setReferenceDbLink (const std::string &r); + std::string getValueDbLink () const; + std::string getRangeDbLink () const; + std::string getReferenceDbLink () const; + + // Reflect ValueInt (ie not used if the link is setuped) + REFLECT_EXPORT_START(CDBViewBar, CViewBitmap) + REFLECT_SINT32 ("value", getValue, setValue); + REFLECT_SINT32 ("range", getRange, setRange); + REFLECT_SINT32 ("reference", getReference, setReference); + REFLECT_STRING ("value_dblink", getValueDbLink, setValueDbLink); + REFLECT_STRING ("range_dblink", getRangeDbLink, setRangeDbLink); + REFLECT_STRING ("reference_dblink", getReferenceDbLink, setReferenceDbLink); + REFLECT_EXPORT_END + + protected: + + CViewBitmap _Slot; + TViewBar _Type; + sint32 _HBar; + NLMISC::CRGBA _ColorNegative; + + // Value of the progression in arbitrary units. should be integer + CInterfaceProperty _Value; + // Max range of the progression in arbitrary units. should be integer + CInterfaceProperty _Range; + // Reference of the progression (substracted from value and range). + CInterfaceProperty _Reference; + + /// Nbs: Values by Int are not used if the Links are setuped. NB: not overwritten by links + sint32 _ValueInt; + sint32 _RangeInt; + sint32 _ReferenceInt; + + void parseValProp(xmlNodePtr cur, CInterfaceProperty &dbProp, sint32 &intProp, const char *name); + sint64 getCurrentValProp(const CInterfaceProperty &dbProp, sint32 intProp); + }; + +} + +#endif // RZ_DBVIEW_BAR_H + +/* End of dbview_bar.h */ diff --git a/code/nel/include/nel/gui/dbview_bar3.h b/code/nel/include/nel/gui/dbview_bar3.h new file mode 100644 index 000000000..785cb165b --- /dev/null +++ b/code/nel/include/nel/gui/dbview_bar3.h @@ -0,0 +1,111 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef RZ_DBVIEW_BAR3_H +#define RZ_DBVIEW_BAR3_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/view_bitmap.h" + +namespace NLGUI +{ + + /** + * class implementing a 3 Bar widget + * \author Matthieu 'TrapII' Besson + * \author Nevrax France + * \date 2002 + */ + class CDBViewBar3 : public CViewBitmap + { + public: + DECLARE_UI_CLASS( CDBViewBar3 ) + + /// Constructor + CDBViewBar3(const TCtorParam ¶m); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + bool parse(xmlNodePtr cur,CInterfaceGroup * parentGroup); + virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } + virtual void updateCoords (); + + void setMini (bool mini); + + virtual void draw (); + + /// Nbs: Values by Int are not used if the Links are setuped + void setValue0 (sint32 r) { _ValueInt[0] = r; } + void setValue1 (sint32 r) { _ValueInt[1] = r; } + void setValue2 (sint32 r) { _ValueInt[2] = r; } + void setRange0 (sint32 r) { _RangeInt[0] = r; } + void setRange1 (sint32 r) { _RangeInt[1] = r; } + void setRange2 (sint32 r) { _RangeInt[2] = r; } + sint32 getValue0 () const { return _ValueInt[0]; } + sint32 getValue1 () const { return _ValueInt[1]; } + sint32 getValue2 () const { return _ValueInt[2]; } + sint32 getRange0 () const { return _RangeInt[0]; } + sint32 getRange1 () const { return _RangeInt[1]; } + sint32 getRange2 () const { return _RangeInt[2]; } + + // Reflect ValueInt (ie not used if the link is setuped) + REFLECT_EXPORT_START(CDBViewBar3, CViewBitmap) + REFLECT_SINT32 ("value1", getValue0, setValue0); + REFLECT_SINT32 ("value2", getValue1, setValue1); + REFLECT_SINT32 ("value3", getValue2, setValue2); + REFLECT_SINT32 ("range1", getRange0, setRange0); + REFLECT_SINT32 ("range2", getRange1, setRange1); + REFLECT_SINT32 ("range3", getRange2, setRange2); + REFLECT_EXPORT_END + + static void forceLink(); + + protected: + + CViewBitmap _Slot; + + // Value of the progression in arbitrary units. should be integer + CInterfaceProperty _Value[3]; + // Max range of the progression in arbitrary units. should be integer + CInterfaceProperty _Range[3]; + + /// Nbs: Values by Int are not used if the Links are setuped. NB: not overwritten by links + sint32 _ValueInt[3]; + sint32 _RangeInt[3]; + + + NLMISC::CRGBA _Colors[3]; + NLMISC::CRGBA _ColorsNegative[3]; + + bool _Mini; + + // Height of the bitmap + sint32 _BarH; + + void parseValProp(xmlNodePtr cur, CInterfaceProperty &dbProp, sint32 &intProp, const char *name); + void setValProp( const std::string &value, CInterfaceProperty &dbProp, sint32 &intProp ); + sint32 getCurrentValProp(const CInterfaceProperty &dbProp, sint32 intProp); + std::string getValProp( const CInterfaceProperty &prop, sint32 intProp ) const; + }; + +} + +#endif // RZ_DBVIEW_BAR3_H + +/* End of dbview_bar3.h */ diff --git a/code/nel/include/nel/gui/dbview_digit.h b/code/nel/include/nel/gui/dbview_digit.h new file mode 100644 index 000000000..33446b2de --- /dev/null +++ b/code/nel/include/nel/gui/dbview_digit.h @@ -0,0 +1,68 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef NL_DBVIEW_DIGIT_H +#define NL_DBVIEW_DIGIT_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/view_base.h" + +namespace NLGUI +{ + + // *************************************************************************** + /** + * A number displayed with special bitmaps + * \author Lionel Berenguier + * \author Nevrax France + * \date 2002 + */ + class CDBViewDigit : public CViewBase + { + public: + DECLARE_UI_CLASS( CDBViewDigit ) + + /// Constructor + CDBViewDigit(const TCtorParam ¶m); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + virtual bool parse (xmlNodePtr cur, CInterfaceGroup * parentGroup); + virtual void draw (); + virtual void updateCoords(); + + protected: + CInterfaceProperty _Number; + sint32 _Cache; + sint32 _NumDigit; + NLMISC::CRGBA _Color; + // space between each digit + sint32 _WSpace; + // The texture digit for the current number + sint32 _DigitId[10]; + uint _DivBase; + + + }; + +} + +#endif // NL_DBVIEW_DIGIT_H + +/* End of dbview_digit.h */ diff --git a/code/nel/include/nel/gui/dbview_number.h b/code/nel/include/nel/gui/dbview_number.h new file mode 100644 index 000000000..2c76a255d --- /dev/null +++ b/code/nel/include/nel/gui/dbview_number.h @@ -0,0 +1,78 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_DBVIEW_NUMBER_H +#define NL_DBVIEW_NUMBER_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/view_text.h" + +namespace NLGUI +{ + + // *************************************************************************** + /** + * Display a text from a database number + * \author Lionel Berenguier + * \author Nevrax France + * \date 2002 + */ + class CDBViewNumber : public CViewText + { + public: + DECLARE_UI_CLASS( CDBViewNumber ) + + /// Constructor + CDBViewNumber(const TCtorParam ¶m); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + virtual bool parse (xmlNodePtr cur, CInterfaceGroup * parentGroup); + virtual void checkCoords(); + virtual void draw (); + + void link (const std::string &dbprop) + { + _Number.link (dbprop.c_str()); + } + + static void forceLink(); + + protected: + + sint64 getVal() { if (_Modulo == 0) return (_Number.getSInt64() / _Divisor); + else return (_Number.getSInt64() / _Divisor)%_Modulo; } + + protected: + + CInterfaceProperty _Number; + sint64 _Cache; + bool _Positive; // only positive values are displayed + bool _Format; // the number will be formatted (like "1,000,000") if >= 10k + sint64 _Divisor, _Modulo; + // string to append to the value (eg: meters) + CStringShared _Suffix; + CStringShared _Prefix; + }; + +} + +#endif // NL_DBVIEW_NUMBER_H + +/* End of dbview_number.h */ diff --git a/code/nel/include/nel/gui/dbview_quantity.h b/code/nel/include/nel/gui/dbview_quantity.h new file mode 100644 index 000000000..67c4e57ba --- /dev/null +++ b/code/nel/include/nel/gui/dbview_quantity.h @@ -0,0 +1,66 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_DBVIEW_QUANTITY_H +#define NL_DBVIEW_QUANTITY_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/view_text.h" + +namespace NLGUI +{ + + // *************************************************************************** + /** + * Display a text in the form of val / max or "empty" + * \author Lionel Berenguier + * \author Nevrax France + * \date 2002 + */ + class CDBViewQuantity : public CViewText + { + public: + DECLARE_UI_CLASS( CDBViewQuantity ) + + /// Constructor + CDBViewQuantity(const TCtorParam ¶m); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + virtual bool parse (xmlNodePtr cur, CInterfaceGroup * parentGroup); + virtual void draw (); + + static void forceLink(); + + + protected: + CInterfaceProperty _Number; + CInterfaceProperty _NumberMax; + sint32 _Cache; + sint32 _CacheMax; + ucstring _EmptyText; + + void buildTextFromCache(); + }; + +} + +#endif // NL_DBVIEW_QUANTITY_H + +/* End of dbview_quantity.h */ diff --git a/code/ryzom/client/src/interface_v3/event_descriptor.h b/code/nel/include/nel/gui/event_descriptor.h similarity index 99% rename from code/ryzom/client/src/interface_v3/event_descriptor.h rename to code/nel/include/nel/gui/event_descriptor.h index fcb9d5f3a..d44448027 100644 --- a/code/ryzom/client/src/interface_v3/event_descriptor.h +++ b/code/nel/include/nel/gui/event_descriptor.h @@ -20,7 +20,10 @@ #define RZ_EVENT_DESCRIPTOR_H #include "nel/misc/types_nl.h" +#include "nel/misc/events.h" +namespace NLGUI +{ // ---------------------------------------------------------------------------- class CEventDescriptor @@ -247,6 +250,8 @@ protected: bool _HasFocus; }; +} + #endif // RZ_EVENT_DESCRIPTOR_H /* End of event_descriptor.h */ diff --git a/code/nel/include/nel/gui/event_listener.h b/code/nel/include/nel/gui/event_listener.h new file mode 100644 index 000000000..06a2d0776 --- /dev/null +++ b/code/nel/include/nel/gui/event_listener.h @@ -0,0 +1,44 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef EVENT_LISTENER +#define EVENT_LISTENER + +#include "nel/misc/event_listener.h" +#include "nel/gui/input_handler.h" + +namespace NLGUI +{ + class CEventListener : public NLMISC::IEventListener + { + public: + CEventListener(); + ~CEventListener(); + void addToServer( NLMISC::CEventServer *server ); + void removeFromServer(); + void operator()( const NLMISC::CEvent &evnt ); + + private: + NLGUI::CInputHandler inputHandler; + NLMISC::CEventServer *eventServer; + }; + +} + +#endif + + diff --git a/code/nel/include/nel/gui/group_container.h b/code/nel/include/nel/gui/group_container.h new file mode 100644 index 000000000..452674aa1 --- /dev/null +++ b/code/nel/include/nel/gui/group_container.h @@ -0,0 +1,664 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef RZ_GROUP_CONTAINER_H +#define RZ_GROUP_CONTAINER_H + +#include "nel/gui/interface_group.h" +#include "nel/gui/group_container_base.h" +#include "nel/misc/smart_ptr.h" + +namespace NLGUI +{ + class CEventDescriptorLocalised; + class CCtrlButton; + class CCtrlScroll; + class CViewText; + class CViewBitmap; + class CGroupList; + class COptionsContainerInsertion; + class COptionsContainerMove; + class COptionsLayer; + class CGroupContainer; + + + + // *************************************************************************** + /** + * class describing a resizer for the container + * \author Matthieu 'TrapII' Besson + * \date 2003 + */ + class CCtrlResizer : public CCtrlBase + { + + public: + DECLARE_UI_CLASS( CCtrlResizer ) + + CCtrlResizer(const TCtorParam ¶m); + virtual void draw (); + virtual bool handleEvent (const NLGUI::CEventDescriptor &event); + // Add a big delta so when the user is over the Resizer, always take it whatever other controls under + virtual uint getDeltaDepth() const { return 100; } + + // get real resizer pos : if parent has pop_min_w == pop_max_w, then horizontal resizer will be discarded + // if parent has pop_min_h == pop_max_h, then vertical resizer will be discarded + THotSpot getRealResizerPos() const; + THotSpot getResizerPos() const { return _ResizerPos; } + void setResizerPos(THotSpot resizerPos) { _ResizerPos = resizerPos; } + + bool IsMaxH; // Do this resizer is a MaxH resizer ? + + // Max sizes for the parent + sint32 WMin, WMax; + sint32 HMin, HMax; + + // from CCtrlBase + virtual bool canChangeVirtualDesktop() const { return !_MouseDown; } + + private: + + sint32 resizeW (sint32 dx); + sint32 resizeH (sint32 dy); + + private: + THotSpot _ResizerPos; // how the resizer should resize its parent + bool _MouseDown; + sint32 _MouseDownX; + sint32 _MouseDownY; + sint32 _XBias; + sint32 _YBias; + }; + + + // *************************************************************************** + /** + * Class describing a Mover for the container + * Clicking on it can also open the container + * This can be used to move a container if it is movable. + * If the container is popable, it will first pull it of the hierarchy, then it becomes movable. + * It can also be used to change the position of a group container that is inserted in the list of another container. + * \author Lionel Berenguier + * \date 2003 + */ + class CCtrlMover : public CCtrlBase + { + public: + DECLARE_UI_CLASS( CCtrlMover ) + + CCtrlMover(const TCtorParam ¶m, bool canMove = true, bool canOpen = true ); + ~CCtrlMover(); + virtual void draw (); + virtual bool handleEvent (const NLGUI::CEventDescriptor &event); + bool canMove() { return _CanMove; } + + bool isMoving() const {return _Moving;} + bool isMovingInParentList() const { return _MovingInParentList; } + + // from CCtrlBase + virtual bool canChangeVirtualDesktop() const { return !_Moving; } + + private: + sint32 _MoveStartX, _MoveStartY; + sint32 _MoveDeltaXReal, _MoveDeltaYReal; + sint64 _ScrollTime; + sint32 _StartIndex; + sint32 _InsertionIndex; + // clip window from parent list + sint32 _ParentListTop; + sint32 _ParentListBottom; + // + sint64 _WaitToOpenCloseDate; + // + bool _CanMove : 1; + bool _CanOpen : 1; + bool _Moving : 1; + bool _MovingInParentList : 1; + bool _HasMoved : 1; + bool _ParentScrollingUp : 1; + bool _ParentScrollingDown : 1; + bool _StopScrolling : 1; // stop scrolling at next draw + bool _WaitToOpenClose : 1; + // + static COptionsContainerInsertion *getInsertionOptions(); + private: + void setPoped(CGroupContainer *gc, sint32 x, sint32 y, const NLGUI::CEventDescriptorMouse &eventDesc); + void setMovingInParent(CGroupContainer *gc, sint32 x, sint32 y, const NLGUI::CEventDescriptorMouse &eventDesc); + void updateInsertionIndex(const CGroupList *gl, sint32 posY); + void stopMove(); + bool runTitleActionHandler(); + void handleScrolling(); + + }; + + + // *************************************************************************** + /** + * class describing a group of views controls and other groups + * \author Matthieu 'TrapII' Besson + * \author Nevrax France + * \date 2002 + */ + class CGroupContainer : public CGroupContainerBase + { + public: + enum { NumResizers = 8 }; + public: + // observer to know when children have moved. This can be used to keep external datas in sync + struct IChildrenObs + { + virtual void childrenMoved(uint srcIndex, uint destIndex, CGroupContainer *children) = 0; + }; + public: + DECLARE_UI_CLASS( CGroupContainer ) + CGroupContainer(const TCtorParam ¶m); + ~CGroupContainer(); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + xmlNodePtr serializeTreeData( xmlNodePtr parentNode ) const; + + virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup); + + virtual void updateCoords (); + + virtual void draw (); + + virtual void clearViews (); + + virtual bool handleEvent (const NLGUI::CEventDescriptor &eventDesc); + + virtual void launch (); + + virtual void setActive (bool state); + + virtual bool getViewsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector &vVB); // Return true if x,y under the group + + virtual bool getCtrlsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector &vICL); + + void open(); + + void close(); + + void setup(); // Create the container + + /** If insertion order is -1, pIC is added at the end of the container + * otherwise it is inserted after containers of a lower order + */ + void attachContainer (CGroupContainer *pIC, sint insertionOrder = -1); + // Insert a container at the given index. + bool attachContainerAtIndex(CGroupContainer *pIC, uint index); + + // Before a container is detached from parent, it should be pop in + void detachContainer (CGroupContainer *pIC); + void removeAllContainers(); + + void setOpen(bool opened) + { + if (opened) + { + open(); + } + else + { + close(); + } + } + bool isOpen() const { return _Opened; } + + // Force Open for container setActive and open() + virtual void forceOpen(); + + /// Set the title open and close + virtual bool isMovable() const {return _Movable;} + void setMovable(bool b); + + void setContent (CInterfaceGroup *pC); + + std::string getTitle () const; + void setTitle (const std::string &title); + std::string getTitleOpened () const; + void setTitleOpened (const std::string &title); + std::string getTitleClosed () const; + void setTitleClosed (const std::string &title); + std::string getTitleColorAsString() const; + void setTitleColorAsString(const std::string &col); + + void setHeaderColor (const std::string &ptr) { _HeaderColor.link(ptr.c_str()); } + + // Get the header color draw. NB: depends if grayed, and if active. + NLMISC::CRGBA getDrawnHeaderColor () const; + + ucstring getUCTitleOpened () const; + void setUCTitleOpened (const ucstring &title); + ucstring getUCTitleClosed () const; + void setUCTitleClosed (const ucstring &title); + ucstring getUCTitle () const; + void setUCTitle (const ucstring &title); + + void setPopable(bool popable) { _Popable = popable; } + bool isPopable() const { return _Popable; } + bool isPopuped() const { return _Poped; } + + + void setMovableInParentList(bool /* movable */) { _MovableInParentList = true; } + bool isMovableInParentList() const { return _MovableInParentList; } + + // high light the border of the container + void setHighLighted(bool hightlighted, uint8 alpha=255) { _HighLighted = hightlighted; _HighLightedAlpha = alpha; } + bool isHighLighted() const { return _HighLighted; } + + // y offset for content of container + sint32 getContentYOffset() const { return (sint32) _ContentYOffset; } + void setContentYOffset(sint32 value); + + // Window requires attention + void requireAttention(); + + // Lua exports + int luaBlink(CLuaState &ls); + int luaSetHeaderColor(CLuaState &ls); + + REFLECT_EXPORT_START(CGroupContainer, CGroupContainerBase) + REFLECT_LUA_METHOD("blink", luaBlink); + REFLECT_LUA_METHOD("setHeaderColor", luaSetHeaderColor); + REFLECT_STRING("title", getTitle, setTitle); + REFLECT_STRING("title_opened", getTitleOpened, setTitleOpened); + REFLECT_STRING("title_closed", getTitleClosed, setTitleClosed); + REFLECT_UCSTRING("uc_title_opened", getUCTitleOpened, setUCTitleOpened); + REFLECT_UCSTRING("uc_title_closed", getUCTitleClosed, setUCTitleClosed); + REFLECT_UCSTRING("uc_title", getUCTitle, setUCTitle); + REFLECT_STRING("title_color", getTitleColorAsString, setTitleColorAsString); + REFLECT_SINT32("pop_min_h", getPopupMinH, setPopupMinH); + REFLECT_SINT32("pop_max_h", getPopupMaxH, setPopupMaxH); + REFLECT_SINT32("pop_min_w", getPopupMinW, setPopupMinW); + REFLECT_SINT32("pop_max_w", getPopupMaxW, setPopupMaxW); + REFLECT_SINT32("title_delta_max_w", getTitleDeltaMaxW, setTitleDeltaMaxW); + REFLECT_SINT32("content_y_offset", getContentYOffset, setContentYOffset); + REFLECT_BOOL("openable", isOpenable, setOpenable); + REFLECT_BOOL("opened", isOpen, setOpen); + REFLECT_BOOL("lockable", isLockable, setLockable); + REFLECT_BOOL("locked", isLocked, setLocked); + + REFLECT_BOOL("header_active", getHeaderActive, setHeaderActive); + REFLECT_BOOL("right_button_enabled", getRightButtonEnabled, setRightButtonEnabled); + REFLECT_EXPORT_END + + sint32 getLayerSetup() const { return _LayerSetup; } + + // if this window is popable, pop it at its actual position + void popupCurrentPos(); + // Popup at previous memorized position + void popup(); + /** Popin the window and possibly put it back in its father container, using the order defined in the list of the container. + * \param putBackInFather When true, put the window back in its former father container, otherwise, the container is unliked from the hierachy (parents are NULL) + * \param insertPos If this is equal to -1, then the window is inserted at its previous position. Otherwise it is inserted before the given position in the list + */ + void popin(sint32 insertPos = -1, bool putBackInFatherContainer = true); + + // get the mover control associated with that control, or NULL if none + CCtrlMover *getCtrlMover() const { return _Mover; } + + // true if there is a mover and if the window is being moved + bool isMoving() const { return _Mover && _Mover->isMoving(); } + + /** Force the container to blink (to tell the user that an event has happened). + * This uses the global color, so the container must use it + * This state is automatically disabled if the container is opened + * \param numBlinks 0 If the container should blink endlessly, the number of blink otherwise + */ + virtual void enableBlink(uint numBlinks = 0); + virtual void disableBlink(); + virtual bool isBlinking() const { return _Blinking; } + + CGroupList *getList() const { return _List; } + + CInterfaceGroup *getHeaderOpened() const { return _HeaderOpened; } + CInterfaceGroup *getHeaderClosed() const { return _HeaderClosed; } + CInterfaceGroup *getContent() const { return _Content; } + + void setChildrenObs(IChildrenObs *obs) { _ChildrenObs = obs; } + IChildrenObs *getChildrenObs() const { return _ChildrenObs; } + + // Get current father container (if any). + CGroupContainer *getFatherContainer() const; + // Get current father container (if any). If the container is popup, it gives the proprietary container + CGroupContainer *getProprietaryContainer() const; + + + bool isOpenable() const { return _Openable; } + void setOpenable(bool openable); + + bool getHeaderActive() const { return _HeaderActive; } + void setHeaderActive(bool active) { _HeaderActive = active; } + + bool getRightButtonEnabled() const { return _EnabledRightButton; } + void setRightButtonEnabled(bool enabled); + + CCtrlScroll *getScroll() const { return _ScrollBar; } + + bool isSavable() const { return _Savable; } + void setSavable(bool savable) { _Savable = savable; } + bool isActiveSavable() const { return _ActiveSavable; } + + bool isLocalize() const { return _Localize; } + void setLocalize(bool localize) { _Localize = localize; } + + void setPopupX(sint32 x) { _PopupX = x; } + void setPopupY(sint32 y) { _PopupY = y; } + void setPopupW(sint32 w) { _PopupW = w; } + void setPopupH(sint32 h) { _PopupH = h; } + + sint32 getPopupX() const { return _PopupX; } + sint32 getPopupY() const { return _PopupY; } + sint32 getPopupW() const { return _PopupW; } + sint32 getPopupH() const { return _PopupH; } + + sint32 getRefW() const { return _RefW; } + + /** Increase the rollover alpha for the current frame. + * Example of use : an edit box that has focus in a group container + */ + void rollOverAlphaUp(); + // force the rollover alpha to its max value, depending on there's keyboard focus or not + void forceRolloverAlpha(); + + bool isOpenWhenPopup() const { return _OpenWhenPopup; } + + /// Locking of window (prevent it from being moved) + void setLockable(bool lockable); + bool isLockable() const { return _Lockable; } + void setLocked(bool locked); + + // to be called by the 'deactive check' handler + static void validateCanDeactivate(bool validate) { _ValidateCanDeactivate = validate; } + const std::string &getAHOnDeactiveCheck() const { return CAHManager::getInstance()->getAHName(_AHOnDeactiveCheck); } + const std::string &getAHOnDeactiveCheckParams() const { return _AHOnDeactiveCheckParams; } + // + const std::string &getAHOnCloseButton() const { return CAHManager::getInstance()->getAHName(_AHOnCloseButton); } + const std::string &getAHOnCloseButtonParams() const { return _AHOnCloseButtonParams; } + // + IActionHandler *getAHOnMovePtr() const { return _AHOnMove; } + const std::string &getAHOnMove() const { return CAHManager::getInstance()->getAHName(_AHOnMove); } + const std::string &getAHOnMoveParams() const { return _AHOnMoveParams; } + // + IActionHandler *getAHOnResizePtr() const { return _AHOnResize; } + const std::string &getAHOnResize() const { return CAHManager::getInstance()->getAHName(_AHOnResize); } + const std::string &getAHOnResizeParams() const { return _AHOnResizeParams; } + // + IActionHandler *getAHOnBeginMovePtr() const { return _AHOnBeginMove; } + const std::string &getAHOnBeginMove() const { return CAHManager::getInstance()->getAHName(_AHOnBeginMove); } + const std::string &getAHOnBeginMoveParams() const { return _AHOnBeginMoveParams; } + + // + void setOnCloseButtonHandler(const std::string &h) { _AHOnCloseButton = CAHManager::getInstance()->getAH(h,_AHOnCloseButtonParams); } + void setOnCloseButtonParams(const std::string &p) { _AHOnCloseButtonParams = p; } + + void setModalParentList (const std::string &name); + bool checkIfModal(const NLGUI::CEventDescriptor& event); // Return true if we can handle the event (and prevent from selecting a window) + bool isGrayed() const; + bool blinkAllSons(); + + // true if the resizer is enabled. + bool getEnabledResizer() const {return _EnabledResizer;} + + sint32 getPopupMinW() const {return _PopupMinW;} + sint32 getPopupMaxW() const {return _PopupMaxW;} + sint32 getPopupMinH() const {return _PopupMinH;} + sint32 getPopupMaxH() const {return _PopupMaxH;} + sint32 getMinW() const {return _MinW;} + void setMinW(sint32 minW) { _MinW = minW;} + void setMaxW(sint32 maxW) { _MaxW = maxW;} + sint32 getMaxW() const {return _MaxW;} + void setPopupMinW(sint32 minW); + void setPopupMaxW(sint32 maxW); + void setPopupMinH(sint32 minW); + void setPopupMaxH(sint32 maxW); + + + // backup the current position of this container + void backupPosition(); + // restore the current position of this container + void restorePosition(); + // get x for backup position + sint32 getBackupX() const { return _BackupX; } + sint32 getBackupY() const { return _BackupY; } + // Set backup position + void setBackupPosition(sint32 x, sint32 y); + // clear backup + void clearBackup() { _PositionBackuped = false; } + // Test if position has been backuped (flag cleared by 'restorePosition()') + bool isPositionBackuped() const { return _PositionBackuped; } + // check if the container has been moved, resized, or popuped by the user (and eventually clear that flag) + bool getTouchFlag(bool clearFlag) const; + // from CInterfaceGroup + virtual void restoreAllContainersBackupPosition() { restorePosition(); } + + // when isModal() is true, the whole interface cannot switch desktop + bool isModal() const { return _Modal; } + void setModal(bool modal) { _Modal = modal; } + + // return true if the container has a modal parent window setuped => the whole interface cannot switch desktop + bool isModalSon() const { return !_ModalParents.empty(); } + + // return the help web page of this container. "" if none + const std::string &getHelpPage() const { return _HelpPage; } + // set the help web page of this container. "" if none. NB: the help button is not updated + void setHelpPage(const std::string &newPage); + + void setTitleDeltaMaxW(sint32 delta) { _TitleDeltaMaxW = delta; } + sint32 getTitleDeltaMaxW() const { return _TitleDeltaMaxW; } + + protected: + uint8 _ICurrentRolloverAlphaContainer; + uint8 _HighLightedAlpha; + float _CurrentRolloverAlphaContainer; + float _CurrentRolloverAlphaContent; + sint32 _LayerSetup; + ucstring _TitleTextOpened; + ucstring _TitleTextClosed; + CViewText *_TitleOpened; + CViewText *_TitleClosed; + sint32 _TitleDeltaMaxW; + CViewBitmap *_ViewOpenState; // Arrow showing if we are opened or not (if we are openable) + CCtrlButton *_RightButton; // Multi usage button : deactive or popup or popin + CCtrlButton *_HelpButton; // Help button + + CGroupList *_List; + CCtrlScroll *_ScrollBar; + CGroupContainer *_OldFatherContainer; + + // NB: _ModalParentNames is a list of modal parent, separated by '|' + std::string _ModalParentNames; // Modal handling between container (container can be linked together, + std::vector _ModalSons; // when the son is active the parent is not active + std::vector _ModalParents; // (but the rest of the interface is)) + + uint _InsertionOrder; + uint _BlinkDT; + uint _NumBlinks; + + CInterfaceGroup *_Content; // Read From Script + CInterfaceGroup *_HeaderOpened; // Read From Script + CInterfaceGroup *_HeaderClosed; // Read From Script + + CCtrlResizer *_Resizer[NumResizers]; // up to 8 resizers are available + + // + CCtrlMover *_Mover; + + IChildrenObs *_Obs; + + // If layer==0 constraint on resize + sint32 _PopupMinW; + sint32 _PopupMaxW; + sint32 _PopupMinH; + sint32 _PopupMaxH; + // If layer>0 constraint on resize + sint32 _MinW; + sint32 _MaxW; + + // backuped position + sint32 _BackupX; + sint32 _BackupY; + + // old position at which the window was popup, -1 values means that the window hasn't been turned into a popup yet + sint32 _PopupX; + sint32 _PopupY; + sint32 _PopupW; + sint32 _PopupH; + // + sint32 _RefW; + + + sint32 _MoverDeltaW; + + // action handler + IActionHandler *_AHOnOpen; + CStringShared _AHOnOpenParams; + IActionHandler *_AHOnClose; + CStringShared _AHOnCloseParams; + IActionHandler *_AHOnCloseButton; + CStringShared _AHOnCloseButtonParams; + IActionHandler *_AHOnMove; + CStringShared _AHOnMoveParams; + IActionHandler *_AHOnResize; + CStringShared _AHOnResizeParams; + IActionHandler *_AHOnBeginMove; + CStringShared _AHOnBeginMoveParams; + + // action handler to test whether the windows can be deactivated (when the close button is pressed) + IActionHandler *_AHOnDeactiveCheck; + CStringShared _AHOnDeactiveCheckParams; + + + // Observer to know when children have moved + IChildrenObs *_ChildrenObs; + + // list of container that are poped up + std::vector _PopedCont; + + // Open management + bool _Openable : 1; // Is the container can be manually opened or closed ? + bool _Opened : 1; // Is the container currently opened or closed ? + bool _OpenWhenPopup : 1; // Does the container must open when poped up ? (layer>0) + // and close when poped in... + bool _OpenAtStart : 1; // Mgt : to setup _Opened state at start + bool _OpenedBeforePopup : 1; // Mgt : Is the container opened before poped up ? (layer>0) + + // Move management + bool _Movable : 1; // Is the container movable ? + bool _MovableInParentList: 1; + bool _Lockable : 1; + bool _MovingInParentList : 1; // Mgt : currently moving ? + + // Pop up / pop in + bool _Popable : 1; + bool _Poped : 1; + + bool _EnabledResizer : 1; + + bool _HighLighted : 1; + bool _Blinking : 1; + bool _BlinkState : 1; + + bool _Savable : 1; + bool _ActiveSavable : 1; + + // Display title background or not + bool _HeaderActive : 1; + bool _EnabledRightButton : 1; // Is the Button Deactive/Popup/Popin is enabled ? + // + enum TTileClass {TitleText=0, TitleTextFormated, TitleTextId, TitleTextDynString}; + uint8 _TitleClass : 2; + // + mutable bool _TouchFlag : 1; + bool _PositionBackuped : 1; + bool _Modal : 1; // the container is modal and prevent from switching virtual desktop + // + bool _EnabledHelpButton : 1; // Is the Button Help is enabled ? + // + bool _TitleOverExtendViewText : 1; // Does the title over extend view text + bool _Localize : 1; + + CInterfaceProperty _HeaderColor; + + + + sint8 _ContentYOffset; + + // Special Top Resizer Height (for Inventory and ChatGroup). <0 (default) => take default option value + sint8 _ResizerTopSize; + uint8 _ICurrentRolloverAlphaContent; + + + static bool _ValidateCanDeactivate; + + CStringShared _OptionsName; + + // Web Page used for help + CStringShared _HelpPage; + + private: + + sint32 getLayer(); + void updateResizerSize(CCtrlResizer *cr); + void updateRightButton(); + void updateHelpButton(); + void updateMover(); + void updateViewOpenState(); + void updateTitle(); + + void createResizer(uint index, THotSpot posRef, THotSpot type, sint32 offsetX, sint32 offsetY, bool bMaxH); + void createResizerMaxH(); + void removeResizerMaxH(); + + TTileClass convertTitleClass(const char *ptr); + + static COptionsContainerMove *getMoveOptions(); + + COptionsLayer *getContainerOptions(sint32 ls=-1); // Depends if overload by OptionsName or default used + + bool hasKeyboardFocus() const; + + // private for modal system + void addModalParent (CGroupContainer *pParent); + void addModalSon (CGroupContainer *pSon); + + // Avoid each frame setup layer0, layer1 etc... + enum {NumLayerName=10}; + static const std::string _OptionLayerName[NumLayerName]; + + public: + // for use by CCtrlMover + // Tell that this group is moving in its parent list + void setMovingInParentList(bool enable); + CGroupList *getPreviousParentList() const { return _OldFatherContainer ? _OldFatherContainer->_List : NULL; } + CCtrlScroll *getPreviousParentScrollBar() const { return _OldFatherContainer ? _OldFatherContainer->_ScrollBar : NULL; } + CGroupContainer *getPreviousContainer() const { return _OldFatherContainer; } + // set the 'hasMoved' flag + void touch(bool touched = true) { _TouchFlag = touched; } + + friend class CICDeactive; + }; + +} + +#endif // RZ_INTERFACE_CONTAINER_H + +/* End of interface_container.h */ diff --git a/code/nel/include/nel/gui/group_container_base.h b/code/nel/include/nel/gui/group_container_base.h new file mode 100644 index 000000000..fe3fc8d07 --- /dev/null +++ b/code/nel/include/nel/gui/group_container_base.h @@ -0,0 +1,117 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef GROUP_CONTAINER_BASE_H +#define GROUP_CONTAINER_BASE_H + +#include "nel/gui/interface_group.h" +#include "nel/misc/rgba.h" + +namespace NLGUI +{ + + class CGroupContainerBase : public CInterfaceGroup + { + public: + DECLARE_UI_CLASS( CGroupContainerBase ) + + CGroupContainerBase( const TCtorParam ¶m ); + virtual ~CGroupContainerBase(); + + virtual void removeAllContainers(); + virtual void setLocked( bool locked ); + bool isLocked() const { return _Locked; } + + uint8 getContainerAlpha() const { return _ContainerAlpha; } + uint8 getContentAlpha() const { return _ContentAlpha; } + uint8 getRolloverAlphaContent() const { return _RolloverAlphaContent; } + uint8 getRolloverAlphaContainer() const { return _RolloverAlphaContainer; } + + void setContainerAlpha( uint8 alpha ); + void setContentAlpha( uint8 alpha ); + void setRolloverAlphaContent( uint8 alpha ); + void setRolloverAlphaContainer( uint8 alpha ); + + // for export + sint32 getContainerAlphaAsSInt32() const{ return (sint32)_ContainerAlpha; } + sint32 getContentAlphaAsSInt32() const{ return (sint32)_ContentAlpha; } + sint32 getRolloverAlphaContentAsSInt32() const{ return (sint32)_RolloverAlphaContent; } + sint32 getRolloverAlphaContainerAsSInt32() const{ return (sint32)_RolloverAlphaContainer; } + + // sin32 versions for export + void setContainerAlpha( sint32 alpha ){ setContainerAlpha((uint8) alpha); } + void setContentAlpha( sint32 alpha ){ setContentAlpha((uint8) alpha); } + void setRolloverAlphaContent( sint32 alpha ){ setRolloverAlphaContent((uint8) alpha); } + void setRolloverAlphaContainer( sint32 alpha ){ setRolloverAlphaContainer((uint8) alpha); } + + void setUseGlobalAlpha( bool use ); + bool isUsingGlobalAlpha() const{ return _UseGlobalAlpha; } + + std::string getAHOnAlphaSettingsChanged() const{ return CAHManager::getInstance()->getAHName( _AHOnAlphaSettingsChanged ); } + std::string getAHOnAlphaSettingsChangedParams() const{ return _AHOnAlphaSettingsChangedParams; } + + void setAHOnAlphaSettingsChanged( const std::string &h ){ _AHOnAlphaSettingsChanged = CAHManager::getInstance()->getAH( h, _AHOnAlphaSettingsChangedParams ); } + void setAHOnAlphaSettingsChangedParams( const std::string &p ){ _AHOnAlphaSettingsChangedParams = p; } + + REFLECT_EXPORT_START( CGroupContainerBase, CInterfaceGroup ) + REFLECT_SINT32("container_alpha", getContainerAlphaAsSInt32, setContainerAlpha); + REFLECT_SINT32("content_alpha", getContentAlphaAsSInt32, setContentAlpha); + REFLECT_SINT32("rollover_content_alpha", getRolloverAlphaContentAsSInt32, setRolloverAlphaContent); + REFLECT_SINT32("rollover_container_alpha", getRolloverAlphaContainerAsSInt32, setRolloverAlphaContainer); + REFLECT_BOOL("use_global_alpha_settings", isUsingGlobalAlpha, setUseGlobalAlpha); + REFLECT_STRING("on_alpha_settings_changed", getAHOnAlphaSettingsChanged, setAHOnAlphaSettingsChanged); + REFLECT_STRING("on_alpha_settings_changed_aparams", getAHOnAlphaSettingsChangedParams, setAHOnAlphaSettingsChangedParams); + REFLECT_EXPORT_END + + virtual bool isMoving() const{ return false; } + + // Get the header color draw. NB: depends if grayed, and if active. + virtual NLMISC::CRGBA getDrawnHeaderColor () const{ return NLMISC::CRGBA(); }; + + uint8 getCurrentContainerAlpha() const{ return _CurrentContainerAlpha; } + uint8 getCurrentContentAlpha() const{ return _CurrentContentAlpha; } + + virtual bool isGrayed() const{ return false; } + virtual bool getTouchFlag(bool clearFlag) const{ return false; } + virtual void backupPosition(){} + virtual void restorePosition(){} + + protected: + void triggerAlphaSettingsChangedAH(); + + uint8 _CurrentContainerAlpha; + uint8 _CurrentContentAlpha; + uint8 _ContainerAlpha; + uint8 _ContentAlpha; + uint8 _RolloverAlphaContainer; // Alpha for the window when mouse not over it + uint8 _RolloverAlphaContent; // Alpha for the content when mouse not over it + bool _Locked : 1; // Is the container locked (ie override movable, openable ...) + bool _UseGlobalAlpha : 1; + + IActionHandler *_AHOnAlphaSettingsChanged; + CStringShared _AHOnAlphaSettingsChangedParams; + + private: + + }; + + + +} + + +#endif diff --git a/code/nel/include/nel/gui/group_editbox.h b/code/nel/include/nel/gui/group_editbox.h new file mode 100644 index 000000000..7ea2ab529 --- /dev/null +++ b/code/nel/include/nel/gui/group_editbox.h @@ -0,0 +1,368 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef RZ_CTRL_EDITBOX_H +#define RZ_CTRL_EDITBOX_H + +#include "nel/gui/interface_group.h" +#include "nel/gui/group_editbox_base.h" +#include "nel/3d/u_texture.h" + +namespace NLGUI +{ + class CEventDescriptor; + class CViewText; + + // ---------------------------------------------------------------------------- + class CGroupEditBox : public CGroupEditBoxBase + { + public: + DECLARE_UI_CLASS( CGroupEditBox ) + + class IComboKeyHandler + { + public: + virtual ~IComboKeyHandler(){} + virtual bool isComboKeyChat( const NLGUI::CEventDescriptorKey &edk ) const = 0; + }; + + enum TEntryType { Text, Integer, PositiveInteger, Float, PositiveFloat, Alpha, AlphaNum, AlphaNumSpace, Password, Filename, PlayerName }; // the type of entry this edit bot can deal with + + /// Constructor + CGroupEditBox(const TCtorParam ¶m); + /// Dtor + ~CGroupEditBox(); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + bool parse(xmlNodePtr cur,CInterfaceGroup * parentGroup); + virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); } + + virtual void draw(); + + virtual bool handleEvent (const NLGUI::CEventDescriptor& eventDesc); + + /// Accessors + ucstring getInputString() const { return _InputString; } + const ucstring &getInputStringRef() const { return _InputString; } + const ucstring &getPrompt() const { return _Prompt; } + + /** Set the prompt + * NB : line returns are encoded as '\n', not '\r\n' + */ + void setPrompt(const ucstring &s) { _Prompt = s; } + void setInputString(const ucstring &str); + void setInputStringRef(const ucstring &str) {_InputString = str; }; + void setInputStringAsInt(sint32 val); + sint32 getInputStringAsInt() const; + void setInputStringAsInt64(sint64 val); + sint64 getInputStringAsInt64() const; + void setInputStringAsFloat(float val); + float getInputStringAsFloat() const; + void setInputStringAsStdString(const std::string &str); + std::string getInputStringAsStdString() const; + void setInputStringAsUtf8(const std::string &str); + std::string getInputStringAsUtf8() const; + void setColor(NLMISC::CRGBA col); + + + /// force the selection of all the text + void setSelectionAll(); + + virtual void checkCoords(); + virtual void updateCoords(); + virtual void clearViews (); + + virtual void setActive (bool state); + + static CGroupEditBox *getMenuFather() { return _MenuFather; } + + void setCommand(const ucstring &command, bool execute); + + // Stop parent from blinking + void stopParentBlink() { if (_Parent) _Parent->disableBlink(); } + + // Get / set cursor position + sint32 getCursorPos () const {return _CursorPos;} + void setCursorPos (sint32 pos) {_CursorPos=pos;} + + // Get / set cursor at previous line end + bool isCursorAtPreviousLineEnd () const {return _CursorAtPreviousLineEnd;} + void setCursorAtPreviousLineEnd (bool setCursor) {_CursorAtPreviousLineEnd=setCursor;} + + // Get / set current selection position + static sint32 getSelectCursorPos () {return _SelectCursorPos;} + static void setSelectCursorPos (sint32 pos) {_SelectCursorPos=pos;} + + // Get the view text + const CViewText *getViewText () const {return _ViewText;} + + // Get the historic information + sint32 getMaxHistoric() const {return _MaxHistoric;} + sint32 getCurrentHistoricIndex () const {return _CurrentHistoricIndex;} + void setCurrentHistoricIndex (sint32 index) {_CurrentHistoricIndex=index;} + const ucstring &getHistoric(uint32 index) const {return _Historic[index];} + uint32 getNumHistoric() const {return (uint32)_Historic.size ();} + + // Get on change action handler + const std::string &getAHOnChange() const {return _AHOnChange;} + const std::string &getParamsOnChange() const {return _ParamsOnChange;} + + void cutSelection(); + + /// From CInterfaceElement + sint32 getMaxUsedW() const; + sint32 getMinUsedW() const; + + // Copy the selection into buffer + void copy(); + // Paste the selection into buffer + void paste(); + // Write the string into buffer + void writeString(const ucstring &str, bool replace = true, bool atEnd = true); + + // Expand the expression (true if there was a '/' at the start of the line) + bool expand(); + + // Back space + void back(); + + // ignore the next char/key event -> useful when a key set the focus on an editbox (keydown is received, the focus, then keychar is received by the editbox again, but is irrelevant) + void bypassNextKey() { _BypassNextKey = true; } + + // True if the editBox loose the focus on enter + bool getLooseFocusOnEnter() const {return _LooseFocusOnEnter;} + // + virtual void clearAllEditBox(); + // From CInterfaceElement + virtual bool wantSerialConfig() const; + // From CInterfaceElement + virtual void serialConfig(NLMISC::IStream &f); + // From CInterfaceElement + virtual void onQuit(); + // From CInterfaceElement + virtual void onLoadConfig(); + + // from CCtrlBase + virtual void elementCaptured(CCtrlBase *capturedElement); + + // from CCtrlBase + virtual void onKeyboardCaptureLost(); + + // set the input string as "default". will be reseted at first click (used for user information) + void setDefaultInputString(const ucstring &str); + + // For Interger and PositiveInteger, can specify min and max values + void setIntegerMinValue(sint32 minValue) {_IntegerMinValue=minValue;} + void setIntegerMaxValue(sint32 maxValue) {_IntegerMaxValue=maxValue;} + void setPositiveIntegerMinValue(uint32 minValue) {_PositiveIntegerMinValue=minValue;} + void setPositiveIntegerMaxValue(uint32 maxValue) {_PositiveIntegerMaxValue=maxValue;} + + void setFocusOnText(); + + int luaSetSelectionAll(CLuaState &ls); + int luaSetupDisplayText(CLuaState &ls); + int luaSetFocusOnText(CLuaState &ls); + int luaCancelFocusOnText(CLuaState &ls); + REFLECT_EXPORT_START(CGroupEditBox, CGroupEditBoxBase) + REFLECT_LUA_METHOD("setupDisplayText", luaSetupDisplayText); + REFLECT_LUA_METHOD("setSelectionAll", luaSetSelectionAll); + REFLECT_LUA_METHOD("setFocusOnText", luaSetFocusOnText); + REFLECT_LUA_METHOD("cancelFocusOnText", luaCancelFocusOnText); + REFLECT_STRING("input_string", getInputStringAsStdString, setInputStringAsStdString); + REFLECT_UCSTRING("uc_input_string", getInputString, setInputString); + REFLECT_EXPORT_END + + /** Restore the original value of the edit box. + * This value is captured when the edit box get focus + * (return true if no undo was available) + * Will always fails ifthe edito box do not have the focus + */ + bool undo(); + + /** Cancel last undo operation + * Return true if redo operation is available + */ + bool redo(); + + /// freeze the control (loose focus, and cannot edit) + void setFrozen (bool state); + bool getFrozen () const { return _Frozen; } + + protected: + + // Cursor infos + float _BlinkTime; + sint32 _CursorPos; + uint32 _MaxNumChar; + uint32 _MaxNumReturn; + uint32 _MaxFloatPrec; // used in setInputStringAsFloat() only + sint32 _MaxCharsSize; + sint32 _FirstVisibleChar; + sint32 _LastVisibleChar; + + // Text selection + static sint32 _SelectCursorPos; + bool _SelectingText; + NLMISC::CRGBA _TextSelectColor; + NLMISC::CRGBA _BackSelectColor; + + // Text info + ucstring _Prompt; + ucstring _InputString; + CViewText *_ViewText; + + // undo / redo + ucstring _StartInputString; // value of the input string when focus was acuired first + ucstring _ModifiedInputString; + + + // Historic info + typedef std::deque THistoric; + THistoric _Historic; + uint32 _MaxHistoric; + sint32 _CurrentHistoricIndex; + sint32 _PrevNumLine; + + // Action Handler + std::string _AHOnChange; + std::string _ParamsOnChange; + std::string _ListMenuRight; + + std::string _AHOnFocusLost; + std::string _AHOnFocusLostParams; + + // entry type + TEntryType _EntryType; + + + bool _Setupped : 1; // setup + bool _BypassNextKey : 1; + bool _BlinkState : 1; + bool _CursorAtPreviousLineEnd : 1; // force the cursor to be displayed at the end of the previous line end (if END has beeen pressed while in a string split accross 2 lines) + bool _LooseFocusOnEnter : 1; + bool _ResetFocusOnHide : 1; + bool _BackupFatherContainerPos : 1; // Backup father container position when characters are typed. + // If the edit box is at the bottom of the screen and if it expands on y + // because of multiline, thz parent container will be moved to top + // The good position can be restored by a press on enter then + bool _WantReturn : 1; // Want return char, don't call the enter action handler + bool _Savable : 1; // should content be saved ? + bool _DefaultInputString : 1; // Is the current input string the default one (should not be edited) + bool _Frozen : 1; // is the control frozen? (cannot edit in it) + + bool _CanRedo : 1; + bool _CanUndo : 1; + + std::vector _NegativeFilter; + + sint _CursorTexID; + sint32 _CursorWidth; + + sint32 _IntegerMinValue; + sint32 _IntegerMaxValue; + uint32 _PositiveIntegerMinValue; + uint32 _PositiveIntegerMaxValue; + + sint32 _ViewTextDeltaX; + + private: + void setupDisplayText(); + void makeTopWindow(); + void handleEventChar(const NLGUI::CEventDescriptorKey &event); + void handleEventString(const NLGUI::CEventDescriptorKey &event); + void setup(); + void triggerOnChangeAH(); + void appendStringFromClipboard(const ucstring &str); + + ucstring getSelection(); + + static CGroupEditBox *_MenuFather; + + static bool isValidAlphaNumSpace(ucchar c) + { + if (c > 255) return false; + char ac = (char) c; + return (ac >= '0' && ac <= '9') || + (ac >= 'a' && ac <= 'z') || + (ac >= 'A' && ac <= 'Z') || + ac==' '; + } + + static bool isValidAlphaNum(ucchar c) + { + if (c > 255) return false; + char ac = (char) c; + return (ac >= '0' && ac <= '9') || + (ac >= 'a' && ac <= 'z') || + (ac >= 'A' && ac <= 'Z'); + } + + static bool isValidAlpha(ucchar c) + { + if (c > 255) return false; + char ac = (char) c; + return (ac >= 'a' && ac <= 'z') || + (ac >= 'A' && ac <= 'Z'); + } + + static bool isValidPlayerNameChar(ucchar c) + { + // valid player name (with possible shard prefix / suffix format + return isValidAlpha(c) || c=='.' || c=='(' || c==')'; + } + + static bool isValidFilenameChar(ucchar c) + { + if (c == '\\' || + c == '/' || + c == ':' || + c == '*' || + c == '?' || + c == '\"' || + c == '<' || + c == '>' || + c == '|') return false; + return true; + } + // + bool isFiltered(ucchar c) + { + uint length = (uint)_NegativeFilter.size(); + for (uint k = 0; k < length; ++k) + { + if ((ucchar) _NegativeFilter[k] == c) return true; + } + return false; + } + + static IComboKeyHandler *comboKeyHandler; + + public: + static void setComboKeyHandler( IComboKeyHandler *handler ){ comboKeyHandler = handler; } + + }; + + +} + +#endif // RZ_CTRL_EDITBOX_H + +/* End of ctrl_editbox.h */ diff --git a/code/nel/include/nel/gui/group_editbox_base.h b/code/nel/include/nel/gui/group_editbox_base.h new file mode 100644 index 000000000..3aa6a555f --- /dev/null +++ b/code/nel/include/nel/gui/group_editbox_base.h @@ -0,0 +1,67 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef GROUP_EDITBOX_BASE_H +#define GROUP_EDITBOX_BASE_H + +#include "nel/gui/interface_group.h" + +namespace NLGUI +{ + + class CGroupEditBoxBase : public CInterfaceGroup + { + public: + DECLARE_UI_CLASS( CGroupEditBoxBase ) + + CGroupEditBoxBase( const TCtorParam ¶m ); + ~CGroupEditBoxBase(); + + // True if the editBox can recover the focus on enter. if not, it does not erase OldCapturedKeyboard when loose focus + bool getRecoverFocusOnEnter() const{ return _RecoverFocusOnEnter; } + void setRecoverFocusOnEnter( bool state ){ _RecoverFocusOnEnter = state; } + + std::string getAHOnFocus(){ return _AHOnFocus; } + std::string getAHOnFocusParams(){ return _AHOnFocusParams; } + + // disable any current selection + static void disableSelection(){ _CurrSelection = NULL; } + + // Get / set current selection + static CGroupEditBoxBase *getCurrSelection(){ return _CurrSelection; } + static void setCurrSelection( CGroupEditBoxBase *selection ){ _CurrSelection = selection; } + + void draw(){} + + REFLECT_EXPORT_START( CGroupEditBoxBase, CInterfaceGroup ) + REFLECT_BOOL( "enter_recover_focus", getRecoverFocusOnEnter, setRecoverFocusOnEnter ); + REFLECT_EXPORT_END + + protected: + bool _RecoverFocusOnEnter : 1; + + std::string _AHOnFocus; + std::string _AHOnFocusParams; + + static CGroupEditBoxBase *_CurrSelection; // the edit box for which the selection is currently active, or NULL if there's none + + }; + +} + +#endif + diff --git a/code/nel/include/nel/gui/group_frame.h b/code/nel/include/nel/gui/group_frame.h new file mode 100644 index 000000000..3d350b4d5 --- /dev/null +++ b/code/nel/include/nel/gui/group_frame.h @@ -0,0 +1,119 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_GROUP_FRAME_H +#define NL_GROUP_FRAME_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/interface_group.h" + + +namespace NLGUI +{ + + + // *************************************************************************** + /** A Group with a background and a frame displayed + * \author Lionel Berenguier + * \author Nevrax France + * \date 2002 + */ + class CGroupFrame : public CInterfaceGroup + { + public: + DECLARE_UI_CLASS( CGroupFrame ) + + /// Constructor + CGroupFrame(const TCtorParam ¶m); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup); + virtual void draw (); + + void copyOptionFrom(const CGroupFrame &other); + void setupOptions(); + + + void setColorAsString(const std::string & col); + std::string getColorAsString() const; + + REFLECT_EXPORT_START(CGroupFrame, CInterfaceGroup) + REFLECT_STRING ("color", getColorAsString, setColorAsString); + REFLECT_EXPORT_END + + + static void resetDisplayTypes() { _DispTypes.clear(); } + + // ****************** + protected: + + bool _DisplayFrame; + + NLMISC::CRGBA _Color; + + uint8 _DispType; + + std::string _Options; + + // Fields Defined in the XML => must not herit them from extends="" + bool _DisplayFrameDefined : 1; + bool _ColorDefined : 1; + bool _DispTypeDefined : 1; + + // Static stuff + enum + { + TextTL= 0, + TextTM, + TextTR, + TextML, + TextMM, + TextMR, + TextBL, + TextBM, + TextBR + }; + + struct SDisplayType + { + std::string Name; + sint32 BorderIds[9]; + uint8 TileBorder[9]; // Dont works for TextTL, TextTR, TextBL, TextBR + sint32 LeftBorder; // enum + sint32 RightBorder; + sint32 TopBorder; + sint32 BottomBorder; + + // ----------------------- + SDisplayType() + { + for (uint i = 0; i < 9; ++i) + TileBorder[i] = 0; + } + }; + static std::vector _DispTypes; + }; + +} + +#endif // NL_GROUP_FRAME_H + +/* End of group_frame.h */ diff --git a/code/nel/include/nel/gui/group_header.h b/code/nel/include/nel/gui/group_header.h new file mode 100644 index 000000000..ab6c94c35 --- /dev/null +++ b/code/nel/include/nel/gui/group_header.h @@ -0,0 +1,97 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CL_GROUP_HEADER_H +#define CL_GROUP_HEADER_H + +#include "nel/gui/group_list.h" + +namespace NLGUI +{ + + class CGroupHeaderEntry; + + // ***************************************************************************************************************** + /** Display a header with movable entries. + * Usually used with a table to change the size of each column (much like the windows file explorer in 'details' mode) + * + * \author Nicolas Vizerie + * \author Nevrax France + * \date 2006 + */ + class CGroupHeader : public CGroupList + { + public: + DECLARE_UI_CLASS( CGroupHeader ) + + REFLECT_EXPORT_START(CGroupHeader, CGroupList) + REFLECT_LUA_METHOD("enlargeColumns", luaEnlargeColumns); + REFLECT_LUA_METHOD("resizeColumnsAndContainer", luaResizeColumnsAndContainer); + REFLECT_EXPORT_END + + CGroupHeader(const TCtorParam ¶m); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + // from CInterfaceGroup + virtual bool parse(xmlNodePtr cur, CInterfaceGroup * parentGroup); + sint32 getHeaderMaxSize() const { return _HeaderMaxSize; } + // get the entries in this header + void getEntries(std::vector &dest); + // ensure that max. content of columns is visible (without the total width becoming more than 'getHeaderMaxSize()' + void enlargeColumns(sint32 margin); + // ensure that content of each column is visible + void resizeColumnsAndContainer(sint32 margin); + private: + sint32 _HeaderMaxSize; + int luaEnlargeColumns(CLuaState &ls); + int luaResizeColumnsAndContainer(CLuaState &ls); + }; + + // ***************************************************************************************************************** + // an entry in a header, includes a "mover control" to move it inside its parent header + // NOTE : when not used inside a CGroupHeader, will work, but there will be no 'max_size' + class CGroupHeaderEntry : public CInterfaceGroup + { + public: + DECLARE_UI_CLASS( CGroupHeaderEntry ) + + CGroupHeaderEntry(const TCtorParam ¶m); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + // from CInterfaceGroup + virtual bool parse(xmlNodePtr cur, CInterfaceGroup * parentGroup); + sint32 getMinSize() const { return _MinSize; } + virtual void updateCoords(); + CInterfaceGroup *getTargetColumn() const; + + const std::string &getAHOnResize() const { return _AHOnResize; } + const std::string &getAHOnResizeParams() const { return _AHOnResizeParams; } + + private: + sint32 _MinSize; + sint32 _ResizerSize; + std::string _TargetColumnId; + std::string _AHOnResize; + std::string _AHOnResizeParams; + }; + + +} + +#endif + diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h new file mode 100644 index 000000000..3f5526197 --- /dev/null +++ b/code/nel/include/nel/gui/group_html.h @@ -0,0 +1,673 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CL_GROUP_HTML_H +#define CL_GROUP_HTML_H + +#define CURL_STATICLIB 1 +#include + +#include "nel/misc/types_nl.h" +#include "nel/gui/interface_group.h" +#include "nel/gui/group_scrolltext.h" +#include "nel/gui/group_tree.h" +#include "nel/gui/ctrl_button.h" +#include "nel/gui/group_table.h" + +typedef std::map TStyle; + +extern "C" +{ +#include "WWWInit.h" +} + +namespace NLGUI +{ + class CCtrlButton; + class CCtrlScroll; + class CGroupList; + class CDBGroupComboBox; + class CGroupParagraph; + + + + // HTML group + /** + * Widget to have a resizable scrolltext and its scrollbar + * \author Cyril 'Hulud' Corvazier + * \author Nevrax France + * \date 2002 + */ + class CGroupHTML : public CGroupScrollText + { + public: + DECLARE_UI_CLASS( CGroupHTML ) + + friend void TextAdd (struct _HText *me, const char * buf, int len); + friend void TextBeginElement (_HText *me, int element_number, const BOOL *present, const char ** value); + friend void TextEndElement (_HText *me, int element_number); + friend void TextLink (struct _HText *me, int element_number, int attribute_number, struct _HTChildAnchor *anchor, const BOOL *present, const char **value); + friend void TextBuild (HText * me, HTextStatus status); + friend void TextBeginUnparsedElement(HText *me, const char *buffer, int length); + friend void TextEndUnparsedElement(HText *me, const char *buffer, int length); + friend int requestTerminater (HTRequest * request, HTResponse * response, void * param, int status); + + /// Web browser options for CGroupHTML + struct SWebOptions + { + public: + /// Id of the browser ( e.g.: Chrome, Firefox, Ryzom ) + std::string appName; + /// Version of the browser + std::string appVersion; + /// Language code of the browser( e.g.: en, hu ) + std::string languageCode; + /// List of domains the widget can consider secure. + std::vector< std::string > trustedDomains; + + SWebOptions() + { + } + }; + + static SWebOptions options; + + // Constructor + CGroupHTML(const TCtorParam ¶m); + ~CGroupHTML(); + + std::string getProperty( const std::string &name ) const; + void setProperty( const std::string &name, const std::string &value ); + xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const; + + // CInterfaceGroup Interface + virtual bool parse (xmlNodePtr cur, CInterfaceGroup *parentGroup); + virtual void draw (); + + // Events + virtual bool handleEvent (const NLGUI::CEventDescriptor& eventDesc); + + // Browse + virtual void browse (const char *url); + + // Refresh + void refresh(); + + // submit form + void submitForm (uint formId, const char *submitButtonName); + + // Browse error + void browseError (const char *msg); + + // stop browse + void stopBrowse (); + + bool isBrowsing(); + + void clean() { stopBrowse(); updateRefreshButton(); removeContent(); } + + // Update coords + void updateCoords(); + + // New paragraph + void newParagraph(uint beginSpace); + + // End of the paragraph + void endParagraph(); + + // Timeout + void setTimeout(float tm) {_TimeoutValue= std::max(0.f, tm);} + float getTimeout() const {return (float)_TimeoutValue;} + + // Some constants + NLMISC::CRGBA BgColor; + NLMISC::CRGBA ErrorColor; + NLMISC::CRGBA LinkColor; + NLMISC::CRGBA TextColor; + NLMISC::CRGBA H1Color; + NLMISC::CRGBA H2Color; + NLMISC::CRGBA H3Color; + NLMISC::CRGBA H4Color; + NLMISC::CRGBA H5Color; + NLMISC::CRGBA H6Color; + bool ErrorColorGlobalColor; + bool LinkColorGlobalColor; + bool TextColorGlobalColor; + bool H1ColorGlobalColor; + bool H2ColorGlobalColor; + bool H3ColorGlobalColor; + bool H4ColorGlobalColor; + bool H5ColorGlobalColor; + bool H6ColorGlobalColor; + uint TextFontSize; + uint H1FontSize; + uint H2FontSize; + uint H3FontSize; + uint H4FontSize; + uint H5FontSize; + uint H6FontSize; + uint TDBeginSpace; + uint PBeginSpace; + uint LIBeginSpace; + uint ULBeginSpace; + uint LIIndent; + uint ULIndent; + float LineSpaceFontFactor; + std::string DefaultButtonGroup; + std::string DefaultFormTextGroup; + std::string DefaultFormTextAreaGroup; + std::string DefaultFormSelectGroup; + std::string DefaultCheckBoxBitmapNormal; + std::string DefaultCheckBoxBitmapPushed; + std::string DefaultCheckBoxBitmapOver; + std::string DefaultBackgroundBitmapView; + std::string CurrentLinkTitle; + + // Browser home + std::string Home; + + // Undo browse: Browse the precedent url browsed. no op if none + void browseUndo (); + // Redo browse: Browse the precedent url undoed. no op if none + void browseRedo (); + // clear undo/redo + void clearUndoRedo(); + + + std::string getURL() const { return _URL; } + void setURL(const std::string &url); + + + int luaBrowse(CLuaState &ls); + int luaRefresh(CLuaState &ls); + int luaRemoveContent(CLuaState &ls); + int luaInsertText(CLuaState &ls); + int luaAddString(CLuaState &ls); + int luaAddImage(CLuaState &ls); + int luaBeginElement(CLuaState &ls); + int luaEndElement(CLuaState &ls); + int luaShowDiv(CLuaState &ls); + + REFLECT_EXPORT_START(CGroupHTML, CGroupScrollText) + REFLECT_LUA_METHOD("browse", luaBrowse) + REFLECT_LUA_METHOD("refresh", luaRefresh) + REFLECT_LUA_METHOD("removeContent", luaRemoveContent) + REFLECT_LUA_METHOD("insertText", luaInsertText) + REFLECT_LUA_METHOD("addString", luaAddString) + REFLECT_LUA_METHOD("addImage", luaAddImage) + REFLECT_LUA_METHOD("beginElement", luaBeginElement) + REFLECT_LUA_METHOD("endElement", luaEndElement) + REFLECT_LUA_METHOD("showDiv", luaShowDiv) + REFLECT_STRING("url", getURL, setURL) + REFLECT_FLOAT("timeout", getTimeout, setTimeout) + REFLECT_EXPORT_END + + protected : + + // \name callback from libwww + + // Begin of the parsing of a HTML document + virtual void beginBuild (); + + // End of the parsing of a HTML document + virtual void endBuild (); + + // A new text block has been parsed + virtual void addText (const char * buf, int len); + + // A link has been parsed + virtual void addLink (uint element_number, uint attribute_number, HTChildAnchor *anchor, const BOOL *present, const char **value); + + // A new begin HTML element has been parsed ( for exemple) + virtual void beginElement (uint element_number, const BOOL *present, const char **value); + + // A new end HTML element has been parsed ( for exemple) + virtual void endElement (uint element_number); + + // A new begin unparsed element has been found + virtual void beginUnparsedElement(const char *buffer, int length); + + // A new end unparsed element has been found + virtual void endUnparsedElement(const char *buffer, int length); + + // Add GET params to the url + virtual void addHTTPGetParams (std::string &url, bool trustedDomain); + + // Add POST params to the libwww list + virtual void addHTTPPostParams (HTAssocList *formfields, bool trustedDomain); + + // the current request is terminated + virtual void requestTerminated(HTRequest *request); + + // Get Home URL + virtual std::string home(); + + // Parse style html tag + TStyle parseStyle(const std::string &str_styles); + + // Handle some work at each pass + virtual void handle (); + + // \name internal methods + + // Add a group in the current parent group + void addGroup (CInterfaceGroup *group, uint beginSpace); + + // Get the current parent group + CInterfaceGroup *getCurrentGroup(); + + // Update current paragraph dependent data + void paragraphChange (); + + // Clear the contexts info + void clearContext(); + + // Translate a char + bool translateChar(ucchar &output, ucchar input, ucchar lastChar) const; + + // Add a string in the current paragraph + void addString(const ucstring &str); + + // Add an image in the current paragraph + void addImage(const char *image, bool globalColor, bool reloadImg=false); + + // Add a text area in the current paragraph + CInterfaceGroup *addTextArea (const std::string &templateName, const char *name, uint rows, uint cols, bool multiLine, const ucstring &content); + + // Add a combo box in the current paragraph + CDBGroupComboBox *addComboBox(const std::string &templateName, const char *name); + + // Add a button in the current paragraph. actionHandler, actionHandlerParams and tooltip can be NULL. + CCtrlButton *addButton(CCtrlButton::EType type, const std::string &name, const std::string &normalBitmap, const std::string &pushedBitmap, + const std::string &overBitmap, bool useGlobalColor, const char *actionHandler, const char *actionHandlerParams, const char *tooltip); + + // Set the background color + void setBackgroundColor (const NLMISC::CRGBA &bgcolor); + + // Set the background + void setBackground (const std::string &bgtex, bool scale, bool tile); + + // Force the current string to be in a single string + void flushString(); + + // Set the title + void setTitle (const ucstring &title); + + // Lookup a url in local file system + bool lookupLocalFile (std::string &result, const char *url, bool isUrl); + + // Delete page content and prepare next page + void removeContent (); + + // Current URL + std::string _URL; + + // Current DOMAIN + bool _TrustedDomain; + + // Title prefix + ucstring _TitlePrefix; + + // Title string + ucstring _TitleString; + + // Need to browse next update coords.. + bool _BrowseNextTime; + bool _PostNextTime; + uint _PostFormId; + std::string _PostFormSubmitButton; + + // Browsing.. + bool _Browsing; + bool _Connecting; + double _TimeoutValue; // the timeout in seconds + double _ConnectingTimeout; + + // minimal embeded lua script support + // Note : any embeded script is executed immediately after the closing + // element has been found + // True when the element has been encountered + bool _ParsingLua; + bool _IgnoreText; + // the script to execute + std::string _LuaScript; + + bool _Object; + std::string _ObjectScript; + + // Someone is conecting. We got problem with libwww : 2 connection requests can deadlock the client. + static CGroupHTML *_ConnectingLock; + + // LibWWW data + class CLibWWWData *_LibWWW; + + // Current paragraph + std::string _DivName; + CGroupParagraph* _Paragraph; + inline CGroupParagraph *getParagraph() + { + return _Paragraph; + /*if (_Paragraph.empty()) + return NULL; + return _Paragraph.back();*/ + } + + // PRE mode + std::vector _PRE; + inline bool getPRE() const + { + if (_PRE.empty()) + return false; + return _PRE.back(); + } + + // UL mode + std::vector _UL; + inline bool getUL() const + { + if (_UL.empty()) + return false; + return _UL.back(); + } + + // A mode + std::vector _A; + inline bool getA() const + { + if (_A.empty()) + return false; + return _A.back(); + } + + // IL mode + bool _LI; + + // Current text color + std::vector _TextColor; + inline const NLMISC::CRGBA &getTextColor() const + { + if (_TextColor.empty()) + return TextColor; + return _TextColor.back(); + } + + // Current global color flag + std::vector _GlobalColor; + inline bool getGlobalColor() const + { + if (_GlobalColor.empty()) + return false; + return _GlobalColor.back(); + } + + // Current font size + std::vector _FontSize; + inline uint getFontSize() const + { + if (_FontSize.empty()) + return TextFontSize; + return _FontSize.back(); + } + + // Current link + std::vector _Link; + inline const char *getLink() const + { + if (_Link.empty()) + return ""; + return _Link.back().c_str(); + } + + std::vector _LinkTitle; + inline const char *getLinkTitle() const + { + if (_LinkTitle.empty()) + return ""; + return _LinkTitle.back().c_str(); + } + std::vector _LinkClass; + inline const char *getLinkClass() const + { + if (_LinkClass.empty()) + return ""; + return _LinkClass.back().c_str(); + } + + // Divs (i.e. interface group) + std::vector _Divs; + inline CInterfaceGroup *getDiv() const + { + if (_Divs.empty()) + return NULL; + return _Divs.back(); + } + + // Tables + std::vector _Tables; + inline CGroupTable *getTable() const + { + if (_Tables.empty()) + return NULL; + return _Tables.back(); + } + + // Cells + std::vector _Cells; + + // TR + std::vector _TR; + inline bool getTR() const + { + if (_TR.empty()) + return false; + return _TR.back(); + } + + // Forms + class CForm + { + public: + + class CEntry + { + public: + CEntry () + { + TextArea = NULL; + Checkbox = NULL; + ComboBox = NULL; + InitialSelection = 0; + } + + // Variable name + std::string Name; + + // Variable value + ucstring Value; + + // Text area group + CInterfaceGroup *TextArea; + + // Checkbox + CCtrlButton *Checkbox; + + // Combobox group + CDBGroupComboBox *ComboBox; + + // select values (for the '; + $c .= ''; $c .= ''._t('enter_password').''; - $c .= ''; + if (RYZOM_IG) + $c .= ''; + else + $c .= ''; $c .= ''; } else { - $c .= '
'; + $c .= '
'; $c .= ''; - $c .= ''; + $c .= ''; $c .= ''; - $c .= ''; + if (RYZOM_IG) + $c .= ''; + else + $c .= ''; $c .= ''; } $c .= '
'._t('login').'
'._t('password').'
'; return $c; } +function ryzom_dialog_yes_no($desc, $action, $name) { // will append ryzom_dialog=yes|no to url + + return '
'.(RYZOM_IG?'':''). + $desc.'
+ + + +
+
'; +} + +$GLOBALS['ryzom_render_title'] = defined('APP_NAME')?APP_NAME:'Ryzom'; + +$ig = (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Ryzom')) || ryzom_get_param('ig'); // need be set using url param because auth is not done +$transparency = $ig?'':''; +$ryzom_render_styles = array(); +$ryzom_render_tmpls = array(); + +$ryzom_render_styles['main title'] = array('#222222'.$transparency, '#FFFFFF'); +$ryzom_render_tmpls['main title'] = '
 ${p[0]}
'."\n"; + +$ryzom_render_styles['section'] = array('#555555'.$transparency, '#FFFFFF'); +$ryzom_render_tmpls['section'] = '
 ${p[0]}
'."\n"; + +$ryzom_render_styles['color'] = array('', ''); +$ryzom_render_tmpls['color'] = ($ig?'':'').'${p[0]}'; + +$ryzom_render_styles['link'] = array('#111111', ''); +$ryzom_render_tmpls['link'] = '
 ${p[0]}
'."\n"; + +$ryzom_render_styles['button'] = array('#000000', ''); +$ryzom_render_tmpls['button'] = '
 ${p[0]}
'."\n"; + +$ryzom_render_styles['links'] = array('#111111'.$transparency, ''); +$ryzom_render_tmpls['links'] = '
 ${p[0]}
'."\n"; + +$ryzom_render_styles['back'] = array('#000000'.$transparency, ''); +$ryzom_render_tmpls['back'] = '
 «'.'main'.'
 
'; + +$ryzom_render_styles['highlight'] = array('#55ff55'.$transparency, ''); +$ryzom_render_tmpls['highlight'] = '${p[0]}'; + +$ryzom_render_styles['backlight'] = array('#272727'.$transparency, ''); +$ryzom_render_tmpls['backlight'] = '
${p[0]}
'."\n"; + +$ryzom_render_styles['actionbar'] = array('#555555'.$transparency, ''); +$ryzom_render_tmpls['actionbar'] = '${p[0]}'."\n"; + +$ryzom_render_styles['table'] = array('#050505'.$transparency, '#FFFFFF'); +$ryzom_render_tmpls['table'] = '${p[0]}
'."\n"; + +$ryzom_render_styles['t header'] = array('#111111'.$transparency, '#FFFFFF'); +$ryzom_render_tmpls['t header'] = '${p[0]}'."\n"; + +$ryzom_render_styles['t row 0'] = array('#353535'.$transparency, ''); +$ryzom_render_tmpls['t row 0'] = '${p[0]}'."\n"; + +$ryzom_render_styles['t row 1'] = array('#252525'.$transparency, ''); +$ryzom_render_tmpls['t row 1'] = '${p[0]}'."\n"; + +$ryzom_render_styles['t element'] = array('#FFFFFF'.$transparency, ''); +$ryzom_render_tmpls['t element'] = '${p[0]}'; + +$ryzom_render_styles['log'] = array('#001100'.$transparency, ''); +$ryzom_render_tmpls['log'] = '
${p[0]}
'."\n"; + +$ryzom_render_styles['message'] = array('#445566'.$transparency, '#FFDDAA'); +$ryzom_render_tmpls['message'] = '
${p[0]}
'."\n"; + +$ryzom_render_styles['message warning'] = array('#AA3300'.$transparency, ''); +$ryzom_render_tmpls['message warning'] = '

 ${p[0]}

'."\n"; + +$ryzom_render_styles['message window'] = array('#5555ff'.$transparency, '#7799ff'); +$ryzom_render_tmpls['message window'] = ''.''. + '
${p[0]}${p[0]}
'."\n"; + +$ryzom_render_styles['message ask'] = array('#333333'.$transparency, ''); +$ryzom_render_tmpls['message ask'] = '
'.($ig?'':'').'${p[0]}
'."\n"; + +$ryzom_render_styles['message error'] = array('#AA2222'.$transparency, ''); +$ryzom_render_tmpls['message error'] = '

 ${p[0]}

'."\n"; + +$ryzom_render_styles['message debug'] = array('#FFAA22'.$transparency, ''); +$ryzom_render_tmpls['message debug'] = '
${p[0]}
'."\n"; + +$ryzom_render_styles['progress bar'] = array('#FF0000'.$transparency, '#000000'); +$ryzom_render_tmpls['progress bar'] = '${p[0]}
 ${p[0]} 
'."\n"; + ?> diff --git a/code/web/api/common/ryform.php b/code/web/api/common/ryform.php new file mode 100644 index 000000000..40373febd --- /dev/null +++ b/code/web/api/common/ryform.php @@ -0,0 +1,680 @@ +. + */ + +include_once (RYAPI_PATH.'/common/ryformBases.php'); + +class ryVar extends basicRyForm { + public $formName = ''; + public $varName = ''; + public $varValue = ''; + + function getFormDefs() { + return array( + new ryFormDef('varName', DEF_TYPE_TEXT), + new ryFormDef('varValue', DEF_TYPE_TEXT), + ); + } + + function getHtmlRepr() { + return $this->varName.' => '.$this->varValue; + } +} + +class ryForm { + + private $name = ''; + private $defines = array(); + private $template = ''; + + static private $forms; + static private $ryformsIcons = array(); + + function __construct($dir, $name) { + $this->name = $name; + self::$forms[$dir.'/'.$name] = $this; + } + + static function addRyFormIcon($ryform_name, $icon) { + self::$ryformsIcons[$ryform_name] = $icon; + } + + function addDefine($def) { + $this->defines[$def->name] = $def; + } + + function setTemplate($template) { + $this->template = $template; + } + + function getTemplate() { + return $this->template; + } + + function addValue($name, $value) { + if (array_key_exists($name, $this->defines)) + $this->defines[$name]->value = $value; + else + return false; + return true; + } + + function addExtraValues($name, $value) { + if (array_key_exists($name, $this->defines)) + $this->defines[$name]->extraValues = $value; + else + return false; + return true; + } + + function getForm($params) { + + if (isset($params['ryform_action']) && $params['ryform_action']) { + $res = $this->doAction($params); + return $res; + } + + if (@$params['validate'] == $this->name) + return array(DATA_FORM_VALUES, $_POST); + + if (isset($params['ryform_parent'])) + $parent_ryform_name = $params['ryform_parent'].'/'; + else + $parent_ryform_name = ''; + + $action =_url(ryzom_get_params(), array('validate' => $this->name)); + $ret = ''; + $ret .= '
'."\n"; + + if (!$this->getTemplate()) { + $ret .= ' '."\n"; + $ret .= ' '._s('t header', '')."\n"; + $tmpl = ''; + } else { + $tmpl = $this->getTemplate(); + } + + $i = 0; + + foreach ($this->defines as $def_id => $def) { + if ($def->name == 'name') + $def->name = '_name'; + + $deffullname = $def->name; + $url_params = ryzom_get_params(); + $type = $def->type; + $infos = $def->infos; + $value = ($def->value !== NULL)?$def->value:$def->defaultValue; + + if (!is_object($value) && !is_array($value)) + $str_value = _h(strval($value)); + else + $str_value = ''; + + if ($def->hidden) + $type = DEF_TYPE_HIDDEN; + + $hidden = false; + $input = ''; + switch ($type) { + + case DEF_TYPE_HIDDEN: + $input = ''."\n"; + $hidden = true; + break; + + case DEF_TYPE_TEXT: + $input = ''; + break; + case DEF_TYPE_NAMEID: + $input = ''; + break; + + case DEF_TYPE_ID: + case DEF_TYPE_INT: + case DEF_TYPE_FLOAT: + $input = ''; + break; + + case DEF_TYPE_BOOL: + $input = ''; + break; + + case DEF_TYPE_OPTION_FUNCTION: + case DEF_TYPE_OPTION: + if ($type == DEF_TYPE_OPTION) + $options = $def->params; + else { + if (is_array($def->defaultValue)) + $options = call_user_func_array($def->params, $def->defaultValue); + else + $options = call_user_func($def->params); + } + $input = ''; + break; + + case DEF_TYPE_COMBO_FUNCTION: + case DEF_TYPE_COMBO: + if ($type == DEF_TYPE_COMBO) + $options = $def->params; + else { + if (is_array($def->defaultValue)) + $options = call_user_func_array($def->params, $def->defaultValue); + else + $options = call_user_func($def->params); + } + if (_user()->ig) { + // TODO : try to do it with lua + } else { // HTML 4 + $input .= ' + '; + } + break; + + case DEF_TYPE_TEXTAREA: + if (!$value) + $value = ""; + $input = '
'.($type == DEF_TYPE_BBCODE?'- BBCode -
':'').'
'; + break; + + case DEF_TYPE_TRAD: + $base = ''; + $param = $def->name; + $value = array_merge(array('en' => '', 'fr' => '', 'de' => '', 'ru' => '', 'es' => ''), $value); + $base = ryzom_get_param('select_base', ''); + $edit = $display = $input_header = ''; + foreach (array('en', 'fr', 'de', 'ru', 'es') as $lang) { + if (_user()->lang == $lang) + $edit = _i($lang == 'en'?API_URL.'data/img/lang/us.png':API_URL.'data/img/lang/'.$lang.'.png').' '; + if ((!$base && $value[$lang]) || $base == $lang) { + $base = $lang; + $display = strtoupper($lang).' = '.str_replace("\n", '
', _h($value[$lang])).'
'; + } + $input .= ''; + $input_header .= _l(_i($lang == 'en'?API_URL.'data/img/lang/us.png':API_URL.'data/img/lang/'.$lang.'.png'), $url_params, array('select_base' => $lang)).'  '; + } + + $input = $input_header.$input.'   '.$display.'
'.$edit; + break; + + case DEF_TYPE_RYFORM: + case DEF_TYPE_RYFORMS_ARRAY: + $savedRyform = $value; + if (is_array($savedRyform)) { + $to_clean = array(); + foreach ($savedRyform as $id => $ryform) { + if (!is_object($ryform)) + $to_clean[] = $id; + } + foreach ($to_clean as $id) + unset($savedRyform[$id]); + $savedRyform = array_values($savedRyform); + } else if (is_object($savedRyform)) { + $savedRyform = array($savedRyform); + } else + $savedRyform = array(); + + $input .= '
'._t('parameter').''._t('value').'
'; + if ($savedRyform) { + foreach ($savedRyform as $id => $ryform) { + if (!is_object($ryform)) { + p('!!! ERROR !!!', $ryform); + continue; + } + $ryform->id = $id+1; + if (!isset($ryform->formName) || !$ryform->formName) + $ryform->formName = 'Element '.$id; + if (count($savedRyform) > 1) + $display_id = ''.strval(intval($id)+1).''; + else + $display_id = ''; + + $script_up = ($id != 0)?_l(_i('16/arrow_up', _t('up')), $url_params, array('ryform_name' => $parent_ryform_name.$deffullname.':'.$id, 'ryform_action' => 'up')).' ':''; + $script_down = ($id != count($savedRyform)-1)?_l(_i('16/arrow_down', _t('down')), $url_params, array('ryform_name' => $parent_ryform_name.$deffullname.':'.$id, 'ryform_action' => 'down')).' ':''; + + $icon = (isset(self::$ryformsIcons[get_class($ryform)]))?self::$ryformsIcons[get_class($ryform)]:_i('32/brick'); + $input .= _s('t row '.($id%2), + ''. + ''. + ''); + } + } + $input .= '
'._l(($def->type == DEF_TYPE_RYFORM?_i('16/arrow_redo', _t('change')):_i('16/add', _t('add'))), $url_params, array('ryform_name' => $parent_ryform_name.$deffullname.':'.strval(intval($id)+1), 'ryform_action' => 'list')).' '.$display_id.''.$script_up.$script_down.' + + + +
'.$icon.''. + _l($ryform->formName, $url_params, array('ryform_name' => $parent_ryform_name.$deffullname.':'.$id, 'ryform_action' => 'edit')).' '. + '
'._t(get_class($ryform).'_short_description').'
'.$ryform->getHtmlRepr().'
'. + _l(_i('16/script_edit', _t('edit')), $url_params, array('ryform_name' => $parent_ryform_name.$deffullname.':'.$id, 'ryform_action' => 'edit')).' '. + _l(_i('16/script_code', _t('edit_source')), $url_params, array('ryform_name' => $parent_ryform_name.$deffullname.':'.$id, 'ryform_action' => 'source')).'      '. + _l(_i('16/script_delete', _t('del')), $url_params, array('ryform_name' => $parent_ryform_name.$deffullname.':'.$id, 'ryform_action' => 'del')).' 
'; + if (count($savedRyform) == 0 || $def->type != DEF_TYPE_RYFORM) { + if (is_string($def->params)) + $infos = _l(_i('16/add', _t('add')), $url_params, array('new_ryform' => $def->params, 'ryform_name' => $parent_ryform_name.$deffullname.':0', 'ryform_action' => 'add')); + else if (count($def->params) == 1) + $infos = _l(_i('16/add', _t('add')), $url_params, array('new_ryform' => $def->params[0], 'ryform_name' => $parent_ryform_name.$deffullname.':0', 'ryform_action' => 'add')); + else + + $infos = _l(_i('16/add', _t('add')), $url_params, array('ryform_name' => $parent_ryform_name.$deffullname.':0', 'ryform_action' => 'list')); + + if ($type == DEF_TYPE_RYFORMS_ARRAY) + $infos .= '   '._l(_i('16/application_form_add', _t('multiadd')), $url_params, array('ryform_name' => $deffullname, 'ryform_action' => 'list_multiadd')); + } + break; + + case DEF_TYPE_FUNCTION: + if (is_array($def->defaultValue)) + list($result_type, $value) = call_user_func_array($def->params, $def->defaultValue); + else + list($result_type, $value) = call_user_func($def->params); + if ($result_type == DATA_HTML_FORM) { + return array(DATA_HTML_FORM, $value); + } else { + unset($url_params[$deffullname.'_action']); + $input = $value; + } + break; + + default: + $input = ''.$value."\n"; + $hidden = true; + + } + + if ($hidden) + $ret .= $input; + else + { + if ($tmpl) { + $tmpl = str_replace('{'.$def->name.'}', 'ig?'color="orange" size="11"':'style="color:orange;"').'>'._t($def->prefixTrad.$def->name).'', $tmpl); + $tmpl = str_replace('{'.$def->name.'.input}', $input, $tmpl); + $tmpl = str_replace('{'.$def->name.'.infos}', $infos, $tmpl); + } else + $ret .= _s('t row '.strval($i % 2), ' '.(!$def->optional?'*':'').($def->superAdmin?'##':'').($def->admin?'#':'')._t($def->prefixTrad.$def->name).''.$input.''.$infos.'')."\n"; + $i++; + } + } + + if ($tmpl) { + $tmpl = str_replace('{submit.input}', '', $tmpl); + $ret .= $tmpl; + $ret .= ''._s('t row '.strval($i % 2), '').'
     '._t('required_fields').'
'; + } else { + $ret .= _s('t row '.strval($i % 2), '     '._t('required_fields').''); + $ret .= ''; + } + $ret .= '

'; + return array(DATA_HTML_FORM, $ret."\n"); + } + + + function doAction($url_params) { + if (!$url_params['ryform_name']) + return array(DATA_RYFORM_VALUE, array()); + $ret = ''; + $ryforms = explode('/', $url_params['ryform_name']); + $this_ryform_name = array_shift($ryforms); + list($ryform_name,$ryform_pos) = explode(':', $this_ryform_name); + if (!isset($this->defines[$ryform_name])) + return 'Bad ryform name'; + $def = $this->defines[$ryform_name]; + + if ($ryforms) { + $action = 'edit'; + $next_action = $url_params['ryform_action']; + } else { + $action = $url_params['ryform_action']; + $next_action = ''; + } + + switch ($action) { + case 'list': + if (isset($url_params['ryform_parent']) && $url_params['ryform_parent']) + $ryform_parent = $url_params['ryform_parent'].'/'; + else + $ryform_parent = ''; + $ret .= ''; + foreach ($def->params as $id => $ryform) { + if (is_array($ryform)) { + $ret .= _s('t row 1', ''); + foreach ($ryform as $subid => $subryform) { + $ret .= _s('t row '.($subid%2), ''); + } + } else + $ret .= _s('t row '.($id%2), ''); + } + $ret .= '
'.ryzom_font(_t('ryform_cat_'.$id), '', '12').''.self::$ryformsIcons[$subryform].'  '. + _l(_t($subryform.'_short_description'), $url_params, array('ryform_name' => $ryform_parent.$url_params['ryform_name'], 'ryform_action' => 'add', 'new_ryform' => $subryform)).''.$subryform.''.self::$ryformsIcons[$ryform].'  '. + _l(_t($ryform.'_short_description'), $url_params, array('ryform_name' => $ryform_parent.$url_params['ryform_name'], 'ryform_action' => 'add', 'new_ryform' => $ryform)).''.$ryform.'
'; + return array(DATA_HTML_FORM, $ret); + break; + + case 'list_multiadd': + // TODO + /* + unset($url_params[$deffullname.'_action']); + $ret .= ''; + foreach ($def->params as $ryform) { + $ret .= ''; + } + $ret .= '
'._l($ryform, $url_params, array('ryform_action' => 'multiadd', 'new_ryform' => $ryform)).'
'; + return array(DATA_HTML_FORM, $ret);*/ + break; + + case 'add': + $new_ryform = ryzom_get_param('new_ryform'); + $valid_ryform = false; + if ($new_ryform) { + + if ((is_string($def->params) && $new_ryform == $def->params) || in_array($new_ryform, $def->params)) + $valid_ryform = true; + else { + foreach ($def->params as $param) { + if (is_array($param) && in_array($new_ryform, $param)) + $valid_ryform = true; + } + } + if (!$valid_ryform) + return array(DATA_HTML_FORM, 'Bad ryform'); + + } else { + $new_ryform = $def->params; + } + $ryform = new $new_ryform($new_ryform, ''); + $ryform->preSerialization(); + if ($def->type != DEF_TYPE_RYFORM) { + p($def->value); + if (!is_array($def->value)) + $savedRyform = array($def->value); + else + $savedRyform = $def->value; + if ($ryform_pos === 0) { + $value = array_values(array_merge(array($ryform), $savedRyform)); + } else if ($ryform_pos !== NULL) { + $begin = array_slice($savedRyform, 0, $ryform_pos); + $end = array_slice($savedRyform, $ryform_pos, count($savedRyform)-$ryform_pos); + $value = array_values(array_merge($begin, array($ryform), $end)); + } else + $value[] = $ryform; + p($ryform_name, $value); + //return array(DATA_RYFORM_VALUE, array('stages' => array())); + return array(DATA_RYFORM_VALUE, array($ryform_name => $value)); + } else { + p($ryform_name, $ryform); + return array(DATA_RYFORM_VALUE, array($ryform_name => $ryform)); + } + break; + + case 'edit': + $a_ryforms = $def->value; + if (is_array($a_ryforms)) + $ryform = $a_ryforms[$ryform_pos]; + else + $ryform = $a_ryforms; + $ryform->postSerialization(); + $validate = isset($url_params['validate']) && $url_params['validate']; + + $form = new ryForm('', $def->name); + foreach ($ryform->getFormDefs() as $form_def) { + $form->addDefine($form_def); + $name = $form_def->name; + // Init form with ryfom values + if (property_exists($ryform, $name)) { + $form->addValue($form_def->name, $ryform->$name); + } + } + foreach ($ryform->getFormDefsExtraValues() as $def_name => $extra_values) + $form->addExtraValues($def_name, $extra_values); + $form->setTemplate($ryform->getTemplate()); + + list($result_type, $value) = $form->getForm(array('action' => $url_params['action'], 'script' => $url_params['script'], 'ryform_action' => $next_action, 'ryform_parent' => $this_ryform_name, 'ryform_name' => implode('/', $ryforms), 'validate' => $validate)); + if ($result_type == DATA_HTML_FORM) { + return array(DATA_HTML_FORM, $value); + } else { + if ($result_type == DATA_FORM_VALUES) + $value = $form->validateFormPost($value); + $ryform->setFormParams($value); + $ryform->preSerialization(); + + } + if (is_array($a_ryforms)) + $a_ryforms[$ryform_pos] = $ryform; + else + $a_ryforms = $ryform; + + $value = array($ryform_name => $a_ryforms); + return array(DATA_RYFORM_VALUE, $value); + break; + + + case 'del': + $id = $ryform_pos; + p($def->value); + if (!is_array($def->value)) + $def->value = array(); + else + unset($def->value[$id]); + $value = array_values($def->value); + return array(DATA_RYFORM_VALUE, array($ryform_name => $value)); + break; + + case 'up': + $a_ryforms = $def->value; + if (!is_array($a_ryforms)) + ryzom_redirect(_url($url_params, array('ryform_action' => ''))); + + $temp_ryform = $a_ryforms[$ryform_pos-1]; + $a_ryforms[$ryform_pos-1] = $a_ryforms[$ryform_pos]; + $a_ryforms[$ryform_pos] = $temp_ryform; + $a_ryforms = array_values($a_ryforms); + p($ryform_name, $a_ryforms); + return array(DATA_RYFORM_VALUE, array($ryform_name => $a_ryforms)); + break; + + case 'down': + $a_ryforms = $def->value; + if (!is_array($a_ryforms)) + ryzom_redirect(_url($url_params, array('ryform_action' => ''))); + + $temp_ryform = $a_ryforms[$ryform_pos+1]; + $a_ryforms[$ryform_pos+1] = $a_ryforms[$ryform_pos]; + $a_ryforms[$ryform_pos] = $temp_ryform; + $a_ryforms = array_values($a_ryforms); + return array(DATA_RYFORM_VALUE, array($ryform_name => $a_ryforms)); + break; + + case 'source': + $a_ryforms = $def->value; + if (is_array($a_ryforms)) + $ryform = $a_ryforms[$ryform_pos]; + else + $ryform = $a_ryforms; + $ryform->postSerialization(); + + $form = new ryForm('', $def->name); + $form->addDefine(new ryFormDef('ryform_source', DEF_TYPE_TEXTAREA, '', base64_encode(serialize($ryform)))); + $validate = isset($url_params['validate']) && $url_params['validate']; + list($result_type, $value) = $form->getForm(array('ryform_action' => $next_action, 'ryform_parent' => $this_ryform_name, 'ryform_name' => implode('/', $ryforms), 'validate' => $validate)); + if ($result_type == DATA_HTML_FORM) { + return array(DATA_HTML_FORM, $value); + } else { + if ($result_type == DATA_FORM_VALUES) + $params = $form->validateFormPost($value); + else + $params = $value; + $ryform = unserialize(base64_decode($params['ryform_source'])); + if (!is_object($ryform)) { + unset($url_params['validate']); + ryzom_redirect(_url($url_params, array('ryform_action' => '', 'message' => 'bad_paste'))); + } + + $is_valid = false; + p($def->params); + foreach ($def->params as $id => $ryform_class) { + if (is_array($ryform_class)) { + if (in_array(get_class($ryform), array_values($ryform_class))) + $is_valid = true; + } else if (get_class($ryform) == $ryform_class) + $is_valid = true; + } + if (!$is_valid) { + p(get_class($ryform), $def->params); + ryzom_redirect(_url($url_params, array($deffullname.'_action' => '', 'message' => 'not_valid_stage'))); + return; + } + if (is_array($a_ryforms)) + $a_ryforms[$ryform_pos] = $ryform; + else + $a_ryforms = $ryform; + $value = array($ryform_name => $a_ryforms); + return array(DATA_RYFORM_VALUE, $value); + } + return; + break; + } + + return $ret; + } + + function validateFormPost($params, $use_default=true) { + $final = array(); + foreach ($this->defines as $def) { + $name = $def->name; + if ($def->name == 'name') + $def->name = '_name'; + + $type = $def->type; + if ($def->hidden) + $type = DEF_TYPE_HIDDEN; + + if (isset($params[$def->name])) { + $value = $params[$def->name]; + } else if (!$use_default) { + continue; + } else { + $value = ''; + } + + + switch ($type) { + + case DEF_TYPE_HIDDEN: + case DEF_TYPE_TEXT: + case DEF_TYPE_OPTION: + case DEF_TYPE_TEXTAREA: + $final[$name] = $value; + break; + + case DEF_TYPE_TRAD: + if (!$value[_user()->lang] && $value['europeanunion']) + $value[_user()->lang] = $value['europeanunion']; + $final[$name] = $value; + break; + + case DEF_TYPE_NAMEID: + $final[$name] = cleanNameID($value); + break; + + case DEF_TYPE_COMBO: + $final[$name] = $value; + break; + + case DEF_TYPE_ID: + case DEF_TYPE_INT: // TODO + $final[$name] = intval($value); + break; + case DEF_TYPE_FLOAT: // TODO + $final[$name] = floatval($value); + break; + + case DEF_TYPE_BOOL: + $final[$name] = $value == 'on'; + break; + + case DEF_TYPE_RYFORM: + if (is_array($value)) + $final[$name] = $value[0]; + break; + case DEF_TYPE_RYFORMS_ARRAY: + break; + + default: + $final[$name] = $value; + + } + } + return $final; + } + +/* + function reset() { + + // Clean all temp files + $userDatas = _tools()->listAppDataFiles($this->dir); + foreach ($userDatas as $userData) { + if (substr($userData, 0, strlen($this->name)) == $this->name) + _tools()->saveAppData($this->dir.'/'.$userData, NULL); + } + }*/ +} + +?> diff --git a/code/web/api/common/ryformBases.php b/code/web/api/common/ryformBases.php new file mode 100644 index 000000000..07762953f --- /dev/null +++ b/code/web/api/common/ryformBases.php @@ -0,0 +1,304 @@ +. + */ + +define('DEF_TYPE_UNKNOWN', 0); +define('DEF_TYPE_HIDDEN', 1); +define('DEF_TYPE_TEXT', 2); +define('DEF_TYPE_ID', 3); +define('DEF_TYPE_INT', 4); +define('DEF_TYPE_FLOAT', 5); +define('DEF_TYPE_BOOL', 6); +define('DEF_TYPE_OPTION', 7); +define('DEF_TYPE_TEXTAREA', 8); +define('DEF_TYPE_TRAD', 9); +define('DEF_TYPE_FORM', 10); +define('DEF_TYPE_ICON', 11); +define('DEF_TYPE_RYFORM', 12); +define('DEF_TYPE_RYFORMS_ARRAY', 13); +define('DEF_TYPE_BBCODE', 14); +define('DEF_TYPE_FUNCTION', 15); +define('DEF_TYPE_COMBO', 16); +define('DEF_TYPE_OPTION_FUNCTION', 17); +define('DEF_TYPE_NAMEID', 18); +define('DEF_TYPE_COMBO_FUNCTION', 19); +define('DEF_TYPE_DATE', 20); + + +define('DEF_TYPE_ICON_UNKNOWN', 0); +define('DEF_TYPE_ICON_SHARED', 1); +define('DEF_TYPE_ICON_RYZITEM', 2); +define('DEF_TYPE_ICON_URL', 3); + +define('DATA_HTML_FORM', 0); +define('DATA_FORM_VALUES', 1); +define('DATA_FORM_VALID_VALUES', 2); +define('DATA_RYFORM_VALUE', 3); + +function cleanFormName($name) { + $final_name = ''; + for ($i=0; $i= ord('a')) && (ord(strtolower($c)) <= ord('z'))) || + (in_array($c, array('-', '.', '_'))) || + (ord(strtolower($c)) >= ord('0')) && (ord(strtolower($c)) <= ord('9')) ) + $final_name .= $c; + } + return $final_name; +} + +function cleanNameID($name) { + $final_name = ''; + for ($i=0; $i= ord('a')) && (ord(strtolower($c)) <= ord('z'))) || + (ord($c) >= ord('0')) && (ord($c) <= ord('9')) ) + $final_name .= $c; + } + return $final_name; +} + +function getNameId($name) { + return str_replace('_', ' ', $name); +} + +function getTrad($value) { + if ($value[_user()->lang]) + $trad = $value[_user()->lang]; + foreach (array('en', 'fr', 'de', 'ru', 'es') as $lang) { + if ($value[$lang]) { + $trad = $value[$lang]; + break; + } + } + if (substr($trad, 0, 2) == '//') + $trad = strstr(str_replace("\r", '', $trad), "\n"); + return substr($trad, 1); +} + +function setRyformSource($object, $src, $indent=0, $protecteds=array()) { + $c = ''; + $src = str_replace("\r", '', $src); + $ssrc = explode("\n", $src); + $mode = 'var'; + $cache = ''; + $current_ryform = NULL; + foreach ($ssrc as $line) { + if (!$line) + continue; + if ($mode != 'ryform') + $c .= str_repeat("\t", $indent); + switch ($mode) { + case 'ryform': + if ($line[0] == "\t") { + $cache .= substr($line, 1)."\n"; + break; + } else { + $mode = 'array'; + } + + case 'array': + if ($line == ')' || $line == '}') { + if ($cache && $current_ryform) { + $c .= $current_ryform->setSource($cache, $indent+1); + $c .= 'SET SOURCE '; + if ($line == ')') + $array[] = $current_ryform; + else + $array = $current_ryform; + } + if (array_key_exists($var_name, $protecteds)) + call_user_func(array($object, $protecteds[$var_name]), $array); + else + $object->$var_name = $array; + $mode = 'var'; + $cache = ''; + continue; + } else if ($line[0] == '[') { + if ($cache && $current_ryform) { + $c .= $current_ryform->setSource($cache, $indent+1); + $array[] = $current_ryform; + $c .= 'SET SOURCE '; + } + $ryform_name = substr($line, 1, strlen($line)-2); + $c .= 'New Ryform: '.$ryform_name."\n"; + $cache = ''; + $current_ryform = new $ryform_name(); + $mode = 'ryform'; + continue; + } + break; + + default: + $sep = strpos($line, '='); + if ($sep) { + $var_name = substr($line, 0, $sep-1); + $value = substr($line, $sep+2); + if ($value == '(' || $value == '{') { + $c .= $var_name.' is ARRAY'."\n"; + $mode = 'array'; + $array = array(); + } else { + $c .= $var_name .' = '.$value."\n"; + if ($value[0] == '\'' && $value[strlen($value)-1] == '\'') + $object->$var_name = str_replace('\n', "\n", substr($value, 1, -1)); + else { + if (is_numeric($value)) + $object->$var_name = eval('return '.$value.';'); + else if ($value == 'false') + $object->$var_name = false; + else if ($value == 'true') + $object->$var_name = true; + else if ($value == 'NULL') + $object->$var_name = NULL; + } + } + } + break; + } + } + return $c; + } + +interface iRyForm { + function getForm($url_params); + function setFormParams($params); + function getHtmlRepr(); + function getFormDefs(); + function getFormDefsExtraValues(); + function preSerialization(); + function postSerialization($vars=array()); + function getTemplate(); +} + +class ryFormDef { + + public $name = ''; + public $type = DEF_TYPE_UNKNOWN; + public $params = array(); + public $infos = ''; + public $defaultValue = NULL; + public $value = NULL; + public $extraValues = array(); + public $hidden = false; + public $optional = false; + public $admin = false; + public $superAdmin = false; + public $prefixTrad = ''; + + function __construct($name, $type, $params=array(), $defaultValue=NULL, $optional=false, $infos='') { + $this->name = $name; + $this->type = $type; + $this->params = $params; + $this->defaultValue = $defaultValue; + $this->optional = $optional; + $this->infos = $infos; + } + +} + +class basicRyForm implements iRyForm { + public $formName = ''; // Used by Form + public $id = 0; + + function __construct($name='', $title='') { + } + + function getForm($url_params) { + $form = new ryForm($this->formName); + $form_defs = $this->getFormDefs(); + foreach ($form_defs as $def) + $form->addDefine($def); + return $form->getForm(_s('section', $this->formName.' ('.get_class($this).')')); + } + + function setFormParams($params) { + foreach ($params as $name => $value) { + if (property_exists($this, $name)) + $this->$name = $value; + } + } + + function getHtmlRepr() { + return $this->formName.' ('.get_class($this).')'; + } + + function getFormDefs() { + return array(); + } + + function getFormDefsExtraValues() { + return array(); + } + + /*function preSerialization() { + unset($this->tools); + }*/ + + function preSerialization() { + $all_defs = array('class_name'); + $this->author = _user()->id; + foreach ($this->getFormDefs() as $def) + $all_defs[] = $def->name; + + foreach (get_object_vars($this) as $name => $value) { + if (!in_array($name, $all_defs)) + unset($this->$name); + } + } + + function postSerialization($vars=array()) { + } + + function getTemplate() { + return ''; + } + + function getSource($indent=0) { + $attrs = $this->getFormDefs(); + $c = str_repeat("\t", $indent-1).'['.get_class($this).']'."\n"; + foreach ($attrs as $attr) { + $c .= str_repeat("\t", $indent).$attr->name.' '; + $var = $this->{$attr->name}; + if (is_object($var)) { + $c .= "= {\n".substr($var->getSource($indent+1), 0, -1)."\n".str_repeat("\t", $indent).'}'; + } else if (is_array($var)) { + $c .= '= ('."\n"; + foreach ($var as $element) { + if (is_object($element)) + $c .= $element->getSource($indent+1); + else if ($element) + $c .= '#'.str_replace("\r", '', str_replace("\n", '\\\\n', var_export($element, true))); + } + $c .= str_repeat("\t", $indent).")"; + } else + $c .= '= '.str_replace("\r", '', str_replace("\n", '\\\\n', var_export($var, true))); + $c .= "\n"; + } + return $c; + } + + function setSource($src, $indent=0) { + $this->preSerialization(); + return setRyformSource($this, $src, $indent); + } +} + +?> diff --git a/code/web/api/common/time.php b/code/web/api/common/time.php new file mode 100644 index 000000000..9d2020efe --- /dev/null +++ b/code/web/api/common/time.php @@ -0,0 +1,130 @@ +. + */ + +/* Basic constants */ +/* 1 IG hour = 3 IRL minutes = 1800 ticks */ +define('RYTIME_HOUR_TICKS', 1800); +define('RYTIME_DAY_HOURS', 24); +define('RYTIME_SEASON_DAYS', 90); +define('RYTIME_MONTH_DAYS', 30); +define('RYTIME_CYCLE_MONTHS', 12); +define('RYTIME_JY_CYCLES', 4); +define('RYTIME_WEEK_DAYS', 6); +/* 0 = spring, 1 = summer, 2 = automn, 3 = winter */ +define('RYTIME_CYCLE_SEASONS', 4); +/* Tick is offset on server of 61 days. */ +define('RYTIME_TICK_OFFSET', 61 * RYTIME_DAY_HOURS * RYTIME_HOUR_TICKS); + +define('RYTIME_START_JY', 2568); + +/* Helpers */ +define('RYTIME_CYCLE_DAYS',RYTIME_CYCLE_MONTHS * RYTIME_MONTH_DAYS); +define('RYTIME_JY_DAYS', RYTIME_CYCLE_DAYS * RYTIME_JY_CYCLES); +define('RYTIME_JY_MONTHS', RYTIME_CYCLE_MONTHS * RYTIME_JY_CYCLES); + +// Takes a server tick and returns a computed array +function ryzom_time_array($tick) { + $out = array(); + $out["server_tick"] = $tick; + + $time_in_hours = ($tick-RYTIME_TICK_OFFSET) / RYTIME_HOUR_TICKS; + $day = $time_in_hours / RYTIME_DAY_HOURS; + + $out["jena_year"] = floor($day / RYTIME_JY_DAYS) + RYTIME_START_JY; + if ($day < 0) $day = RYTIME_JY_DAYS - abs($day) % RYTIME_JY_DAYS; + $out["day_of_jy"] = $day % RYTIME_JY_DAYS; + $out["month_of_jy"] = floor($out["day_of_jy"] / RYTIME_MONTH_DAYS); + + $out["cycle"] = floor($out["day_of_jy"] / RYTIME_CYCLE_DAYS); + $out["day_of_cycle"] = $day % RYTIME_CYCLE_DAYS; + $out["month_of_cycle"] = $out["month_of_jy"] % RYTIME_CYCLE_MONTHS; + + $out["day_of_month"] = $out["day_of_jy"] % RYTIME_MONTH_DAYS; + $out["day_of_week"] = $day % RYTIME_WEEK_DAYS; + + $out["season"] = ($day / RYTIME_SEASON_DAYS) % RYTIME_CYCLE_SEASONS; + $out["day_of_season"] = $day % RYTIME_SEASON_DAYS; + + $out["time_of_day"] = abs($time_in_hours) % RYTIME_DAY_HOURS; + if ($time_in_hours < 0 && $out["time_of_day"]) $out["time_of_day"] = RYTIME_DAY_HOURS - $out["time_of_day"]; + + return $out; +} + +function ryzom_time_xml_without_cache($rytime) { + $out = new SimpleXMLElement(''); + foreach($rytime as $key => $value) { + $out->addChild($key, $value); + } + return $out; +} + +/** + * Take number of the month (0-11) and returns its name + */ +function ryzom_month_name($month_number) { + if ($month_number < 0 || $month_number > 11) return "bad month"; + + $RYTIME_MONTHS = array( + 'Winderly', 'Germinally', 'Folially', 'Floris', + 'Medis', 'Thermis', 'Harvestor', 'Frutor', + 'Fallenor', 'Pluvia', 'Mystia', 'Nivia' + ); + + return $RYTIME_MONTHS[(int)$month_number]; +} + + +/** + * Take number of the day of week (0-5) and returns its name + */ +function ryzom_day_name($day_number) { + if ($day_number < 0 || $day_number > 5) return "bad day of week"; + + $RYTIME_DAYS = array( + 'Prima', 'Dua', 'Tria', + 'Quarta', 'Quinteth', 'Holeth' + ); + + return $RYTIME_DAYS[(int)$day_number]; +} + +/** + * Take a computed ryzom time array and returns the formatted date + * (Official 2004 Format without trailing JY) + */ +function ryzom_time_txt($rytime, $lang = "en") { + if ($lang != "en" && $lang != "fr" && $lang != "de") $lang = "en"; + + $RYTIME_AC = array( + "de" => array("1. AZ", "2. AZ", "3. AZ", "4. AZ"), + "en" => array("1st AC", "2nd AC", "3rd AC", "4th AC"), + "fr" => array("1er CA", "2e CA", "3e CA", "4e CA") + ); + + # Day, Month DayOfMonth, CycleNth AC JY + return sprintf("%sh - %s, %s %d, %s %d", + $rytime["time_of_day"], + ryzom_day_name($rytime["day_of_week"]), + ryzom_month_name($rytime["month_of_cycle"]), + $rytime["day_of_month"] + 1, + $RYTIME_AC[$lang][$rytime["cycle"]], + $rytime["jena_year"]); +} + +?> \ No newline at end of file diff --git a/code/web/api/common/user.php b/code/web/api/common/user.php index 62a2de0c8..055332e97 100644 --- a/code/web/api/common/user.php +++ b/code/web/api/common/user.php @@ -1,3 +1,69 @@ . + */ + + +class ryUser { + private $infos; + + function __construct($infos) { + $this->infos = $infos; + } + + function __get($name) + { + if (array_key_exists($name, $this->infos)) { + return $this->infos[$name]; + } else { + /** TODO **/ + return NULL; + } + } + + function inGroup($groups) { + $groups = explode(':', $groups); + foreach ($groups as $group) { + if ($group != '') { + if (in_array($group, $this->groups)) + return true; + if ('P_'.$this->id == $group) + return true; + if ('G_'.$this->guild_id == $group) + return true; + if ($group == '*') + return true; + } + } + return false; + } +} + +function ryzom_auth_user($ask_login=true, $welcome_message='') { + global $user, $_USER; + + $result = ryzom_app_authenticate($user, $ask_login, $welcome_message, true); + $_USER = new RyUser($user); + return $result; +} + +function _user() { + global $_USER; + return $_USER; +} + ?> diff --git a/code/web/api/common/utils.php b/code/web/api/common/utils.php index 9f12fdfc1..129d67d9d 100644 --- a/code/web/api/common/utils.php +++ b/code/web/api/common/utils.php @@ -1,6 +1,40 @@ . + */ + include_once('logger.php'); +include_once('dfm.php'); + +define('SERVER', 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']); + +function stripslashes_deep($value) +{ + $value = is_array($value) ? + array_map('stripslashes_deep', $value) : + stripslashes($value); + + return $value; +} + +if (ini_get('magic_quotes_gpc') == 1) { + $_POST = stripslashes_deep($_POST); + $_GET = stripslashes_deep($_GET); +} // Always use this function to get param because in game, the param can be pass by _GET or by _POST function ryzom_get_param($var, $default='') @@ -24,13 +58,30 @@ function parse_query($var) foreach($var as $val) { $x = explode('=', $val); - $arr[$x[0]] = urldecode($x[1]); + if (count($x) > 1) + $arr[$x[0]] = urldecode($x[1]); + else + $arr[$x[0]] = ''; } unset($val, $x, $var); } return $arr; } +function ryzom_get_params() +{ + if (!isset($GLOBALS['URL_PARAMS'])) + $GLOBALS['URL_PARAMS'] = parse_query($_SERVER['REQUEST_URI']); + return $GLOBALS['URL_PARAMS']; +} + +function ryzom_unset_url_param($name) { + if (!isset($GLOBALS['URL_PARAMS'])) + $GLOBALS['URL_PARAMS'] = parse_query($_SERVER['REQUEST_URI']); + unset($GLOBALS['URL_PARAMS'][$name]); + return $GLOBALS['URL_PARAMS']; +} + if (!function_exists('http_build_query')) { function http_build_query($data, $prefix='', $sep='', $key='') { $ret = array(); @@ -50,6 +101,55 @@ if (!function_exists('http_build_query')) { } } +if(!function_exists('_url')){ + function _url($base_params=null, $add_params=array()){ + if ($base_params !== null) + return SERVER.'?'.http_build_query(array_merge($base_params, $add_params)); + else + return SERVER; + } +} + + +if(!function_exists('_h')){ + function _h($s){ + return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); + } +} + +if(!function_exists('_i')){ + function _i($img, $alt=''){ + if (substr($img, strlen($img)-4) == '.tga') // img from client texture : ig only + return $img; + + if (is_file(RYAPI_PATH.'/data/icons/'.$img.'.png')) + $img = RYAPI_URL.'/data/icons/'.$img.'.png'; + else if (is_file(RYAPP_PATH.'/data/icons/'.$img.'.png')) + $img = RYAPP_URL.'/data/icons/'.$img.'.png'; + else + $img = 'view_remove'; + + if ($alt) + return ''.utf8_decode($alt).''; + else + return ''; + + } +} + +if(!function_exists('_l')){ + function _l($text, $base_params=array(), $add_params=array()) + { + return ''.$text.''; + } +} + +if(!function_exists('_b')){ + function _b($text, $base_params=array(), $add_params=array()) + { + return ''.$text.''; + } +} /*** * @@ -66,8 +166,10 @@ function translation_exists($id) { function get_translation($id, $lang, $args=array()) { global $ryzom_texts, $user; if(!isset($ryzom_texts[$id])) return '{'.$id.'}'; - if(!isset($ryzom_texts[$id][$lang])) return '{'.$id.'['.$lang.']}'; - if($ryzom_texts[$id][$lang] == '' && isset($ryzom_texts[$id]['en'])) return @vsprintf($ryzom_texts[$id]['en'], $args); + if(empty($ryzom_texts[$id][$lang])){ + if(isset($ryzom_texts[$id]['en'])) return @vsprintf($ryzom_texts[$id]['en'], $args); + return '{'.$id.'['.$lang.']}'; + } return @vsprintf($ryzom_texts[$id][$lang], $args); } @@ -87,10 +189,12 @@ function _t($id, $args=array()) { $a = ' '.strval($args); } if(!isset($ryzom_texts[$id])) return '{'.$id.$a.'}'; - if(!isset($ryzom_texts[$id][$user['lang']])) return '{'.$id.'['.$user['lang'].']'.$a.'}'; - if($ryzom_texts[$id][$user['lang']] == '' && isset($ryzom_texts[$id]['en']) && $ryzom_texts[$id]['en'] != '') return @vsprintf($ryzom_texts[$id]['en'], $args); - if($ryzom_texts[$id][$user['lang']] == '' && isset($ryzom_texts[$id]['fr']) && $ryzom_texts[$id]['fr'] != '') return '{'.$id.$a.'}'; - if($ryzom_texts[$id][$user['lang']] == '' && isset($ryzom_texts[$id]['de']) && $ryzom_texts[$id]['de'] != '') return '{'.$id.$a.'}'; + if(empty($ryzom_texts[$id][$user['lang']])){ + if(!empty($ryzom_texts[$id]['en'])) return @vsprintf($ryzom_texts[$id]['en'], $args); + if(!empty($ryzom_texts[$id]['fr'])) return '{'.$id.$a.'}'; + if(!empty($ryzom_texts[$id]['de'])) return '{'.$id.$a.'}'; + return '{'.$id.'['.$user['lang'].']'.$a.'}'; + } return @vsprintf($ryzom_texts[$id][$user['lang']], $args); } @@ -100,7 +204,20 @@ function _t($id, $args=array()) { * * ***/ - +function ryzom_timer($timestamp) { + $d = intval($timestamp / 86400); + $timestamp = $timestamp % 86400; + $h = intval($timestamp / 3600); + $timestamp = $timestamp % 3600; + $m = intval($timestamp / 60); + $s = $timestamp % 60; + if ($d>1) + return sprintf('%d'._t('days').' %02d:%02d:%02d', $d, $h, $m, $s); + else if ($d) + return sprintf('%d'._t('day').' %02d:%02d:%02d', $d, $h, $m, $s); + else + return sprintf("%02d:%02d:%02d", $h, $m, $s); +} // Get a human and translated readable time, for example "3 days ago" function ryzom_relative_time($timestamp) { @@ -133,7 +250,10 @@ function ryzom_relative_time($timestamp) { } } - $final = $ryzom_periods[$user['lang']][$form][$j]; + if(!empty($ryzom_periods[$user['lang']][$form][$j])) + $final = $ryzom_periods[$user['lang']][$form][$j]; + else + $final = $ryzom_periods['en'][$form][$j]; $text = _t('date_format', array($difference, $final, $ending)); return $text; } @@ -150,33 +270,197 @@ function ryzom_absolute_time($timestamp) { return $text; } + +/*** + * + * Ryzom utilities + * + * + * ***/ + +function ryzom_generate_password($length=8, $level=2, $oneofeach=false) { + $validchars[1] = "0123456789abcdfghjkmnpqrstvwxyz"; + $validchars[2] = "0123456789abcdfghjkmnpqrstvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + $validchars[3] = "0123456789_!@#$%&*()-=+/abcdfghjkmnpqrstvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_!@#$%&*()-=+/"; + + $password = ""; + $counter = 0; + + while ($counter < $length) { + $actChar = substr($validchars[$level], rand(0, strlen($validchars[$level])-1), 1); + + // if $oneofeach then All character must be different (slower) + if (!$oneofeach || !strstr($password, $actChar)) { + $password .= $actChar; + $counter++; + } + } + + return $password; +} + + +function file_get_contents_cached($fn, $cache_time=300) { + global $ryzom_bench_text; + + $lfn = 'tmp/'.strtr($fn, ':/.?&=', '____________'); + + // get the new file from internet every $cache_time (default=5min) + if (file_exists($lfn) && filesize($lfn) > 0 && time() < filemtime($lfn) + $cache_time) { + $content = file_get_contents($lfn); + } else { + $content = file_get_contents($fn); + if ($content != '') file_put_contents($lfn, $content); + } + return $content; +} + +function ryzom_redirect($url, $group='', $extra_lua='') { + global $user; + $lua = $extra_lua."\n"; + if ($user['ig']) { + if (!$group) + $lua .= 'getUI(__CURRENT_WINDOW__):browse("'.str_replace('&', '&', $url).'")'; + else { + if (substr($group, 0, 3) == 'ui:') + $lua .= 'getUI("'.$group.'"):browse("'.str_replace('&', '&', $url).'")'; + else + $lua .= 'getUI("ui:interface:'.$group.':content:html"):browse("'.str_replace('&', '&', $url).'")'; + } + echo ''.$lua.''; + exit(); + } else { + header('Location: '.$url); + exit(); + } +} + /*** * * Debug tools * * ***/ -function p($var, $value=NULL) { +function alert($var, $value=NULL, $level=1) { + p($var, $value, '#FF7777', $level); +} + +define('pNULL', '§$£¤*µ%ù²&#!;,;:.?/?.<>'); + +function p($var, $value=pNULL, $color='#FFFF00', $level=0) { ob_start(); debug_print_backtrace(); $bt = ob_get_contents(); ob_end_clean(); - $bt = explode("\n",$bt); - $bt = explode('[', $bt[1]); - ob_start(); - echo ''.substr($bt[count($bt)-1], 0, -1)."\n"; - if ($value !== NULL) { - echo ''.$var.' : '; + $bt = explode("\n#",$bt); + if (isset($bt[$level])) + $bt1 = explode('[', $bt[$level]); + else + $bt1 = array(''); + + if (isset($bt[$level+1])) + $bt2 = explode('[', $bt[$level+1]); + else + $bt2 = array(''); + + $c = ''; + if ($value !== pNULL) { + $c .= ''.$var.' : '; $var = $value; } - //if (is_array($var)) - echo '
';
-	print_r($var);
-	echo '
'; -// else - // var_dump($var); - ryLogger::getInstance()->addPrint(ob_get_contents()); + $c .= ''.substr(str_replace("\n", "", $bt2[count($bt2)-1]), 0, -1).' => '.substr(str_replace("\n", "", $bt1[count($bt1)-1]), 0, -1)." "; + ryLogger::getInstance()->addPrint($c); + ob_start(); + var_dump($var); + ryLogger::getInstance()->addPrint(_h(ob_get_contents()), $color); ob_end_clean(); } + +/*** + * + * Lua tools + * + * ***/ + + class ryLua { + + static private $lua = array(); + static private $luaend = array(); + static private $indent; + static private $indentend; + static private $linkTargetId = 0; + + static function add($code, $indent=NULL) { + if ($indent !== NULL) + self::$indent += $indent; + $tabs = str_repeat(" ", self::$indent); + $a = $tabs.str_replace("\n", "\n ".$tabs, $code); + self::$lua[] = $a; + } + + static function addEnd($code, $indent=NULL) { + if ($indent !== NULL) + self::$indentend += $indent; + $tabs = str_repeat(" ", self::$indentend); + $a = $tabs.str_replace("\n", "\n ".$tabs, $code); + self::$luaend[] = $a; + } + + + static function get($ig) { + ryLogger::getInstance()->addPrint(implode("\n", self::$lua), '#FF00FF'); + $ret = ($ig)?"\n".implode("\n", self::$lua)."\n":''; + self::$lua = array(); + return $ret; + } + + static function getEnd($ig) { + ryLogger::getInstance()->addPrint(implode("\n", self::$luaend), '#FF55FF'); + $ret = ($ig)?"\n".implode("\n", self::$luaend)."\n":''; + self::$luaend = array(); + return $ret; + } + + static function text($text) { + return str_replace('"', '\"', $text); + } + + static function url($base_params=null, $add_params=array()) { + return str_replace('&', '&', _url($base_params, $add_params)); + } + + + function openLink($text, $target='webig', $base_params=array(), $add_params=array(), $urllua='', $runlua='') + { + $url = self::url($base_params, $add_params); + if ($target == "help_browser") + $url .= "&ignore="; + $id = ryzom_generate_password(8).strval(time()).strval(self::$linkTargetId++); + $lua = <<< END +function openLink{$id}() + runAH(nil, "browse", "name=ui:interface:{$target}:content:html|url={$url}"{$urllua}) + {$runlua} +end +END; + self::add($lua); + if (RYZOM_IG) + return ''.$text.''; + return $text; + } + + static function link($id, $luacode, $text) { + $lua = <<'.$text.''; + return $text; + } + +} + ?> diff --git a/code/web/api/common/xml_utils.php b/code/web/api/common/xml_utils.php new file mode 100644 index 000000000..28d166866 --- /dev/null +++ b/code/web/api/common/xml_utils.php @@ -0,0 +1,23 @@ +. + */ + +function ryzom_display_xml_header() { + header('Content-Type: application/xml; charset=UTF-8'); +} + +?> \ No newline at end of file diff --git a/code/web/api/data/css/ryzom_ui.css b/code/web/api/data/css/ryzom_ui.css index 8342b77f8..8b8e9ed37 100644 --- a/code/web/api/data/css/ryzom_ui.css +++ b/code/web/api/data/css/ryzom_ui.css @@ -33,14 +33,18 @@ color: white; } .ryzom-ui input, .ryzom-ui select { - border-top: 1px solid #030403; - border-right: 1px solid #6e7f57; - border-bottom: 1px solid #889e6c; - border-left: 1px solid #272d1f; - background-color: #37402b; - color: #ddd; + border-bottom: 1px solid #7B7E80; + border-left: 1px solid #7B7E80; + border-top: 1px solid #101010; + border-right: 1px solid #101010; + background-color: #1D1D1D; + border-radius: 3px; + color: #BBB; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; font-size: 12px; margin: 2px 0 5px 0; + padding: 1px; } .ryzom-ui input[type=text] { width: 100%; @@ -52,27 +56,43 @@ /* input[type=submit] will make IE6 to ignore whole CSS rule, so cant combine this with .ryzom-ui-button below */ input[type=submit] { - border-bottom: 1px solid #030403; - border-left: 1px solid #6e7f57; - border-top: 1px solid #889e6c; - border-right: 1px solid #272d1f; - background-color: #435120; + border-bottom: 1px solid #7B7E80; + border-left: 1px solid #7B7E80; + border-top: 1px solid #7B7E80; + border-right: 1px solid #7B7E80; + background-color: #232323; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + color: #BBB; +} +input[type=submit]:hover { + border-bottom: 1px solid #FFFFFF; + border-left: 1px solid #FFFFFF; + border-top: 1px solid #FFFFFF; + border-right: 1px solid #FFFFFF; + color: #FFF; } input.ryzom-ui-button, .ryzom-ui-button { - border-bottom: 1px solid #030403; - border-left: 1px solid #6e7f57; - border-top: 1px solid #889e6c; - border-right: 1px solid #272d1f; - background-color: #435120; + border-bottom: 1px solid #7B7E80; + border-left: 1px solid #7B7E80; + border-top: 1px solid #7B7E80; + border-right: 1px solid #7B7E80; + background-color: #232323; + border-radius: 3px; + color: #BBB; } a.ryzom-ui-button, a.ryzom-ui-button:visited { - color: white; - padding: 0 .5em; + color: #DDD; + padding: .2em .5em; text-decoration: none; } a.ryzom-ui-button:hover { - background: #536130; - color: #ddd; + border-bottom: 1px solid #FFFFFF; + border-left: 1px solid #FFFFFF; + border-top: 1px solid #FFFFFF; + border-right: 1px solid #FFFFFF; + color: #FFF; } /* window without title - just borders */ .ryzom-ui-tl { diff --git a/code/web/api/data/icons/add_app.png b/code/web/api/data/icons/add_app.png new file mode 100644 index 000000000..12cfb5546 Binary files /dev/null and b/code/web/api/data/icons/add_app.png differ diff --git a/code/web/api/data/icons/edit.png b/code/web/api/data/icons/edit.png new file mode 100644 index 000000000..315b5d8b4 Binary files /dev/null and b/code/web/api/data/icons/edit.png differ diff --git a/code/web/api/data/icons/edit_16.png b/code/web/api/data/icons/edit_16.png new file mode 100644 index 000000000..9a0dd7a37 Binary files /dev/null and b/code/web/api/data/icons/edit_16.png differ diff --git a/code/web/api/data/icons/no_action.png b/code/web/api/data/icons/no_action.png new file mode 100644 index 000000000..93aef43b3 Binary files /dev/null and b/code/web/api/data/icons/no_action.png differ diff --git a/code/web/api/data/icons/spe_com.png b/code/web/api/data/icons/spe_com.png new file mode 100644 index 000000000..9e3f48ecc Binary files /dev/null and b/code/web/api/data/icons/spe_com.png differ diff --git a/code/web/api/data/img/backgrounds/parchemin.png b/code/web/api/data/img/backgrounds/parchemin.png new file mode 100644 index 000000000..2b889c048 Binary files /dev/null and b/code/web/api/data/img/backgrounds/parchemin.png differ diff --git a/code/web/api/data/img/bordure.png b/code/web/api/data/img/bordure.png new file mode 100644 index 000000000..6c8da76f6 Binary files /dev/null and b/code/web/api/data/img/bordure.png differ diff --git a/code/web/api/data/img/lang/de.png b/code/web/api/data/img/lang/de.png index 767abe088..787c68830 100644 Binary files a/code/web/api/data/img/lang/de.png and b/code/web/api/data/img/lang/de.png differ diff --git a/code/web/api/data/img/lang/en.png b/code/web/api/data/img/lang/en.png index 2673310cc..6505dc41b 100644 Binary files a/code/web/api/data/img/lang/en.png and b/code/web/api/data/img/lang/en.png differ diff --git a/code/web/api/data/img/lang/es.png b/code/web/api/data/img/lang/es.png new file mode 100644 index 000000000..a2e450fbc Binary files /dev/null and b/code/web/api/data/img/lang/es.png differ diff --git a/code/web/api/data/img/lang/fr.png b/code/web/api/data/img/lang/fr.png index 420474693..60ed561d4 100644 Binary files a/code/web/api/data/img/lang/fr.png and b/code/web/api/data/img/lang/fr.png differ diff --git a/code/web/api/data/img/lang/ru.png b/code/web/api/data/img/lang/ru.png index 53aaf57be..281cf66f2 100644 Binary files a/code/web/api/data/img/lang/ru.png and b/code/web/api/data/img/lang/ru.png differ diff --git a/code/web/api/data/img/lang/sp.png b/code/web/api/data/img/lang/sp.png deleted file mode 100644 index 5ef5123ba..000000000 Binary files a/code/web/api/data/img/lang/sp.png and /dev/null differ diff --git a/code/web/api/data/js/combobox.js b/code/web/api/data/js/combobox.js new file mode 100644 index 000000000..0a9440909 --- /dev/null +++ b/code/web/api/data/js/combobox.js @@ -0,0 +1,17 @@ + +function comboInit(thelist) +{ + theinput = document.getElementById(theinput); + var idx = thelist.selectedIndex; + var content = thelist.options[idx].value; + if(theinput.value == "") + theinput.value = content; +} + +function combo(thelist, theinput) +{ + theinput = document.getElementById(theinput); + var idx = thelist.selectedIndex; + var content = thelist.options[idx].value; + theinput.value = content; +} diff --git a/code/web/api/data/js/jquery-1.7.1.js b/code/web/api/data/js/jquery-1.7.1.js new file mode 100644 index 000000000..8ccd0ea78 --- /dev/null +++ b/code/web/api/data/js/jquery-1.7.1.js @@ -0,0 +1,9266 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = ( context ? context.ownerDocument || context : document ); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.7.1", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.add( fn ); + + return this; + }, + + eq: function( i ) { + i = +i; + return i === -1 ? + this.slice( i ) : + this.slice( i, i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.fireWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery.Callbacks( "once memory" ); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array, i ) { + var len; + + if ( array ) { + if ( indexOf ) { + return indexOf.call( array, elem, i ); + } + + len = array.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in array && array[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +// String to Object flags format cache +var flagsCache = {}; + +// Convert String-formatted flags into Object-formatted ones and store in cache +function createFlags( flags ) { + var object = flagsCache[ flags ] = {}, + i, length; + flags = flags.split( /\s+/ ); + for ( i = 0, length = flags.length; i < length; i++ ) { + object[ flags[i] ] = true; + } + return object; +} + +/* + * Create a callback list using the following parameters: + * + * flags: an optional list of space-separated flags that will change how + * the callback list behaves + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible flags: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( flags ) { + + // Convert flags from String-formatted to Object-formatted + // (we check in cache first) + flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; + + var // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = [], + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Add one or several callbacks to the list + add = function( args ) { + var i, + length, + elem, + type, + actual; + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + // Inspect recursively + add( elem ); + } else if ( type === "function" ) { + // Add if not in unique mode and callback is not in + if ( !flags.unique || !self.has( elem ) ) { + list.push( elem ); + } + } + } + }, + // Fire callbacks + fire = function( context, args ) { + args = args || []; + memory = !flags.memory || [ context, args ]; + firing = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { + memory = true; // Mark as halted + break; + } + } + firing = false; + if ( list ) { + if ( !flags.once ) { + if ( stack && stack.length ) { + memory = stack.shift(); + self.fireWith( memory[ 0 ], memory[ 1 ] ); + } + } else if ( memory === true ) { + self.disable(); + } else { + list = []; + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + var length = list.length; + add( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away, unless previous + // firing was halted (stopOnFalse) + } else if ( memory && memory !== true ) { + firingStart = length; + fire( memory[ 0 ], memory[ 1 ] ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + var args = arguments, + argIndex = 0, + argLength = args.length; + for ( ; argIndex < argLength ; argIndex++ ) { + for ( var i = 0; i < list.length; i++ ) { + if ( args[ argIndex ] === list[ i ] ) { + // Handle firingIndex and firingLength + if ( firing ) { + if ( i <= firingLength ) { + firingLength--; + if ( i <= firingIndex ) { + firingIndex--; + } + } + } + // Remove the element + list.splice( i--, 1 ); + // If we have some unicity property then + // we only need to do this once + if ( flags.unique ) { + break; + } + } + } + } + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + if ( list ) { + var i = 0, + length = list.length; + for ( ; i < length; i++ ) { + if ( fn === list[ i ] ) { + return true; + } + } + } + return false; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory || memory === true ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( stack ) { + if ( firing ) { + if ( !flags.once ) { + stack.push( [ context, args ] ); + } + } else if ( !( flags.once && memory ) ) { + fire( context, args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!memory; + } + }; + + return self; +}; + + + + +var // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + + Deferred: function( func ) { + var doneList = jQuery.Callbacks( "once memory" ), + failList = jQuery.Callbacks( "once memory" ), + progressList = jQuery.Callbacks( "memory" ), + state = "pending", + lists = { + resolve: doneList, + reject: failList, + notify: progressList + }, + promise = { + done: doneList.add, + fail: failList.add, + progress: progressList.add, + + state: function() { + return state; + }, + + // Deprecated + isResolved: doneList.fired, + isRejected: failList.fired, + + then: function( doneCallbacks, failCallbacks, progressCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); + return this; + }, + always: function() { + deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); + return this; + }, + pipe: function( fnDone, fnFail, fnProgress ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ], + progress: [ fnProgress, "notify" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + obj = promise; + } else { + for ( var key in promise ) { + obj[ key ] = promise[ key ]; + } + } + return obj; + } + }, + deferred = promise.promise({}), + key; + + for ( key in lists ) { + deferred[ key ] = lists[ key ].fire; + deferred[ key + "With" ] = lists[ key ].fireWith; + } + + // Handle state + deferred.done( function() { + state = "resolved"; + }, failList.disable, progressList.lock ).fail( function() { + state = "rejected"; + }, doneList.disable, progressList.lock ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = sliceDeferred.call( arguments, 0 ), + i = 0, + length = args.length, + pValues = new Array( length ), + count = length, + pCount = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(), + promise = deferred.promise(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + function progressFunc( i ) { + return function( value ) { + pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + deferred.notifyWith( promise, pValues ); + }; + } + if ( length > 1 ) { + for ( ; i < length; i++ ) { + if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return promise; + } +}); + + + + +jQuery.support = (function() { + + var support, + all, + a, + select, + opt, + input, + marginDiv, + fragment, + tds, + events, + eventName, + i, + isSupported, + div = document.createElement( "div" ), + documentElement = document.documentElement; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute("href") === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Tests for enctype support on a form(#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains its value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.lastChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + fragment.removeChild( input ); + fragment.appendChild( div ); + + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( window.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.style.width = "2px"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Technique from Juriy Zaytsev + // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + }) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + fragment.removeChild( div ); + + // Null elements to avoid leaks in IE + fragment = select = opt = marginDiv = div = input = null; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, outer, inner, table, td, offsetSupport, + conMarginTop, ptlm, vb, style, html, + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + conMarginTop = 1; + ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; + vb = "visibility:hidden;border:0;"; + style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; + html = "
" + + "" + + "
"; + + container = document.createElement("div"); + container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; + body.insertBefore( container, body.firstChild ); + + // Construct the test element + div = document.createElement("div"); + container.appendChild( div ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + div.innerHTML = "
t
"; + tds = div.getElementsByTagName( "td" ); + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE <= 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Figure out if the W3C box model works as expected + div.innerHTML = ""; + div.style.width = div.style.paddingLeft = "1px"; + jQuery.boxModel = support.boxModel = div.offsetWidth === 2; + + if ( typeof div.style.zoom !== "undefined" ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.style.cssText = ptlm + vb; + div.innerHTML = html; + + outer = div.firstChild; + inner = outer.firstChild; + td = outer.nextSibling.firstChild.firstChild; + + offsetSupport = { + doesNotAddBorder: ( inner.offsetTop !== 5 ), + doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) + }; + + inner.style.position = "fixed"; + inner.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); + inner.style.position = inner.style.top = ""; + + outer.style.overflow = "hidden"; + outer.style.position = "relative"; + + offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); + offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); + + body.removeChild( container ); + div = container = null; + + jQuery.extend( support, offsetSupport ); + }); + + return support; +})(); + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var privateCache, thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, + isEvents = name === "events"; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = ++jQuery.uuid; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + privateCache = thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Users should not attempt to inspect the internal events object using jQuery.data, + // it is undocumented and subject to change. But does anyone listen? No. + if ( isEvents && !thisCache[ name ] ) { + return privateCache.events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ internalKey ] : internalKey; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the cache and need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ internalKey ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + } else { + elem[ internalKey ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var parts, attr, name, + data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { + attr = this[0].attributes; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + jQuery._data( this[0], "parsedAttrs", true ); + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var self = jQuery( this ), + args = [ parts[0], value ]; + + self.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + jQuery.isNumeric( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery._data( elem, deferDataKey ); + if ( defer && + ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && + ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery._data( elem, queueDataKey ) && + !jQuery._data( elem, markDataKey ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.fire(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = ( type || "fx" ) + "mark"; + jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); + if ( count ) { + jQuery._data( elem, key, count ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + var q; + if ( elem ) { + type = ( type || "fx" ) + "queue"; + q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + hooks = {}; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + jQuery._data( elem, type + ".run", hooks ); + fn.call( elem, function() { + jQuery.dequeue( elem, type ); + }, hooks ); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue " + type + ".run", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { + count++; + tmp.add( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + nodeHook, boolHook, fixSpecified; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = ( value || "" ).split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, i, max, option, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + i = one ? index : 0; + max = one ? index + 1 : options.length; + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var propName, attrNames, name, l, + i = 0; + + if ( value && elem.nodeType === 1 ) { + attrNames = value.toLowerCase().split( rspace ); + l = attrNames.length; + + for ( ; i < l; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + + // See #9699 for explanation of this approach (setting first, then removal) + jQuery.attr( elem, name, "" ); + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && propName in elem ) { + elem[ propName ] = false; + } + } + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) +jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode, + property = jQuery.prop( elem, name ); + return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + fixSpecified = { + name: true, + id: true + }; + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return ( ret.nodeValue = value + "" ); + } + }; + + // Apply the nodeHook to tabindex + jQuery.attrHooks.tabindex.set = nodeHook.set; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + if ( value === "" ) { + value = "false"; + } + nodeHook.set( elem, value, name ); + } + }; +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = "" + value ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); + + + + +var rformElems = /^(?:textarea|input|select)$/i, + rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, + rhoverHack = /\bhover(\.\S+)?\b/, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, + quickParse = function( selector ) { + var quick = rquickIs.exec( selector ); + if ( quick ) { + // 0 1 2 3 + // [ _, tag, id, class ] + quick[1] = ( quick[1] || "" ).toLowerCase(); + quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); + } + return quick; + }, + quickIs = function( elem, m ) { + var attrs = elem.attributes || {}; + return ( + (!m[1] || elem.nodeName.toLowerCase() === m[1]) && + (!m[2] || (attrs.id || {}).value === m[2]) && + (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) + ); + }, + hoverHack = function( events ) { + return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); + }; + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + add: function( elem, types, handler, data, selector ) { + + var elemData, eventHandle, events, + t, tns, type, namespaces, handleObj, + handleObjIn, quick, handlers, special; + + // Don't attach events to noData or text/comment nodes (allow plain objects tho) + if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + events = elemData.events; + if ( !events ) { + elemData.events = events = {}; + } + eventHandle = elemData.handle; + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = jQuery.trim( hoverHack(types) ).split( " " ); + for ( t = 0; t < types.length; t++ ) { + + tns = rtypenamespace.exec( types[t] ) || []; + type = tns[1]; + namespaces = ( tns[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: tns[1], + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + quick: quickParse( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + handlers = events[ type ]; + if ( !handlers ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + t, tns, type, origType, namespaces, origCount, + j, events, special, handle, eventType, handleObj; + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = jQuery.trim( hoverHack( types || "" ) ).split(" "); + for ( t = 0; t < types.length; t++ ) { + tns = rtypenamespace.exec( types[t] ) || []; + type = origType = tns[1]; + namespaces = tns[2]; + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector? special.delegateType : special.bindType ) || type; + eventType = events[ type ] || []; + origCount = eventType.length; + namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + + // Remove matching events + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !namespaces || namespaces.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + eventType.splice( j--, 1 ); + + if ( handleObj.selector ) { + eventType.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery.removeData( elem, [ "events", "handle" ], true ); + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Don't do events on text and comment nodes + if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + return; + } + + // Event object or event type + var type = event.type || event, + namespaces = [], + cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "!" ) >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf( "." ) >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.isTrigger = true; + event.exclusive = exclusive; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; + + // Handle a global trigger + if ( !elem ) { + + // TODO: Stop taunting the data cache; remove global events and always attach to document + cache = jQuery.cache; + for ( i in cache ) { + if ( cache[ i ].events && cache[ i ].events[ type ] ) { + jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); + } + } + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + eventPath = [[ elem, special.bindType || type ]]; + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; + old = null; + for ( ; cur; cur = cur.parentNode ) { + eventPath.push([ cur, bubbleType ]); + old = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( old && old === elem.ownerDocument ) { + eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + } + } + + // Fire handlers on the event path + for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + + cur = eventPath[i][0]; + event.type = eventPath[i][1]; + + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + // Note that this is a bare JS function and not a jQuery handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + // IE<9 dies on focus/blur to hidden element (#1486) + if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( old ) { + elem[ ontype ] = old; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event || window.event ); + + var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), + delegateCount = handlers.delegateCount, + args = [].slice.call( arguments, 0 ), + run_all = !event.exclusive && !event.namespace, + handlerQueue = [], + i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Determine handlers that should run if there are delegated events + // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) + if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { + + // Pregenerate a single jQuery object for reuse with .is() + jqcur = jQuery(this); + jqcur.context = this.ownerDocument || this; + + for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + selMatch = {}; + matches = []; + jqcur[0] = cur; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + sel = handleObj.selector; + + if ( selMatch[ sel ] === undefined ) { + selMatch[ sel ] = ( + handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) + ); + } + if ( selMatch[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, matches: matches }); + } + } + } + + // Add the remaining (directly-bound) handlers + if ( handlers.length > delegateCount ) { + handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + } + + // Run delegates first; they may want to stop propagation beneath us + for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { + matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { + handleObj = matched.matches[ j ]; + + // Triggered event must either 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + + event.data = handleObj.data; + event.handleObj = handleObj; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + return event.result; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = jQuery.Event( originalEvent ); + + for ( i = copy.length; i; ) { + prop = copy[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Target should not be a text node (#504, Safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) + if ( event.metaKey === undefined ) { + event.metaKey = event.ctrlKey; + } + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady + }, + + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + + focus: { + delegateType: "focusin" + }, + blur: { + delegateType: "focusout" + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +// Some plugins are using, but it's undocumented/deprecated and will be removed. +// The 1.7 special event interface should provide all the hooks needed now. +jQuery.event.handle = jQuery.event.dispatch; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var target = this, + related = event.relatedTarget, + handleObj = event.handleObj, + selector = handleObj.selector, + ret; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !form._submit_attached ) { + jQuery.event.add( form, "submit._submit", function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + }); + form._submit_attached = true; + } + }); + // return undefined since we don't need an event listener + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + jQuery.event.simulate( "change", this, event, true ); + } + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + elem._change_attached = true; + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on.call( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + var handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( var type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + live: function( types, data, fn ) { + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }, + die: function( types, fn ) { + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + expando = "sizcache" + (Math.random() + '').replace('.', ''), + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rReturn = /\r\n/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context, seed ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set, seed ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set, i, len, match, type, left; + + if ( !expr ) { + return []; + } + + for ( i = 0, len = Expr.order.length; i < len; i++ ) { + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + type, found, item, filter, left, + i, pass, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + filter = Expr.filter[ type ]; + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + pass = not ^ found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Utility function for retreiving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +var getText = Sizzle.getText = function( elem ) { + var i, node, + nodeType = elem.nodeType, + ret = ""; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 ) { + // Use textContent || innerText for elements + if ( typeof elem.textContent === 'string' ) { + return elem.textContent; + } else if ( typeof elem.innerText === 'string' ) { + // Replace IE's carriage returns + return elem.innerText.replace( rReturn, '' ); + } else { + // Traverse it's children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + } else { + + // If no nodeType, this is expected to be an array + for ( i = 0; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + if ( node.nodeType !== 8 ) { + ret += getText( node ); + } + } + } + return ret; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var first, last, + doneName, parent, cache, + count, diff, + type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + first = match[2]; + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + doneName = match[0]; + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { + count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent[ expando ] = doneName; + } + + diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Sizzle.attr ? + Sizzle.attr( elem, name ) : + Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + !type && Sizzle.attr ? + result != null : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context, seed ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet, seed ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +Sizzle.selectors.attrMap = {}; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + POS.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array (deprecated as of jQuery 1.7) + if ( jQuery.isArray( selectors ) ) { + var level = 1; + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( i = 0; i < selectors.length; i++ ) { + + if ( jQuery( cur ).is( selectors[ i ] ) ) { + ret.push({ selector: selectors[ i ], elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} + + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
", "
" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + col: [ 2, "", "
" ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }, + safeFragment = createSafeFragment( document ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and "; + break; + case 'LOG': + $log->logf("MySQL ERROR: ".$error); + break; + default: + flush(); + break; + } + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/conf.php b/code/web/api/server/scripts/achievement_script/conf.php new file mode 100644 index 000000000..62f05526d --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/conf.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/include/functions_inc.php b/code/web/api/server/scripts/achievement_script/include/functions_inc.php new file mode 100644 index 000000000..bc0a1d960 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/include/functions_inc.php @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/launch_parse_new_xml.sh b/code/web/api/server/scripts/achievement_script/launch_parse_new_xml.sh new file mode 100644 index 000000000..1a9c721ee --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/launch_parse_new_xml.sh @@ -0,0 +1,5 @@ +#!/bin/sh - + +cd /home/api/public_html/server/scripts/achievement_script + +sudo -u api nohup ./parse_new_xml.sh & diff --git a/code/web/api/server/scripts/achievement_script/log/_logDefaultDir_ b/code/web/api/server/scripts/achievement_script/log/_logDefaultDir_ new file mode 100644 index 000000000..e69de29bb diff --git a/code/web/api/server/scripts/achievement_script/log/xml_tmp/_xml_tmp_dir b/code/web/api/server/scripts/achievement_script/log/xml_tmp/_xml_tmp_dir new file mode 100644 index 000000000..e69de29bb diff --git a/code/web/api/server/scripts/achievement_script/parse_new_xml.sh b/code/web/api/server/scripts/achievement_script/parse_new_xml.sh new file mode 100644 index 000000000..ade33c6d1 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/parse_new_xml.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +cd /home/api/public_html/server/scripts/achievement_script + +SRC=/home/api/public_html/server/scripts/achievement_script/new_xml +DST=/home/api/public_html/server/scripts/achievement_script/parse_xml + +while true; do + + FN=`inotifywait -r -e close_write --format '%w%f' $SRC` + + for f in $SRC/*; do + NAME="$DST/"`basename $f` + mv -f $f $DST + echo "Processing $NAME" + php AchWebParser.php $NAME + rm -f $NAME + done + +done + +#cd - diff --git a/code/web/api/server/scripts/achievement_script/script/_scriptDir b/code/web/api/server/scripts/achievement_script/script/_scriptDir new file mode 100644 index 000000000..e69de29bb diff --git a/code/web/api/server/scripts/achievement_script/script/item_grade_script.php b/code/web/api/server/scripts/achievement_script/script/item_grade_script.php new file mode 100644 index 000000000..4be071adc --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/script/item_grade_script.php @@ -0,0 +1,13 @@ +sendSQL("SELECT grade FROM ryzom_nimetu_item_data WHERE sheetid='".str_replace(".sitem","",$item)."'","ARRAY"); + + #echo $res[0]['grade']; + + return $res[0]['grade']; +} +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/script/places/continents.php b/code/web/api/server/scripts/achievement_script/script/places/continents.php new file mode 100644 index 000000000..25ad07db7 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/script/places/continents.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/script/places/global.php b/code/web/api/server/scripts/achievement_script/script/places/global.php new file mode 100644 index 000000000..1b6609f53 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/script/places/global.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/script/statsdb.php b/code/web/api/server/scripts/achievement_script/script/statsdb.php new file mode 100644 index 000000000..a91655dfd --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/script/statsdb.php @@ -0,0 +1,89 @@ +registerValue("_money","_statsdb_money"); + function _statsdb_money($money,$_P,$_CB) { + global $cdata,$DBc,$statsdb; + $_IDENT = "_money"; + + #$DBc->sendSQL("UPDATE stat_players SET sp_money='".$money."' WHERE sp_char='".$cdata['cid']."'","NONE"); + $statsdb->setValue('sp_money',$money); + + $_P->unregisterValue($_IDENT,$_CB); + } + + $this->registerValue("_race","_statsdb_race"); + function _statsdb_race($race,$_P,$_CB) { + global $cdata,$DBc,$statsdb; + $_IDENT = "_race"; + + $race = "r_".strtolower($race); + + #$DBc->sendSQL("UPDATE stat_players SET sp_race='".$race."' WHERE sp_char='".$cdata['cid']."'","NONE"); + $statsdb->setValue('sp_race',$race); + + $_P->unregisterValue($_IDENT,$_CB); + } + + $this->registerValue("yubopoints","_statsdb_yubototal"); + function _statsdb_yubototal($yubo,$_P,$_CB) { + global $cdata,$DBc,$statsdb; + $_IDENT = "yubopoints"; + + #$DBc->sendSQL("UPDATE stat_players SET sp_yubototal='".$yubo."' WHERE sp_char='".$cdata['cid']."'","NONE"); + $statsdb->setValue('sp_yubototal',$yubo); + + $_P->unregisterValue($_IDENT,$_CB); + } + + $this->registerValue("petcount","_statsdb_mekcount"); + function _statsdb_mekcount($count,$_P,$_CB) { + global $cdata,$DBc,$statsdb; + $_IDENT = "petcount"; + + #$DBc->sendSQL("UPDATE stat_players SET sp_mekcount='".$count."' WHERE sp_char='".$cdata['cid']."'","NONE"); + $statsdb->setValue('sp_mekcount',$count); + + $_P->unregisterValue($_IDENT,$_CB); + } + + $this->registerEntity("skilllist","_statsdb_maxlevel"); + function _statsdb_maxlevel($skills,$_P,$_CB) { + global $cdata,$DBc,$log,$statsdb; + $_IDENT = "skilllist"; + + #$log->logf("rcv skilllist: ".var_export($skills,true)); + + $lvl = 0; + foreach($skills->skills as $elem) { + if($elem->current > $lvl) { + $lvl = $elem->current; + } + } + + #$DBc->sendSQL("UPDATE stat_players SET sp_maxlevel='".$lvl."' WHERE sp_char='".$cdata['cid']."'","NONE"); + $statsdb->setValue('sp_maxlevel',$lvl); + + $_P->unregisterEntity($_IDENT,$_CB); + } + + $this->registerValue("_guildid","_statsdb_guildid"); + function _statsdb_guildid($id,$_P,$_CB) { + global $cdata,$DBc,$statsdb; + $_IDENT = "_guildid"; + + #$DBc->sendSQL("UPDATE stat_players SET sp_guildid='".$id."' WHERE sp_char='".$cdata['cid']."'","NONE"); + $statsdb->setValue('sp_guildid',$id); + + $_P->unregisterValue($_IDENT,$_CB); + } + + $this->registerValue("itemcount","_statsdb_itemcount"); + function _statsdb_itemcount($count,$_P,$_CB) { + global $cdata,$DBc,$statsdb; + $_IDENT = "itemcount"; + + #$DBc->sendSQL("UPDATE stat_players SET sp_itemcount='".$count."' WHERE sp_char='".$cdata['cid']."'","NONE"); + $statsdb->setValue('sp_itemcount',$count); + + $_P->unregisterValue($_IDENT,$_CB); + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/BillingSummary/BillingSummary_class.php b/code/web/api/server/scripts/achievement_script/source/BillingSummary/BillingSummary_class.php new file mode 100644 index 000000000..bf3872c0a --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/BillingSummary/BillingSummary_class.php @@ -0,0 +1,29 @@ +sendSQL("SELECT SUM(amount) as anz, currency FROM coupons_billing WHERE iduser='".$cdata['aid']."' AND status='captured' GROUP by 'currency'","ARRAY"); + + $billed = 0; + + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + if($res[$i]['currency'] == "USD") { + $res[$i]['anz'] = $res[$i]['anz']*0.7950; + } + + if($res[$i]['currency'] == "GBP") { + $res[$i]['anz'] = $res[$i]['anz']*1.2623; + } + + $billed += $res[$i]['anz']; + } + + $_DISPATCHER->dispatchValue("user_billed_sum",$billed);*/ + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/PDRtoXMLdriver_class.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/PDRtoXMLdriver_class.php new file mode 100644 index 000000000..9fdc4ff22 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/PDRtoXMLdriver_class.php @@ -0,0 +1,972 @@ +lock = 0; + $this->open = null; + $this->entity = null; + $this->inv = null; + $this->iblock = false; + + $this->petcount = 0; + $this->itemcount = 0; + + $this->gear = new Gear(); + $this->skills = new SkillList(); + $this->mission = new MissionList(); + $this->friendlist = new Friendlist(); + $this->tplist = new TPlist(); + + $this->hasChoice = false; + $this->hasExcellent = false; + $this->hasSupreme = false; + + $this->tool_list = array('itrtje.sitem','icokamtjewel_1.sitem','icokamtjewel_2.sitem','icokartjewel_1.sitem','icokartjewel_2.sitem','itjewel.sitem','itmwea.sitem','itrtmw.sitem','icokamtmwea_1.sitem','icokamtmwea_2.sitem','icokartmwea_1.sitem','icokartmwea_2.sitem','itrtfo.sitem','itforage.sitem','itforagekam_ep2_1.sitem','itforagekam_ep2_2.sitem','itforagekam_ep2_3.sitem','itforagekar_ep2_1.sitem','itforagekar_ep2_2.sitem','itforagekar_ep2_3.sitem','icokamtforage_1.sitem','icokamtforage_2.sitem','icokartforage_1.sitem','icokartforage_2.sitem','itrwea.sitem','itrtrw.sitem','icokamtrwea_1.sitem','icokamtrwea_2.sitem','icokartrwea_1.sitem','icokartrwea_2.sitem','itammo.sitem','itrtam.sitem','icokamtammo_1.sitem','icokamtammo_2.sitem','icokartammo_1.sitem','icokartammo_2.sitem','itarmor.sitem','itrtar.sitem','icokamtarmor_1.sitem','icokamtarmor_2.sitem','icokartarmor_1.sitem','icokartarmor_2.sitem'); + + $this->itemignore = false; + + $this->tracked_items = array(); + $res = $DBc->sendSQL("SELECT api_item FROM ach_player_item WHERE api_player='".$cdata['cid']."'","ARRAY"); + foreach($res as $elem) { + $this->tracked_items[] = $elem['api_item']; + } + + $this->tracked_items_new = array(); + + //these nodes are ignored, but children are processed + $this->ignore = array(); + $this->ignore[] = "XML"; + $this->ignore[] = "ENTITYBASE"; + $this->ignore[] = "NORMALPOSITIONS"; + $this->ignore[] = "_VEC"; + $this->ignore[] = "SESSIONID"; + #$this->ignore[] = "POSSTATE"; + $this->ignore[] = "_PLAYERROOM"; + $this->ignore[] = "_INVENTORYID"; + $this->ignore[] = "_PHYSCHARACS"; + $this->ignore[] = "_PHYSSCORES"; + $this->ignore[] = "_SKILLS"; + $this->ignore[] = "_FAMES"; + + //these nodes are ignored, as well as their children + $this->ignore_block = array(); + $this->ignore_block[] = "_MEMORIZEDPHRASES"; + $this->ignore_block[] = "_FORBIDPOWERDATES"; + $this->ignore_block[] = "_INEFFECTIVEAURAS"; + $this->ignore_block[] = "_CONSUMABLEOVERDOSEENDDATES"; + $this->ignore_block[] = "_MODIFIERSINDB"; + $this->ignore_block[] = "_MISSIONS"; + $this->ignore_block[] = "RINGREWARDPOINTS"; + $this->ignore_block[] = "_PACT"; + $this->ignore_block[] = "_KNOWNPHRASES"; + $this->ignore_block[] = "STARTINGCHARACTERISTICVALUES"; + $this->ignore_block[] = "_ENCYCLOCHAR"; + $this->ignore_block[] = "_GAMEEVENT"; + $this->ignore_block[] = "_ENTITYPOSITION"; + $this->ignore_block[] = "_MISSIONHISTORIES"; + $this->ignore_block[] = "_KNOWNBRICKS"; + $this->ignore_block[] = "_BOUGHTPHRASES"; + $this->ignore_block[] = "SKILLPOINTS"; + #$this->ignore_block[] = "SPENTSKILLPOINTS"; + $this->ignore_block[] = "_LASTLOGSTATS"; + $this->ignore_block[] = "FACTIONPOINTS"; + } + + function drive($cdata) { + global $_DISPATCHER,$MY_PATH,$log,$DBc; + + #$file = $this->conf['xml_dir']."account_".$uid."_".$slot."_pdr.xml"; + $file = $_REQUEST['file']; + + $xml_parser = xml_parser_create(); + xml_set_object($xml_parser,$this); + xml_set_element_handler($xml_parser, "startElement", "endElement"); + + // temporary storage for xml files for debug purpose + $ftmp = fopen($MY_PATH."/log/xml_tmp/char_".$cdata['cid'].".xml","w"); + $fcont = file_get_contents($file); + fwrite($ftmp,$fcont); + fclose($ftmp); + # end of temp xml store + + if(!xml_parse($xml_parser, $fcont)) { + $log->logf("FATAL ERROR (PDRtoXMLdriver): unable to parse given XML!"); + $log->close(); + die(); + } + + xml_parser_free($xml_parser); + + $_DISPATCHER->dispatchEntity($this->gear->getName(),$this->gear); + #echo var_export($this->gear,true); + $_DISPATCHER->dispatchEntity($this->skills->getName(),$this->skills); + $_DISPATCHER->dispatchEntity($this->friendlist->getName(),$this->friendlist); + $_DISPATCHER->dispatchEntity($this->tplist->getName(),$this->tplist); + $_DISPATCHER->dispatchValue('petcount',$this->petcount); + $_DISPATCHER->dispatchValue('itemcount',$this->itemcount); + + $_DISPATCHER->dispatchValue('has_choice',$this->hasChoice); + $_DISPATCHER->dispatchValue('has_excellent',$this->hasExcellent); + $_DISPATCHER->dispatchValue('has_supreme',$this->hasSupreme); + + $qry = array(); + foreach($this->tracked_items_new as $elem) { + $qry[] = "('".$DBc->mre($elem)."','".$cdata['cid']."','".time()."')"; + } + if(sizeof($qry) > 0) { + $DBc->sendSQL("INSERT DELAYED INTO ach_player_item (api_item,api_player,api_date) VALUES ".implode(',',$qry),"NONE"); + } + + $DBc->sendSQL("DELETE FROM ach_player_item WHERE api_date<'".(time()-605800)."'","NONE"); + } + + function startElement($parser, $name, $attrs) { + global $_DISPATCHER,$DBc,$XMLgenerator; + + array_push($this->pathid,$name); + + $XMLgenerator->xml_split(implode("/",$this->pathid),$name,$attrs,true); + + if($this->lock == 1) { + return null; + } + + if(in_array($name,$this->ignore)) { + return null; + } + + if(in_array($name,$this->ignore_block)) { + $this->lock = 1; + return null; + } + + /* has shop item */ + if($name == '_ITEMSFORSALE') { + $this->lock = 1; + $this->ignore_block[] = "_ITEMSINSHOPSTORE"; + $_DISPATCHER->dispatchValue('has_store',true); + } + + /* death penalty */ + if($name == "_DEATHPENALTIES") { + $this->open = "_DEATHPENALTIES"; + $this->entity = new DeathPenalty(); + return null; + } + + if($this->open == "_DEATHPENALTIES") { + if($name == "_NBDEATH") { + $this->entity->NbDeath = $attrs['VALUE']; + } + + if($name == "_CURRENTDEATHXP") { + $this->entity->CurrentDeathXP = $attrs['VALUE']; + } + + if($name == "_DEATHXPTOGAIN") { + $this->entity->DeathXPToGain = $attrs['VALUE']; + } + + if($name == "_BONUSUPDATETIME") { + $this->entity->BonusUpdateTime = $attrs['VALUE']; + } + } + + /* spawn points */ + if($name == "RESPAWNPOINTS" && !$attrs['VALUE']) { + $this->open = "RESPAWNPOINTS"; + $this->entity = new RespawnPoints(); + return null; + } + + if($this->open == "RESPAWNPOINTS") { + if($name == "RESPAWNPOINTS") { + $this->respawn_outer = 0; + $this->entity->spawns[] = $attrs['VALUE']; + } + } + + /* faction points */ + if($name == "FACTIONPOINTS") { + $this->open = "FACTIONPOINTS"; + return null; + } + + if($this->open == "FACTIONPOINTS") { + if($name == "__KEY__") { + $this->entity = new FactionPoints(); + $this->entity->faction = $attrs['VALUE']; + return null; + } + + if($name == "__VAL__") { + $this->entity->value = $attrs['VALUE']; + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + return null; + } + + /* Fame */ + if($name == "_FAME") { + $this->open = "_FAME"; + return null; + } + + if($this->open == "_FAME") { + if($name == "__KEY__") { + $this->entity = new Fame(); + $this->entity->faction = $attrs['VALUE']; + return null; + } + + if($name == "FAME") { + $this->entity->fame = $attrs['VALUE']; + return null; + } + if($name == "FAMEMEMORY") { + $this->entity->famememory = $attrs['VALUE']; + return null; + } + if($name == "LASTFAMECHANGETREND") { + $this->entity->lastfamechangetrend = $attrs['VALUE']; + return null; + } + + return null; + } + + /* last log stats */ + if($name == "_LASTLOGSTATS") { + $this->open = "_LASTLOGSTATS"; + $this->entity = new LastLogStats(); + return null; + } + + if($this->open == "_LASTLOGSTATS") { + if($name == "LOGINTIME") { + $this->entity->logintime = $attrs['VALUE']; + return null; + } + if($name == "DURATION") { + $this->entity->duration = $attrs['VALUE']; + return null; + } + if($name == "LOGOFFTIME") { + $this->entity->logofftime = $attrs['VALUE']; + return null; + } + + return null; + } + + /* mission */ + if($name == "_MISSIONHISTORIES") { + $this->open = "_MISSIONHISTORIES"; + return null; + } + + if($this->open == "_MISSIONHISTORIES") { + if($name == "__KEY__") { + $this->entity = new Mission(); + $this->entity->mission = $attrs['VALUE']; + return null; + } + + if($name == "SUCCESSFULL") { + $this->entity->successfull = $attrs['VALUE']; + return null; + } + if($name == "UTC_LASTSUCCESSDATE") { + $this->entity->utc_lastsuccessdate = $attrs['VALUE']; + return null; + } + + return null; + } + + if($name == "_FRIENDSLIST") { + $this->entity = new Friend(); + $this->entity->id = $attrs['VALUE']; + $this->friendlist->friends[] = $this->entity; + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + } + + if($name == "_ISFRIENDOF") { + $this->entity = new FriendOf(); + $this->entity->id = $attrs['VALUE']; + $this->friendlist->friendof[] = $this->entity; + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + } + + /* permanent mod */ + if($name == "SCOREPERMANENTMODIFIERS") { + $this->open = "SCOREPERMANENTMODIFIERS"; + return null; + } + + if($this->open == "SCOREPERMANENTMODIFIERS") { + if($name == "__KEY__") { + $this->entity = new PermanentMod(); + $this->entity->score = $attrs['VALUE']; + return null; + } + + if($name == "__VAL__") { + $this->entity->value = $attrs['VALUE']; + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + return null; + } + + /* pet */ + if($name == "_PLAYERPETS") { + $this->open = "_PLAYERPETS"; + return null; + } + + if($this->open == "_PLAYERPETS") { + if($name == "__KEY__") { + $this->entity = new Pet(); + $this->entity->pet = $attrs['VALUE']; + return null; + } + + if($name == "TICKETPETSHEETID") { + $this->entity->ticketpetsheetid = $attrs['VALUE']; + return null; + } + if($name == "PETSHEETID") { + $this->entity->petsheetid = $attrs['VALUE']; + $this->petcount++; + return null; + } + if($name == "PRICE") { + $this->entity->price = $attrs['VALUE']; + return null; + } + if($name == "OWNERID") { + $this->entity->ownerid = $attrs['VALUE']; + return null; + } + if($name == "STABLEALIAS") { + $this->entity->stablealias = $attrs['VALUE']; + return null; + } + if($name == "LANDSCAPE_X") { + $this->entity->landscape_x = $attrs['VALUE']; + return null; + } + if($name == "LANDSCAPE_Y") { + $this->entity->landscape_y = $attrs['VALUE']; + return null; + } + if($name == "LANDSCAPE_Z") { + $this->entity->landscape_z = $attrs['VALUE']; + return null; + } + if($name == "UTC_DEATHTICK") { + $this->entity->utc_deathtick = $attrs['VALUE']; + return null; + } + if($name == "PETSTATUS") { + $this->entity->petstatus = $attrs['VALUE']; + return null; + } + if($name == "SLOT") { + $this->entity->slot = $attrs['VALUE']; + return null; + } + if($name == "ISTPALLOWED") { + $this->entity->istpallowed = $attrs['VALUE']; + return null; + } + if($name == "SATIETY") { + $this->entity->satiety = $attrs['VALUE']; + return null; + } + if($name == "CUSTOMNAME") { + $this->entity->customname = $attrs['VALUE']; + return null; + } + + return null; + } + + /* physical characteristics */ + if($name == "_PHYSICALCHARACTERISTICS") { + $this->open = "_PHYSICALCHARACTERISTICS"; + return null; + } + + if($this->open == "_PHYSICALCHARACTERISTICS") { + if($name == "__KEY__") { + $this->entity = new PhysCharacs(); + $this->entity->charac = $attrs['VALUE']; + return null; + } + + if($name == "__VAL__") { + $this->entity->value = $attrs['VALUE']; + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + return null; + } + + /* physical scores */ + if($name == "PHYSICALSCORES") { + $this->open = "PHYSICALSCORES"; + return null; + } + + if($this->open == "PHYSICALSCORES") { + if($name == "__KEY__") { + $this->entity = new PhysScores(); + $this->entity->score = $attrs['VALUE']; + return null; + } + + if($name == "CURRENT") { + $this->entity->current = $attrs['VALUE']; + return null; + } + if($name == "BASE") { + $this->entity->base = $attrs['VALUE']; + return null; + } + if($name == "MAX") { + $this->entity->max = $attrs['VALUE']; + return null; + } + if($name == "BASEREGENERATEREPOS") { + $this->entity->baseregeneraterepos = $attrs['VALUE']; + return null; + } + if($name == "BASEREGENERATEACTION") { + $this->entity->baseregenerateaction = $attrs['VALUE']; + return null; + } + if($name == "CURRENTREGENERATE") { + $this->entity->currentregenerate = $attrs['VALUE']; + return null; + } + + return null; + } + + /* skill points */ + if($name == "SKILLPOINTS") { + $this->open = "SKILLPOINTS"; + return null; + } + + if($this->open == "SKILLPOINTS") { + if($name == "__KEY__") { + $this->entity = new SkillPoints(); + $this->entity->skill = $attrs['VALUE']; + return null; + } + + if($name == "__VAL__") { + $this->entity->value = $attrs['VALUE']; + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + return null; + } + + /* spent skill points */ + if($name == "SPENTSKILLPOINTS") { + $this->open = "SPENTSKILLPOINTS"; + return null; + } + + if($this->open == "SPENTSKILLPOINTS") { + if($name == "__KEY__") { + $this->entity = new SpentSkillPoints(); + $this->entity->skill = $attrs['VALUE']; + return null; + } + + if($name == "__VAL__") { + $this->entity->value = $attrs['VALUE']; + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + return null; + } + + /* skills */ + if($name == "SKILLS") { + $this->open = "SKILLS"; + return null; + } + + if($this->open == "SKILLS") { + if($name == "__KEY__") { + $this->entity = new Skill(); + $this->entity->skill = $attrs['VALUE']; + return null; + } + + if($name == "BASE") { + $this->entity->base = $attrs['VALUE']; + return null; + } + if($name == "CURRENT") { + $this->entity->current = $attrs['VALUE']; + return null; + } + if($name == "MAXLVLREACHED") { + $this->entity->maxlvlreached = $attrs['VALUE']; + return null; + } + if($name == "XP") { + $this->entity->xp = $attrs['VALUE']; + return null; + } + if($name == "XPNEXTLVL") { + $this->entity->xpnextlvl = $attrs['VALUE']; + return null; + } + + return null; + } + + /* Position */ + if($name == "POSSTATE") { + $this->open = "POSSTATE"; + $this->entity = new Position(); + return null; + } + + if($this->open == "POSSTATE") { + if($name == "X") { + $this->entity->x = $attrs['VALUE']; + return null; + } + if($name == "Y") { + $this->entity->y = $attrs['VALUE']; + return null; + } + if($name == "Z") { + $this->entity->z = $attrs['VALUE']; + return null; + } + if($name == "HEADING") { + $this->entity->heading = $attrs['VALUE']; + return null; + } + + return null; + } + + /* items */ + + if($name == "ROOMINVENTORY") { + $this->inv = "room"; + return null; + } + + if($name == "INVENTORY") { + $this->iblock = true; + return null; + } + + if($this->iblock == true) { + if($name == "__KEY__") { + $this->inv = $attrs['VALUE']; + } + if($name == "__VAL__") { + return null; + } + } + + if($name == '_ITEMS' || $name == '_ITEM') { + #echo "i
"; + $this->open = '_ITEM'; + $this->entity = new Item(); + $this->entity->inventory = $this->inv; + $this->itemcount++; + return null; + } + + if($this->open == '_ITEM') { + if($this->itemignore == true) { + return null; + } + + if($name == '_CRAFTPARAMETERS') { + $this->icraft = true; + return null; + } + + if($this->icraft == true) { + if($name == 'HPBUFF' || $name == 'SAPBUFF' || $name == 'FOCUSBUFF' || $name == 'STABUFF') { + $this->entity->_craftparameters[strtolower($name)] = $attrs['VALUE']; + } + return null; + } + + if($name == '_ITEMID') { + $this->entity->_itemid = $attrs['VALUE']; + return null; + } + if($name == '_SHEETID') { + if($attrs['VALUE']{0} == '#') { + $tmp = str_replace("#","",$attrs['VALUE']); + $res = $DBc->sendSQL("SELECT * FROM ryzom_nimetu_sheets WHERE nsh_numid='".$tmp."'","ARRAY"); + $attrs['VALUE'] = $res[0]['nsh_name']."".$res[0]['nsh_suffix']; + } + + if(substr($attrs['VALUE'],0,3) == 'tp_') { + $this->tplist->tps[] = $attrs['VALUE']; + $this->itemignore = true; + return null; + } + + if(substr($attrs['VALUE'],0,1) == 'm') { + $this->itemignore = true; + if($this->hasChoice == false || $this->hasExcellent == false || $this->hasSupreme == false) { + + switch(substr($attrs['VALUE'],-9,-8)) { + case 'f': + $this->hasSupreme = true; + break; + case 'e': + $this->hasExcellent = true; + break; + case 'd': + $this->hasChoice = true; + break; + } + } + return null; + } + + $this->entity->_sheetid = $attrs['VALUE']; + + if($this->entity->inventory != 'bag' && in_array($this->entity->_itemid,$this->tracked_items) && !in_array($this->entity->_sheetid,$this->tool_list)) { + $this->itemignore = true; + } + + $this->tracked_items_new[] = $this->entity->_itemid; + + return null; + } + if($name == '_LOCSLOT') { + $this->entity->_locslot = $attrs['VALUE']; + return null; + } + if($name == '_HP') { + $this->entity->_hp = $attrs['VALUE']; + return null; + } + if($name == '_RECOMMENDED') { + $this->entity->_recommended = $attrs['VALUE']; + return null; + } + if($name == '_CREATORID') { + $this->entity->_creatorid = $attrs['VALUE']; + return null; + } + if($name == '_PHRASEID') { + $this->entity->_phraseid = $attrs['VALUE']; + return null; + } + if($name == '_REFINVENTORYSLOT') { + $this->entity->_refinventoryslot = $attrs['VALUE']; + #if($this->entity->refinventoryid != null) { + $this->gear->items[] = $this->entity; + #} + return null; + } + if($name == 'REFINVENTORYID') { + $this->entity->refinventoryid = $attrs['VALUE']; + return null; + } + if($name == '_USENEWSYSTEMREQUIREMENT') { + $this->entity->_usenewsystemrequirement = $attrs['VALUE']; + return null; + } + if($name == '_REQUIREDSKILLLEVEL') { + $this->entity->_requiredskilllevel = $attrs['VALUE']; + return null; + } + if($name == '_CUSTOMTEXT') { + $this->entity->_customtext = $attrs['VALUE']; + return null; + } + if($name == '_LOCKEDBYOWNER') { + $this->entity->_lockedbyowner = $attrs['VALUE']; + return null; + } + if($name == '_DROPABLE') { + $this->entity->_dropable = $attrs['VALUE']; + return null; + } + if($name == 'STACKSIZE') { + $this->entity->stacksize = $attrs['VALUE']; + return null; + } + } + + + + + + if($attrs['VALUE'] != '') { + $_DISPATCHER->dispatchValue(strtolower($name),$attrs['VALUE']); + } + } + + function endElement($parser, $name) { + global $_DISPATCHER,$XMLgenerator; + + $XMLgenerator->xml_split(implode("/",$this->pathid),$name,null,false); + array_pop($this->pathid); + + if(in_array($name,$this->ignore_block)) { + $this->lock = 0; + return null; + } + + if($this->lock == 1) { + return null; + } + + /* death penalty */ + if($name == "_DEATHPENALTIES") { + $this->open = null; + $this->entity->DeathXPToGain = $this->entity->DeathXPToGain*min(10,$this->entity->NbDeath); + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + /* respawn points */ + if($name == "RESPAWNPOINTS") { + $this->respawn_outer++; // increment to track double close at end of block + } + + if($name == "RESPAWNPOINTS" && $this->respawn_outer > 1) { + $this->open = null; + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + /* faction points */ + if($name == "FACTIONPOINTS") { + $this->open = null; + return null; + } + + /* fame */ + if($name == "__VAL__" && $this->open == "_FAME") { + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + if($name == "_FAME") { + $this->open = null; + return null; + } + + /* last log stats */ + if($name == "_LASTLOGSTATS") { + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + /* mission */ + if($name == "__VAL__" && $this->open == "_MISSIONHISTORIES") { + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->mission->missions[] = $this->entity; + $this->entity = null; + return null; + } + + if($name == "_MISSIONHISTORIES") { + $this->open = null; + return null; + } + + /* permanent mod */ + if($name == "SCOREPERMANENTMODIFIERS") { + $this->open = null; + return null; + } + + /* pet */ + if($name == "__VAL__" && $this->open == "_PLAYERPETS") { + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + #echo "dispatched"; + $this->entity = null; + return null; + } + + if($name == "_PLAYERPETS") { + $this->open = null; + return null; + } + + /* physical characteristics */ + if($name == "_PHYSICALCHARACTERISTICS") { + $this->open = null; + return null; + } + + /* physical scores */ + if($name == "__VAL__" && $this->open == "PHYSICALSCORES") { + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + if($name == "PHYSICALSCORES") { + $this->open = null; + return null; + } + + /* skill points */ + if($name == "SKILLPOINTS") { + $this->open = null; + return null; + } + + /* spent skill points */ + if($name == "SPENTSKILLPOINTS") { + $this->open = null; + return null; + } + + /* skills */ + if($name == "__VAL__" && $this->open == "SKILLS") { + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->skills->skills[] = $this->entity; + $this->entity = null; + return null; + } + + if($name == "SKILLS") { + $this->open = null; + return null; + } + + /* position */ + if($name == "POSSTATE") { + $this->entity->loadPlace(); + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + $this->entity = null; + return null; + } + + /* items */ + if($name == '_ITEMS' || $name == '_ITEM') { + #echo "c
"; + if($this->open == '_ITEM') { + #echo var_export($this->entity,true); + if($this->itemignore == false) { + $_DISPATCHER->dispatchEntity($this->entity->getName(),$this->entity); + } + $this->itemignore = false; + $this->entity = null; + } + $this->open = null; + return null; + } + + if($name == 'INVENTORY') { + $this->iblock = false; + return null; + } + + if($name == '_CRAFTPARAMETERS') { + $this->icraft = false; + return null; + } + + /*if($name == "_ITEM" || $name == "_ITEMS") { + $this->open = null; + return null; + }*/ + + + } + + + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/DeathPenalty_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/DeathPenalty_entity.php new file mode 100644 index 000000000..16f696c51 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/DeathPenalty_entity.php @@ -0,0 +1,13 @@ +setName("death_penalty"); + } +} +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/FactionPoints_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/FactionPoints_entity.php new file mode 100644 index 000000000..fa18a0fc6 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/FactionPoints_entity.php @@ -0,0 +1,10 @@ +setName("faction_points"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Fame_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Fame_entity.php new file mode 100644 index 000000000..0cfc5f15b --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Fame_entity.php @@ -0,0 +1,12 @@ +setName("fame"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/FriendOf_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/FriendOf_entity.php new file mode 100644 index 000000000..27978963f --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/FriendOf_entity.php @@ -0,0 +1,15 @@ +setName("friendof"); + } + + function getRealID() { + $tmp = explode(":",$this->id); + + return $tmp[0]; + } +} +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Friend_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Friend_entity.php new file mode 100644 index 000000000..72a9d1ee1 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Friend_entity.php @@ -0,0 +1,15 @@ +setName("friend"); + } + + function getRealID() { + $tmp = explode(":",$this->id); + + return $tmp[0]; + } +} +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Friendlist_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Friendlist_entity.php new file mode 100644 index 000000000..471190de1 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Friendlist_entity.php @@ -0,0 +1,29 @@ +setName("friendlist"); + } + + function countConfirmed() { + if($this->confirmed == false) { + $count = 0; + foreach($this->friends as $elem) { + $id = $elem->getRealID(); + foreach($this->friendof as $elem2) { + if($elem2->getRealID() == $id) { + $count++; + } + } + } + + $this->confirmed = $count; + } + + return $this->confirmed; + } +} +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Gear_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Gear_entity.php new file mode 100644 index 000000000..b84008061 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Gear_entity.php @@ -0,0 +1,9 @@ +setName("gear"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Item_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Item_entity.php new file mode 100644 index 000000000..2ffb89316 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Item_entity.php @@ -0,0 +1,28 @@ +setName("item"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/LastLogStats_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/LastLogStats_entity.php new file mode 100644 index 000000000..30878f04a --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/LastLogStats_entity.php @@ -0,0 +1,11 @@ +setName("lastlogstats"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/MissionList_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/MissionList_entity.php new file mode 100644 index 000000000..ab4a7bea9 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/MissionList_entity.php @@ -0,0 +1,9 @@ +setName("missionlist"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Mission_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Mission_entity.php new file mode 100644 index 000000000..7a95ac744 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Mission_entity.php @@ -0,0 +1,11 @@ +setName("mission"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/PermanentMod_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/PermanentMod_entity.php new file mode 100644 index 000000000..008a74895 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/PermanentMod_entity.php @@ -0,0 +1,10 @@ +setName("permanentmodifiers"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Pet_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Pet_entity.php new file mode 100644 index 000000000..e92499d93 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Pet_entity.php @@ -0,0 +1,24 @@ +setName("pet"); + #echo "created"; + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/PhysCharacs_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/PhysCharacs_entity.php new file mode 100644 index 000000000..c71109d02 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/PhysCharacs_entity.php @@ -0,0 +1,10 @@ +setName("phys_characs"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/PhysScores_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/PhysScores_entity.php new file mode 100644 index 000000000..d7deca5bb --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/PhysScores_entity.php @@ -0,0 +1,15 @@ +setName("phys_scores"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Position_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Position_entity.php new file mode 100644 index 000000000..c96cb35dc --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Position_entity.php @@ -0,0 +1,74 @@ +setName("position"); + $this->placeid = "place_unknown"; + } + + function loadPlace() { + global $_DISPATCHER; + + @include_once("script/include_InPoly_class.php"); + $region = array(); + $subregion = false; + + include("script/places/global.php"); + + $point = floor($this->x/1000)." ".floor($this->y/1000); + + $pointLocation = new pointLocation(); + + $res = $pointLocation->pointInPolygon($point, $region['place_silan'], false); + + if($res != "outside") { + include("script/places/silan.php"); + } + else { + include("script/places/continents.php"); + $region2 = $region; + foreach($region2 as $key=>$r) { + $res = $pointLocation->pointInPolygon($point, $r, false); + if($res != "outside") { + include("script/places/".$key.".php"); + if($subregion == true) { + foreach($region as $key2=>$r2) { + $res2 = $pointLocation->pointInPolygon($point, $r2, false); + if($res2 != "outside") { + include("script/places/".$key."/".$key2.".php"); + break; + } + } + } + break; + } + } + } + + foreach($region as $key=>$r) { + $res = $pointLocation->pointInPolygon($point, $r, false); + if($res != "outside") { + if($this->placeid == "place_unknown") { + $this->placeid = $key; + } + else { + $tmp = new Position(); + $tmp->x = $this->x; + $tmp->y = $this->y; + $tmp->z = $this->z; + $tmp->heading = $this->heading; + $tmp->placeid = $key; + + $_DISPATCHER->dispatchEntity($tmp->getName(),$tmp); + } + #break; + } + } + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/RespawnPoints_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/RespawnPoints_entity.php new file mode 100644 index 000000000..f1973a134 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/RespawnPoints_entity.php @@ -0,0 +1,80 @@ +setName("respawn_points"); + + $this->spawns = array(); + + $this->region_map = array(); + $this->region_map['spawn_global_bagne_matis'] = "roots"; + $this->region_map['spawn_global_bagne_nexus'] = "roots"; + $this->region_map['spawn_global_route_gouffre_fyros'] = "roots"; + $this->region_map['spawn_global_route_gouffre_nexus'] = "roots"; + $this->region_map['spawn_global_route_gouffre_tryker'] = "roots"; + $this->region_map['spawn_global_route_gouffre_zorai'] = "roots"; + $this->region_map['spawn_global_sources_fyros'] = "roots"; + $this->region_map['spawn_global_sources_zorai'] = "roots"; + $this->region_map['spawn_global_terre_nexus'] = "roots"; + $this->region_map['spawn_global_terre_zorai'] = "roots"; + $this->region_map['spawn_global_nexus_bagne'] = "roots"; + $this->region_map['spawn_global_nexus_route_gouffre'] = "roots"; + $this->region_map['spawn_global_nexus_terre'] = "roots"; + // 13/13 + + $this->region_map['spawn_global_fyros_matis'] = "desert"; + $this->region_map['spawn_global_fyros_route_gouffre'] = "desert"; + $this->region_map['spawn_global_fyros_sources'] = "desert"; + $this->region_map['spawn_global_fyros_to_zorai'] = "desert"; + $this->region_map['spawn_kami_place_pyr'] = "desert"; + $this->region_map['spawn_kami_place_thesos'] = "desert"; + $this->region_map['spawn_karavan_place_pyr'] = "desert"; + // 7/7 + + $this->region_map['spawn_global_matis_bagne'] = "forest"; + $this->region_map['spawn_global_matis_fyros'] = "forest"; + $this->region_map['spawn_global_matis_tryker'] = "forest"; + $this->region_map['spawn_kami_place_dyron'] = "forest"; + $this->region_map['spawn_kami_place_yrkanis'] = "forest"; + $this->region_map['spawn_karavan_place_avalae'] = "forest"; + $this->region_map['spawn_karavan_place_davae'] = "forest"; + #$this->region_map['spawn_karavan_place_yrkanis'] = "forest"; + // 8/7 + + $this->region_map['spawn_global_tryker_matis'] = "lakes"; + $this->region_map['spawn_global_tryker_route_gouffre'] = "lakes"; + #$this->region_map['spawn_kami_place_fairhaven'] = "lakes"; + $this->region_map['spawn_karavan_place_avendale'] = "lakes"; + $this->region_map['spawn_karavan_place_crystabell'] = "lakes"; + $this->region_map['spawn_karavan_place_fairhaven'] = "lakes"; + $this->region_map['spawn_karavan_place_windermeer'] = "lakes"; + // 7/6 + + $this->region_map['spawn_kami_place_hoi_cho'] = "jungle"; + $this->region_map['spawn_kami_place_jen_lai'] = "jungle"; + $this->region_map['spawn_kami_place_min_cho'] = "jungle"; + $this->region_map['spawn_global_zorai_route_gouffre'] = "jungle"; + $this->region_map['spawn_global_zorai_sources'] = "jungle"; + $this->region_map['spawn_global_zorai_terre'] = "jungle"; + $this->region_map['spawn_global_zorai_to_fyros'] = "jungle"; + $this->region_map['spawn_kami_place_zora'] = "jungle"; + #$this->region_map['spawn_karavan_place_zora'] = "jungle"; + // 9/8 + + } + + function countRegion($r) { + $c = 0; + + foreach($this->spawns as $elem) { + if($this->region_map[$elem] == $r) { + $c++; + } + } + + return $c; + } +} +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/SkillList_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/SkillList_entity.php new file mode 100644 index 000000000..6dc2202b3 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/SkillList_entity.php @@ -0,0 +1,10 @@ +setName("skilllist"); + $this->skills = array(); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/SkillPoints_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/SkillPoints_entity.php new file mode 100644 index 000000000..81582b703 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/SkillPoints_entity.php @@ -0,0 +1,10 @@ +setName("skillpoints"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Skill_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Skill_entity.php new file mode 100644 index 000000000..f06132ac8 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Skill_entity.php @@ -0,0 +1,14 @@ +setName("skill"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/SpentSkillPoints_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/SpentSkillPoints_entity.php new file mode 100644 index 000000000..5bacb0e52 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/SpentSkillPoints_entity.php @@ -0,0 +1,10 @@ +setName("spentskillpoints"); + } + } +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/TPlist_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/TPlist_entity.php new file mode 100644 index 000000000..7b4987d05 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/TPlist_entity.php @@ -0,0 +1,14 @@ +setName("TPlist"); + $this->tps = array(); + } + + function hasTP($tp) { + return in_array($tp,$this->tps); + } +} +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Title_entity.php b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Title_entity.php new file mode 100644 index 000000000..0186b37a7 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/source/PDRtoXMLdriver/entity/Title_entity.php @@ -0,0 +1,20 @@ +setName("title"); + $this->title_id = ""; + $this->title = null; + } + + function loadID() { + global $DBc; + + $res = $DBc->sendSQL("SELECT t_id FROM ryzom_title WHERE t_male='".$DBc->mre($this->title)."' OR t_female='".$DBc->mre($this->title)."'","ARRAY"); + + $this->title_id = $res[0]['t_id']; + } +} +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/debug.php b/code/web/api/server/scripts/achievement_script/xmldef/debug.php new file mode 100644 index 000000000..0f009cf5f --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/debug.php @@ -0,0 +1,84 @@ +def['XML/UTC__PVPFLAGLASTTIMECHANGE'] = array("debug"); +$this->def['XML/UTC__PVPRECENTACTIONTIME'] = array("debug"); +$this->def['XML/UTC__PVPFLAGTIMESETTEDON'] = array("debug"); +$this->def['XML/_REGIONKILLEDINPVP'] = array("debug"); +$this->def['XML/_CREATIONPOINTSREPARTITION'] = array("debug"); +$this->def['XML/UTC__FORBIDAURAUSESTARTDATE'] = array("debug"); +$this->def['XML/UTC__FORBIDAURAUSEENDDATE'] = array("debug"); +array_push($this->def['XML/_TITLE'],"debug"); +$this->def['XML/NAMESTRINGID'] = array("debug"); +$this->def['XML/_HAIRCUTEDISCOUNT'] = array("debug"); + $this->addWildcard("XML/_FORBIDPOWERDATES","debug"); +$this->def['XML/_INEFFECTIVEAURAS'] = array("debug"); +$this->def['XML/_INEFFECTIVEAURAS/_AURAACTIVATIONDATES'] = array("debug"); +$this->def['XML/_INEFFECTIVEAURAS/_AURAACTIVATIONDATES/DEACTIVATIONDATE'] = array("debug"); +$this->def['XML/_INEFFECTIVEAURAS/_AURAACTIVATIONDATES/ACTIVATIONDATE'] = array("debug"); +$this->def['XML/_INEFFECTIVEAURAS/_AURAACTIVATIONDATES/CONSUMABLEFAMILYID'] = array("debug"); +$this->def['XML/_INEFFECTIVEAURAS/_AURAACTIVATIONDATES/POWERTYPE'] = array("debug"); +$this->def['XML/_MODIFIERSINDB'] = array("debug"); + $this->addWildcard("XML/_MODIFIERSINDB/BONUS","debug"); + $this->addWildcard("XML/_MODIFIERSINDB/MALUS","debug"); +$this->def['XML/ENTITYBASE'] = array("debug"); +$this->def['XML/ENTITYBASE/_SHEETID'] = array("debug"); +$this->def['XML/ENTITYBASE/MELEEATTACKMODIFIERONENEMY'] = array("debug"); +$this->def['XML/ENTITYBASE/MELEEATTACKMODIFIERONSELF'] = array("debug"); +$this->def['XML/ENTITYBASE/MAGICCASTINGMODIFIERONSELF'] = array("debug"); +$this->def['XML/ENTITYBASE/MAGICCASTINGMODIFIERONENEMY'] = array("debug"); +$this->def['XML/ENTITYBASE/RANGEATTACKMODIFIERONENEMY'] = array("debug"); +$this->def['XML/ENTITYBASE/RANGEATTACKMODIFIERONSELF'] = array("debug"); +$this->def['XML/ENTITYBASE/ATTACKMODIFIERONSELF'] = array("debug"); +$this->def['XML/ENTITYBASE/CHANCETOFAILSTRATEGY'] = array("debug"); +$this->def['XML/ENTITYBASE/CHANCETOFAILSPELL'] = array("debug"); +$this->def['XML/ENTITYBASE/CHANCETOFAILFABER'] = array("debug"); +$this->def['XML/ENTITYBASE/CHANCETOFAILHARVEST'] = array("debug"); +$this->def['XML/ENTITYBASE/CHANCETOFAILTRACKING'] = array("debug"); +$this->def['XML/ENTITYBASE/MELEEATTACKSLOW'] = array("debug"); +$this->def['XML/ENTITYBASE/MELEESLASHINGDAMAGEARMOR'] = array("debug"); +$this->def['XML/ENTITYBASE/MELEEBLUNTDAMAGEARMOR'] = array("debug"); +$this->def['XML/ENTITYBASE/MELEEPIERCINGDAMAGEARMOR'] = array("debug"); +$this->def['XML/ENTITYBASE/MELEEDAMAGEMODIFIERFACTOR'] = array("debug"); +$this->def['XML/ENTITYBASE/RANGEDAMAGEMODIFIERFACTOR'] = array("debug"); +$this->def['XML/ENTITYBASE/CREATUREMELEETAKENDAMAGEFACTOR'] = array("debug"); +$this->def['XML/ENTITYBASE/CREATURERANGETAKENDAMAGEFACTOR'] = array("debug"); +$this->def['XML/ENTITYBASE/COMBATBRICKLATENCYMULTIPLIER'] = array("debug"); +$this->def['XML/ENTITYBASE/MAGICBRICKLATENCYMULTIPLIER'] = array("debug"); +$this->def['XML/ENTITYBASE/ARMORQUALITYMODIFIER'] = array("debug"); +$this->def['XML/ENTITYBASE/WEAPONQUALITYMODIFIER'] = array("debug"); +$this->def['XML/ENTITYBASE/ARMORABSORBTIONMULTIPLIER'] = array("debug"); +$this->def['XML/RINGREWARDPOINTS'] = array("debug"); +$this->def['XML/RINGREWARDPOINTS/RINGREWARDPOINTS/__KEY__'] = array("debug"); +$this->def['XML/RINGREWARDPOINTS/RINGREWARDPOINTS/__VAL__'] = array("debug"); + $this->addWildcard("XML/_PERSISTENTEFFECTS","debug"); +$this->def['XML/_PACT'] = array("debug"); +$this->def['XML/_PACT/PACTNATURE'] = array("debug"); +$this->def['XML/_PACT/PACTTYPE'] = array("debug"); +array_push($this->def['XML/_PLAYERPETS'],"debug"); +array_push($this->def['XML/_PLAYERPETS/__KEY__'],"debug"); +array_push($this->def['XML/_PLAYERPETS/__VAL__'],"debug"); +$this->def['XML/_PLAYERPETS/__VAL__/TICKETPETSHEETID'] = array("debug"); +$this->def['XML/_PLAYERPETS/__VAL__/PRICE'] = array("debug"); +$this->def['XML/_PLAYERPETS/__VAL__/OWNERID'] = array("debug"); +$this->def['XML/_PLAYERPETS/__VAL__/STABLEALIAS'] = array("debug"); +$this->def['XML/_PLAYERPETS/__VAL__/SLOT'] = array("debug"); +$this->def['XML/_PLAYERPETS/__VAL__/ISTPALLOWED'] = array("debug"); +$this->def['XML/_PLAYERPETS/__VAL__/CUSTOMNAME'] = array("debug"); +$this->def['XML/STARTINGCHARACTERISTICVALUES'] = array("debug"); +$this->def['XML/STARTINGCHARACTERISTICVALUES/__KEY__'] = array("debug"); +$this->def['XML/STARTINGCHARACTERISTICVALUES/__VAL__'] = array("debug"); +$this->def['XML/_ENCYCLOCHAR'] = array("debug"); +$this->def['XML/_ENCYCLOCHAR/_ENCYCHARALBUMS'] = array("debug"); +$this->def['XML/_ENCYCLOCHAR/_ENCYCHARALBUMS/ALBUMSTATE'] = array("debug"); +$this->def['XML/_ENCYCLOCHAR/_ENCYCHARALBUMS/THEMAS'] = array("debug"); +$this->def['XML/_ENCYCLOCHAR/_ENCYCHARALBUMS/THEMAS/THEMASTATE'] = array("debug"); +$this->def['XML/_ENCYCLOCHAR/_ENCYCHARALBUMS/THEMAS/RITETASKSTATEPACKED'] = array("debug"); +$this->def['XML/_GAMEEVENT'] = array("debug"); +$this->def['XML/_GAMEEVENT/UTC__DATE'] = array("debug"); + $this->addWildcard("XML/ENTITYBASE/_ENTITYPOSITION","debug"); + $this->addWildcard("XML/_ENTITYPOSITION","debug"); +$this->def['XML/INVISIBLE'] = array("debug"); +$this->def['XML/AGGROABLE'] = array("debug"); +$this->def['XML/GODMODE'] = array("debug"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/faction.php b/code/web/api/server/scripts/achievement_script/xmldef/faction.php new file mode 100644 index 000000000..f4ca5ddad --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/faction.php @@ -0,0 +1,12 @@ +def['XML/FACTIONPOINTS'] = array("faction"); +$this->def['XML/FACTIONPOINTS/__KEY__'] = array("faction"); +$this->def['XML/FACTIONPOINTS/__VAL__'] = array("faction"); +$this->def['XML/_ORGANIZATION'] = array("faction"); +$this->def['XML/_ORGANIZATIONSTATUS'] = array("faction"); +$this->def['XML/_ORGANIZATIONPOINTS'] = array("faction"); +$this->def['XML/DECLAREDCULT'] = array("faction"); +$this->def['XML/DECLAREDCIV'] = array("faction"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/fame.php b/code/web/api/server/scripts/achievement_script/xmldef/fame.php new file mode 100644 index 000000000..568d18362 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/fame.php @@ -0,0 +1,10 @@ +def['XML/_FAMES/_FAME'] = array("fame"); +$this->def['XML/_FAMES/_FAME/__KEY__'] = array("fame"); +$this->def['XML/_FAMES/_FAME/__VAL__'] = array("fame"); +$this->def['XML/_FAMES/_FAME/__VAL__/FAME'] = array("fame"); +$this->def['XML/_FAMES/_FAME/__VAL__/FAMEMEMORY'] = array("fame"); +$this->def['XML/_FAMES/_FAME/__VAL__/LASTFAMECHANGETREND'] = array("fame"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/inventory.php b/code/web/api/server/scripts/achievement_script/xmldef/inventory.php new file mode 100644 index 000000000..47f11512f --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/inventory.php @@ -0,0 +1,133 @@ +def['XML/_MONEY'] = array("inventory"); +$this->def['XML/_PLAYERROOM'] = array("inventory"); +$this->def['XML/_PLAYERROOM/BUILDING'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_ITEMID'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_SHEETID'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_LOCSLOT'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_HP'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_RECOMMENDED'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CREATORID'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_PHRASEID'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_USENEWSYSTEMREQUIREMENT'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_REQUIREDSKILLLEVEL'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CUSTOMTEXT'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_LOCKEDBYOWNER'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/STACKSIZE'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/DURABILITY'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/WEIGHT'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/STATENERGY'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/DODGEMODIFIER'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/PARRYMODIFIER'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/PROTECTIONFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/MAXSLASHINGPROTECTION'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/MAXBLUNTPROTECTION'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/MAXPIERCINGPROTECTION'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/COLOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/FOCUSBUFF'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/HPBUFF'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/SAPBUFF'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/STABUFF'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/PROTECTION'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/PROTECTION1'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/PROTECTION2'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/PROTECTION3'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/SAPLOAD'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/DMG'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/SPEED'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/RANGE'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/ADVERSARYDODGEMODIFIER'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/ADVERSARYPARRYMODIFIER'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/PROTECTION1FACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/PROTECTION2FACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/PROTECTION3FACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/DESERTRESISTANCEFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/FORESTRESISTANCEFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/LACUSTRERESISTANCEFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/JUNGLERESISTANCEFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/PRIMARYROOTRESISTANCEFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/ELEMENTALCASTINGTIMEFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/ELEMENTALPOWERFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/OFFENSIVEAFFLICTIONCASTINGTIMEFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/OFFENSIVEAFFLICTIONPOWERFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/HEALCASTINGTIMEFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/HEALPOWERFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/DEFENSIVEAFFLICTIONCASTINGTIMEFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/DEFENSIVEAFFLICTIONPOWERFACTOR'] = array("inventory"); +$this->def['XML/_PLAYERROOM/ROOMINVENTORY/_ITEMS/_CRAFTPARAMETERS/_ENCHANTMENT'] = array("inventory"); +$this->def['XML/_PLAYERPETS'] = array("inventory"); +$this->def['XML/_PLAYERPETS/__KEY__'] = array("inventory"); +$this->def['XML/_PLAYERPETS/__VAL__'] = array("inventory"); +$this->def['XML/_PLAYERPETS/__VAL__/PETSHEETID'] = array("inventory"); +$this->def['XML/_PLAYERPETS/__VAL__/LANDSCAPE_X'] = array("inventory"); +$this->def['XML/_PLAYERPETS/__VAL__/LANDSCAPE_Y'] = array("inventory"); +$this->def['XML/_PLAYERPETS/__VAL__/LANDSCAPE_Z'] = array("inventory"); +$this->def['XML/_PLAYERPETS/__VAL__/UTC_DEATHTICK'] = array("inventory"); +$this->def['XML/_PLAYERPETS/__VAL__/PETSTATUS'] = array("inventory"); +$this->def['XML/_PLAYERPETS/__VAL__/SATIETY'] = array("inventory"); +$this->def['XML/INVENTORY'] = array("inventory"); +$this->def['XML/INVENTORY/__KEY__'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_ITEMID'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_SHEETID'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_LOCSLOT'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_HP'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_RECOMMENDED'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CREATORID'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_PHRASEID'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_USENEWSYSTEMREQUIREMENT'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_REQUIREDSKILLLEVEL'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CUSTOMTEXT'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_LOCKEDBYOWNER'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/STACKSIZE'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/DURABILITY'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/WEIGHT'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/STATENERGY'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/DODGEMODIFIER'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/PARRYMODIFIER'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/PROTECTIONFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/MAXSLASHINGPROTECTION'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/MAXBLUNTPROTECTION'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/MAXPIERCINGPROTECTION'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/COLOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/FOCUSBUFF'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/HPBUFF'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/SAPBUFF'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/STABUFF'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/PROTECTION'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/PROTECTION1'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/PROTECTION2'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/PROTECTION3'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/SAPLOAD'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/DMG'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/SPEED'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/RANGE'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/ADVERSARYDODGEMODIFIER'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/ADVERSARYPARRYMODIFIER'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/PROTECTION1FACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/PROTECTION2FACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/PROTECTION3FACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/DESERTRESISTANCEFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/FORESTRESISTANCEFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/LACUSTRERESISTANCEFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/JUNGLERESISTANCEFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/PRIMARYROOTRESISTANCEFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/ELEMENTALCASTINGTIMEFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/ELEMENTALPOWERFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/OFFENSIVEAFFLICTIONCASTINGTIMEFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/OFFENSIVEAFFLICTIONPOWERFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/HEALCASTINGTIMEFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/HEALPOWERFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/DEFENSIVEAFFLICTIONCASTINGTIMEFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/DEFENSIVEAFFLICTIONPOWERFACTOR'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_CRAFTPARAMETERS/_ENCHANTMENT'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/_REFINVENTORYSLOT'] = array("inventory"); +$this->def['XML/INVENTORY/__VAL__/_ITEM/REFINVENTORYID'] = array("inventory"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/knowledge.php b/code/web/api/server/scripts/achievement_script/xmldef/knowledge.php new file mode 100644 index 000000000..5ba75d2cc --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/knowledge.php @@ -0,0 +1,11 @@ +def['XML/_BOUGHTPHRASES'] = array("knowledge"); +$this->def['XML/_KNOWNBRICKS'] = array("knowledge"); +$this->def['XML/_KNOWNPHRASES'] = array("knowledge"); +$this->def['XML/_MEMORIZEDPHRASES'] = array("knowledge"); +$this->def['XML/_MEMORIZEDPHRASES/PHRASEDESC/NAME'] = array("knowledge"); +$this->def['XML/_MEMORIZEDPHRASES/PHRASEDESC/BRICKS'] = array("knowledge"); +$this->def['XML/RESPAWNPOINTS/RESPAWNPOINTS'] = array("knowledge"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/logs.php b/code/web/api/server/scripts/achievement_script/xmldef/logs.php new file mode 100644 index 000000000..acfd7b726 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/logs.php @@ -0,0 +1,11 @@ +def['XML/_FIRSTCONNECTEDTIME'] = array("logs"); +$this->def['XML/_LASTCONNECTEDTIME'] = array("logs"); +$this->def['XML/_PLAYEDTIME'] = array("logs"); +$this->def['XML/_LASTLOGSTATS'] = array("logs"); +$this->def['XML/_LASTLOGSTATS/LOGINTIME'] = array("logs"); +$this->def['XML/_LASTLOGSTATS/DURATION'] = array("logs"); +$this->def['XML/_LASTLOGSTATS/LOGOFFTIME'] = array("logs"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/missions.php b/code/web/api/server/scripts/achievement_script/xmldef/missions.php new file mode 100644 index 000000000..ea3a198ec --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/missions.php @@ -0,0 +1,3 @@ +addWildcard("XML/_MISSIONS","missions"); +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/public.php b/code/web/api/server/scripts/achievement_script/xmldef/public.php new file mode 100644 index 000000000..5b510db0c --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/public.php @@ -0,0 +1,40 @@ +def['XML/_HAIRTYPE'] = array("public"); +$this->def['XML/HAIRTYPE'] = array("public"); +$this->def['XML/_HAIRCOLOR'] = array("public"); +$this->def['XML/HAIRCOLOR'] = array("public"); +$this->def['XML/_HATCOLOR'] = array("public"); +$this->def['XML/_JACKETCOLOR'] = array("public"); +$this->def['XML/_ARMSCOLOR'] = array("public"); +$this->def['XML/_TROUSERSCOLOR'] = array("public"); +$this->def['XML/_FEETCOLOR'] = array("public"); +$this->def['XML/_HANDSCOLOR'] = array("public"); +$this->def['XML/_PVPFLAG'] = array("public"); +$this->def['XML/_GUILDID'] = array("public"); +$this->def['XML/_TITLE'] = array("public"); +$this->def['XML/GABARITHEIGHT'] = array("public"); +$this->def['XML/GABARITTORSOWIDTH'] = array("public"); +$this->def['XML/GABARITARMSWIDTH'] = array("public"); +$this->def['XML/GABARITLEGSWIDTH'] = array("public"); +$this->def['XML/GABARITBREASTSIZE'] = array("public"); +$this->def['XML/MORPHTARGET1'] = array("public"); +$this->def['XML/MORPHTARGET2'] = array("public"); +$this->def['XML/MORPHTARGET3'] = array("public"); +$this->def['XML/MORPHTARGET4'] = array("public"); +$this->def['XML/MORPHTARGET5'] = array("public"); +$this->def['XML/MORPHTARGET6'] = array("public"); +$this->def['XML/MORPHTARGET7'] = array("public"); +$this->def['XML/MORPHTARGET8'] = array("public"); +$this->def['XML/EYESCOLOR'] = array("public"); +$this->def['XML/TATTOO'] = array("public"); +$this->def['XML/NORMALPOSITIONS/VEC/POSSTATE'] = array("public"); +$this->def['XML/NORMALPOSITIONS/VEC/POSSTATE/X'] = array("public"); +$this->def['XML/NORMALPOSITIONS/VEC/POSSTATE/Y'] = array("public"); +$this->def['XML/NORMALPOSITIONS/VEC/POSSTATE/Z'] = array("public"); +$this->def['XML/NORMALPOSITIONS/VEC/POSSTATE/HEADING'] = array("public"); +$this->def['XML/ENTITYBASE/_NAME'] = array("public"); +$this->def['XML/ENTITYBASE/_GENDER'] = array("public"); +$this->def['XML/ENTITYBASE/_SIZE'] = array("public"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/shop.php b/code/web/api/server/scripts/achievement_script/xmldef/shop.php new file mode 100644 index 000000000..5d842a17a --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/shop.php @@ -0,0 +1,66 @@ +def['XML/_ITEMSINSHOPSTORE'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_PRICE'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_RETIREPRICE'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/UTC__STARTSALECYCLE'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_OWNER'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_CONTINENT'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_QUANTITY'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_IDENTIFIER'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_ITEMID'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_SHEETID'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_LOCSLOT'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_HP'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_RECOMMENDED'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CREATORID'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_PHRASEID'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/STACKSIZE'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_USENEWSYSTEMREQUIREMENT'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CUSTOMTEXT'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_LOCKEDBYOWNER'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/DURABILITY'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/WEIGHT'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/STATENERGY'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/DODGEMODIFIER'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/PARRYMODIFIER'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/PROTECTIONFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/MAXSLASHINGPROTECTION'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/MAXBLUNTPROTECTION'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/MAXPIERCINGPROTECTION'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/COLOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/FOCUSBUFF'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/HPBUFF'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/SAPBUFF'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/STABUFF'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/PROTECTION'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/PROTECTION1'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/PROTECTION2'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/PROTECTION3'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/SAPLOAD'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/DMG'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/SPEED'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/RANGE'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/ADVERSARYDODGEMODIFIER'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/ADVERSARYPARRYMODIFIER'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/PROTECTION1FACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/PROTECTION2FACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/PROTECTION3FACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/DESERTRESISTANCEFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/FORESTRESISTANCEFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/LACUSTRERESISTANCEFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/JUNGLERESISTANCEFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/PRIMARYROOTRESISTANCEFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/ELEMENTALCASTINGTIMEFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/ELEMENTALPOWERFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/OFFENSIVEAFFLICTIONCASTINGTIMEFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/OFFENSIVEAFFLICTIONPOWERFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/HEALCASTINGTIMEFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/HEALPOWERFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/DEFENSIVEAFFLICTIONCASTINGTIMEFACTOR'] = array("shop"); +$this->def['XML/_ITEMSINSHOPSTORE/_ITEMSFORSALE/_ITEMPTR/_CRAFTPARAMETERS/DEFENSIVEAFFLICTIONPOWERFACTOR'] = array("shop"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/skills.php b/code/web/api/server/scripts/achievement_script/xmldef/skills.php new file mode 100644 index 000000000..f0f8e2113 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/skills.php @@ -0,0 +1,21 @@ +def['XML/ENTITYBASE/_SKILLS/SKILLS'] = array("skills"); +$this->def['XML/ENTITYBASE/_SKILLS/SKILLS/__KEY__'] = array("skills"); +$this->def['XML/ENTITYBASE/_SKILLS/SKILLS/__VAL__'] = array("skills"); +$this->def['XML/ENTITYBASE/_SKILLS/SKILLS/__VAL__/BASE'] = array("skills"); +$this->def['XML/ENTITYBASE/_SKILLS/SKILLS/__VAL__/CURRENT'] = array("skills"); +$this->def['XML/ENTITYBASE/_SKILLS/SKILLS/__VAL__/MAXLVLREACHED'] = array("skills"); +$this->def['XML/ENTITYBASE/_SKILLS/SKILLS/__VAL__/XP'] = array("skills"); +$this->def['XML/ENTITYBASE/_SKILLS/SKILLS/__VAL__/XPNEXTLVL'] = array("skills"); +$this->def['XML/SKILLPOINTS'] = array("skills"); +$this->def['XML/SKILLPOINTS/__KEY__'] = array("skills"); +$this->def['XML/SKILLPOINTS/__VAL__'] = array("skills"); +$this->def['XML/SPENTSKILLPOINTS'] = array("skills"); +$this->def['XML/SPENTSKILLPOINTS/__KEY__'] = array("skills"); +$this->def['XML/SPENTSKILLPOINTS/__VAL__'] = array("skills"); +$this->def['XML/SCOREPERMANENTMODIFIERS'] = array("skills"); +$this->def['XML/SCOREPERMANENTMODIFIERS/__KEY__'] = array("skills"); +$this->def['XML/SCOREPERMANENTMODIFIERS/__VAL__'] = array("skills"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/social.php b/code/web/api/server/scripts/achievement_script/xmldef/social.php new file mode 100644 index 000000000..92c015fd8 --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/social.php @@ -0,0 +1,7 @@ +def['XML/_FRIENDSLIST'] = array("social"); +$this->def['XML/_ISFRIENDOF'] = array("social"); +$this->def['XML/FRIENDVISIBILITy'] = array("social"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/achievement_script/xmldef/stats.php b/code/web/api/server/scripts/achievement_script/xmldef/stats.php new file mode 100644 index 000000000..014202f1b --- /dev/null +++ b/code/web/api/server/scripts/achievement_script/xmldef/stats.php @@ -0,0 +1,27 @@ +def['XML/_HPB'] = array("stats"); +$this->def['XML/_PVPPOINT'] = array("stats"); +$this->def['XML/_DEATHPENALTIES'] = array("stats"); +$this->def['XML/_DEATHPENALTIES/_NBDEATH'] = array("stats"); +$this->def['XML/_DEATHPENALTIES/_CURRENTDEATHXP'] = array("stats"); +$this->def['XML/_DEATHPENALTIES/_DEATHXPTOGAIN'] = array("stats"); +$this->def['XML/_DEATHPENALTIES/_BONUSUPDATETIME'] = array("stats"); +$this->def['XML/ENTITYBASE/_DODGEASDEFENSE'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSCHARACS/_PHYSICALCHARACTERISTICS'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSCHARACS/_PHYSICALCHARACTERISTICS/__KEY__'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSCHARACS/_PHYSICALCHARACTERISTICS/__VAL__'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/BASEWALKSPEED'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/BASERUNSPEED'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/CURRENTWALKSPEED'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/CURRENTRUNSPEED'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/__KEY__'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/__VAL__/CURRENT'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/__VAL__/BASE'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/__VAL__/MAX'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/__VAL__/BASEREGENERATEREPOS'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/__VAL__/BASEREGENERATEACTION'] = array("stats"); +$this->def['XML/ENTITYBASE/_PHYSSCORES/__VAL__/CURRENTREGENERATE'] = array("stats"); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/create_guilds_xml.php b/code/web/api/server/scripts/create_guilds_xml.php new file mode 100644 index 000000000..6e815cd2b --- /dev/null +++ b/code/web/api/server/scripts/create_guilds_xml.php @@ -0,0 +1,142 @@ +asXML(); + // save in clear xml + file_put_contents($filename, $txt_xml); + // save in clear compressed xml + $gz = gzopen($filename.'.gz','w9'); + gzwrite($gz, $txt_xml); + gzclose($gz); +} + +function create_guild($out, $filename, $shard) { + global $db, $time, $guilds_cache_timeout; + + $src = simplexml_load_file($filename); + + echo "$filename\n"; + + $guild = $out->addChild('guild'); + $guild->addChild('gid', $src->Id['value']); + $guild->addChild('name', $src->_Name['value']); + $guild->addChild('race', $src->Race['value']); + $guild->addChild('icon', $src->Icon['value']); + $guild->addChild('creation_date', $src->CreationDate['value']); + + $desc = (string)$src->_Description['value']; + $desc = iconv("UTF-8", "ISO-8859-1", $desc); + $replace = array('&', '<', '>'); + $into = array('&', '<', '>'); + $desc = str_replace($replace, $into, $desc); + $guild->addChild('description', $desc); + + // create the full guild xml + + $xml = simplexml_load_string(''); + + $cache = $xml->addChild('cache'); + $cache->addAttribute('created', $time); + $cache->addAttribute('expire', $time+$guilds_cache_timeout); + + $xml->addChild('name', $src->_Name['value']); + $xml->addChild('gid', $src->Id['value']); + $xml->addChild('race', $src->Race['value']); + $xml->addChild('icon', $src->Icon['value']); + $xml->addChild('creation_date', $src->CreationDate['value']); + $xml->addChild('shard', $shard); + $xml->addChild('description', $desc); + $xml->addChild('money', $src->Money['value']); + $xml->addChild('building', $src->Building['value']); + + $xml->addChild('cult', strtolower($src->DeclaredCult['value'])); + $xml->addChild('civ', strtolower($src->DeclaredCiv['value'])); + + $motd = (string)$src->_MessageOfTheDay['value']; + $motd = iconv("UTF-8", "ISO-8859-1", $motd); + $motd = str_replace($replace, $into, $motd); + $xml->addChild('motd', $motd); + + // guild members + $members = $xml->addChild('members'); + $i = 0; + do { + $m = $src->Members->__Key__[$i]['value']; + if(!isset($m)) break; + $m2 = $src->Members->__Val__[$i]; + $mem = $members->addChild('member'); + $cid = hexdec(substr($m2->Members->Id['value'], 3, 10)); + $mem->addChild('cid', $cid); + $sql = "SELECT char_name FROM characters WHERE char_id=$cid"; + $result = $db->query($sql); + $name = $db->fetch_row($result); + $db->free_result($result); + $mem->addChild('name', $name[0]); + $mem->addChild('grade', $m2->Members->Grade['value']); + $mem->addChild('joined_date', $m2->Members->EnterTime['value']); + $i++; + } while(true); + + // guild fame + $factions = array('fyros', 'matis', 'tryker', 'zorai', 'kami', 'karavan'); + $fames = $xml->addChild('fames'); + $i = 0; + do { + $f = $src->FameContainer->FameContainer->__Parent__->Entries->__Key__[$i]['value']; + if(!isset($f)) break; + $f2 = $src->FameContainer->FameContainer->__Parent__->Entries->__Val__[$i]; + $fac = basename($f2->Sheet['value'], '.faction'); + if(in_array($fac, $factions)) { + $fames->addChild($fac, $f2->Fame['value']); + } + $i++; + } while(true); + + // guild items +/* $inventory = $xml->addChild('room'); + $result = $src->xpath('/xml/GuildInventory/_Items'); + while(list( , $node) = each($result)) { + ryzom_item_insert($inventory, $node); + } +*/ + save_xml("guild_".$src->Id['value'], $xml); +} + +function create_guilds_xml($shard) { + global $time, $guilds_cache_timeout; + + $xml = simplexml_load_string(''); + + $cache = $xml->addChild('cache'); + $cache->addAttribute('created', $time); + $cache->addAttribute('expire', $time+$guilds_cache_timeout); + $xml->addChild('shard', $shard); + + foreach(glob("/home/api/public_html/data/cache/guilds/guild_?????.xml") as $fn) { + create_guild($xml, $fn, $shard); + } +// $dirname = "tmp/$shard"; +// if ($handle = opendir($dirname)) { +// while (false !== ($file = readdir($handle))) { +// if (end(explode(".", $file)) == 'xml') { +// create_guild($xml, "$dirname/$file"); +// } +// } +// closedir($handle); +// } + + save_xml("guilds_$shard", $xml); +} + +create_guilds_xml('atys'); + +?> \ No newline at end of file diff --git a/code/web/api/server/scripts/generate_guild_icon.sh b/code/web/api/server/scripts/generate_guild_icon.sh new file mode 100644 index 000000000..0f1fcd970 --- /dev/null +++ b/code/web/api/server/scripts/generate_guild_icon.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +echo $1; + +let "back=($1 & 15) - 1" +let "symbol=($1 >> 4 & 63) - 1" +let "invert=$1 >> 10 & 1" +let "col1R=$1 >> 11 & 255" +let "col1G=$1 >> 19 & 255" +let "col1B=$1 >> 27 & 255" +let "col2R=$1 >> 35 & 255" +let "col2G=$1 >> 43 & 255" +let "col2B=$1 >> 51 & 255" + +size="$2" + +png_path='/home/api/public_html/data/ryzom/guild_png/'; +final_path='/home/api/public_html/data/cache/guild_icons/'; +tmp_path="$final_path/tmp"; +img_back=`printf $png_path/guild_back_%s_%02d_1.png $size $back` +img_back2=`printf $png_path/guild_back_%s_%02d_2.png $size $back` +img_symbol=`printf $png_path/guild_symbol_%s_%02d.png $size $symbol` +img_final=`printf $final_path/%d_%s.png $1 $size` + +convert $img_back -fill "rgb($col1R,$col1G,$col1B)" -colorize 100,100,100 $tmp_path/$1_$2_part_1.png +convert $img_back2 -fill "rgb($col2R,$col2G,$col2B)" -colorize 100,100,100 $tmp_path/$1_$2_part_2.png +convert -composite $tmp_path/$1_$2_part_1.png $tmp_path/$1_$2_part_2.png $tmp_path/$1_$2_back.png + +if [[ $invert == 1 ]] +then + convert -negate $img_symbol $tmp_path/$1_$2_symb.png + composite -compose plus $tmp_path/$1_$2_back.png $tmp_path/$1_$2_symb.png $img_final +else + composite -compose multiply $tmp_path/$1_$2_back.png $img_symbol $img_final +fi + +composite -compose copy-opacity $tmp_path/$1_$2_back.png $img_final $img_final + +rm $tmp_path/$1_$2_* diff --git a/code/web/api/server/scripts/get_guilds_xml.sh b/code/web/api/server/scripts/get_guilds_xml.sh new file mode 100644 index 000000000..f4619f459 --- /dev/null +++ b/code/web/api/server/scripts/get_guilds_xml.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +cd /home/api/public_html/server/scripts + +# get guilds + +rm /home/api/public_html/data/cache/guilds/* + +rsync -az --rsh=ssh nevrax@shard.ryzom.com:/home/nevrax/code/ryzom/server/save_shard/live_atys/guilds/guild_*.bin /home/api/public_html/data/cache/guilds/ + +./pdr_util -x -s/home/app/web_hg/api/server/scripts/sheet_id.bin /home/api/public_html/data/cache/guilds/guild_*.bin + +rm /home/api/public_html/data/cache/guilds/guild_*.bin + +/usr/bin/php ./create_guilds_xml.php + +rm /home/api/public_html/data/cache/guilds/guild_?????.xml + +rm log.log + +/root/bin/own.sh api /home/api/public_html/data/cache/guilds/ + +# get tick + +rsync -az --rsh=ssh nevrax@shard.ryzom.com:/home/nevrax/code/ryzom/server/save_shard/live_atys/game_cycle.ticks /home/api/public_html/data/cache/ + +chown api:api /home/api/public_html/data/cache/game_cycle.ticks + +cd - diff --git a/code/web/api/server/time.php b/code/web/api/server/time.php new file mode 100644 index 000000000..17166d19d --- /dev/null +++ b/code/web/api/server/time.php @@ -0,0 +1,46 @@ +. + */ + +$tick_cache_timeout = 60; + +function ryzom_time_tick() { + $fn = RYAPI_PATH.'data/cache/game_cycle.ticks'; + $handle = fopen($fn, "r"); + $version = fread($handle, 1); + $raw_tick = fread($handle, 4); + fclose($handle); + $arr = unpack("V", $raw_tick); + $tick = $arr[1]; + return sprintf("%u", $tick & 0xffffffff); +} + + +/** + * Takes a computed ryzom time array and returns a SimpleXMLElement + */ +function ryzom_time_xml($rytime) { + global $tick_cache_timeout; + $out = ryzom_time_xml_without_cache($rytime); + $filename = RYAPI_PATH.'data/cache/game_cycle.ticks'; + $cache = $out->addChild('cache'); + $cache->addAttribute('created', filemtime($filename)); + $cache->addAttribute('expire', (filemtime($filename)+$tick_cache_timeout)); + return $out; +} + +?> \ No newline at end of file diff --git a/code/web/api/server/user.php b/code/web/api/server/user.php index 9124191ae..713e6c399 100644 --- a/code/web/api/server/user.php +++ b/code/web/api/server/user.php @@ -16,15 +16,81 @@ * along with ryzom_api. If not, see . */ -function ryzom_user_get_info($cid) { +include_once(RYAPI_PATH.'server/guilds.php'); + + +function ryzom_get_user_id($cid, $name, $creation_date) { + $name = strtolower($name); + + $db = ryDB::getInstance('webig'); + + $dev_shard = ((isset($_SESSION['dev_shard']) && $_SESSION['dev_shard']) || (isset($_GET['shardid']) && $_GET['shardid'] == RYAPI_DEV_SHARDID))?1:0; + if ($dev_shard) + $_SESSION['dev_shard'] = 1; + $charsWithSameName = $db->query('players', array('name' => $name, 'deleted' => 0, 'dev_shard' => $dev_shard)); + + foreach ($charsWithSameName as $charWithSameName) { + // Another char with same name => delete it + if (intval($cid) != intval($charWithSameName['cid'])) { + $db->update('players', array('deleted' => 1), array('id' => $charWithSameName['id'])); + } + } + + $charProps = $db->querySingle('players', array('cid' => intval($cid), 'deleted' => 0, 'dev_shard' => $dev_shard)); + // new char => create record + if (!$charProps) { + $charProps = array('name' => $name, 'cid' => $cid, 'creation_date' => $creation_date, 'deleted' => 0, 'dev_shard' => $dev_shard); + $charProps['id'] = $db->insert('players', $charProps); + if (!$charProps['id']) + die('ryDb New Char Error'); + } else { + // char deleted and recreated => change to deleted + if ($charProps['creation_date'] != $creation_date) { + if (!$db->update('players', array('deleted' => 1), array('id' => $charProps['id']))) + die('ryDb Delete char Error: '.$db->getErrors()); + $charProps = array('name' => $name, 'cid' => $cid, 'creation_date' => $creation_date, 'deleted' => 0, 'dev_shard' => $dev_shard); + if (!$charProps['id'] = $db->insert('players', $charProps)) + die('ryDb New Char in Slot Error'); + } else { + // char renamed => update record + if ($charProps['name'] != $name) + if (!$db->update('players', array('name' => $name), array('id' => $charProps['id']))) + die('ryDb Rename Char Error'); + } + } + return $charProps['id']; +} + +function ryzom_get_user_gender($id) { + $db = ryDB::getInstance('webig'); + $player = $db->querySingle('players', array('id' => $id)); + if ($player) { + if ($player['gender']) + return intval($player['gender']); + $cid = $player['cid']; + $xml = @simplexml_load_file(RYAPI_PATH.'data/cache/players/public/'.substr($cid, strlen($cid)-1).'/'.$cid.'.xml'); + if ($xml !== false) { + $gender = (string)$xml->public->_gender; + $db->update('players', array('gender' => intval($gender)+1), array('id' => $id)); + return $gender+1; + } + } + return false; +} + +function ryzom_user_get_info($cid, $webprivs=false, $player_stats=false) { // User information global $_RYZOM_API_CONFIG; - $db = new ServerDatabase(RYAPI_NELDB_HOST, RYAPI_NELDB_LOGIN, RYAPI_NELDB_PASS, RYAPI_NELDB_RING); + + if (isset($_SESSION['dev_shard']) && $_SESSION['dev_shard']) + $db = new ServerDatabase(RYAPI_NELDB_HOST, RYAPI_NELDB_LOGIN, RYAPI_NELDB_PASS, RYAPI_NELDB_RING_DEV); + else + $db = new ServerDatabase(RYAPI_NELDB_HOST, RYAPI_NELDB_LOGIN, RYAPI_NELDB_PASS, RYAPI_NELDB_RING); $sql = "SELECT char_name, race, civilisation, cult, guild_id, creation_date, last_played_date FROM characters WHERE char_id = $cid"; $result = $db->query($sql) or die('Could not query on ryzom_user_get_info'); $found = $db->num_rows($result) >= 1; if (!$found) - die('Could not found on ryzom_user_get_info'); + return array('char_name' => _t('guest'), 'cid' => $cid, 'ERROR' => 'unknown_user', 'groups' => array('GUEST')); $row = $db->fetch_assoc($result); $db->free_result($result); if ($row) { @@ -32,8 +98,8 @@ function ryzom_user_get_info($cid) { $row['cult'] = substr($row['cult'], 2); $row['civ'] = substr($row['civilisation'], 2); if ($row['guild_id'] != '0') { - //$xml = @simplexml_load_file(ryzom_guild($row['guild_id'], false)); - $xml = false; + $xml = @simplexml_load_file(ryzom_guild($row['guild_id'], false)); + // $xml = false; if ($xml !== false) { $row['guild_icon'] = (string)$xml->icon; $row['guild_name'] = (string)$xml->name; @@ -45,16 +111,20 @@ function ryzom_user_get_info($cid) { } } } - + $uid = intval($cid / 16); $db = new ServerDatabase(RYAPI_NELDB_HOST, RYAPI_NELDB_LOGIN, RYAPI_NELDB_PASS, RYAPI_NELDB_NEL); $sql = "SELECT Privilege FROM user WHERE UId = $uid"; $result = $db->query($sql) or die("Could not query."); - $priv_row = $db->fetch_row($result, MYSQL_NUM); + $priv_row = $db->fetch_row($result, MYSQLI_NUM); $priv = $priv_row[0]; $db->free_result($result); $groups = array(); - + + $row['uid'] = $uid; + $row['cid'] = $cid; + $row['slot'] = $cid%16; + if (strpos($priv, ':DEV:') !== false) { $groups[] = 'DEV'; $groups[] = 'SGM'; @@ -64,14 +134,14 @@ function ryzom_user_get_info($cid) { $groups[] = 'VG'; $groups[] = 'G'; } - + if (strpos($priv, ':SGM:') !== false) { $groups[] = 'SGM'; $groups[] = 'GM'; $groups[] = 'VG'; $groups[] = 'G'; } - + if (strpos($priv, ':GM:') !== false) { $groups[] = 'GM'; $groups[] = 'VG'; @@ -86,25 +156,43 @@ function ryzom_user_get_info($cid) { if (strpos($priv, ':G:') !== false) { $groups[] = 'G'; } - + if (strpos($priv, ':SEM:') !== false) { $groups[] = 'SEM'; $groups[] = 'EM'; $groups[] = 'EG'; } - + if (strpos($priv, ':EM:') !== false) { $groups[] = 'EM'; $groups[] = 'EG'; } - + if (strpos($priv, ':EG:') !== false) { $groups[] = 'EG'; } $groups[] = 'PLAYER'; - $row['groups'] = $groups; + if (isset($_SESSION['dev_shard']) && $_SESSION['dev_shard']) + $groups[] = 'DEV_SHARD'; + + if ($webprivs) { + $db = new ServerDatabase(RYAPI_WEBDB_HOST, RYAPI_WEBDB_LOGIN, RYAPI_WEBDB_PASS, 'webig'); + $sql = 'SELECT web_privs FROM accounts WHERE uid = '.intval($cid/16); + $result = $db->query($sql) or die("Could not query.".$db->get_error()); + if ($result->num_rows == 0) + $db->query('INSERT INTO accounts (`uid`, `web_privs`) VALUES ('.intval($cid/16).', \'\')') or die("Could not query.".$db->get_error()); + $priv_row = $db->fetch_row($result, MYSQLI_NUM); + $privs = $priv_row[0]; + $db->free_result($result); + $groups = array_merge($groups, explode(':', $privs)); + } + if ($player_stats) { + include_once(RYAPI_PATH.'server/player_stats.php'); + $row['fames'] = ryzom_player_fames_array($cid); + } + $row['groups'] = $groups; return $row; } diff --git a/code/web/api/server/utils.php b/code/web/api/server/utils.php index 49860d24e..2d7146176 100644 --- a/code/web/api/server/utils.php +++ b/code/web/api/server/utils.php @@ -38,7 +38,7 @@ function ryzom_name_to_file($name) function ryzom_get_user_dir($user) { global $_RYZOM_API_CONFIG; - + if ($user == "") die("INTERNAL ERROR CODE 1"); diff --git a/code/web/api/time.php b/code/web/api/time.php new file mode 100644 index 000000000..34d8847fb --- /dev/null +++ b/code/web/api/time.php @@ -0,0 +1,35 @@ +asXML(); + break; +} + +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/_API/ach_progress.php b/code/web/app/app_achievements/_API/ach_progress.php new file mode 100644 index 000000000..eaffd703d --- /dev/null +++ b/code/web/app/app_achievements/_API/ach_progress.php @@ -0,0 +1,41 @@ +connect($_CONF['mysql_server'],$_CONF['mysql_user'],$_CONF['mysql_pass'],$_CONF['mysql_database']); + + echo ''; + echo ""; + + echo ""; + $res = $DBc->sendSQL("SELECT * FROM ach_player_task WHERE apt_player='".$DBc->mre($_REQUEST['cid'])."'","ARRAY"); + foreach($res as $elem) { + echo ""; + } + echo ""; + + echo ""; + echo ""; + $res = $DBc->sendSQL("SELECT * FROM ach_player_objective WHERE apo_player='".$DBc->mre($_REQUEST['cid'])."'","ARRAY"); + foreach($res as $elem) { + echo ""; + } + echo ""; + $res = $DBc->sendSQL("SELECT ao_id,(SELECT count(*) FROM ach_player_atom,ach_atom WHERE apa_player='".$DBc->mre($_REQUEST['cid'])."' AND atom_id=apa_atom AND atom_objective=ao_id) as anz FROM ach_objective WHERE ao_display='value' AND NOT EXISTS (SELECT * FROM ach_player_objective WHERE apo_player='".$DBc->mre($_REQUEST['cid'])."' AND apo_objective='ao_id') AND EXISTS (SELECT * FROM ach_player_atom,ach_atom WHERE apa_player='".$DBc->mre($_REQUEST['cid'])."' AND atom_id=apa_atom AND atom_objective=ao_id)","ARRAY"); + foreach($res as $elem) { + echo ""; + } + echo ""; + echo ""; + + echo ""; + + exit(0); +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/_API/ach_struct.php b/code/web/app/app_achievements/_API/ach_struct.php new file mode 100644 index 000000000..b640dd1d2 --- /dev/null +++ b/code/web/app/app_achievements/_API/ach_struct.php @@ -0,0 +1,113 @@ +connect($_CONF['mysql_server'],$_CONF['mysql_user'],$_CONF['mysql_pass'],$_CONF['mysql_database']); + + echo ''; + + function print_cat(&$iter3) { + while($iter3->hasNext()) { + $curr3 = $iter3->getNext(); + echo "getImage()."'>getName()."]]>"; + if($curr3->getTieRace() != null) { + echo "".$curr3->getTieRace().""; + } + if($curr3->getTieCult() != null) { + echo "".$curr3->getTieCult().""; + } + if($curr3->getTieCiv() != null) { + echo "".$curr3->getTieCiv().""; + } + echo ""; + $iter4 = $curr3->getIterator(); + while($iter4->hasNext()) { + $curr4 = $iter4->getNext(); + echo "getDisplayName()."]]>"; + $iter5 = $curr4->getIterator(); + while($iter5->hasNext()) { + $curr5 = $iter5->getNext(); + echo "getMetaImage()."'>getDisplayName()."]]>"; + } + echo ""; + } + echo ""; + } + } + + $menu = new AchMenu(0); + $menu->removeChild(0); + + $iter = $menu->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + echo "getImage()."'>getName()."]]>"; + $iter2 = $curr->getIterator(); + while($iter2->hasNext()) { + $curr2 = $iter2->getNext(); + echo "getImage()."'>getName()."]]>"; + $cat = new AchCategory($curr2->getID(),null,null); + $iter3 = $cat->getIterator(); + print_cat($iter3); + echo ""; + } + + $cat = new AchCategory($curr->getID(),null,null); + $iter3 = $cat->getIterator(); + print_cat($iter3); + echo ""; + } + + echo ""; + + exit(0); +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/_API/class/mySQL_class.php b/code/web/app/app_achievements/_API/class/mySQL_class.php new file mode 100644 index 000000000..002abb709 --- /dev/null +++ b/code/web/app/app_achievements/_API/class/mySQL_class.php @@ -0,0 +1,166 @@ +$elem) { + $in[$key] = mysql_real_escape_string(stripslashes($elem)); + } + } + else { + $in = mysql_real_escape_string(stripslashes($in)); + } + return $in; + } + + function mySQL($err=false) { + $this->DBstats = array(); + $this->DBc = false; + if($err === "DIE" || $err === "PRINT" || $err === "ALERT" || $err === "HIDE" || $err === "LOG") { + $this->DBerror = $err; + } + else { + $this->DBerror = "HIDE"; + } + $this->resetStats(); + $this->cached = false; + } + + function connect($ip,$user,$pass,$db=false) { + $this->DBc = mysql_pconnect($ip,$user,$pass) or $this->error(mysql_error()); + if($this->DBc && $db) { + $this->database($db); + } + $this->resetStats(); + } + + function database($db) { + if(!$this->DBc) { + return false; + } + mysql_select_db($db,$this->DBc) or $this->error(mysql_error()); + + return true; + } + + function resetStats() { + $this->DBstats['query'] = 0; + $this->DBstats['error'] = 0; + } + + function getStats() { + return $this->DBstats; + } + + function sqlQuery($query) { + return $this->sendSQL($query,"ARRAY"); + } + + function sendSQL($query,$handling="PLAIN",$buffer=false) { // can be INSERT, DELETE, UPDATE, ARRAY, NONE, PLAIN + #if($this->cached !== false) { + #$this->unlinkSql($this->cached); + #} + if(!$this->DBc) { + return false; + } + + if($buffer === false && $handling !== "PLAIN") { + $res = mysql_unbuffered_query($query,$this->DBc) or $this->error(mysql_error(),$query); + } + else { + $res = mysql_query($query,$this->DBc) or $this->error(mysql_error(),$query); + } + + #$this->cached = $res; + + $this->DBstats['query']++; + + if($res) { + if($handling === "INSERT") { + $tmp = mysql_insert_id($this->DBc) or $this->error(mysql_error());; + $this->unlinkSql($res); + return $tmp; + } + elseif($handling === "DELETE" || $handling === "UPDATE") { + $tmp = mysql_affected_rows($this->DBc) or $this->error(mysql_error()); + $this->unlinkSql($res); + return $tmp; + } + elseif($handling === "ARRAY") { + $tmp = $this->parseSql($res); + $this->unlinkSql($res); + return $tmp; + } + elseif($handling === "NONE") { + $this->unlinkSql($res); + return true; + } + else { + return $res; + } + //mysql_free_result($res); + } + else { + return false; + } + } + + function unlinkSql($res) { + @mysql_free_result($res); + } + + private function parseSql($res) { + $data = array(); + $k = 0; + while($tmp = mysql_fetch_array($res,MYSQL_ASSOC)) { + $data[$k] = $tmp; + $k++; + } + + return $data; + } + + function getNext($res) { + if($res) { + if($tmp = mysql_fetch_array($res,MYSQL_ASSOC)) { + return $tmp; + } + else { + return false; + } + } + else { + return false; + } + } + + private function error($error,$query = false) { + $this->DBstats['error']++; + + if($query != false) { + $error .= " -->|".$query."|<--"; + } + + switch($this->DBerror) { + case 'DIE': + die($error); + break; + case 'PRINT': + echo "
".$error."
"; + break; + case 'ALERT': + echo ""; + break; + case 'LOG': + logf("MySQL ERROR: ".$error); + break; + default: + flush(); + break; + } + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/_API/conf.php b/code/web/app/app_achievements/_API/conf.php new file mode 100644 index 000000000..79f94ca9e --- /dev/null +++ b/code/web/app/app_achievements/_API/conf.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/code/web/app/app_achievements/_doc/Class_scheme.dia b/code/web/app/app_achievements/_doc/Class_scheme.dia new file mode 100644 index 000000000..111831ea0 Binary files /dev/null and b/code/web/app/app_achievements/_doc/Class_scheme.dia differ diff --git a/code/web/app/app_achievements/_doc/Class_scheme.png b/code/web/app/app_achievements/_doc/Class_scheme.png new file mode 100644 index 000000000..9c37c3570 Binary files /dev/null and b/code/web/app/app_achievements/_doc/Class_scheme.png differ diff --git a/code/web/app/app_achievements/_doc/ER & Class Schema.pdf b/code/web/app/app_achievements/_doc/ER & Class Schema.pdf new file mode 100644 index 000000000..721d6d59e Binary files /dev/null and b/code/web/app/app_achievements/_doc/ER & Class Schema.pdf differ diff --git a/code/web/app/app_achievements/_doc/ER_scheme.dia b/code/web/app/app_achievements/_doc/ER_scheme.dia new file mode 100644 index 000000000..c2ae2694d Binary files /dev/null and b/code/web/app/app_achievements/_doc/ER_scheme.dia differ diff --git a/code/web/app/app_achievements/_doc/ER_scheme.png b/code/web/app/app_achievements/_doc/ER_scheme.png new file mode 100644 index 000000000..898378ac0 Binary files /dev/null and b/code/web/app/app_achievements/_doc/ER_scheme.png differ diff --git a/code/web/app/app_achievements/_doc/Ryzom Player Achievements.pdf b/code/web/app/app_achievements/_doc/Ryzom Player Achievements.pdf new file mode 100644 index 000000000..92734385a Binary files /dev/null and b/code/web/app/app_achievements/_doc/Ryzom Player Achievements.pdf differ diff --git a/code/web/app/app_achievements/_doc/devshot_001.jpg b/code/web/app/app_achievements/_doc/devshot_001.jpg new file mode 100644 index 000000000..e8777e896 Binary files /dev/null and b/code/web/app/app_achievements/_doc/devshot_001.jpg differ diff --git a/code/web/app/app_achievements/_doc/devshot_002.jpg b/code/web/app/app_achievements/_doc/devshot_002.jpg new file mode 100644 index 000000000..8244cb103 Binary files /dev/null and b/code/web/app/app_achievements/_doc/devshot_002.jpg differ diff --git a/code/web/app/app_achievements/_doc/devshot_003.jpg b/code/web/app/app_achievements/_doc/devshot_003.jpg new file mode 100644 index 000000000..18d969ed8 Binary files /dev/null and b/code/web/app/app_achievements/_doc/devshot_003.jpg differ diff --git a/code/web/app/app_achievements/_doc/devshot_004.jpg b/code/web/app/app_achievements/_doc/devshot_004.jpg new file mode 100644 index 000000000..22557eedb Binary files /dev/null and b/code/web/app/app_achievements/_doc/devshot_004.jpg differ diff --git a/code/web/app/app_achievements/_doc/structure_app_achievements.sql b/code/web/app/app_achievements/_doc/structure_app_achievements.sql new file mode 100644 index 000000000..be8f9259d --- /dev/null +++ b/code/web/app/app_achievements/_doc/structure_app_achievements.sql @@ -0,0 +1,363 @@ +-- -------------------------------------------------------- +-- Host: 178.33.225.92 +-- Server Version: 5.5.28-0ubuntu0.12.04.2-log - (Ubuntu) +-- Server Betriebssystem: debian-linux-gnu +-- HeidiSQL Version: 7.0.0.4328 +-- -------------------------------------------------------- + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; + +-- Exportiere Struktur von Tabelle app_achievements.ach_achievement +CREATE TABLE IF NOT EXISTS `ach_achievement` ( + `aa_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `aa_category` bigint(20) unsigned NOT NULL, + `aa_parent` bigint(20) unsigned DEFAULT NULL, + `aa_tie_race` varchar(64) COLLATE utf8_bin DEFAULT NULL, + `aa_tie_cult` varchar(64) COLLATE utf8_bin DEFAULT NULL, + `aa_tie_civ` varchar(64) COLLATE utf8_bin DEFAULT NULL, + `aa_image` varchar(64) COLLATE utf8_bin NOT NULL, + `aa_dev` tinyint(1) unsigned NOT NULL DEFAULT '0', + `aa_sticky` tinyint(1) unsigned NOT NULL, + PRIMARY KEY (`aa_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_achievement_lang +CREATE TABLE IF NOT EXISTS `ach_achievement_lang` ( + `aal_achievement` bigint(20) unsigned NOT NULL, + `aal_lang` varchar(2) COLLATE utf8_bin NOT NULL, + `aal_name` varchar(255) COLLATE utf8_bin NOT NULL, + `aal_template` varchar(255) COLLATE utf8_bin DEFAULT NULL, + PRIMARY KEY (`aal_achievement`,`aal_lang`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_atom +CREATE TABLE IF NOT EXISTS `ach_atom` ( + `atom_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `atom_objective` bigint(20) unsigned NOT NULL, + `atom_mandatory` tinyint(1) unsigned NOT NULL, + `atom_ruleset` blob NOT NULL, + `atom_ruleset_parsed` blob NOT NULL, + PRIMARY KEY (`atom_id`), + KEY `atom_objective` (`atom_objective`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_category +CREATE TABLE IF NOT EXISTS `ach_category` ( + `ac_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `ac_parent` bigint(20) unsigned DEFAULT NULL, + `ac_order` smallint(5) unsigned NOT NULL, + `ac_image` varchar(64) COLLATE utf8_bin DEFAULT NULL, + `ac_dev` tinyint(1) unsigned NOT NULL DEFAULT '0', + `ac_heroic` tinyint(1) unsigned NOT NULL, + `ac_contest` tinyint(1) unsigned NOT NULL, + `ac_allow_civ` tinyint(1) unsigned NOT NULL, + `ac_allow_cult` tinyint(1) unsigned NOT NULL, + PRIMARY KEY (`ac_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_category_lang +CREATE TABLE IF NOT EXISTS `ach_category_lang` ( + `acl_category` bigint(20) unsigned NOT NULL, + `acl_lang` varchar(2) COLLATE utf8_bin NOT NULL, + `acl_name` varchar(255) COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`acl_category`,`acl_lang`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_fb_token +CREATE TABLE IF NOT EXISTS `ach_fb_token` ( + `aft_player` bigint(20) unsigned NOT NULL, + `aft_token` varchar(255) NOT NULL, + `aft_date` bigint(20) unsigned NOT NULL, + `aft_allow` tinyint(1) unsigned NOT NULL, + PRIMARY KEY (`aft_player`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_objective +CREATE TABLE IF NOT EXISTS `ach_objective` ( + `ao_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `ao_task` bigint(20) unsigned NOT NULL, + `ao_condition` enum('all','any','value') COLLATE utf8_bin NOT NULL, + `ao_value` bigint(20) unsigned DEFAULT NULL, + `ao_display` enum('simple','meta','value','hidden') COLLATE utf8_bin NOT NULL DEFAULT 'hidden', + `ao_metalink` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`ao_id`), + KEY `ao_task` (`ao_task`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_objective_lang +CREATE TABLE IF NOT EXISTS `ach_objective_lang` ( + `aol_objective` bigint(20) unsigned NOT NULL, + `aol_lang` varchar(2) COLLATE utf8_bin NOT NULL, + `aol_name` varchar(255) COLLATE utf8_bin DEFAULT NULL, + PRIMARY KEY (`aol_objective`,`aol_lang`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_player_atom +CREATE TABLE IF NOT EXISTS `ach_player_atom` ( + `apa_atom` bigint(10) unsigned NOT NULL, + `apa_player` bigint(10) unsigned NOT NULL, + `apa_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `apa_date` bigint(20) unsigned NOT NULL, + `apa_expire` blob, + `apa_state` enum('GRANT','DENY') COLLATE utf8_bin NOT NULL, + `apa_value` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`apa_id`), + KEY `apa_atom` (`apa_atom`,`apa_player`), + KEY `apa_atom_2` (`apa_atom`,`apa_player`,`apa_state`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=FIXED; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_player_item +CREATE TABLE IF NOT EXISTS `ach_player_item` ( + `api_item` varchar(32) COLLATE utf8_bin NOT NULL, + `api_player` int(10) unsigned NOT NULL, + `api_date` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`api_item`,`api_player`), + KEY `Index 2` (`api_player`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_player_objective +CREATE TABLE IF NOT EXISTS `ach_player_objective` ( + `apo_objective` bigint(20) unsigned NOT NULL, + `apo_player` bigint(20) unsigned NOT NULL, + `apo_date` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`apo_objective`,`apo_player`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_player_task +CREATE TABLE IF NOT EXISTS `ach_player_task` ( + `apt_task` bigint(20) unsigned NOT NULL, + `apt_player` bigint(20) unsigned NOT NULL, + `apt_date` bigint(20) unsigned NOT NULL, + `apt_fb` tinyint(1) unsigned NOT NULL, + PRIMARY KEY (`apt_task`,`apt_player`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin DELAY_KEY_WRITE=1; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_player_valuecache +CREATE TABLE IF NOT EXISTS `ach_player_valuecache` ( + `apv_name` varchar(10) COLLATE utf8_bin NOT NULL, + `apv_player` bigint(10) unsigned NOT NULL, + `apv_value` varchar(255) COLLATE utf8_bin NOT NULL, + `apv_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `apv_date` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`apv_id`), + UNIQUE KEY `key1` (`apv_name`,`apv_player`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_task +CREATE TABLE IF NOT EXISTS `ach_task` ( + `at_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `at_achievement` bigint(20) unsigned NOT NULL, + `at_parent` bigint(20) unsigned DEFAULT NULL, + `at_value` int(10) unsigned NOT NULL, + `at_condition` enum('all','any','value') COLLATE utf8_bin NOT NULL DEFAULT 'all', + `at_condition_value` int(10) unsigned DEFAULT NULL, + `at_dev` tinyint(1) unsigned NOT NULL DEFAULT '0', + `at_torder` smallint(5) unsigned NOT NULL, + `at_inherit` tinyint(1) unsigned NOT NULL, + PRIMARY KEY (`at_id`), + UNIQUE KEY `ap_parent` (`at_parent`), + KEY `at_achievement` (`at_achievement`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_task_lang +CREATE TABLE IF NOT EXISTS `ach_task_lang` ( + `atl_task` bigint(20) unsigned NOT NULL, + `atl_lang` varchar(2) COLLATE utf8_bin NOT NULL, + `atl_name` varchar(255) COLLATE utf8_bin NOT NULL, + `atl_template` varchar(255) COLLATE utf8_bin DEFAULT NULL, + PRIMARY KEY (`atl_task`,`atl_lang`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_task_tie_align +CREATE TABLE IF NOT EXISTS `ach_task_tie_align` ( + `atta_task` bigint(20) unsigned NOT NULL DEFAULT '0', + `atta_alignment` varchar(64) NOT NULL DEFAULT '', + PRIMARY KEY (`atta_task`,`atta_alignment`), + KEY `Index 2` (`atta_task`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_task_tie_civ +CREATE TABLE IF NOT EXISTS `ach_task_tie_civ` ( + `attciv_task` int(10) DEFAULT NULL, + `attciv_civ` int(10) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_task_tie_cult +CREATE TABLE IF NOT EXISTS `ach_task_tie_cult` ( + `attcult_cult` int(10) DEFAULT NULL, + `attcult_task` int(10) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ach_task_tie_race +CREATE TABLE IF NOT EXISTS `ach_task_tie_race` ( + `attr_task` bigint(20) unsigned NOT NULL, + `attr_race` varchar(64) NOT NULL, + PRIMARY KEY (`attr_task`,`attr_race`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ryzom_nimetu_item_data +CREATE TABLE IF NOT EXISTS `ryzom_nimetu_item_data` ( + `sheetid` varchar(64) COLLATE utf8_bin NOT NULL, + `type` int(10) unsigned NOT NULL, + `item_type` int(10) unsigned NOT NULL, + `race` int(10) unsigned NOT NULL, + `quality` int(10) unsigned NOT NULL, + `craftplan` varchar(32) COLLATE utf8_bin NOT NULL, + `skill` varchar(16) COLLATE utf8_bin NOT NULL, + `damage` int(10) unsigned NOT NULL, + `reach` int(10) unsigned NOT NULL, + `ecosystem` int(10) unsigned NOT NULL, + `grade` int(10) unsigned NOT NULL, + `mpft` bigint(20) unsigned NOT NULL, + `color` int(10) unsigned NOT NULL, + `is_looted` int(10) unsigned NOT NULL, + `is_mission` int(10) unsigned NOT NULL, + `index` int(10) unsigned NOT NULL, + `txt` text COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`sheetid`), + KEY `type` (`type`), + KEY `item_type` (`item_type`), + KEY `type_2` (`type`,`item_type`), + KEY `race` (`race`), + KEY `quality` (`quality`), + KEY `craftplan` (`craftplan`), + KEY `skill` (`skill`), + KEY `damage` (`damage`), + KEY `reach` (`reach`), + KEY `ecosystem` (`ecosystem`), + KEY `grade` (`grade`), + KEY `mpft` (`mpft`), + KEY `color` (`color`), + KEY `is_looted` (`is_looted`), + KEY `is_mission` (`is_mission`), + KEY `index` (`index`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ryzom_nimetu_sheets +CREATE TABLE IF NOT EXISTS `ryzom_nimetu_sheets` ( + `nsh_numid` bigint(20) NOT NULL, + `nsh_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `nsh_suffix` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`nsh_numid`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.ryzom_title +CREATE TABLE IF NOT EXISTS `ryzom_title` ( + `t_id` varchar(255) CHARACTER SET utf8 NOT NULL, + `t_lang` varchar(2) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `t_male` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `t_female` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`t_id`,`t_lang`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.stat_daily +CREATE TABLE IF NOT EXISTS `stat_daily` ( + `sd_day` date NOT NULL DEFAULT '0000-00-00', + `sd_players` bigint(20) unsigned DEFAULT NULL, + `sd_money_total` bigint(20) unsigned DEFAULT NULL, + `sd_money_avg` int(10) unsigned DEFAULT NULL, + `sd_money_mean` int(10) unsigned DEFAULT NULL, + `sd_mek_total` bigint(20) unsigned DEFAULT NULL, + `sd_mek_avg` smallint(5) unsigned DEFAULT NULL, + `sd_mek_mean` smallint(5) unsigned DEFAULT NULL, + `sd_lvl_total` bigint(20) unsigned DEFAULT NULL, + `sd_lvl_avg` int(10) unsigned DEFAULT NULL, + `sd_lvl_mean` int(10) unsigned DEFAULT NULL, + `sd_item_total` bigint(20) unsigned DEFAULT NULL, + `sd_item_avg` int(10) unsigned DEFAULT NULL, + `sd_item_mean` int(10) unsigned DEFAULT NULL, + `sd_yubo_total` bigint(20) unsigned DEFAULT NULL, + `sd_yubo_avg` int(10) unsigned DEFAULT NULL, + `sd_yubo_mean` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`sd_day`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- Daten Export vom Benutzer nicht ausgewählt + + +-- Exportiere Struktur von Tabelle app_achievements.stat_players +CREATE TABLE IF NOT EXISTS `stat_players` ( + `sp_char` bigint(10) unsigned NOT NULL DEFAULT '0', + `sp_money` bigint(20) unsigned DEFAULT NULL, + `sp_race` enum('r_matis','r_tryker','r_fyros','r_zorai') DEFAULT NULL, + `sp_yubototal` int(10) unsigned DEFAULT NULL, + `sp_mekcount` int(10) unsigned DEFAULT NULL, + `sp_maxlevel` smallint(5) unsigned DEFAULT NULL, + `sp_guildid` int(10) unsigned DEFAULT NULL, + `sp_itemcount` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`sp_char`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 DELAY_KEY_WRITE=1; + +-- Daten Export vom Benutzer nicht ausgewählt +/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; +/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; diff --git a/code/web/app/app_achievements/class/AVLTree_class.php b/code/web/app/app_achievements/class/AVLTree_class.php new file mode 100644 index 000000000..3af314081 --- /dev/null +++ b/code/web/app/app_achievements/class/AVLTree_class.php @@ -0,0 +1,340 @@ +root = null; + $this->debug = $log; + } + + function preorder() { + $this->AVLpreorder($this->root); + } + + private function AVLpreorder($p) { // recursive; output preorder representation + if($p != null) { + echo $p->getID().", "; + $this->AVLpreorder($p->getLeft()); + $this->AVLpreorder($p->getRight()); + } + } + + function inorder() { + $this->AVLinorder($this->root); + } + + private function AVLinorder($p) { // recursive; output postorder representation + if($p != null) { + $this->AVLinorder($p->getLeft()); + echo $p->getID().", "; + $this->AVLinorder($p->getRight()); + } + } + + function insert($node) { // insert a new node + if($this->root == null) { + $this->root = new AVLTreeNode($node); + } + else { + $this->root = $this->AVLinsert($this->root,new AVLTreeNode($node)); + } + } + + function remove($id) { // remove a node + $n = $this->AVLfind($id,$this->root); + + if($n != null) { + $this->AVLremove($this->root,$n); + return $n->getNode(); + } + return null; + } + + function find($id) { // find a node + $res = $this->AVLfind($id,$this->root); + if($res != null) { + return $res->getNode(); + } + return null; + } + + private function AVLfind($id,$n) { // recursive; search for a node + if($n != null) { + if($n->getID() != $id) { + if($n->getID() > $id) { + $n = $this->AVLfind($id,$n->getLeft()); + } + else { + $n = $this->AVLfind($id,$n->getRight()); + } + } + } + + return $n; + } + + private function AVLremove($r,$n) { // remove a node from the actual tree + if($n->getLeft() == null || $n->getRight() == null) { + $s = $n; + } + else { + $s = $this->Successor($n); + $n->setNode($r->getNode()); + } + + if($r->getLeft() != null) { + $p = $s->getLeft(); + } + else { + $p = $s->getRight(); + } + + if($p != null) { + $p->setParent($s->getParent()); + } + + if($r->getParent() == null) { + $r = $p; + } + else { + $tmp = $s->getParent(); + if($s == $tmp->getLeft()) { + $tmp->setLeft($p); + } + else { + $tmp->setRight($p); + } + } + + return $r; + } + + private function AVLinsert($r,$n) { // insert a node into the actual tree + if($r == null) { + $r = $n; + } + else { + if($n->getID() < $r->getID()) { + $r->setLeft($this->AVLinsert($r->getLeft(),$n)); + + $r = $this->balance($r); // rebalance + } + elseif($n->getID() > $r->getID()) { + $r->setRight($this->AVLinsert($r->getRight(),$n)); + + $r = $this->balance($r); // rebalance + } + + $r->setHeight(max($r->getHeightLeft(),$r->getHeightRight())+1); + } + + return $r; + } + + private function balance($r) { // do a rebalancation of the tree + if($r->bal() == -2) { + $lc = $r->getLeft(); + if($lc->getHeightLeft() >= $lc->getHeightRight()) { + $r = $this->RotateToRight($r); + } + else { + $r = $this->DoubleRotateLeftRight($r); + } + } + + if($r->bal() == 2) { + $rc = $r->getRight(); + if($rc->getHeightRight() >= $rc->getHeightLeft()) { + $r = $this->RotateToLeft($r); + } + else { + $r = $this->DoubleRotateRightLeft($r); + } + } + + return $r; + } + + private function Successor($r) { // find the successor for a node + if($r->getRight() != null) { + return $this->Minimum($r->getRight()); + } + else { + $n = $r->getParent(); + + while($n != null && $r == $n->getRight()) { + $r = $n; + $n = $n->getParent(); + } + return $n; + } + } + + private function Minimum($r) { // find the minimum of a tree + if($r == null) { + return null; + } + + if($r->getLeft() == null) { + return $r; + } + + $p = $r; + while($p->getLeft() != null) { + $p = $p->getLeft(); + } + + return $p; + } + + //rotations + + private function RotateToRight($r) { + if($this->debug) { + echo "rotaRight
"; + } + $v = $r->getLeft(); + $r->setLeft($v->getRight()); + $v->setRight($r); + + $r->setHeight(max($r->getHeightLeft(),$r->getHeightRight())+1); + $v->setHeight(max($v->getHeightLeft(),$r->getHeight())+1); + + return $v; + } + + private function DoubleRotateLeftRight($r) { + $r->setLeft($this->RotateToLeft($r->getLeft())); + return $this->RotateToRight($r); + } + + private function RotateToLeft($r) { + if($this->debug) { + echo "rotaLeft
"; + } + $v = $r->getRight(); + $r->setRight($v->getLeft()); + $v->setLeft($r); + + $r->setHeight(max($r->getHeightLeft(),$r->getHeightRight())+1); + $v->setHeight(max($v->getHeightRight(),$r->getHeight())+1); + + return $v; + } + + private function DoubleRotateRightLeft($r) { + $r->setRight($this->RotateToRight($r->getRight())); + return $this->RotateToLeft($r); + } + + //end rotations + } + + /* + * AVL tree nodes + */ + + class AVLTreeNode { + private $height; + private $left; + private $right; + private $node; + private $parent; + + function AVLTreeNode($node) { + $this->height = 0; + $this->left = null; // left child + $this->right = null; // right child + $this->node = $node; // actual data stored + $this->parent = null; // parent node + } + + function getParent() { + return $this->parent; + } + + function setParent($p) { + $this->parent = $p; + } + + function getNode() { + return $this->node; + } + + function getLeft() { + return $this->left; + } + + function getRight() { + return $this->right; + } + + function getHeightLeft() { + if($this->left == null) { + return -1; + } + return $this->left->getHeight(); + } + + function getHeightRight() { + if($this->right == null) { + return -1; + } + return $this->right->getHeight(); + } + + function bal() { // calculate value to eval balancing + $r = -1; + $l = -1; + + if($this->right != null) { + $r = $this->right->getHeight(); + } + + if($this->left != null) { + $l = $this->left->getHeight(); + } + + return ($r-$l); + } + + function getID() { + return $this->node->getID(); + } + + function getHeight() { + return $this->height; + } + + function setHeight($h) { + $this->height = $h; + } + + function setRight($r) { + $this->right = $r; + if($r != null) { + $r->setParent($this); + } + } + + function setLeft($l) { + $this->left = $l; + if($l != null) { + $l->setParent($this); + } + } + + function setNode($n) { + $this->node = $n; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/AchAchievement_class.php b/code/web/app/app_achievements/class/AchAchievement_class.php new file mode 100644 index 000000000..8fc2753f7 --- /dev/null +++ b/code/web/app/app_achievements/class/AchAchievement_class.php @@ -0,0 +1,315 @@ +dev == 1); + } + + function getDev() { + return $this->dev; + } + + function setInDev($tf) { + if($tf == true) { + $this->setDev(1); + } + else { + $this->setDev(0); + } + + $this->update(); + } + + function setDev($d) { + $this->dev = $d; + } + ######################### + + protected $parent_id; + protected $category; + #protected $tie_race; + #protected $tie_civ; + #protected $tie_cult; + protected $image; + protected $name; + protected $template; + protected $sticky; + + function AchAchievement($data,&$parent) { + global $DBc,$_USER,$_CONF; + + parent::__construct(); + + $this->setParent($parent); // real parent node + $this->setID($data['aa_id']); + $this->parent_id = $data['aa_parent']; // id of parent + $this->category = $data['aa_category']; + #$this->tie_race = $data['aa_tie_race']; + #$this->tie_civ = $data['aa_tie_civ']; + #$this->tie_cult = $data['aa_tie_cult']; + $this->image = $data['aa_image']; + $this->name = $data['aal_name']; + $this->template = $data['aal_template']; + $this->dev = $data['aa_dev']; + $this->sticky = $data['aa_sticky']; + + if($this->name == null) { + $res = $DBc->sqlQuery("SELECT * FROM ach_achievement_lang WHERE aal_lang='".$_CONF['default_lang']."' AND aal_achievement='".$this->id."'"); + $this->name = $res[0]['aal_name']; + $this->template = $res[0]['aal_template']; + } + + $res = $DBc->sqlQuery("SELECT * FROM ach_task LEFT JOIN (ach_task_lang) ON (atl_lang='".$_USER->getLang()."' AND atl_task=at_id) LEFT JOIN (ach_player_task) ON (apt_task=at_id AND apt_player='".$_USER->getID()."') WHERE at_achievement='".$this->id."' AND (NOT EXISTS (SELECT * FROM ach_task_tie_align WHERE atta_task=at_id) OR EXISTS (SELECT * FROM ach_task_tie_align WHERE atta_task=at_id AND atta_alignment LIKE '".$parent->getCurrentCult().'|'.$parent->getCurrentCiv()."')) ORDER by at_torder ASC"); + + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + $tmp = $this->makeChild($res[$i]); + + if($tmp->isDone()) { + $this->addDone($tmp); + } + else { + $this->addOpen($tmp); + } + } + + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $curr->loadHeritage(); + } + } + + function parentDone() { // check if the parent is complete + if($this->parent_id == null) { + return true; + } + else { + $p = $this->parent->getChildDataByID($this->parent_id); + if($p == null) { + return true; + } + + return ($p->hasOpen() == false); + } + } + + #@override Parentum::makeChild() + protected function makeChild($a) { + return new AchTask($a,$this); + } + + function getParentID() { + return $this->parent_id; + } + + function hasTieRace_open() { + #return $this->tie_race; + $iter = $this->child_open->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieRace_open() && !$curr->inDev()) { + return true; + } + } + + return false; + } + + function hasTieAlign_open() { + #return $this->tie_civ; + $iter = $this->child_open->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieAlign_open() && !$curr->inDev()) { + return true; + } + } + + return false; + } + + function hasTieRace_done() { + #return $this->tie_race; + $iter = $this->child_done->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieRace_done() && !$curr->inDev()) { + return true; + } + } + + return false; + } + + function hasTieAlign_done() { + #return $this->tie_civ; + $iter = $this->child_done->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieAlign_done() && !$curr->inDev()) { + return true; + } + } + + return false; + } + + function hasTieRaceDev() { + #return $this->tie_race; + $iter = $this->nodes->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieRaceDev()) { + return true; + } + } + + return false; + } + + function hasTieAlignDev() { + #return $this->tie_civ; + $iter = $this->nodes->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieAlignDev()) { + return true; + } + } + + return false; + } + + + + function isTiedRace_open($r) { + #return $this->tie_race; + $iter = $this->child_open->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->isTiedRace_open($r)) { + return true; + } + } + + return false; + } + + function isTiedAlign_open($cult,$civ) { + #return $this->tie_civ; + $iter = $this->child_open->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->isTiedAlign_open($cult,$civ)) { + return true; + } + } + + return false; + } + + function isTiedRace_done($r) { + #return $this->tie_race; + $iter = $this->child_done->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->isTiedRace_done($r)) { + return true; + } + } + + return false; + } + + function isTiedAlign_done($cult,$civ) { + #return $this->tie_civ; + $iter = $this->child_done->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->isTiedAlign_done($cult,$civ)) { + return true; + } + } + + return false; + } + + + function getImage() { + return $this->image; + } + + function getName() { + return $this->name; + } + + function getValueDone() { // calculate the yubopoints that are already done + $val = 0; + $iter = $this->getDone(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $val += $curr->getValue(); + } + return $val; + } + + function getValueOpen() { // get the yubopoints of the next open task + $iter = $this->getOpen(); + if($iter->hasNext()) { + $curr = $iter->getNext(); + return $curr->getValue(); + } + return 0; + } + + function fillTemplate($insert = array()) { // fill the naming template with given value + if($this->template == null) { + return implode(";",$insert); + } + else { + $tmp = $this->template; + $match = array(); + preg_match_all('#\[([0-9]+)\]#', $this->template, $match); + foreach($match[0] as $key=>$elem) { + $tmp = str_replace("[".$match[1][$key]."]",$insert[$key],$tmp); + } + return $tmp; + } + } + + function getTemplate() { + return $this->template; + } + + function getCategory() { + return $this->category; + } + + function getSticky() { + return $this->sticky; + } + + function isSticky() { + return ($this->sticky == 1); + } + + function isHeroic() { // check parent category if it is heroic + return $this->parent->isHeroic(); + } + + function isContest() { + return $this->parent->isContest(); + } + + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/AchCategory_class.php b/code/web/app/app_achievements/class/AchCategory_class.php new file mode 100644 index 000000000..34ab628b7 --- /dev/null +++ b/code/web/app/app_achievements/class/AchCategory_class.php @@ -0,0 +1,213 @@ +sqlEscape($civ); + } + if($cult != "%") { + $cult = $DBc->sqlEscape($cult); + } + $race = $DBc->sqlEscape($race); + + /*if($race == null) { + $race = $_USER->getRace(); + } + + if($cult == null) { + $cult = $_USER->getCult(); + } + + if($civ == null) { + $civ = $_USER->getCiv(); + }*/ + + $this->cult = $cult; + $this->civ = $civ; + $this->rave = $race; + + $this->id = $DBc->sqlEscape($id); + + $res = $DBc->sqlQuery("SELECT * FROM ach_achievement LEFT JOIN (ach_achievement_lang) ON (aal_lang='".$_USER->getLang()."' AND aal_achievement=aa_id) WHERE aa_category='".$this->id."' ORDER by aa_sticky DESC, aal_name ASC"); + + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + $tmp = $this->makeChild($res[$i]); + + if($tmp->hasOpen()) { + $this->addOpen($tmp); #AchList::addOpen() + } + if($tmp->hasDone()) { + $this->addDone($tmp); #AchList::addDone() + } + } + + $res = $DBc->sqlQuery("SELECT ac_heroic,ac_contest,ac_allow_civ,ac_allow_cult FROM ach_category WHERE ac_id='".$this->id."'"); + $this->heroic = $res[0]['ac_heroic']; + $this->contest = $res[0]['ac_contest']; + $this->allow_civ = $res[0]['ac_allow_civ']; + $this->allow_cult = $res[0]['ac_allow_cult']; + + + $iter = $this->nodes->getIterator(); + $tmp = false; + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieRace_open() && !$curr->inDev()) { + $tmp = true; + break; + } + } + $this->ties_race_open = $tmp; + + $iter = $this->nodes->getIterator(); + $tmp = false; + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieAlign_open() && !$curr->inDev()) { + $tmp = true; + break; + } + } + $this->ties_align_open = $tmp; + + $iter = $this->nodes->getIterator(); + $tmp = false; + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieRace_done() && !$curr->inDev()) { + $tmp = true; + break; + } + } + $this->ties_race_done = $tmp; + + $iter = $this->nodes->getIterator(); + $tmp = false; + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieAlign_done() && !$curr->inDev()) { + $tmp = true; + break; + } + } + $this->ties_align_done = $tmp; + + $iter = $this->nodes->getIterator(); + $tmp = false; + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieRaceDev()) { + $tmp = true; + break; + } + } + $this->ties_race_dev = $tmp; + + $iter = $this->nodes->getIterator(); + $tmp = false; + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->hasTieAlignDev()) { + $tmp = true; + break; + } + } + $this->ties_align_dev = $tmp; + } + + #@override Parentum::makeChild() + protected function makeChild($a) { + return new AchAchievement($a,$this); + } + + function isAllowedCult() { + return ($this->allow_cult == 1); + } + + function isAllowedCiv() { + return ($this->allow_civ == 1); + } + + function hasTieRace_open() { + return $this->ties_race_open; + } + + function hasTieAlign_open() { + return $this->ties_align_open; + } + + function hasTieRace_done() { + return $this->ties_race_done; + } + + function hasTieAlign_done() { + return $this->ties_align_done; + } + + function hasTieRaceDev() { + return $this->ties_race_dev; + } + + function hasTieAlignDev() { + return $this->ties_align_dev; + } + + function getCurrentCiv() { + return $this->civ; + } + + function getCurrentCult() { + return $this->cult; + } + + function getCurrentRace() { + return $this->race; + } + + function isTiedRace_open($r) { + return null; + } + + function isTiedAlign_open($cult,$civ) { + return null; + } + + function isTiedRace_done($r) { + return null; + } + + function isTiedAlign_done($cult,$civ) { + return null; + } + + function isHeroic() { + return ($this->heroic == 1); + } + + function isContest() { + return ($this->contest == 1); + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/AchList_abstract.php b/code/web/app/app_achievements/class/AchList_abstract.php new file mode 100644 index 000000000..77ed94786 --- /dev/null +++ b/code/web/app/app_achievements/class/AchList_abstract.php @@ -0,0 +1,81 @@ +child_done = new DLL(); + $this->child_open = new DLL(); + } + + final function getDone() { + return $this->child_done->getIterator(); + } + + final function getOpen() { + return $this->child_open->getIterator(); + } + + final function hasOpen() { + return ($this->child_open->getSize() != 0); + } + + final function hasDone() { + return ($this->child_done->getSize() != 0); + } + + final function addOpen($data,$b = null) { + $this->child_open->addNode($data,$b); + $this->addChild($data,$b); #Parentum::addChild() + } + + final function addDone($data,$b = null) { + $this->child_done->addNode($data,$b); + $this->addChild($data,$b); #Parentum::addChild() + } + + final function setChildDone($id) { + $this->addChildDone($id); + $this->removeChildOpen($id); + } + + final function setChildOpen($id) { + $this->addChildOpen($id); + $this->removeChildDone($id); + } + + final function addChildDone($id) { + $data = $this->getChildDataByID($id); + $this->child_done->addNode($data); + } + + final function addChildOpen($id) { + $data = $this->getChildDataByID($id); + $this->child_open->addNode($data); + } + + final function removeChildDone($id) { + $this->child_done->removeNode($id); + } + + final function removeChildOpen($id) { + $this->child_open->removeNode($id); + } + + #@OVERRIDE Parentum::removeChild() + function removeChild($id) { + parent::removeChild($id); + + $this->child_open->removeNode($id); + $this->child_done->removeNode($id); + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/AchMenuNode_class.php b/code/web/app/app_achievements/class/AchMenuNode_class.php new file mode 100644 index 000000000..cae6b6b75 --- /dev/null +++ b/code/web/app/app_achievements/class/AchMenuNode_class.php @@ -0,0 +1,107 @@ +dev == 1); + } + + function getDev() { + return $this->dev; + } + + function setInDev($tf) { + if($tf == true) { + $this->setDev(1); + } + else { + $this->setDev(0); + } + + $this->update(); + } + + function setDev($d) { + $this->dev = $d; + } + ######################### + + protected $parent_id; + protected $name; + protected $open; + protected $image; + protected $order; + + function AchMenuNode($data,$parent) { + global $DBc,$_USER,$_CONF; + + parent::__construct(); + + $this->setParent($parent); + $this->setID($data['ac_id']); + $this->parent_id = $data['ac_parent']; + $this->name = $data['acl_name']; + $this->image = $data['ac_image']; + $this->order = $data['ac_order']; + $this->open = ($this->id == $data['open']); + $this->dev = $data['ac_dev']; + + if($this->name == null) { + $res = $DBc->sqlQuery("SELECT * FROM ach_category_lang WHERE acl_lang='".$_CONF['default_lang']."' AND acl_category='".$this->id."'"); + $this->name = $res[0]['acl_name']; + } + + $res = $DBc->sqlQuery("SELECT * FROM ach_category LEFT JOIN (ach_category_lang) ON (acl_lang='".$_USER->getLang()."' AND acl_category=ac_id) WHERE ac_parent='".$this->id."' ORDER by ac_order ASC, acl_name ASC"); + + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + $res[$i]['open'] = $data['open']; + $this->addChild($this->makeChild($res[$i])); + } + } + + #@override Parentum::makeChild() + protected function makeChild($a) { + return new AchMenuNode($a,$this); + } + + function getName() { + return $this->name; + } + + function getParentID() { + return $this->parent_id; + } + + function hasOpenCat() { // finds the currently open MenuNode and returns it's ID. If not found the result will be 0 instead. + if($this->open) { + return $this->id; + } + + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $res = $curr->hasOpenCat(); + if($res != 0) { + return $res; + } + } + return 0; + } + + function isOpen() { + return $this->open; + } + + function getImage() { + return $this->image; + } + + function getOrder() { + return $this->order; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/AchMenu_class.php b/code/web/app/app_achievements/class/AchMenu_class.php new file mode 100644 index 000000000..333271af4 --- /dev/null +++ b/code/web/app/app_achievements/class/AchMenu_class.php @@ -0,0 +1,58 @@ +open = $open; + + // the summary page is autogenerated and has no database entry. We add it manually here. + $tmp = array(); + $tmp['ac_id'] = 0; + $tmp['ac_parent'] = null; + $tmp['acl_name'] = get_translation('ach_summary',$_USER->getLang()); + $tmp['ac_image'] = "summary.png"; + $tmp['ac_order'] = -1; + $tmp['open'] = $open; + $this->addChild(new AchMenuNode($tmp,$this)); + + $res = $DBc->sqlQuery("SELECT * FROM ach_category LEFT JOIN (ach_category_lang) ON (acl_lang='".$_USER->getLang()."' AND acl_category=ac_id) WHERE ac_parent IS NULL ORDER by ac_order ASC, acl_name ASC"); + + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + $res[$i]['open'] = $open; + $this->addChild($this->makeChild($res[$i])); + } + + } + + function getOpen() { // just returns the previously set ID of the currently open MenuNode + return $this->open; + } + + function getOpenCat() { // finds the currently open MenuNode and returns it's ID. If not found the result will be 0 instead. + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $res = $curr->hasOpenCat(); + if($res != 0) { + return $res; + } + } + return 0; + } + + #@override Parentum::makeChild() + protected function makeChild($a) { + return new AchMenuNode($a,$this); + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/AchObjective_class.php b/code/web/app/app_achievements/class/AchObjective_class.php new file mode 100644 index 000000000..a818e8c18 --- /dev/null +++ b/code/web/app/app_achievements/class/AchObjective_class.php @@ -0,0 +1,104 @@ +setParent($parent); + $this->setID($data['ao_id']); + $this->task = $data['ao_task']; + $this->condition = $data['ao_condition']; + $this->value = $data['ao_value']; + $this->name = $data['aol_name']; + $this->display = $data['ao_display']; + $this->done = $data['apo_date']; + $this->meta_image = $data['aa_image']; + $this->metalink = $data['ao_metalink']; + + if($this->metalink != null) { + $this->name = $data['aal_name']; + + if($this->name == null) { + $res = $DBc->sqlQuery("SELECT * FROM ach_achievement_lang WHERE aal_lang='".$_CONF['default_lang']."' AND aal_achievement='".$this->metalink."'"); + $this->name = $res[0]['aal_name']; + } + } + else { + if($this->name == null) { + $res = $DBc->sqlQuery("SELECT * FROM ach_objective_lang WHERE aol_lang='en' AND aol_objective='".$this->id."'"); + $this->name = $res[0]['aol_name']; + } + } + + $this->progress = $this->value; + + if(!$this->isDone()) { + $res = $DBc->sqlQuery("SELECT sum(apa_value) as anz FROM ach_player_atom,ach_atom WHERE apa_atom=atom_id AND atom_objective='".$this->id."' AND apa_player='".$_USER->getID()."'"); + $this->progress = $res[0]['anz']; + } + } + + #@override: Parentum::makeChild() + protected function makeChild($a) { + return null; + } + + function getMetaImage() { + return $this->meta_image; + } + + function getMetalink() { + return $this->metalink; + } + + function getTask() { + return $this->task; + } + + function getCondition() { + return $this->condition; + } + + function getValue() { + return $this->value; + } + + function getProgress() { + return $this->progress; + } + + function getName() { + return $this->name; + } + + function getDisplayName() { + if(substr($this->name,0,1) == "!") { + return substr($this->name,1); + } + return $this->parent->fillTemplate(explode(";",$this->name)); + } + + function getDisplay() { + return $this->display; + } + + function isDone() { + return ($this->done > 0); + } + + function getDone() { + return $this->done; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/AchSummary_class.php b/code/web/app/app_achievements/class/AchSummary_class.php new file mode 100644 index 000000000..040e0a887 --- /dev/null +++ b/code/web/app/app_achievements/class/AchSummary_class.php @@ -0,0 +1,172 @@ +menu = $menu; + + #die("x:".$size); + + //read all recent tasks of user + //make distinct achievement list + + $res = $DBc->sqlQuery("SELECT DISTINCT apt_date,aa_id,ach.*,(SELECT aal_name FROM ach_achievement_lang WHERE aal_lang='".$_USER->getLang()."' AND aal_achievement=ach.aa_id) as aal_name, (SELECT aal_template FROM ach_achievement_lang WHERE aal_lang='".$_USER->getLang()."' AND aal_achievement=ach.aa_id) as aal_template FROM ach_achievement as ach,ach_task,ach_player_task WHERE at_achievement=aa_id AND ach.aa_dev='0' AND apt_player='".$_USER->getID()."' AND apt_task=at_id ORDER by apt_date DESC LIMIT 0,".$size); + + #echo var_export($res,true); + + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + $this->addDone($this->makeChild($res[$i])); + } + } + + #@override: Parentum::makeChild() + protected function makeChild($a) { + return new AchAchievement($a,$this); + } + + function getSummary() { + if(!is_array($this->stats)) { // only load if needed + //now we have to find the # of tasks for each main menu entry + //and also sum up how many have been completed + $this->stats = array(); // [][name,done,total] + + $iter = $this->menu->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + + if($curr->getID() == 0 || $curr->inDev()) { + continue; // skip summary page + } + + $res = $this->sumStats($curr); + $this->stats[] = array($curr->getName(),$res[0],$res[1],$res[2]); + } + } + + return $this->stats; + } + + private function sumStats(&$node) { + global $DBc,$_USER; + + #return array(0,0); + + #echo ">".gettype($node)."<"; + + $done = 0; + $total = 0; + $hero = false; + + //read for current ID + //sum + $res = $DBc->sqlQuery("SELECT count(at_id) as anz FROM ach_task,ach_achievement,ach_player_task WHERE aa_category='".$node->getID()."' AND at_achievement=aa_id AND apt_player='".$_USER->getID()."' AND apt_task=at_id"); + $done += $res[0]["anz"]; + + $res = $DBc->sqlQuery("SELECT count(at_id) as anz FROM ach_task,ach_achievement WHERE aa_category='".$node->getID()."' AND at_achievement=aa_id AND aa_dev='0' AND at_dev='0'"); + $total += $res[0]["anz"]; + + $res = $DBc->sqlQuery("SELECT ac_heroic FROM ach_category WHERE ac_id='".$node->getID()."' AND ac_dev='0'"); + if($res[0]["ac_heroic"] == 1) { + $hero = true; + } + + $iter = $node->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + $res = $this->sumStats($curr); + $done += $res[0]; + $total += $res[1]; + $hero = ($hero == true || $res[2] == true); + } + + return array($done,$total,$hero); + + } + + function isTiedCult() { + return false; + } + + function isTiedCiv() { + return false; + } + + function getCurrentCiv() { + return "c_neutral"; + } + + function getCurrentCult() { + return "c_neutral"; + } + + function getCurrentRace() { + return "r_matis"; + } + + function isHeroic() { + return false; + } + + function isContest() { + return false; + } + + function hasTieRace_open() + { + return false; + } + + function hasTieAlign_open() + { + return false; + } + + function hasTieRace_done() + { + return false; + } + + function hasTieAlign_done() + { + return false; + } + + function hasTieRaceDev() + { + return false; + } + + function hasTieAlignDev() + { + return false; + } + + function isTiedRace_open($r) + { + return true; + } + + function isTiedAlign_open($cult, $civ) + { + return true; + } + + function isTiedRace_done($r) + { + return true; + } + + function isTiedAlign_done($cult, $civ) + { + return true; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/AchTask_class.php b/code/web/app/app_achievements/class/AchTask_class.php new file mode 100644 index 000000000..3ffbaf523 --- /dev/null +++ b/code/web/app/app_achievements/class/AchTask_class.php @@ -0,0 +1,286 @@ +dev == 1); + } + + function getDev() { + return $this->dev; + } + + function setInDev($tf) { + if($tf == true) { + $this->setDev(1); + } + else { + $this->setDev(0); + } + + $this->update(); + } + + function setDev($d) { + $this->dev = $d; + } + ######################### + + protected $achievement; + protected $value; + protected $name; + protected $done; + protected $template; + protected $parent_id; + protected $inherit_obj; + private $heritage_list; + protected $tie_race; + #protected $tie_cult; + #protected $tie_civ; + protected $tie_align; + + function AchTask($data,$parent) { + global $DBc,$_USER,$_CONF; + + parent::__construct(); + + #$this->heritage_list = array(); + + $this->setParent($parent); + $this->setID($data['at_id']); + $this->achievement = $data['at_achievement']; + $this->value = $data['at_value']; + $this->name = $data['atl_name']; + $this->done = $data['apt_date']; + $this->dev = $data['at_dev']; + $this->template = $data['atl_template']; + $this->parent_id = $data['at_parent']; + $this->inherit_obj = $data['at_inherit']; + + if($this->inherit_obj == 1) { + $this->heritage_list = new AVLTree(); + } + else { + $this->heritage_list = null; + } + + if($this->name == null) { + $res = $DBc->sqlQuery("SELECT * FROM ach_task_lang WHERE atl_lang='".$_CONF['default_lang']."' AND atl_task='".$this->id."'"); + $this->name = $res[0]['atl_name']; + $this->template = $res[0]['atl_template']; + } + + $res = $DBc->sqlQuery("SELECT * FROM ach_objective LEFT JOIN (ach_objective_lang) ON (aol_lang='".$_USER->getLang()."' AND aol_objective=ao_id) LEFT JOIN (ach_player_objective) ON (apo_objective=ao_id AND apo_player='".$_USER->getID()."') LEFT JOIN (ach_achievement,ach_achievement_lang) ON (aa_id=ao_metalink AND aa_id=aal_achievement AND aal_lang='".$_USER->getLang()."') WHERE ao_task='".$this->id."' ORDER by aol_name ASC,aal_name ASC"); + + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + $this->addChild($this->makeChild($res[$i])); + } + + //load ties + $res = $DBc->sqlQuery("SELECT attr_race FROM ach_task_tie_race WHERE attr_task='".$this->id."'"); + $sz = sizeof($res); + + $this->tie_race = array(); + for($i=0;$i<$sz;$i++) { + $this->tie_race[] = $res[$i]['attr_race']; + } + + /*$res = $DBc->sqlQuery("SELECT attcult_cult FROM ach_task_tie_cult WHERE attcult_task='".$this->id."'"); + $sz = sizeof($res); + + $this->tie_cult = array(); + for($i=0;$i<$sz;$i++) { + $this->tie_cult[] = $res[$i]['attcult_cult']; + } + + $res = $DBc->sqlQuery("SELECT attciv_civ FROM ach_task_tie_civ WHERE attciv_task='".$this->id."'"); + $sz = sizeof($res); + + $this->tie_civ = array(); + for($i=0;$i<$sz;$i++) { + $this->tie_civ[] = $res[$i]['attciv_civ']; + }*/ + + $res = $DBc->sqlQuery("SELECT atta_alignment FROM ach_task_tie_align WHERE atta_task='".$this->id."'"); + $sz = sizeof($res); + + $this->tie_align = array(); + for($i=0;$i<$sz;$i++) { + $this->tie_align[] = $res[$i]['atta_alignment']; + } + } + + function loadHeritage() { + if($this->inherit_obj == 0) { + return false; + } + $child = $this->parent->getChildDataByID($this->parent_id); + if($child == null) { + return false; + } + $iter = $child->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $this->addChild($curr); + $this->heritage_list->insert($curr); + } + return true; + } + + #@override Parentum::makeChild() + protected function makeChild($a) { + return new AchObjective($a,$this); + } + + function getHeritage() { + return $this->inherit_obj; + } + + function isInherited($id) { + if($this->getHeritage() == 0) { + return false; + } + if($this->heritage_list == null) { + return false; + } + return ($this->heritage_list->find($id) != null); + } + + function hasTieRace() { + if($this->dev == 1) { + return false; + } + return (sizeof($this->tie_race) != 0); + } + + function hasTieAlign() { + if($this->dev == 1) { + return false; + } + return (sizeof($this->tie_align) != 0); + } + + function hasTieRace_open() { + return $this->hasTieRace(); + } + + function hasTieRace_done() { + return $this->hasTieRace(); + } + + function hasTieAlign_open() { + return $this->hasTieAlign(); + } + + function hasTieAlign_done() { + return $this->hasTieAlign(); + } + + function hasTieRaceDev() { + return (sizeof($this->tie_race) != 0); + } + + function hasTieAlignDev() { + return (sizeof($this->tie_align) != 0); + } + + function isTiedRace($r) { + if(sizeof($this->tie_race) == 0) { + return true; + } + return in_array($r,$this->tie_race); + } + + function isTiedAlign($cult,$civ) { + if($cult == "%" || $civ == "%") { + return true; + } + if(sizeof($this->tie_align) == 0) { + return true; + } + return in_array(($cult.'|'.$civ),$this->tie_align); + } + + function isTiedRace_open($r) { + return $this->isTiedRace($r); + } + + function isTiedRace_done($r) { + return $this->isTiedRace($r); + } + + function isTiedAlign_done($cult,$civ) { + return $this->isTiedAlign($cult,$civ); + } + + function isTiedAlign_open($cult,$civ) { + return $this->isTiedAlign($cult,$civ); + } + + function getAchievement() { + return $this->achievement; + } + + function getValue() { + return $this->value; + } + + function getDisplayName() { + if(substr($this->name,0,1) == "!") { + return substr($this->name,1); + } + return $this->parent->fillTemplate(explode(";",$this->name)); + } + + function getName() { + return $this->name; + } + + function objDrawable() { + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->getDisplay() != "hidden") { + return true; + } + } + + return false; + } + + function isDone() { + return ($this->done > 0); + } + + function getDone() { + return $this->done; + } + + function fillTemplate($insert = array()) { + if($this->template == null) { + return implode(";",$insert); + } + else { + $tmp = $this->template; + $match = array(); + preg_match_all('#\[([0-9]+)\]#', $this->template, $match); + foreach($match[0] as $key=>$elem) { + $tmp = str_replace("[".$match[1][$key]."]",$insert[$key],$tmp); + } + return $tmp; + } + } + + function getTemplate() { + return $this->template; + } + + function getParentID() { + return $this->parent_id; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/DLL_class.php b/code/web/app/app_achievements/class/DLL_class.php new file mode 100644 index 000000000..49c5f3483 --- /dev/null +++ b/code/web/app/app_achievements/class/DLL_class.php @@ -0,0 +1,167 @@ +avl = new AVLTree(); + + $this->first = null; + $this->last = null; + + $this->size = 0; + } + + function getIterator() { + return new NodeIterator($this->first); + } + + final function getSize() { + return $this->size; + } + + final function isEmpty() { + return ($this->size == 0); + } + + function getFirst() { + return $this->first; + } + + function getLast() { + return $this->last; + } + + function addNode($data,$before = null) { // add a node + if($this->findNode($data->getID()) != null) { + return false; + } + $n = new DLLnode($data); + if($before == null) { + //insert as last + if($this->last != null) { + $this->last->setChild($n); + } + $n->setParent($this->last); + $this->last = $n; + } + else { + //insert before + $b = $this->findNode($before); + if($b != null) { + if($b == $this->first) { + $this->first = $n; + } + $tmp = $b->getParent(); + $b->setParent($n); + $n->setChild($b); + if($tmp != null) { + $tmp->setChild($n); + } + } + else { + $this->addNode($data); + return null; + } + } + + if($this->first == null) { + $this->first = $n; + } + + $this->avl->insert($n); // pass on to avl tree + $this->size++; + + return null; + } + + function removeNode($id) { // remove a node + #$this->avl->inorder(); + + $n = $this->findNode($id); + if($n != null) { + + $p = $n->getParent(); + $c = $n->getChild(); + + if($c != null) { + $c->setParent($p); + if($p != null) { + $p->setChild($c); + } + } + else { + if($p != null) { + $p->setChild(null); + } + $this->last = $p; + } + + if($p == null) { + if($c != null) { + $c->setParent(null); + $this->first = $c; + } + else { + $this->first = null; + } + } + + $this->avl->remove($id); // pass on to avl tree + $this->size--; + } + + } + + function findNode($id) { + return $this->avl->find($id); + } + } + + /* + * List nodes + */ + + class DLLnode { + private $parent; + private $child; + public $data; + + function DLLNode($d) { + $this->parent = null; + $this->child = null; + $this->data = $d; // actual data + } + + final function getParent() { + return $this->parent; + } + + final function setParent($p) { + $this->parent = $p; + } + + final function getChild() { + return $this->child; + } + + final function setChild($c) { + $this->child = $c; + } + + final function getIterator() { + return new NodeIterator($this); + } + + function getID() { + return $this->data->getID(); + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/InDev_trait.php b/code/web/app/app_achievements/class/InDev_trait.php new file mode 100644 index 000000000..8fd627e35 --- /dev/null +++ b/code/web/app/app_achievements/class/InDev_trait.php @@ -0,0 +1,33 @@ +dev == 1); + } + + final function getDev() { + return $this->dev; + } + + final function setInDev($tf) { + if($tf == true) { + $this->setDev(1); + } + else { + $this->setDev(0); + } + + $this->update(); + } + + final function setDev($d) { + $this->dev = $d; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/NodeIterator_class.php b/code/web/app/app_achievements/class/NodeIterator_class.php new file mode 100644 index 000000000..5508ff86e --- /dev/null +++ b/code/web/app/app_achievements/class/NodeIterator_class.php @@ -0,0 +1,33 @@ +hasNext()) { + $curr = $iter->getNext(); + // ... + } + ---------------------------*/ + private $node; + + function NodeIterator($node) { + $this->node = $node; + } + + function hasNext() { + if($this->node == null) { + return false; + } + + return true; + } + + function getNext() { + $n = $this->node; + $this->node = $this->node->getChild(); + return $n->data; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/Node_abstract.php b/code/web/app/app_achievements/class/Node_abstract.php new file mode 100644 index 000000000..7b15d74b4 --- /dev/null +++ b/code/web/app/app_achievements/class/Node_abstract.php @@ -0,0 +1,32 @@ +id; + } + + final function getParent() { + return $this->parent; + } + + final function setID($id) { + $this->id = $id; + } + + final function setParent($p) { + $this->parent = $p; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/Parentum_abstract.php b/code/web/app/app_achievements/class/Parentum_abstract.php new file mode 100644 index 000000000..5bd0c45c4 --- /dev/null +++ b/code/web/app/app_achievements/class/Parentum_abstract.php @@ -0,0 +1,49 @@ +nodes = new DLL(); // Doubly Linked List + } + + abstract protected function makeChild($args); // overwriteable child generator; allows to define child type (eg.: admin classes that inherit from base class) + + function isEmpty() { + return $this->nodes->isEmpty(); + } + + function addChild($data,$b = null) { + $this->nodes->addNode($data,$b); + } + + function removeChild($id) { + $this->nodes->removeNode($id); + } + + function getChildByID($id) { // returns a DLL node + return $this->nodes->findNode($id); + } + + function getChildDataByID($id) { // returns the actual content of the found DLL node + $tmp = $this->getChildByID($id); + if($tmp != null) { + return $tmp->data; + } + return null; + } + + function getIterator() { + return $this->nodes->getIterator(); + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/RyzomUser_class.php b/code/web/app/app_achievements/class/RyzomUser_class.php new file mode 100644 index 000000000..83fece663 --- /dev/null +++ b/code/web/app/app_achievements/class/RyzomUser_class.php @@ -0,0 +1,41 @@ +data = $data; + } + + function getID() { + return $this->data["id"]; + } + + function getLang() { + return $this->data['lang']; + } + + function isIG() { + return $this->data['ig']; + } + + function getParam($p) { + return $this->data[$p]; + } + + function getRace() { + return 'r_'.$this->data['race']; + } + + function getCiv() { + return 'c_'.$this->data['civ']; + } + + function getCult() { + return 'c_'.$this->data['cult']; + } + + function getName() { + return $this->data['char_name']; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/class/Tieable_inter.php b/code/web/app/app_achievements/class/Tieable_inter.php new file mode 100644 index 000000000..92cc5914c --- /dev/null +++ b/code/web/app/app_achievements/class/Tieable_inter.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/code/web/app/app_achievements/conf.php b/code/web/app/app_achievements/conf.php new file mode 100644 index 000000000..55ff0c72f --- /dev/null +++ b/code/web/app/app_achievements/conf.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/code/web/app/app_achievements/favicon.ico b/code/web/app/app_achievements/favicon.ico new file mode 100644 index 000000000..6f7d82846 Binary files /dev/null and b/code/web/app/app_achievements/favicon.ico differ diff --git a/code/web/app/app_achievements/favicon.png b/code/web/app/app_achievements/favicon.png new file mode 100644 index 000000000..0e26ec6e2 Binary files /dev/null and b/code/web/app/app_achievements/favicon.png differ diff --git a/code/web/app/app_achievements/fb/base_facebook.php b/code/web/app/app_achievements/fb/base_facebook.php new file mode 100644 index 000000000..772cc97e1 --- /dev/null +++ b/code/web/app/app_achievements/fb/base_facebook.php @@ -0,0 +1,1269 @@ + + */ +class FacebookApiException extends Exception +{ + /** + * The result from the API server that represents the exception information. + */ + protected $result; + + /** + * Make a new API Exception with the given result. + * + * @param array $result The result from the API server + */ + public function __construct($result) { + $this->result = $result; + + $code = isset($result['error_code']) ? $result['error_code'] : 0; + + if (isset($result['error_description'])) { + // OAuth 2.0 Draft 10 style + $msg = $result['error_description']; + } else if (isset($result['error']) && is_array($result['error'])) { + // OAuth 2.0 Draft 00 style + $msg = $result['error']['message']; + } else if (isset($result['error_msg'])) { + // Rest server style + $msg = $result['error_msg']; + } else { + $msg = 'Unknown Error. Check getResult()'; + } + + parent::__construct($msg, $code); + } + + /** + * Return the associated result object returned by the API server. + * + * @return array The result from the API server + */ + public function getResult() { + return $this->result; + } + + /** + * Returns the associated type for the error. This will default to + * 'Exception' when a type is not available. + * + * @return string + */ + public function getType() { + if (isset($this->result['error'])) { + $error = $this->result['error']; + if (is_string($error)) { + // OAuth 2.0 Draft 10 style + return $error; + } else if (is_array($error)) { + // OAuth 2.0 Draft 00 style + if (isset($error['type'])) { + return $error['type']; + } + } + } + + return 'Exception'; + } + + /** + * To make debugging easier. + * + * @return string The string representation of the error + */ + public function __toString() { + $str = $this->getType() . ': '; + if ($this->code != 0) { + $str .= $this->code . ': '; + } + return $str . $this->message; + } +} + +/** + * Provides access to the Facebook Platform. This class provides + * a majority of the functionality needed, but the class is abstract + * because it is designed to be sub-classed. The subclass must + * implement the four abstract methods listed at the bottom of + * the file. + * + * @author Naitik Shah + */ +abstract class BaseFacebook +{ + /** + * Version. + */ + const VERSION = '3.1.1'; + + /** + * Default options for curl. + */ + public static $CURL_OPTS = array( + CURLOPT_CONNECTTIMEOUT => 10, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 60, + CURLOPT_USERAGENT => 'facebook-php-3.1', + ); + + /** + * List of query parameters that get automatically dropped when rebuilding + * the current URL. + */ + protected static $DROP_QUERY_PARAMS = array( + 'code', + 'state', + 'signed_request', + ); + + /** + * Maps aliases to Facebook domains. + */ + public static $DOMAIN_MAP = array( + 'api' => 'https://api.facebook.com/', + 'api_video' => 'https://api-video.facebook.com/', + 'api_read' => 'https://api-read.facebook.com/', + 'graph' => 'https://graph.facebook.com/', + 'graph_video' => 'https://graph-video.facebook.com/', + 'www' => 'https://www.facebook.com/', + ); + + /** + * The Application ID. + * + * @var string + */ + protected $appId; + + /** + * The Application App Secret. + * + * @var string + */ + protected $appSecret; + + /** + * The ID of the Facebook user, or 0 if the user is logged out. + * + * @var integer + */ + protected $user; + + /** + * The data from the signed_request token. + */ + protected $signedRequest; + + /** + * A CSRF state variable to assist in the defense against CSRF attacks. + */ + protected $state; + + /** + * The OAuth access token received in exchange for a valid authorization + * code. null means the access token has yet to be determined. + * + * @var string + */ + protected $accessToken = null; + + /** + * Indicates if the CURL based @ syntax for file uploads is enabled. + * + * @var boolean + */ + protected $fileUploadSupport = false; + + /** + * Initialize a Facebook Application. + * + * The configuration: + * - appId: the application ID + * - secret: the application secret + * - fileUpload: (optional) boolean indicating if file uploads are enabled + * + * @param array $config The application configuration + */ + public function __construct($config) { + $this->setAppId($config['appId']); + $this->setAppSecret($config['secret']); + if (isset($config['fileUpload'])) { + $this->setFileUploadSupport($config['fileUpload']); + } + + $state = $this->getPersistentData('state'); + if (!empty($state)) { + $this->state = $this->getPersistentData('state'); + } + } + + /** + * Set the Application ID. + * + * @param string $appId The Application ID + * @return BaseFacebook + */ + public function setAppId($appId) { + $this->appId = $appId; + return $this; + } + + /** + * Get the Application ID. + * + * @return string the Application ID + */ + public function getAppId() { + return $this->appId; + } + + /** + * Set the App Secret. + * + * @param string $apiSecret The App Secret + * @return BaseFacebook + * @deprecated + */ + public function setApiSecret($apiSecret) { + $this->setAppSecret($apiSecret); + return $this; + } + + /** + * Set the App Secret. + * + * @param string $appSecret The App Secret + * @return BaseFacebook + */ + public function setAppSecret($appSecret) { + $this->appSecret = $appSecret; + return $this; + } + + /** + * Get the App Secret. + * + * @return string the App Secret + * @deprecated + */ + public function getApiSecret() { + return $this->getAppSecret(); + } + + /** + * Get the App Secret. + * + * @return string the App Secret + */ + public function getAppSecret() { + return $this->appSecret; + } + + /** + * Set the file upload support status. + * + * @param boolean $fileUploadSupport The file upload support status. + * @return BaseFacebook + */ + public function setFileUploadSupport($fileUploadSupport) { + $this->fileUploadSupport = $fileUploadSupport; + return $this; + } + + /** + * Get the file upload support status. + * + * @return boolean true if and only if the server supports file upload. + */ + public function getFileUploadSupport() { + return $this->fileUploadSupport; + } + + /** + * DEPRECATED! Please use getFileUploadSupport instead. + * + * Get the file upload support status. + * + * @return boolean true if and only if the server supports file upload. + */ + public function useFileUploadSupport() { + return $this->getFileUploadSupport(); + } + + /** + * Sets the access token for api calls. Use this if you get + * your access token by other means and just want the SDK + * to use it. + * + * @param string $access_token an access token. + * @return BaseFacebook + */ + public function setAccessToken($access_token) { + $this->accessToken = $access_token; + return $this; + } + + /** + * Determines the access token that should be used for API calls. + * The first time this is called, $this->accessToken is set equal + * to either a valid user access token, or it's set to the application + * access token if a valid user access token wasn't available. Subsequent + * calls return whatever the first call returned. + * + * @return string The access token + */ + public function getAccessToken() { + if ($this->accessToken !== null) { + // we've done this already and cached it. Just return. + return $this->accessToken; + } + + // first establish access token to be the application + // access token, in case we navigate to the /oauth/access_token + // endpoint, where SOME access token is required. + $this->setAccessToken($this->getApplicationAccessToken()); + $user_access_token = $this->getUserAccessToken(); + if ($user_access_token) { + $this->setAccessToken($user_access_token); + } + + return $this->accessToken; + } + + /** + * Determines and returns the user access token, first using + * the signed request if present, and then falling back on + * the authorization code if present. The intent is to + * return a valid user access token, or false if one is determined + * to not be available. + * + * @return string A valid user access token, or false if one + * could not be determined. + */ + protected function getUserAccessToken() { + // first, consider a signed request if it's supplied. + // if there is a signed request, then it alone determines + // the access token. + $signed_request = $this->getSignedRequest(); + if ($signed_request) { + // apps.facebook.com hands the access_token in the signed_request + if (array_key_exists('oauth_token', $signed_request)) { + $access_token = $signed_request['oauth_token']; + $this->setPersistentData('access_token', $access_token); + return $access_token; + } + + // the JS SDK puts a code in with the redirect_uri of '' + if (array_key_exists('code', $signed_request)) { + $code = $signed_request['code']; + $access_token = $this->getAccessTokenFromCode($code, ''); + if ($access_token) { + $this->setPersistentData('code', $code); + $this->setPersistentData('access_token', $access_token); + return $access_token; + } + } + + // signed request states there's no access token, so anything + // stored should be cleared. + $this->clearAllPersistentData(); + return false; // respect the signed request's data, even + // if there's an authorization code or something else + } + + $code = $this->getCode(); + if ($code && $code != $this->getPersistentData('code')) { + $access_token = $this->getAccessTokenFromCode($code); + if ($access_token) { + $this->setPersistentData('code', $code); + $this->setPersistentData('access_token', $access_token); + return $access_token; + } + + // code was bogus, so everything based on it should be invalidated. + $this->clearAllPersistentData(); + return false; + } + + // as a fallback, just return whatever is in the persistent + // store, knowing nothing explicit (signed request, authorization + // code, etc.) was present to shadow it (or we saw a code in $_REQUEST, + // but it's the same as what's in the persistent store) + return $this->getPersistentData('access_token'); + } + + /** + * Retrieve the signed request, either from a request parameter or, + * if not present, from a cookie. + * + * @return string the signed request, if available, or null otherwise. + */ + public function getSignedRequest() { + if (!$this->signedRequest) { + if (isset($_REQUEST['signed_request'])) { + $this->signedRequest = $this->parseSignedRequest( + $_REQUEST['signed_request']); + } else if (isset($_COOKIE[$this->getSignedRequestCookieName()])) { + $this->signedRequest = $this->parseSignedRequest( + $_COOKIE[$this->getSignedRequestCookieName()]); + } + } + return $this->signedRequest; + } + + /** + * Get the UID of the connected user, or 0 + * if the Facebook user is not connected. + * + * @return string the UID if available. + */ + public function getUser() { + if ($this->user !== null) { + // we've already determined this and cached the value. + return $this->user; + } + + return $this->user = $this->getUserFromAvailableData(); + } + + /** + * Determines the connected user by first examining any signed + * requests, then considering an authorization code, and then + * falling back to any persistent store storing the user. + * + * @return integer The id of the connected Facebook user, + * or 0 if no such user exists. + */ + protected function getUserFromAvailableData() { + // if a signed request is supplied, then it solely determines + // who the user is. + $signed_request = $this->getSignedRequest(); + if ($signed_request) { + if (array_key_exists('user_id', $signed_request)) { + $user = $signed_request['user_id']; + $this->setPersistentData('user_id', $signed_request['user_id']); + return $user; + } + + // if the signed request didn't present a user id, then invalidate + // all entries in any persistent store. + $this->clearAllPersistentData(); + return 0; + } + + $user = $this->getPersistentData('user_id', $default = 0); + $persisted_access_token = $this->getPersistentData('access_token'); + + // use access_token to fetch user id if we have a user access_token, or if + // the cached access token has changed. + $access_token = $this->getAccessToken(); + if ($access_token && + $access_token != $this->getApplicationAccessToken() && + !($user && $persisted_access_token == $access_token)) { + $user = $this->getUserFromAccessToken(); + if ($user) { + $this->setPersistentData('user_id', $user); + } else { + $this->clearAllPersistentData(); + } + } + + return $user; + } + + /** + * Get a Login URL for use with redirects. By default, full page redirect is + * assumed. If you are using the generated URL with a window.open() call in + * JavaScript, you can pass in display=popup as part of the $params. + * + * The parameters: + * - redirect_uri: the url to go to after a successful login + * - scope: comma separated list of requested extended perms + * + * @param array $params Provide custom parameters + * @return string The URL for the login flow + */ + public function getLoginUrl($params=array()) { + $this->establishCSRFTokenState(); + $currentUrl = $this->getCurrentUrl(); + + // if 'scope' is passed as an array, convert to comma separated list + $scopeParams = isset($params['scope']) ? $params['scope'] : null; + if ($scopeParams && is_array($scopeParams)) { + $params['scope'] = implode(',', $scopeParams); + } + + return $this->getUrl( + 'www', + 'dialog/oauth', + array_merge(array( + 'client_id' => $this->getAppId(), + 'redirect_uri' => $currentUrl, // possibly overwritten + 'state' => $this->state), + $params)); + } + + /** + * Get a Logout URL suitable for use with redirects. + * + * The parameters: + * - next: the url to go to after a successful logout + * + * @param array $params Provide custom parameters + * @return string The URL for the logout flow + */ + public function getLogoutUrl($params=array()) { + return $this->getUrl( + 'www', + 'logout.php', + array_merge(array( + 'next' => $this->getCurrentUrl(), + 'access_token' => $this->getAccessToken(), + ), $params) + ); + } + + /** + * Get a login status URL to fetch the status from Facebook. + * + * The parameters: + * - ok_session: the URL to go to if a session is found + * - no_session: the URL to go to if the user is not connected + * - no_user: the URL to go to if the user is not signed into facebook + * + * @param array $params Provide custom parameters + * @return string The URL for the logout flow + */ + public function getLoginStatusUrl($params=array()) { + return $this->getUrl( + 'www', + 'extern/login_status.php', + array_merge(array( + 'api_key' => $this->getAppId(), + 'no_session' => $this->getCurrentUrl(), + 'no_user' => $this->getCurrentUrl(), + 'ok_session' => $this->getCurrentUrl(), + 'session_version' => 3, + ), $params) + ); + } + + /** + * Make an API call. + * + * @return mixed The decoded response + */ + public function api(/* polymorphic */) { + $args = func_get_args(); + if (is_array($args[0])) { + return $this->_restserver($args[0]); + } else { + return call_user_func_array(array($this, '_graph'), $args); + } + } + + /** + * Constructs and returns the name of the cookie that + * potentially houses the signed request for the app user. + * The cookie is not set by the BaseFacebook class, but + * it may be set by the JavaScript SDK. + * + * @return string the name of the cookie that would house + * the signed request value. + */ + protected function getSignedRequestCookieName() { + return 'fbsr_'.$this->getAppId(); + } + + /** + * Constructs and returns the name of the coookie that potentially contain + * metadata. The cookie is not set by the BaseFacebook class, but it may be + * set by the JavaScript SDK. + * + * @return string the name of the cookie that would house metadata. + */ + protected function getMetadataCookieName() { + return 'fbm_'.$this->getAppId(); + } + + /** + * Get the authorization code from the query parameters, if it exists, + * and otherwise return false to signal no authorization code was + * discoverable. + * + * @return mixed The authorization code, or false if the authorization + * code could not be determined. + */ + protected function getCode() { + if (isset($_REQUEST['code'])) { + if ($this->state !== null && + isset($_REQUEST['state']) && + $this->state === $_REQUEST['state']) { + + // CSRF state has done its job, so clear it + $this->state = null; + $this->clearPersistentData('state'); + return $_REQUEST['code']; + } else { + self::errorLog('CSRF state token does not match one provided.'); + return false; + } + } + + return false; + } + + /** + * Retrieves the UID with the understanding that + * $this->accessToken has already been set and is + * seemingly legitimate. It relies on Facebook's Graph API + * to retrieve user information and then extract + * the user ID. + * + * @return integer Returns the UID of the Facebook user, or 0 + * if the Facebook user could not be determined. + */ + protected function getUserFromAccessToken() { + try { + $user_info = $this->api('/me'); + return $user_info['id']; + } catch (FacebookApiException $e) { + return 0; + } + } + + /** + * Returns the access token that should be used for logged out + * users when no authorization code is available. + * + * @return string The application access token, useful for gathering + * public information about users and applications. + */ + protected function getApplicationAccessToken() { + return $this->appId.'|'.$this->appSecret; + } + + /** + * Lays down a CSRF state token for this process. + * + * @return void + */ + protected function establishCSRFTokenState() { + if ($this->state === null) { + $this->state = md5(uniqid(mt_rand(), true)); + $this->setPersistentData('state', $this->state); + } + } + + /** + * Retrieves an access token for the given authorization code + * (previously generated from www.facebook.com on behalf of + * a specific user). The authorization code is sent to graph.facebook.com + * and a legitimate access token is generated provided the access token + * and the user for which it was generated all match, and the user is + * either logged in to Facebook or has granted an offline access permission. + * + * @param string $code An authorization code. + * @return mixed An access token exchanged for the authorization code, or + * false if an access token could not be generated. + */ + protected function getAccessTokenFromCode($code, $redirect_uri = null) { + if (empty($code)) { + return false; + } + + if ($redirect_uri === null) { + $redirect_uri = $this->getCurrentUrl(); + } + + try { + // need to circumvent json_decode by calling _oauthRequest + // directly, since response isn't JSON format. + $access_token_response = + $this->_oauthRequest( + $this->getUrl('graph', '/oauth/access_token'), + $params = array('client_id' => $this->getAppId(), + 'client_secret' => $this->getAppSecret(), + 'redirect_uri' => $redirect_uri, + 'code' => $code)); + } catch (FacebookApiException $e) { + // most likely that user very recently revoked authorization. + // In any event, we don't have an access token, so say so. + return false; + } + + if (empty($access_token_response)) { + return false; + } + + $response_params = array(); + parse_str($access_token_response, $response_params); + if (!isset($response_params['access_token'])) { + return false; + } + + return $response_params['access_token']; + } + + /** + * Invoke the old restserver.php endpoint. + * + * @param array $params Method call object + * + * @return mixed The decoded response object + * @throws FacebookApiException + */ + protected function _restserver($params) { + // generic application level parameters + $params['api_key'] = $this->getAppId(); + $params['format'] = 'json-strings'; + + $result = json_decode($this->_oauthRequest( + $this->getApiUrl($params['method']), + $params + ), true); + + // results are returned, errors are thrown + if (is_array($result) && isset($result['error_code'])) { + $this->throwAPIException($result); + } + + if ($params['method'] === 'auth.expireSession' || + $params['method'] === 'auth.revokeAuthorization') { + $this->destroySession(); + } + + return $result; + } + + /** + * Return true if this is video post. + * + * @param string $path The path + * @param string $method The http method (default 'GET') + * + * @return boolean true if this is video post + */ + protected function isVideoPost($path, $method = 'GET') { + if ($method == 'POST' && preg_match("/^(\/)(.+)(\/)(videos)$/", $path)) { + return true; + } + return false; + } + + /** + * Invoke the Graph API. + * + * @param string $path The path (required) + * @param string $method The http method (default 'GET') + * @param array $params The query/post data + * + * @return mixed The decoded response object + * @throws FacebookApiException + */ + protected function _graph($path, $method = 'GET', $params = array()) { + if (is_array($method) && empty($params)) { + $params = $method; + $method = 'GET'; + } + $params['method'] = $method; // method override as we always do a POST + + if ($this->isVideoPost($path, $method)) { + $domainKey = 'graph_video'; + } else { + $domainKey = 'graph'; + } + + $result = json_decode($this->_oauthRequest( + $this->getUrl($domainKey, $path), + $params + ), true); + + // results are returned, errors are thrown + if (is_array($result) && isset($result['error'])) { + $this->throwAPIException($result); + } + + return $result; + } + + /** + * Make a OAuth Request. + * + * @param string $url The path (required) + * @param array $params The query/post data + * + * @return string The decoded response object + * @throws FacebookApiException + */ + protected function _oauthRequest($url, $params) { + if (!isset($params['access_token'])) { + $params['access_token'] = $this->getAccessToken(); + } + + // json_encode all params values that are not strings + foreach ($params as $key => $value) { + if (!is_string($value)) { + $params[$key] = json_encode($value); + } + } + + return $this->makeRequest($url, $params); + } + + /** + * Makes an HTTP request. This method can be overridden by subclasses if + * developers want to do fancier things or use something other than curl to + * make the request. + * + * @param string $url The URL to make the request to + * @param array $params The parameters to use for the POST body + * @param CurlHandler $ch Initialized curl handle + * + * @return string The response text + */ + protected function makeRequest($url, $params, $ch=null) { + if (!$ch) { + $ch = curl_init(); + } + + $opts = self::$CURL_OPTS; + if ($this->getFileUploadSupport()) { + $opts[CURLOPT_POSTFIELDS] = $params; + } else { + $opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&'); + } + $opts[CURLOPT_URL] = $url; + + // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait + // for 2 seconds if the server does not support this header. + if (isset($opts[CURLOPT_HTTPHEADER])) { + $existing_headers = $opts[CURLOPT_HTTPHEADER]; + $existing_headers[] = 'Expect:'; + $opts[CURLOPT_HTTPHEADER] = $existing_headers; + } else { + $opts[CURLOPT_HTTPHEADER] = array('Expect:'); + } + + curl_setopt_array($ch, $opts); + $result = curl_exec($ch); + + if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT + self::errorLog('Invalid or no certificate authority found, '. + 'using bundled information'); + curl_setopt($ch, CURLOPT_CAINFO, + dirname(__FILE__) . '/fb_ca_chain_bundle.crt'); + $result = curl_exec($ch); + } + + if ($result === false) { + $e = new FacebookApiException(array( + 'error_code' => curl_errno($ch), + 'error' => array( + 'message' => curl_error($ch), + 'type' => 'CurlException', + ), + )); + curl_close($ch); + throw $e; + } + curl_close($ch); + return $result; + } + + /** + * Parses a signed_request and validates the signature. + * + * @param string $signed_request A signed token + * @return array The payload inside it or null if the sig is wrong + */ + protected function parseSignedRequest($signed_request) { + list($encoded_sig, $payload) = explode('.', $signed_request, 2); + + // decode the data + $sig = self::base64UrlDecode($encoded_sig); + $data = json_decode(self::base64UrlDecode($payload), true); + + if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') { + self::errorLog('Unknown algorithm. Expected HMAC-SHA256'); + return null; + } + + // check sig + $expected_sig = hash_hmac('sha256', $payload, + $this->getAppSecret(), $raw = true); + if ($sig !== $expected_sig) { + self::errorLog('Bad Signed JSON signature!'); + return null; + } + + return $data; + } + + /** + * Build the URL for api given parameters. + * + * @param $method String the method name. + * @return string The URL for the given parameters + */ + protected function getApiUrl($method) { + static $READ_ONLY_CALLS = + array('admin.getallocation' => 1, + 'admin.getappproperties' => 1, + 'admin.getbannedusers' => 1, + 'admin.getlivestreamvialink' => 1, + 'admin.getmetrics' => 1, + 'admin.getrestrictioninfo' => 1, + 'application.getpublicinfo' => 1, + 'auth.getapppublickey' => 1, + 'auth.getsession' => 1, + 'auth.getsignedpublicsessiondata' => 1, + 'comments.get' => 1, + 'connect.getunconnectedfriendscount' => 1, + 'dashboard.getactivity' => 1, + 'dashboard.getcount' => 1, + 'dashboard.getglobalnews' => 1, + 'dashboard.getnews' => 1, + 'dashboard.multigetcount' => 1, + 'dashboard.multigetnews' => 1, + 'data.getcookies' => 1, + 'events.get' => 1, + 'events.getmembers' => 1, + 'fbml.getcustomtags' => 1, + 'feed.getappfriendstories' => 1, + 'feed.getregisteredtemplatebundlebyid' => 1, + 'feed.getregisteredtemplatebundles' => 1, + 'fql.multiquery' => 1, + 'fql.query' => 1, + 'friends.arefriends' => 1, + 'friends.get' => 1, + 'friends.getappusers' => 1, + 'friends.getlists' => 1, + 'friends.getmutualfriends' => 1, + 'gifts.get' => 1, + 'groups.get' => 1, + 'groups.getmembers' => 1, + 'intl.gettranslations' => 1, + 'links.get' => 1, + 'notes.get' => 1, + 'notifications.get' => 1, + 'pages.getinfo' => 1, + 'pages.isadmin' => 1, + 'pages.isappadded' => 1, + 'pages.isfan' => 1, + 'permissions.checkavailableapiaccess' => 1, + 'permissions.checkgrantedapiaccess' => 1, + 'photos.get' => 1, + 'photos.getalbums' => 1, + 'photos.gettags' => 1, + 'profile.getinfo' => 1, + 'profile.getinfooptions' => 1, + 'stream.get' => 1, + 'stream.getcomments' => 1, + 'stream.getfilters' => 1, + 'users.getinfo' => 1, + 'users.getloggedinuser' => 1, + 'users.getstandardinfo' => 1, + 'users.hasapppermission' => 1, + 'users.isappuser' => 1, + 'users.isverified' => 1, + 'video.getuploadlimits' => 1); + $name = 'api'; + if (isset($READ_ONLY_CALLS[strtolower($method)])) { + $name = 'api_read'; + } else if (strtolower($method) == 'video.upload') { + $name = 'api_video'; + } + return self::getUrl($name, 'restserver.php'); + } + + /** + * Build the URL for given domain alias, path and parameters. + * + * @param $name string The name of the domain + * @param $path string Optional path (without a leading slash) + * @param $params array Optional query parameters + * + * @return string The URL for the given parameters + */ + protected function getUrl($name, $path='', $params=array()) { + $url = self::$DOMAIN_MAP[$name]; + if ($path) { + if ($path[0] === '/') { + $path = substr($path, 1); + } + $url .= $path; + } + if ($params) { + $url .= '?' . http_build_query($params, null, '&'); + } + + return $url; + } + + /** + * Returns the Current URL, stripping it of known FB parameters that should + * not persist. + * + * @return string The current URL + */ + protected function getCurrentUrl() { + if (isset($_SERVER['HTTPS']) && + ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || + isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && + $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') { + $protocol = 'https://'; + } + else { + $protocol = 'http://'; + } + $currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; + $parts = parse_url($currentUrl); + + $query = ''; + if (!empty($parts['query'])) { + // drop known fb params + $params = explode('&', $parts['query']); + $retained_params = array(); + foreach ($params as $param) { + if ($this->shouldRetainParam($param)) { + $retained_params[] = $param; + } + } + + if (!empty($retained_params)) { + $query = '?'.implode($retained_params, '&'); + } + } + + // use port if non default + $port = + isset($parts['port']) && + (($protocol === 'http://' && $parts['port'] !== 80) || + ($protocol === 'https://' && $parts['port'] !== 443)) + ? ':' . $parts['port'] : ''; + + // rebuild + return $protocol . $parts['host'] . $port . $parts['path'] . $query; + } + + /** + * Returns true if and only if the key or key/value pair should + * be retained as part of the query string. This amounts to + * a brute-force search of the very small list of Facebook-specific + * params that should be stripped out. + * + * @param string $param A key or key/value pair within a URL's query (e.g. + * 'foo=a', 'foo=', or 'foo'. + * + * @return boolean + */ + protected function shouldRetainParam($param) { + foreach (self::$DROP_QUERY_PARAMS as $drop_query_param) { + if (strpos($param, $drop_query_param.'=') === 0) { + return false; + } + } + + return true; + } + + /** + * Analyzes the supplied result to see if it was thrown + * because the access token is no longer valid. If that is + * the case, then we destroy the session. + * + * @param $result array A record storing the error message returned + * by a failed API call. + */ + protected function throwAPIException($result) { + $e = new FacebookApiException($result); + switch ($e->getType()) { + // OAuth 2.0 Draft 00 style + case 'OAuthException': + // OAuth 2.0 Draft 10 style + case 'invalid_token': + // REST server errors are just Exceptions + case 'Exception': + $message = $e->getMessage(); + if ((strpos($message, 'Error validating access token') !== false) || + (strpos($message, 'Invalid OAuth access token') !== false) || + (strpos($message, 'An active access token must be used') !== false) + ) { + $this->destroySession(); + } + break; + } + + throw $e; + } + + + /** + * Prints to the error log if you aren't in command line mode. + * + * @param string $msg Log message + */ + protected static function errorLog($msg) { + // disable error log if we are running in a CLI environment + // @codeCoverageIgnoreStart + if (php_sapi_name() != 'cli') { + error_log($msg); + } + // uncomment this if you want to see the errors on the page + // print 'error_log: '.$msg."\n"; + // @codeCoverageIgnoreEnd + } + + /** + * Base64 encoding that doesn't need to be urlencode()ed. + * Exactly the same as base64_encode except it uses + * - instead of + + * _ instead of / + * + * @param string $input base64UrlEncoded string + * @return string + */ + protected static function base64UrlDecode($input) { + return base64_decode(strtr($input, '-_', '+/')); + } + + /** + * Destroy the current session + */ + public function destroySession() { + $this->accessToken = null; + $this->signedRequest = null; + $this->user = null; + $this->clearAllPersistentData(); + + // Javascript sets a cookie that will be used in getSignedRequest that we + // need to clear if we can + $cookie_name = $this->getSignedRequestCookieName(); + if (array_key_exists($cookie_name, $_COOKIE)) { + unset($_COOKIE[$cookie_name]); + if (!headers_sent()) { + // The base domain is stored in the metadata cookie if not we fallback + // to the current hostname + $base_domain = '.'. $_SERVER['HTTP_HOST']; + + $metadata = $this->getMetadataCookie(); + if (array_key_exists('base_domain', $metadata) && + !empty($metadata['base_domain'])) { + $base_domain = $metadata['base_domain']; + } + + setcookie($cookie_name, '', 0, '/', $base_domain); + } else { + self::errorLog( + 'There exists a cookie that we wanted to clear that we couldn\'t '. + 'clear because headers was already sent. Make sure to do the first '. + 'API call before outputing anything' + ); + } + } + } + + /** + * Parses the metadata cookie that our Javascript API set + * + * @return an array mapping key to value + */ + protected function getMetadataCookie() { + $cookie_name = $this->getMetadataCookieName(); + if (!array_key_exists($cookie_name, $_COOKIE)) { + return array(); + } + + // The cookie value can be wrapped in "-characters so remove them + $cookie_value = trim($_COOKIE[$cookie_name], '"'); + + if (empty($cookie_value)) { + return array(); + } + + $parts = explode('&', $cookie_value); + $metadata = array(); + foreach ($parts as $part) { + $pair = explode('=', $part, 2); + if (!empty($pair[0])) { + $metadata[urldecode($pair[0])] = + (count($pair) > 1) ? urldecode($pair[1]) : ''; + } + } + + return $metadata; + } + + /** + * Each of the following four methods should be overridden in + * a concrete subclass, as they are in the provided Facebook class. + * The Facebook class uses PHP sessions to provide a primitive + * persistent store, but another subclass--one that you implement-- + * might use a database, memcache, or an in-memory cache. + * + * @see Facebook + */ + + /** + * Stores the given ($key, $value) pair, so that future calls to + * getPersistentData($key) return $value. This call may be in another request. + * + * @param string $key + * @param array $value + * + * @return void + */ + abstract protected function setPersistentData($key, $value); + + /** + * Get the data for $key, persisted by BaseFacebook::setPersistentData() + * + * @param string $key The key of the data to retrieve + * @param boolean $default The default value to return if $key is not found + * + * @return mixed + */ + abstract protected function getPersistentData($key, $default = false); + + /** + * Clear the data with $key from the persistent storage + * + * @param string $key + * @return void + */ + abstract protected function clearPersistentData($key); + + /** + * Clear all data from the persistent storage + * + * @return void + */ + abstract protected function clearAllPersistentData(); +} diff --git a/code/web/app/app_achievements/fb/facebook.php b/code/web/app/app_achievements/fb/facebook.php new file mode 100644 index 000000000..c577c2aa4 --- /dev/null +++ b/code/web/app/app_achievements/fb/facebook.php @@ -0,0 +1,93 @@ +constructSessionVariableName($key); + $_SESSION[$session_var_name] = $value; + } + + protected function getPersistentData($key, $default = false) { + if (!in_array($key, self::$kSupportedKeys)) { + self::errorLog('Unsupported key passed to getPersistentData.'); + return $default; + } + + $session_var_name = $this->constructSessionVariableName($key); + return isset($_SESSION[$session_var_name]) ? + $_SESSION[$session_var_name] : $default; + } + + protected function clearPersistentData($key) { + if (!in_array($key, self::$kSupportedKeys)) { + self::errorLog('Unsupported key passed to clearPersistentData.'); + return; + } + + $session_var_name = $this->constructSessionVariableName($key); + unset($_SESSION[$session_var_name]); + } + + protected function clearAllPersistentData() { + foreach (self::$kSupportedKeys as $key) { + $this->clearPersistentData($key); + } + } + + protected function constructSessionVariableName($key) { + return implode('_', array('fb', + $this->getAppId(), + $key)); + } +} diff --git a/code/web/app/app_achievements/fb/fb_ca_chain_bundle.crt b/code/web/app/app_achievements/fb/fb_ca_chain_bundle.crt new file mode 100644 index 000000000..b92d7190e --- /dev/null +++ b/code/web/app/app_achievements/fb/fb_ca_chain_bundle.crt @@ -0,0 +1,121 @@ +-----BEGIN CERTIFICATE----- +MIIFgjCCBGqgAwIBAgIQDKKbZcnESGaLDuEaVk6fQjANBgkqhkiG9w0BAQUFADBm +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSUwIwYDVQQDExxEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBDQS0zMB4XDTEwMDExMzAwMDAwMFoXDTEzMDQxMTIzNTk1OVowaDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVBhbG8gQWx0bzEX +MBUGA1UEChMORmFjZWJvb2ssIEluYy4xFzAVBgNVBAMUDiouZmFjZWJvb2suY29t +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9rzj7QIuLM3sdHu1HcI1VcR3g +b5FExKNV646agxSle1aQ/sJev1mh/u91ynwqd2BQmM0brZ1Hc3QrfYyAaiGGgEkp +xbhezyfeYhAyO0TKAYxPnm2cTjB5HICzk6xEIwFbA7SBJ2fSyW1CFhYZyo3tIBjj +19VjKyBfpRaPkzLmRwIDAQABo4ICrDCCAqgwHwYDVR0jBBgwFoAUUOpzidsp+xCP +nuUBINTeeZlIg/cwHQYDVR0OBBYEFPp+tsFBozkjrHlEnZ9J4cFj2eM0MA4GA1Ud +DwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMF8GA1UdHwRYMFYwKaAnoCWGI2h0dHA6 +Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9jYTMtZmIuY3JsMCmgJ6AlhiNodHRwOi8vY3Js +NC5kaWdpY2VydC5jb20vY2EzLWZiLmNybDCCAcYGA1UdIASCAb0wggG5MIIBtQYL +YIZIAYb9bAEDAAEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0 +LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIB +UgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkA +YwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEA +bgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMA +UABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkA +IABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwA +aQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8A +cgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMA +ZQAuMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQUF +AAOCAQEACOkTIdxMy11+CKrbGNLBSg5xHaTvu/v1wbyn3dO/mf68pPfJnX6ShPYy +4XM4Vk0x4uaFaU4wAGke+nCKGi5dyg0Esg7nemLNKEJaFAJZ9enxZm334lSCeARy +wlDtxULGOFRyGIZZPmbV2eNq5xdU/g3IuBEhL722mTpAye9FU/J8Wsnw54/gANyO +Gzkewigua8ip8Lbs9Cht399yAfbfhUP1DrAm/xEcnHrzPr3cdCtOyJaM6SRPpRqH +ITK5Nc06tat9lXVosSinT3KqydzxBYua9gCFFiR3x3DgZfvXkC6KDdUlDrNcJUub +a1BHnLLP4mxTHL6faAXYd05IxNn/IA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGVTCCBT2gAwIBAgIQCFH5WYFBRcq94CTiEsnCDjANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA3MDQwMzAwMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR +CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv +KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5 +BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf +1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs +zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d +32duXvsCAwEAAaOCAvcwggLzMA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w +ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3 +LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH +AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy +AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj +AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg +AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ +AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt +AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj +AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl +AHIAZQBuAGMAZQAuMA8GA1UdEwEB/wQFMAMBAf8wNAYIKwYBBQUHAQEEKDAmMCQG +CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSBhzCB +hDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFz +c3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQu +Y29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSMEGDAW +gBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUBINTe +eZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAF1PhPGoiNOjsrycbeUpSXfh59bcqdg1 +rslx3OXb3J0kIZCmz7cBHJvUV5eR13UWpRLXuT0uiT05aYrWNTf58SHEW0CtWakv +XzoAKUMncQPkvTAyVab+hA4LmzgZLEN8rEO/dTHlIxxFVbdpCJG1z9fVsV7un5Tk +1nq5GMO41lJjHBC6iy9tXcwFOPRWBW3vnuzoYTYMFEuFFFoMg08iXFnLjIpx2vrF +EIRYzwfu45DC9fkpx1ojcflZtGQriLCnNseaIGHr+k61rmsb5OPs4tk8QUmoIKRU +9ZKNu8BVIASm2LAXFszj0Mi0PeXZhMbT9m5teMl5Q+h6N/9cNUm/ocU= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEQjCCA6ugAwIBAgIEQoclDjANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEy +MjIxNTI3MjdaFw0xNDA3MjIxNTU3MjdaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK +EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNV +BAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD +1ZQ0Z6IKHLBfaaZAscS3so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80lt +cZF+Y7arpl/DpIT4T2JRvvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46 +OFBbdzEbjbPHJEWap6xtABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZd +HFMsfpjNGgYWpGhz0DQEE1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdm +t4i3ePLKCqg4qwpkwr9mXZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjggET +MIIBDzASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwQwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdo +dHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8v +Y3JsLmVudHJ1c3QubmV0L3NlcnZlcjEuY3JsMB0GA1UdDgQWBBSxPsNpA/i/RwHU +mCYaCALvY2QrwzALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7 +UISX8+1i0BowGQYJKoZIhvZ9B0EABAwwChsEVjcuMQMCAIEwDQYJKoZIhvcNAQEF +BQADgYEAUuVY7HCc/9EvhaYzC1rAIo348LtGIiMduEl5Xa24G8tmJnDioD2GU06r +1kjLX/ktCdpdBgXadbjtdrZXTP59uN0AXlsdaTiFufsqVLPvkp5yMnqnuI3E2o6p +NpAkoQSbB6kUCNnXcW26valgOjDLZFOnr241QiwdBAJAAE/rRa8= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 +MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE +ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j +b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg +U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ +I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 +wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC +AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb +oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 +BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 +MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi +E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa +MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI +hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN +95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd +2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- diff --git a/code/web/app/app_achievements/include/ach_render_common.php b/code/web/app/app_achievements/include/ach_render_common.php new file mode 100644 index 000000000..d3f291038 --- /dev/null +++ b/code/web/app/app_achievements/include/ach_render_common.php @@ -0,0 +1,29 @@ +getLang()); + + return $t[$cc]; + } + + function ach_render_forbidden($ig) { + if($ig) { + return "This app is NOT available INGAME!"; + } + else { + return "This app is NOT available from the WEB!"; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/include/ach_render_ig.php b/code/web/app/app_achievements/include/ach_render_ig.php new file mode 100644 index 000000000..b87f4258a --- /dev/null +++ b/code/web/app/app_achievements/include/ach_render_ig.php @@ -0,0 +1,533 @@ + + + ".ach_render_yubopoints()." + + + + + + + + +
"; + + $menu = new AchMenu($_REQUEST['cat']); + + $c .= ach_render_menu($menu); + + $c .= ""; + + $open = $menu->getOpenCat(); + + if($open != 0) { + if($_REQUEST['cult']) { + $cult = $_REQUEST['cult']; + } + else { + $cult = $_USER->getCult(); + } + + if($_REQUEST['civ']) { + $civ = $_REQUEST['civ']; + } + else { + $civ = $_USER->getCiv(); + } + + $cat = new AchCategory($open,$_USER->getRace(),$cult,$civ); + } + else { + $cat = new AchSummary($menu,$_CONF['summary_size']); + $c .= ach_render_summary_header(); + } + + $c .= ach_render_category($cat); + if($open == 0) { + $c .= ach_render_summary_footer($cat); + } + + $c .= "
"; + + return $c; + } + + function ach_render_tiebar($cult = "c_neutral", $civ = "c_neutral",&$cat) { + global $_USER; + + $html = "
+ + "; + if($cat->isAllowedCult()) { + $html.= ""; + } + if($task->objDrawable()) { + $html .= ""; + } + + return $html; + } + + function ach_render_task_done(&$ach,&$cat) { + global $_CONF; + $html = ""; + + $task_list = $ach->getDone(); + while($task_list->hasNext()) { + $task = $task_list->getNext(); + + if($task->inDev() || !$task->isTiedRace_open($cat->getCurrentRace()) || !$task->isTiedAlign_open($cat->getCurrentCult(),$cat->getCurrentCiv())) { + continue; + } + $html .= ""; + } + + return $html; + } + + function ach_render_obj_list($obj) { + $html = "
+ + "; + } + + $iter = $menu->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + #$sz = $menu->getSize(); + #for($i=0;$i<$sz;$i++) { + #$curr = $menu->getChild($i); + if($curr->inDev()) { + continue; + } + if($sub == 0) { + $html .= ""; + } + + $html .= " + "; + + if($curr->hasOpenCat() != 0) { + $html .= ach_render_menu($curr,($sub+4)); + } + } + + if($sub == 0) { + $html .= "
"; + if($sub == 0) { + $html .= "getImage()."?cacheid=".$_CONF['image_cdate']."' />"; + } + else { + $html .= ""; + } + $html .= "isOpen()) { + $html .= " color='orange'"; + } + $html .= ">".$curr->getName()."
"; + } + + return $html; + } + + function ach_render_category(&$cat) { + global $_USER; + + $html = ""; + + if($cat->isHeroic() && !$cat->hasDone()) { + return "
".get_translation('ach_no_heroic_deeds',$_USER->getLang())."
"; + } + + if($cat->hasTieAlign_done() || $cat->hasTieAlign_open()) { + $html .= ach_render_tiebar($cat->getCurrentCult(),$cat->getCurrentCiv(),$cat); + } + + $iter = $cat->getDone(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + if($curr->inDev() || !$curr->parentDone() || !$curr->isTiedRace_done($cat->getCurrentRace()) || !$curr->isTiedAlign_done($cat->getCurrentCult(),$cat->getCurrentCiv())) { + continue; + } + $html .= ach_render_achievement_done($curr,$cat); + } + + if($cat->isHeroic()) { + return $html; + } + + $iter = $cat->getOpen(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + if($curr->inDev() || !$curr->parentDone() || !$curr->isTiedRace_open($cat->getCurrentRace()) || !$curr->isTiedAlign_open($cat->getCurrentCult(),$cat->getCurrentCiv())) { + continue; + } + $html .= ach_render_achievement_open($curr,$cat); + } + + return $html; + } + + function ach_render_achievement_done(&$ach,&$cat) { + global $_CONF; + + $html = " + + + + + +
+ + + + + + +
getImage()."?cacheid=".$_CONF['image_cdate']."'>
".$ach->getName()."
+ ".ach_render_task_done($ach,$cat)."
+
"; + if((!$ach->isHeroic() && !$ach->isContest()) && $ach->getValueDone() > 0) { + $html .= "".$ach->getValueDone()."
"; + } + else { + $html .= '
'; + } + $html .= "
+
 
"; + + return $html; + } + + function ach_render_achievement_open(&$ach,&$cat) { + global $_CONF; + + $html = " + + + + + +
+ + + + + + +
getImage()."?cacheid=".$_CONF['image_cdate']."'>
".$ach->getName()."
+ ".ach_render_task_open($ach)."
+
"; + if(!$ach->isHeroic() && !$ach->isContest()) { + $html .= "".$ach->getValueOpen()."
"; + } + $html .= "
+
 
"; + + return $html; + } + + function ach_render_task_open(&$ach) { + $html = ""; + + $task_list = $ach->getOpen(); + $task = $task_list->getNext(); + + if($task->inDev()) { + return $html; + } + + if($task->getName() != null) { + $html .= "
".$task->getDisplayName()."
 
".ach_render_obj_list($task->getIterator())."
".$task->getDisplayName()."
( ".date('d.m.Y',$task->getDone())." )"; + if($task->getValue() > 0) { + $html .= " ".$task->getValue(); + } + $html .= "
"; + + $i = 0; + $skip = false; + + while($obj->hasNext()) { + $elem = $obj->getNext(); + if(($i%2) == 0) { + $html .= ""; + } + + switch($elem->getDisplay()) { + case "meta": + $html .= ""; + break; + case "value": + if(($i%2) == 1) { + $html .= ""; + } + $html .= ""; + $i++; + break; + case "simple": + $html .= ""; + break; + case "hidden": + default: + //do nothing + $skip = true; + break; + } + + if(($i%2) == 1) { + $html .= ""; + } + + + if(!$skip) { + $i++; + } + $skip = false; + } + + if(($i%2) == 1) { + $html .= ""; + } + + $html .= "
".ach_render_obj_meta($elem)."
".ach_render_obj_value($elem)."
".ach_render_obj_simple($elem)."
"; + + return $html; + } + + function ach_render_obj_simple(&$obj) { + global $_CONF; + + $html = ""; + if($obj->isdone()) { + $html .= ""; + } + + $html .= ""; + + $sum_done += $elem[1]; + $sum_total += $elem[2]; + + if(($i%2) == 2) { + $html .= ""; + } + + $i++; + } + + if(($i%2) == 2) { + $html .= ""; + } + + $html = "

+ ".get_translation('ach_summary_stats',$_USER->getLang())." +

 "; + } + else { + $html .= "
 "; + } + + $html .= $obj->getDisplayName()."
"; + + return $html; + } + + function ach_render_obj_meta(&$obj) { + global $_CONF; + + if($obj->isdone()) { + $col = "#71BE02"; + $grey = ""; + } + else { + $col = "#999999"; + $grey = "grey/"; + } + + return " + + + + + +
getMetaImage()."?cacheid=".$_CONF['image_cdate']."' /> ".$obj->getDisplayName()."
"; + } + + function ach_render_obj_value(&$obj) { + $html = ""; + if($obj->getName() != null) { + if($obj->isdone()) { + $col = "#71BE02"; + } + else { + $col = "#999999"; + } + $html .= "".$obj->getDisplayName().""; + } + + $html .= ach_render_progressbar($obj->getProgress(),$obj->getValue(),250); + + return $html; + } + + function ach_render_progressbar($prog,$val,$width) { + $hero = false; + if($val == false) { + $hero = true; + $val = $prog; + } + $val = max(1,$val); + $left = floor($width*(100*($prog/$val))/100); + $left = max(1,$left); + + $html = " + + + + +
+ + + + + +
"; + if($hero == false) { + if(($prog/$val) > 0.5) { + $html .= " ".nf($prog)." / ".nf($val)." "; + } + $html .= ""; + if(($prog/$val) <= 0.5) { + $html .= " ".nf($prog)." / ".nf($val)." "; + } + } + else { + $html .= " ".nf($prog)." "; + } + $html .= "
"; + + return $html; + } + + function ach_render_summary_header() { + global $_USER; + + return "".get_translation('ach_summary_header',$_USER->getLang()).""; + } + + function ach_render_summary_footer(&$summary) { + global $_USER; + + $nodes = $summary->getSummary(); + $html = ""; + + $sum_done = 0; + $sum_total = 0; + + $i = 0; + foreach($nodes as $elem) { + if(($i%2) == 0) { + $html .= "
".$elem[0]; + if($elem[3] == false) { + $html .= ach_render_progressbar($elem[1],$elem[2],150); + } + else { + $html .= ach_render_progressbar($elem[1],false,150); + } + + $html .= "
+ + + + + + +
".get_translation('ach_summary_stats_total',$_USER->getLang()).ach_render_progressbar($sum_done,$sum_total,350)."
".$html."
"; + + return $html; + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/include/ach_render_web.php b/code/web/app/app_achievements/include/ach_render_web.php new file mode 100644 index 000000000..b3206a4dc --- /dev/null +++ b/code/web/app/app_achievements/include/ach_render_web.php @@ -0,0 +1,583 @@ + + + + + + + + +
+
+
".ach_render_yubopoints()."
+
".ach_render_facebook()."
+
+
+ +
"; + #$_REQUEST['mid'] = 1; + + $menu = new AchMenu($_REQUEST['cat']); + + $c .= ach_render_menu($menu); + + $c .= "
"; + + /*for($i=0;$i<15;$i++) { + $c .= ach_render_box_done("Bejeweled"); + }*/ + + $open = $menu->getOpenCat(); + + if($open != 0) { + if($_REQUEST['cult']) { + $cult = $_REQUEST['cult']; + } + else { + $cult = $_USER->getCult(); + } + + if($_REQUEST['civ']) { + $civ = $_REQUEST['civ']; + } + else { + $civ = $_USER->getCiv(); + } + + $cat = new AchCategory($open,$_USER->getRace(),$cult,$civ); + } + else { + #die($_CONF['summary_size']); + $cat = new AchSummary($menu,$_CONF['summary_size']); + $c .= ach_render_summary_header(); + } + + $c .= ach_render_category($cat); + if($open == 0) { + $c .= ach_render_summary_footer($cat); + } + + $c .= "
"; + + return $c; + } + + function ach_render_tiebar($cult = "c_neutral", $civ = "c_neutral", &$cat) { + global $_USER; + + $html = " + +
+ + "; + if($cat->isAllowedCult()) { + $html.= ""; + if($task->getValue() > 0) { + $html .= ""; + } + $html .= ""; + } + + return $html; + } + + function ach_render_obj_list($obj) { + $html = "
+ + + + + + + + + +
connected
+ + + "; + } + + function ach_render_twitter() { + + } + + function ach_render_menu(&$menu,$sub = 0) { + $html = ""; + + return $html.ach_render_mnode($menu,$sub); + } + + function ach_render_mnode(&$menu,$sub) { + global $_CONF; + + $html = ""; + + $iter = $menu->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + if($curr->inDev()) { + continue; + } + $html .= " + "; + if($sub == 0) { + $html .= ""; + } + $html .= " + +
getImage()."' />".$curr->getName()."
"; + if($curr->hasOpenCat() != 0) { + $html .= "
".ach_render_mnode($curr,($sub+4))."
"; + } + } + + return $html; + } + + function ach_render_category(&$cat) { + global $_USER; + $html = ""; + + if($cat->isHeroic() && !$cat->hasDone()) { + return "
".get_translation('ach_no_heroic_deeds',$_USER->getLang())."
"; + } + + if($cat->hasTieAlign_done() || $cat->hasTieAlign_open()) { + $html .= ach_render_tiebar($cat->getCurrentCult(),$cat->getCurrentCiv(),$cat); + } + + $iter = $cat->getDone(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + if($curr->inDev() || !$curr->parentDone() || !$curr->isTiedRace_done($cat->getCurrentRace()) || !$curr->isTiedAlign_done($cat->getCurrentCult(),$cat->getCurrentCiv())) { + continue; + } + $html .= ach_render_achievement_done($curr,$cat); + } + + if($cat->isHeroic()) { + return $html; + } + + $iter = $cat->getOpen(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + if($curr->inDev() || !$curr->parentDone() || !$curr->isTiedRace_open($cat->getCurrentRace()) || !$curr->isTiedAlign_open($cat->getCurrentCult(),$cat->getCurrentCiv())) { + continue; + } + $html .= ach_render_achievement_open($curr,$cat); + } + + return $html; + } + + function ach_render_achievement_done(&$ach,&$cat) { + global $_CONF; + + $html = '
+ + + + + + + + + + + + + + + +
+
+ + + + +
'.$ach->getName().'
'; + if((!$ach->isHeroic() && !$ach->isContest()) && $ach->getValueDone() > 0) { + $html .= $ach->getValueDone().'
'; + } + else { + $html .= '
 '; + } + $html .= '
'; + $html .= ach_render_task_done($ach,$cat); + $html .= '
+
'; + + return $html; + } + + function ach_render_achievement_open(&$ach,&$cat) { + global $_CONF; + + $html = '
+ + + + + + + + + + + + + + + +
+
+ + + + +
'.$ach->getName().'
'; + if(!$ach->isHeroic() && !$ach->isContest()) { + $html .= $ach->getValueOpen().'
'; + } + else { + $html .= ''; + } + $html .= '
'; + $html .= ach_render_task_open($ach); + $html .= '
+
'; + + return $html; + } + + function ach_render_task_open(&$ach) { + $html = ""; + + $task_list = $ach->getOpen(); + $task = $task_list->getNext(); + + if($task->inDev()) { + return $html; + } + + if($task->getName() != null) { + $html .= "".$task->getDisplayName().""; + } + if($task->objDrawable()) { + $html .= ach_render_obj_list($task->getIterator()); + } + + return $html; + } + + function ach_render_task_done(&$ach,&$cat) { + global $_CONF; + $html = ""; + + $task_list = $ach->getDone(); + while($task_list->hasNext()) { + $task = $task_list->getNext(); + + if($task->inDev() || !$task->isTiedRace_open($cat->getCurrentRace()) || !$task->isTiedAlign_open($cat->getCurrentCult(),$cat->getCurrentCiv())) { + continue; + } + $html .= "
".$task->getDisplayName()."( ".date('d.m.Y',$task->getDone())." ) ".$task->getValue()."
"; + + $i = 0; + $skip = false; + + while($obj->hasNext()) { + + $elem = $obj->getNext(); + if(($i%2) == 0) { + $html .= ""; + } + + switch($elem->getDisplay()) { + case "meta": + $html .= ""; + break; + case "value": + if(($i%2) == 1) { + $html .= ""; + } + $html .= ""; + $i++; + break; + case "simple": + $html .= ""; + break; + case "hidden": + default: + //do nothing + $skip = true; + break; + } + + if(($i%2) == 1) { + $html .= ""; + } + + + if(!$skip) { + $i++; + } + $skip = false; + } + + if(($i%2) == 1) { + $html .= ""; + } + + $html .= "
".ach_render_obj_meta($elem)."
".ach_render_obj_value($elem)."
".ach_render_obj_simple($elem)."
"; + + return $html; + } + + function ach_render_obj_simple(&$obj) { + global $_CONF; + $html = ""; + if($obj->isdone()) { + $html .= " "; + } + else { + $html .= " "; + } + + $html .= $obj->getDisplayName().""; + + return $html; + } + + function ach_render_obj_meta(&$obj) { + global $_CONF; + + if($obj->isdone()) { + $col = "#71BE02"; + $grey = ""; + } + else { + $col = "#999999"; + $grey = "grey/"; + } + + return " + + + + +
getMetaImage()."' width='20px' /> ".$obj->getDisplayName()."
"; + } + + function ach_render_obj_value(&$obj) { + $html = ""; + if($obj->getName() != null) { + if($obj->isdone()) { + $col = "#71BE02"; + } + else { + $col = "#999999"; + } + $html .= "
".$obj->getDisplayName()."
"; + } + + $html .= ach_render_progressbar($obj->getProgress(),$obj->getValue(),350); + + return $html; + } + + function ach_render_progressbar($prog,$val,$width) { + $hero = false; + if($val == false) { + $hero = true; + $val = $prog; + } + $val = max(1,$val); + $left = floor($width*(100*($prog/$val))/100); + + $html = " + + + + + +
"; + if($hero == false) { + if(($prog/$val) > 0.5) { + $html .= " ".nf($prog)." / ".nf($val)." "; + } + $html .= ""; + if(($prog/$val) <= 0.5) { + $html .= " ".nf($prog)." / ".nf($val)." "; + } + } + else { + $html .= " ".nf($prog)." "; + } + $html .= "
"; + + return $html; + } + + function ach_render_summary_header() { + global $_USER; + + return "
".get_translation('ach_summary_header',$_USER->getLang())."
"; + } + + function ach_render_summary_footer(&$summary) { + global $_USER; + + $nodes = $summary->getSummary(); + $html = ""; + + $sum_done = 0; + $sum_total = 0; + + $i = 0; + foreach($nodes as $elem) { + if(($i%3) == 0) { + $html .= ""; + } + + $html .= "".$elem[0]."
"; + if($elem[3] == 0) { + $html .= ach_render_progressbar($elem[1],$elem[2],200); + } + else { + $html .= ach_render_progressbar($elem[1],false,200); + } + $html .= ""; + $sum_done += $elem[1]; + $sum_total += $elem[2]; + + if(($i%3) == 2) { + $html .= ""; + } + + $i++; + } + + if(($i%3) == 2) { + $html .= ""; + } + + $html = "

+

".get_translation('ach_summary_stats',$_USER->getLang())."
+ + + + + ".$html." +
".get_translation('ach_summary_stats_total',$_USER->getLang())."
".ach_render_progressbar($sum_done,$sum_total,450)."
"; + + return $html; + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements/index.php b/code/web/app/app_achievements/index.php new file mode 100644 index 000000000..90ce612bb --- /dev/null +++ b/code/web/app/app_achievements/index.php @@ -0,0 +1,110 @@ +isIG()) { + require_once("include/ach_render_ig.php"); +} +else { + require_once("include/ach_render_web.php"); +} +require_once("include/ach_render_common.php"); + +require_once("class/DLL_class.php"); +#require_once("class/InDev_trait.php"); +require_once("class/Node_abstract.php"); +require_once("class/AVLTree_class.php"); +require_once("class/Parentum_abstract.php"); +require_once("class/AchList_abstract.php"); +require_once("class/Tieable_inter.php"); +require_once("class/NodeIterator_class.php"); + + +require_once("class/AchMenu_class.php"); +require_once("class/AchMenuNode_class.php"); +require_once("class/AchSummary_class.php"); +require_once("class/AchCategory_class.php"); +require_once("class/AchAchievement_class.php"); +require_once("class/AchTask_class.php"); +require_once("class/AchObjective_class.php"); + +#require_once("fb/facebook.php"); + +// Update user acces on Db +#$DBc = ryDB::getInstance(APP_NAME."_test"); +$DBc = ryDB::getInstance(APP_NAME); + +$c = ""; +if(!$_USER->isIG()) { + /*$facebook = new Facebook(array( + 'appId' => $_CONF['fb_id'], + 'secret' => $_CONF['fb_secret'], + 'cookie' => true + )); + + #code taken from facebook tutorial + + // Get the url to redirect for login to facebook + // and request permission to write on the user's wall. + $login_url = $facebook->getLoginUrl( + array('scope' => 'publish_stream') + ); + + // If not authenticated, redirect to the facebook login dialog. + // The $login_url will take care of redirecting back to us + // after successful login. + if (! $facebook->getUser()) { + $c .= ';'; + } + else { + $DBc->sqlQuery("INSERT INTO ach_fb_token (aft_player,aft_token,aft_date,aft_allow) VALUES ('".$_USER->getID()."','".$DBc->sqlEscape($facebook->getAccessToken())."','".time()."','1') ON DUPLICATE KEY UPDATE aft_token='".$DBc->sqlEscape($facebook->getAccessToken())."', aft_date='".time()."'"); + }*/ + + +} + +if(!$_USER->isIG && $_CONF['enable_webig'] == false) { + $c .= ach_render_forbidden(false); +} +elseif($_USER->isIG && $_CONF['enable_offgame'] == false) { + $c .= ach_render_forbidden(true); +} +else { + $c .= ach_render(); +} + + +echo ryzom_app_render(strtoupper(get_translation('ach_app_name',$_USER->getLang())), $c, $_USER->isIG()); + +?> diff --git a/code/web/app/app_achievements/lang.php b/code/web/app/app_achievements/lang.php new file mode 100644 index 000000000..9d05959d0 --- /dev/null +++ b/code/web/app/app_achievements/lang.php @@ -0,0 +1,91 @@ + + array ( + 'en' => 'Summary', + 'fr' => 'Résumé', + 'de' => 'Übersicht', + 'ru' => 'Резюме', + ), + 'ach_summary_header' => + array ( + 'en' => 'Recent Achievements', + 'fr' => 'Derniers Accomplissements', + 'de' => 'Aktuelle Erfolge', + 'ru' => 'недавние достижения', + ), + 'ach_summary_stats' => + array ( + 'en' => 'Statistics', + 'fr' => 'Statistiques', + 'de' => 'Statistik', + 'ru' => '', + ), + 'ach_summary_stats_total' => + array ( + 'en' => 'Total', + 'fr' => 'Total', + 'de' => 'Gesamt', + 'ru' => '', + ), + 'ach_c_neutral' => + array ( + 'en' => 'Neutral', + 'fr' => 'Neutre', + 'de' => 'Neutral', + 'ru' => '', + ), + 'ach_allegiance_neutral_cult' => + array ( + 'en' => 'While being of %s allegiance with the higher powers', + 'fr' => 'En ayant %s de renommée avec les puissances', + 'de' => '', + 'ru' => '', + ), + 'ach_allegiance_neutral_civ' => + array ( + 'en' => 'While being of %s allegiance with the homin civilizations', + 'fr' => 'En ayant %s de renommée avec les nations homines', + 'de' => '', + 'ru' => '', + ), + 'ach_allegiance_neutral' => + array ( + 'en' => 'While being of %s allegiance', + 'fr' => 'En ayant %s de renommée', + 'de' => '', + 'ru' => '', + ), + 'ach_allegiance_start' => + array ( + 'en' => 'While being aligned with the ', + 'fr' => 'En appartenant à', + 'de' => '', + 'ru' => '', + ), + 'ach_allegiance_and' => + array ( + 'en' => ' and the ', + 'fr' => ' et le', + 'de' => '', + 'ru' => '', + ), + 'ach_allegiance_end' => + array ( + 'en' => ', accomplish the following achievements:', + 'fr' => ', effectuez les accomplissements suivants : ', + 'de' => ', erfüllen die folgenden Leistungen: ', + 'ru' => '', + ), + 'ach_no_heroic_deeds' => + array ( + 'en' => 'You haven\'t earned any Heroic Deeds so far.', + 'fr' => 'Vous n\'avez gagné aucun acte héroïque jusqu\'à présent.', + 'de' => 'Du hast noch keine Heldentaten vollbracht.', + 'ru' => '', + ), +); +if(isset($ryzom_texts)) + $ryzom_texts = array_merge ($__texts, $ryzom_texts); +else + $ryzom_texts = $__texts; diff --git a/code/web/app/app_achievements/pic/ach_news.png b/code/web/app/app_achievements/pic/ach_news.png new file mode 100644 index 000000000..2c8497fa4 Binary files /dev/null and b/code/web/app/app_achievements/pic/ach_news.png differ diff --git a/code/web/app/app_achievements/pic/bar_done_b.png b/code/web/app/app_achievements/pic/bar_done_b.png new file mode 100644 index 000000000..955d64955 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_done_b.png differ diff --git a/code/web/app/app_achievements/pic/bar_done_bg.png b/code/web/app/app_achievements/pic/bar_done_bg.png new file mode 100644 index 000000000..896894dfd Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_done_bg.png differ diff --git a/code/web/app/app_achievements/pic/bar_done_bl.png b/code/web/app/app_achievements/pic/bar_done_bl.png new file mode 100644 index 000000000..fe5111c09 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_done_bl.png differ diff --git a/code/web/app/app_achievements/pic/bar_done_br.png b/code/web/app/app_achievements/pic/bar_done_br.png new file mode 100644 index 000000000..33a2cda6f Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_done_br.png differ diff --git a/code/web/app/app_achievements/pic/bar_done_l.png b/code/web/app/app_achievements/pic/bar_done_l.png new file mode 100644 index 000000000..8eb5821ef Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_done_l.png differ diff --git a/code/web/app/app_achievements/pic/bar_done_r.png b/code/web/app/app_achievements/pic/bar_done_r.png new file mode 100644 index 000000000..4f654862c Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_done_r.png differ diff --git a/code/web/app/app_achievements/pic/bar_done_u.png b/code/web/app/app_achievements/pic/bar_done_u.png new file mode 100644 index 000000000..ca2cfd9a2 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_done_u.png differ diff --git a/code/web/app/app_achievements/pic/bar_done_ul.png b/code/web/app/app_achievements/pic/bar_done_ul.png new file mode 100644 index 000000000..05e179979 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_done_ul.png differ diff --git a/code/web/app/app_achievements/pic/bar_done_ur.png b/code/web/app/app_achievements/pic/bar_done_ur.png new file mode 100644 index 000000000..694428c86 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_done_ur.png differ diff --git a/code/web/app/app_achievements/pic/bar_pending_b.png b/code/web/app/app_achievements/pic/bar_pending_b.png new file mode 100644 index 000000000..70d847d32 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_pending_b.png differ diff --git a/code/web/app/app_achievements/pic/bar_pending_bl.png b/code/web/app/app_achievements/pic/bar_pending_bl.png new file mode 100644 index 000000000..178a37c2a Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_pending_bl.png differ diff --git a/code/web/app/app_achievements/pic/bar_pending_br.png b/code/web/app/app_achievements/pic/bar_pending_br.png new file mode 100644 index 000000000..1fea3d2a9 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_pending_br.png differ diff --git a/code/web/app/app_achievements/pic/bar_pending_l.png b/code/web/app/app_achievements/pic/bar_pending_l.png new file mode 100644 index 000000000..790c9b0c0 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_pending_l.png differ diff --git a/code/web/app/app_achievements/pic/bar_pending_r.png b/code/web/app/app_achievements/pic/bar_pending_r.png new file mode 100644 index 000000000..57631ef2f Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_pending_r.png differ diff --git a/code/web/app/app_achievements/pic/bar_pending_u.png b/code/web/app/app_achievements/pic/bar_pending_u.png new file mode 100644 index 000000000..33c487fa9 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_pending_u.png differ diff --git a/code/web/app/app_achievements/pic/bar_pending_ul.png b/code/web/app/app_achievements/pic/bar_pending_ul.png new file mode 100644 index 000000000..b417e8cf5 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_pending_ul.png differ diff --git a/code/web/app/app_achievements/pic/bar_pending_ur.png b/code/web/app/app_achievements/pic/bar_pending_ur.png new file mode 100644 index 000000000..9ea44bce8 Binary files /dev/null and b/code/web/app/app_achievements/pic/bar_pending_ur.png differ diff --git a/code/web/app/app_achievements/pic/check.png b/code/web/app/app_achievements/pic/check.png new file mode 100644 index 000000000..2e454932a Binary files /dev/null and b/code/web/app/app_achievements/pic/check.png differ diff --git a/code/web/app/app_achievements/pic/f-connect.png b/code/web/app/app_achievements/pic/f-connect.png new file mode 100644 index 000000000..ee067c17b Binary files /dev/null and b/code/web/app/app_achievements/pic/f-connect.png differ diff --git a/code/web/app/app_achievements/pic/facebook-logo.png b/code/web/app/app_achievements/pic/facebook-logo.png new file mode 100644 index 000000000..c469dafac Binary files /dev/null and b/code/web/app/app_achievements/pic/facebook-logo.png differ diff --git a/code/web/app/app_achievements/pic/icon/grey/small/test.png b/code/web/app/app_achievements/pic/icon/grey/small/test.png new file mode 100644 index 000000000..5123d8d30 Binary files /dev/null and b/code/web/app/app_achievements/pic/icon/grey/small/test.png differ diff --git a/code/web/app/app_achievements/pic/icon/grey/test.png b/code/web/app/app_achievements/pic/icon/grey/test.png new file mode 100644 index 000000000..6b2d0a9a3 Binary files /dev/null and b/code/web/app/app_achievements/pic/icon/grey/test.png differ diff --git a/code/web/app/app_achievements/pic/icon/small/test.png b/code/web/app/app_achievements/pic/icon/small/test.png new file mode 100644 index 000000000..e6a5b2818 Binary files /dev/null and b/code/web/app/app_achievements/pic/icon/small/test.png differ diff --git a/code/web/app/app_achievements/pic/icon/test.png b/code/web/app/app_achievements/pic/icon/test.png new file mode 100644 index 000000000..9e0e8f14a Binary files /dev/null and b/code/web/app/app_achievements/pic/icon/test.png differ diff --git a/code/web/app/app_achievements/pic/menu/ig_summary.png b/code/web/app/app_achievements/pic/menu/ig_summary.png new file mode 100644 index 000000000..e1dadd442 Binary files /dev/null and b/code/web/app/app_achievements/pic/menu/ig_summary.png differ diff --git a/code/web/app/app_achievements/pic/menu/ig_test.png b/code/web/app/app_achievements/pic/menu/ig_test.png new file mode 100644 index 000000000..a3085a681 Binary files /dev/null and b/code/web/app/app_achievements/pic/menu/ig_test.png differ diff --git a/code/web/app/app_achievements/pic/menu/summary.png b/code/web/app/app_achievements/pic/menu/summary.png new file mode 100644 index 000000000..599952056 Binary files /dev/null and b/code/web/app/app_achievements/pic/menu/summary.png differ diff --git a/code/web/app/app_achievements/pic/menu/test.png b/code/web/app/app_achievements/pic/menu/test.png new file mode 100644 index 000000000..5c9c0e507 Binary files /dev/null and b/code/web/app/app_achievements/pic/menu/test.png differ diff --git a/code/web/app/app_achievements/pic/menu_space.png b/code/web/app/app_achievements/pic/menu_space.png new file mode 100644 index 000000000..b104b9014 Binary files /dev/null and b/code/web/app/app_achievements/pic/menu_space.png differ diff --git a/code/web/app/app_achievements/pic/pending.png b/code/web/app/app_achievements/pic/pending.png new file mode 100644 index 000000000..451521d93 Binary files /dev/null and b/code/web/app/app_achievements/pic/pending.png differ diff --git a/code/web/app/app_achievements/pic/star_done.png b/code/web/app/app_achievements/pic/star_done.png new file mode 100644 index 000000000..d087adc79 Binary files /dev/null and b/code/web/app/app_achievements/pic/star_done.png differ diff --git a/code/web/app/app_achievements/pic/yubo_done.png b/code/web/app/app_achievements/pic/yubo_done.png new file mode 100644 index 000000000..8707db016 Binary files /dev/null and b/code/web/app/app_achievements/pic/yubo_done.png differ diff --git a/code/web/app/app_achievements/pic/yubo_done_small.png b/code/web/app/app_achievements/pic/yubo_done_small.png new file mode 100644 index 000000000..f5dc1b3e8 Binary files /dev/null and b/code/web/app/app_achievements/pic/yubo_done_small.png differ diff --git a/code/web/app/app_achievements/pic/yubo_pending.png b/code/web/app/app_achievements/pic/yubo_pending.png new file mode 100644 index 000000000..df66d1248 Binary files /dev/null and b/code/web/app/app_achievements/pic/yubo_pending.png differ diff --git a/code/web/app/app_achievements_admin/_doc/ADM_scheme.dia b/code/web/app/app_achievements_admin/_doc/ADM_scheme.dia new file mode 100644 index 000000000..a8285315f Binary files /dev/null and b/code/web/app/app_achievements_admin/_doc/ADM_scheme.dia differ diff --git a/code/web/app/app_achievements_admin/_doc/ADM_scheme.png b/code/web/app/app_achievements_admin/_doc/ADM_scheme.png new file mode 100644 index 000000000..7191a3842 Binary files /dev/null and b/code/web/app/app_achievements_admin/_doc/ADM_scheme.png differ diff --git a/code/web/app/app_achievements_admin/class/ADM_inter.php b/code/web/app/app_achievements_admin/class/ADM_inter.php new file mode 100644 index 000000000..b1fc15a3d --- /dev/null +++ b/code/web/app/app_achievements_admin/class/ADM_inter.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/AdmAchievement_class.php b/code/web/app/app_achievements_admin/class/AdmAchievement_class.php new file mode 100644 index 000000000..5722457d2 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/AdmAchievement_class.php @@ -0,0 +1,173 @@ +getChildDataByID($id); + if($res != null) { + $res->delete_me(); + $this->removeChild($id); + } + } + + function updateNode($id) { // PROBABLY USELESS! + $res = $this->getChildDataByID($id); + if($res != null) { + $res->update(); + } + } + + function getPathID($path = "") { + if($path != "") { + $path = ";".$path; + } + $path = $this->getID().$path; + if($this->parent != null) { + return $this->parent->getPathID($path); + } + + return $path; + } + + function getElementByPath($pid) { + $tmp = explode(";",$pid); + if($tmp[0] == $this->getID()) { + if(sizeof($tmp) > 1) { + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { + unset($tmp[0]); + return $c->getElementByPath(implode(";",$tmp)); + } + return null; + } + else { + return $this; + } + } + return null; + } + ######################### + + function AdmAchievement($data,$parent) { + parent::__construct($data,$parent); + } + + protected function makeChild($d) { + return new AdmTask($d,$this); + } + + function getLang($lang) { + global $DBc; + + $res = $DBc->sqlQuery("SELECT * FROM ach_achievement_lang WHERE aal_achievement='".$this->getID()."' AND aal_lang='".$lang."'"); + + return array(0=>$res[0]['aal_name'],1=>$res[0]['aal_template']); + } + + function setLang($lang,$txt,$tpl) { + global $DBc,$_USER; + + $DBc->sqlQuery("INSERT INTO ach_achievement_lang (aal_achievement,aal_lang,aal_name,aal_template) VALUES ('".$this->getID()."','".$DBc->sqlEscape($lang)."','".$DBc->sqlEscape($txt)."',".mkn($tpl).") ON DUPLICATE KEY UPDATE aal_name='".$DBc->sqlEscape($txt)."',aal_template=".mkn($tpl).""); + + if($_USER->getLang() == $lang) { + $this->name = $txt; + $this->template = $tpl; + } + } + + #@overrides AdmDispatcher::insertNode() + function insertNode($n) { + $n->insert(); + $this->addOpen($n); + } + + function delete_me() { + global $DBc; + + $DBc->sqlQuery("DELETE FROM ach_achievement WHERE aa_id='".$this->getID()."'"); + $DBc->sqlQuery("DELETE FROM ach_objective WHERE ao_metalink='".$this->getID()."'"); + $DBc->sqlQuery("DELETE FROM ach_achievement_lang WHERE NOT EXISTS (SELECT * FROM ach_achievement WHERE aa_id=aal_achievement)"); + + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $curr->delete_me(); + $this->removeChild($curr->getID()); + } + } + + function update() { + global $DBc; + + $DBc->sqlQuery("UPDATE ach_achievement SET aa_category='".$this->getCategory()."',aa_parent=".mkn($this->getParentID()).",aa_image='".$DBc->sqlEscape($this->getImage())."',aa_dev='".$this->getDev()."',aa_sticky='".$DBc->sqlEscape($this->getSticky())."' WHERE aa_id='".$this->getID()."'"); + + #MISSING: update lang entry + $DBc->sqlQuery("INSERT INTO ach_achievement_lang (aal_achievement,aal_lang,aal_name,aal_template) VALUES ('".$this->getID()."','en','".$DBc->sqlEscape($this->getName())."',".mkn($this->getTemplate()).") ON DUPLICATE KEY UPDATE aal_name='".$DBc->sqlEscape($this->getName())."',aal_template=".mkn($this->getTemplate()).""); + } + + function insert() { + global $DBc; + + $this->dev = 1; + + $DBc->sqlQuery("INSERT INTO ach_achievement (aa_category,aa_parent,aa_image,aa_dev,aa_sticky) VALUES ('".$this->getCategory()."',".mkn($this->getParentID()).",'".$DBc->sqlEscape($this->getImage())."','1','".$DBc->sqlEscape($this->getSticky())."')"); + $id = $DBc->insertID(); + $this->setID($id); + + $DBc->sqlQuery("INSERT INTO ach_achievement_lang (aal_achievement,aal_lang,aal_name,aal_template) VALUES ('".$this->getID()."','en','".$DBc->sqlEscape($this->getName())."',".mkn($this->getTemplate()).")"); + } + + + function setCategory($c) { + $this->category = $c; + } + + function setImage($i) { + $this->image = $i; + } + + function setName($n) { + $this->name = $n; + } + + function setTemplate($t) { + $this->template = $t; + } + + function orderTasks() { + + $i = 0; + $start = $this->findParentID(null); + + while($start != null) { + $start->setTorder($i); + $start->update(); + $i++; + #echo $i; + $start = $this->findParentID($start->getID()); + } + } + + private function findParentID($id) { + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->getParentID() == $id) { + return $curr; + } + } + + return null; + } + + function setParentID($p) { + $this->parent_id = $p; + } + + function setSticky($s) { + $this->sticky = $s; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/AdmAtom_class.php b/code/web/app/app_achievements_admin/class/AdmAtom_class.php new file mode 100644 index 000000000..dd66e0cc7 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/AdmAtom_class.php @@ -0,0 +1,347 @@ +setParent($this); + $n->insert(); + $this->addChild($n); + } + + function removeNode($id) { + $res = $this->getChildDataByID($id); + if($res != null) { + $res->delete_me(); + $this->removeChild($id); + } + } + + function updateNode($id) { // PROBABLY USELESS! + $res = $this->getChildDataByID($id); + if($res != null) { + $res->update(); + } + } + + function getPathID($path = "") { + if($path != "") { + $path = ";".$path; + } + $path = $this->getID().$path; + if($this->parent != null) { + return $this->parent->getPathID($path); + } + + return $path; + } + + function getElementByPath($pid) { + $tmp = explode(";",$pid); + if($tmp[0] == $this->getID()) { + if(sizeof($tmp) > 1) { + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { + unset($tmp[0]); + return $c->getElementByPath(implode(";",$tmp)); + } + return null; + } + else { + return $this; + } + } + return null; + } + ######################### + + protected $objective; + protected $mandatory; + protected $ruleset; + protected $ruleset_parsed; + protected $parent_id; + + function AdmAtom($data,$parent) { + $this->parent = $parent; + $this->id = $data['atom_id']; + $this->objective = $data['atom_objective']; + $this->mandatory = $data['atom_mandatory']; + $this->ruleset = $data['atom_ruleset']; + $this->ruleset_parsed = $data['atom_ruleset_parsed']; + } + + function delete_me() { // aaaaand... it's gone ^^ + global $DBc; + + $DBc->sqlQuery("DELETE FROM ach_atom WHERE atom_id='".$this->id."'"); + $DBc->sqlQuery("DELETE FROM ach_player_atom WHERE apa_atom='".$this->id."'"); + } + + function update() { // write updated data to database + global $DBc; + + $DBc->sqlQuery("UPDATE ach_atom SET atom_mandatory='".$this->getMandatory()."',atom_ruleset='".$DBc->sqlEscape($this->getRuleset())."',atom_ruleset_parsed='".$DBc->sqlEscape($this->getRulesetParsed())."' WHERE atom_id='".$this->id."'"); + } + + function insert() { // insert atoms as new row + global $DBc; + + $DBc->sqlQuery("INSERT INTO ach_atom (atom_objective,atom_mandatory,atom_ruleset,atom_ruleset_parsed) VALUES ('".$this->getObjective()."','".$this->getMandatory()."','".$DBc->sqlEscape($this->getRuleset())."','".$DBc->sqlEscape($this->getRulesetParsed())."')"); + $id = $DBc->insertID(); + $this->setID($id); + } + + function getObjective() { + return $this->objective; + } + + function setObjective($o) { + $this->objective = $o; + } + + function setMandatory($ft) { + if($ft == true) { + $this->mandatory = 1; + } + else { + $this->mandatory = 0; + } + } + + function setRuleset($r) { + $this->ruleset = $r; + $this->parse(); + } + + function getMandatory() { + return $this->mandatory; + } + + function isMandatory() { + return ($this->mandatory == 1); + } + + function getRuleset() { + return $this->ruleset; + } + + function getRulesetParsed() { + return $this->ruleset_parsed; + } + + private function parse() { // parsing the ruleset + /* +VALUE _money AS $money { + + CACHE blach AS $test; + + if($money >= 10000 && $test == 0) { + RESET; + GRANT $money UNTIL TIMER:3600; + FINAL; + } + else { + CACHE blach SET $money; + } + + SCRIPT wealth($money) AS $res; + + if($res == "lol") { + DENY; + } +} + +ENTITY _pos AS $pos { + SCRIPT inside($pos,"majestic_garden") AS $region; + + if($region == true) { + GRANT; + } +} +*/ + + $res = $this->ruleset; + + #VALUE ([^ ]+) AS ([$][^ ]+) {# + $match = array(); + preg_match_all("#VALUE ([^ ]+) AS ([$][^ ]+) {#",$this->ruleset,$match); + foreach($match[0] as $key=>$elem) { + $func = "_".md5(microtime()); + + $tmp = '$this->registerValue("'.$match[1][$key].'","'.$func.'"); + +function '.$func.'('.$match[2][$key].',$_P,$_CB) { + global $_CACHE; + $_IDENT = "'.$match[1][$key].'";'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #ENTITY ([^ ]+) AS ([$][^ ]+) {# + $match = array(); + preg_match_all("#ENTITY ([^ ]+) AS ([$][^ ]+) {#",$this->ruleset,$match); + foreach($match[0] as $key=>$elem) { + $func = "_".md5(microtime()); + + $tmp = '$this->registerEntity("'.$match[1][$key].'","'.$func.'"); + +function '.$func.'('.$match[2][$key].',$_P,$_CB) { + global $_CACHE; + $_IDENT = "'.$match[1][$key].'";'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #EVENT ([^ ]+) AS ([$][^ ]+) {# + $match = array(); + preg_match_all("#EVENT ([^ ]+) AS ([$][^ ]+) {#",$this->ruleset,$match); + foreach($match[0] as $key=>$elem) { + $func = "_".md5(microtime()); + + $tmp = '$this->registerEvent("'.$match[1][$key].'","'.$func.'"); + +function '.$func.'('.$match[2][$key].',$_P,$_CB) { + global $_CACHE; + $_IDENT = "'.$match[1][$key].'";'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #GRANT ([^;]*);# + $match = array(); + preg_match_all("#GRANT ([^;]*);#",$this->ruleset,$match); + foreach($match[0] as $key=>$elem) { + $tmp = '$_P->grant('.$match[1][$key].');'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #GRANT;# + $match = array(); + preg_match_all("#GRANT;#",$this->ruleset,$match); + foreach($match[0] as $elem) { + $tmp = '$_P->grant();'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #DENY;# + $match = array(); + preg_match_all("#DENY;#",$this->ruleset,$match); + foreach($match[0] as $elem) { + $tmp = '$_P->deny();'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #UNLOCK;# + $match = array(); + preg_match_all("#UNLOCK;#",$this->ruleset,$match); + foreach($match[0] as $elem) { + $tmp = '$_P->unlock();'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #RESET;# + $match = array(); + preg_match_all("#RESET;#",$this->ruleset,$match); + foreach($match[0] as $elem) { + $tmp = '$_P->reset_();'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #UNLOCK_ALL;# + $match = array(); + preg_match_all("#UNLOCK_ALL;#",$this->ruleset,$match); + foreach($match[0] as $elem) { + $tmp = '$_P->unlock_all();'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #RESET_ALL;# + $match = array(); + preg_match_all("#RESET_ALL;#",$this->ruleset,$match); + foreach($match[0] as $elem) { + $tmp = '$_P->reset_all();'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #FINAL VALUE;# + $match = array(); + preg_match_all("#FINAL VALUE;#",$this->ruleset,$match); + foreach($match[0] as $elem) { + $tmp = '$_P->unregisterValue($_IDENT,$_CB);'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #FINAL ENTITY;# + $match = array(); + preg_match_all("#FINAL ENTITY;#",$this->ruleset,$match); + foreach($match[0] as $elem) { + $tmp = '$_P->unregisterEntity($_IDENT,$_CB);'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + #FINAL EVENT;# + $match = array(); + preg_match_all("#FINAL EVENT;#",$this->ruleset,$match); + foreach($match[0] as $elem) { + $tmp = '$_P->unregisterEvent($_IDENT,$_CB);'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #CACHE ([^ ]+) AS ([$][^ ]+);# + $match = array(); + preg_match_all("#CACHE ([^ ]+) AS ([$][^;]+);#",$this->ruleset,$match); + foreach($match[0] as $key=>$elem) { + $tmp = $match[2][$key].' = $_CACHE->getData(\''.$match[1][$key].'\');'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #CACHE ([^ ]+) SET ([$][^ ]+);# + $match = array(); + preg_match_all("#CACHE ([^ ]+) SET ([$][^;]+);#",$this->ruleset,$match); + foreach($match[0] as $key=>$elem) { + $tmp = '$_CACHE->writeData(\''.$match[1][$key].'\','.$match[2][$key].');'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + #SCRIPT ([^ ]+) AS ([$][^ ]+);# + $match = array(); + preg_match_all("#SCRIPT ([^\(]+)\(([^\)]*)\) AS ([$][^;]+);#",$this->ruleset,$match); + foreach($match[0] as $key=>$elem) { + $tmp = '@include_once("script/'.$match[1][$key].'_script.php"); + '.$match[3][$key].' = '.$match[1][$key].'('.$match[2][$key].');'; + + //replace + $res = str_replace($elem,$tmp,$res); + } + + $this->ruleset_parsed = $res; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/AdmCategory_class.php b/code/web/app/app_achievements_admin/class/AdmCategory_class.php new file mode 100644 index 000000000..523cced89 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/AdmCategory_class.php @@ -0,0 +1,86 @@ +getChildDataByID($id); + if($res != null) { + $res->delete_me(); + $this->removeChild($id); + } + } + + function updateNode($id) { // PROBABLY USELESS! + $res = $this->getChildDataByID($id); + if($res != null) { + $res->update(); + } + } + + function getPathID($path = "") { + if($path != "") { + $path = ";".$path; + } + $path = $this->getID().$path; + if($this->parent != null) { + return $this->parent->getPathID($path); + } + + return $path; + } + + function getElementByPath($pid) { + $tmp = explode(";",$pid); + if($tmp[0] == $this->getID()) { + if(sizeof($tmp) > 1) { + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { + unset($tmp[0]); + return $c->getElementByPath(implode(";",$tmp)); + } + return null; + } + else { + return $this; + } + } + return null; + } + ######################### + + function AdmCategory($id,$race,$cult = null,$civ = null) { + parent::__construct($id,$race,$cult,$civ); + } + + protected function makeChild($d) { + $a = new AdmAchievement($d,$this); + return $a; + } + + #@overrides AdmDispatcher::insertNode() + function insertNode($n) { + $n->insert(); + $this->addOpen($n); + } + + function setLang($lang,$txt) { + global $DBc; + + $DBc->sqlQuery("INSERT INTO ach_category_lang (acl_category,acl_lang,acl_name) VALUES ('".$this->getID()."','".$DBc->sqlEscape($lang)."','".$DBc->sqlEscape($txt)."') ON DUPLICATE KEY UPDATE acl_name='".$DBc->sqlEscape($txt)."'"); + } + + function getLang($lang) { + global $DBc; + + $res = $DBc->sqlQuery("SELECT acl_name FROM ach_category_lang WHERE acl_category='".$this->getID()."' AND acl_lang='".$DBc->sqlEscape($lang)."'"); + return $res[0]['acl_name']; + } + + function update() { + global $DBc; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/AdmDispatcher_trait.php b/code/web/app/app_achievements_admin/class/AdmDispatcher_trait.php new file mode 100644 index 000000000..65fd13663 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/AdmDispatcher_trait.php @@ -0,0 +1,70 @@ +setParent($this); + $n->insert(); + $this->addChild($n); + } + + function removeNode($id) { + $res = $this->getChildDataByID($id); + if($res != null) { + $res->delete_me(); + $this->removeChild($id); + } + } + + function updateNode($id) { // PROBABLY USELESS! + $res = $this->getChildDataByID($id); + if($res != null) { + $res->update(); + } + } + + function getPathID($path = "") { + if($path != "") { + $path = ";".$path; + } + $path = $this->getID().$path; + if($this->parent != null) { + return $this->parent->getPathID($path); + } + + return $path; + } + + function getElementByPath($pid) { + $tmp = explode(";",$pid); + if($tmp[0] == $this->getID()) { + if(sizeof($tmp) > 1) { + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { + unset($tmp[0]); + return $c->getElementByPath(implode(";",$tmp)); + } + return null; + } + else { + return $this; + } + } + return null; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/AdmMenuNode_class.php b/code/web/app/app_achievements_admin/class/AdmMenuNode_class.php new file mode 100644 index 000000000..cde7d89ba --- /dev/null +++ b/code/web/app/app_achievements_admin/class/AdmMenuNode_class.php @@ -0,0 +1,163 @@ +sqlQuery("SELECT count(*) as anz FROM ach_achievement WHERE aa_category='".$this->id."'"); + $this->ach_count = $res[0]['anz']; + } + + protected function makeChild($d) { // override child generator to use admin classes + return new AdmMenuNode($d,$this); + } + + function hasAchievements() { + if($this->ach_count != 0) { + return true; + } + else { + $iter = $this->getIterator(); + while($iter->hasNext()) { + $elem = $iter->getNext(); + $res = $elem->hasAchievements(); + if($res == true) { + return true; + } + } + + return false; + } + } + + function getNode($id) { // try to find the child node that has the given ID. Return null on failure. + $res = $this->getChildDataByID($id); + if($res != null) { + return $res; + } + + $iter = $this->getIterator(); + while($iter->hasNext()) { // check children + $curr = $iter->getNext(); + $tmp = $curr->getNode($id); + if($tmp != null) { + return $tmp; + } + } + + return null; + } + + function delete_me() { // remove this node + global $DBc; + + // remove from database + $DBc->sqlQuery("DELETE FROM ach_category WHERE ac_id='".$this->getID()."'"); + $DBc->sqlQuery("DELETE FROM ach_category WHERE ac_parent='".$this->getID()."'"); + $DBc->sqlQuery("DELETE FROM ach_category_lang WHERE NOT EXISTS (SELECT * FROM ach_category WHERE ac_id=acl_category)"); + + // call delete function for all children + foreach($this->nodes as $elem) { + $elem->delete_me(); + $this->removeChild($elem->getID()); + } + } + + function insertChild(&$n) { // insert a new child + // insert command to create database entry + $n->insert(); + + // set the new child's parent and add it to the node list + $n->setParent($this); + $this->addChild($n); + } + + function update() { + global $DBc,$_USER; + + $DBc->sqlQuery("UPDATE ach_category SET ac_parent=".mkn($this->getParentID()).",ac_order='".$this->getOrder()."',ac_image=".mkn($this->getImage()).",ac_dev='".$this->getDev()."' WHERE ac_id='".$this->getID()."'"); + #echo "
".$this->getImage()." =>UPDATE ach_category SET ac_parent=".mkn($this->getParentID()).",ac_order='".$this->getOrder()."',ac_image=".mkn($this->getImage()).",ac_dev='".$this->getDev()."' WHERE ac_id='".$this->getID()."'"; + + #MISSING: update lang entry + $DBc->sqlQuery("INSERT IGNORE INTO ach_category_lang (acl_category,acl_lang,acl_name) VALUES ('".$this->getID()."','".$_USER->getLang()."','".$DBc->sqlEscape($this->getName())."') ON DUPLICATE KEY UPDATE acl_name='".$DBc->sqlEscape($this->getName())."'"); + } + + function insert() { // write $this to the database as a new entry + global $DBc,$_USER; + + $this->setOrder($this->parent->getNextOrder()); + + $DBc->sqlQuery("INSERT INTO ach_category (ac_parent,ac_order,ac_image,ac_dev) VALUES (".mkn($this->getParentID()).",'".$this->getOrder()."',".mkn($this->getImage()).",'1')"); + $id = $DBc->insertID(); + $this->setID($id); + #MISSING: insert lang entry + $DBc->sqlQuery("INSERT INTO ach_category_lang (acl_category,acl_lang,acl_name) VALUES ('".$this->getID()."','".$_USER->getLang()."','".$DBc->sqlEscape($this->getName())."')"); + + } + + private function setOrder($o) { + $this->order = $o; + $this->update(); + } + + function swapChild($a,$b) { + $ids = array(); + foreach($this->nodes as $key=>$elem) { + if($a == $elem->getID() || $b == $elem->getID()) { + $ids[] = $key; + } + + if(sizeof($ids) == 2) { + break; + } + } + + $tmp = $this->nodes[$ids[0]]; + $this->nodes[$ids[0]] = $this->nodes[$tmp[1]]; + $this->nodes[$ids[1]] = $tmp; + } + + function setName($n) { + $this->name = $n; + } + + function setImage($i) { + if($i == null || strtolower($i) == "null") { + $this->image = null; + } + else { + $this->image = $i; + } + } + + + function setParentID($p) { + if($p == null || strtolower($p) == "null") { + $this->parent_id = null; + } + else { + $this->parent_id = $p; + } + } + + + function getNextOrder() { + if($this->isEmpty()) { + return 0; + } + + $val = array(); + $iter = $this->getIterator(); + while($iter->hasNext()) { + $elem = $iter->getNext(); + $val[] = $elem->getOrder(); + } + + return (max($val)+1); + } + } + +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/AdmMenu_class.php b/code/web/app/app_achievements_admin/class/AdmMenu_class.php new file mode 100644 index 000000000..c7ff8383d --- /dev/null +++ b/code/web/app/app_achievements_admin/class/AdmMenu_class.php @@ -0,0 +1,133 @@ +getID().$path; + if($this->parent != null) { + return $this->parent->getPathID($path); + } + + return $path; + } + + function getElementByPath($pid) { + $tmp = explode(";",$pid); + if($tmp[0] == $this->getID()) { + if(sizeof($tmp) > 1) { + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { + unset($tmp[0]); + return $c->getElementByPath(implode(";",$tmp)); + } + return null; + } + else { + return $this; + } + } + return null; + } + ######################### + + function AdmMenu($open) { + parent::__construct($open); + + #$this->drawTree(); + + $this->removeChild(0); // unset the auto-generated "summary" node + } + + protected function makeChild($d) { // override child generator to use admin classes + return new AdmMenuNode($d,$this); + } + + function removeNode($id) { // find the node that has the ID we want to delete. If found, call it's delete function. + $res = $this->getNode($id); + if($res != null) { + $res->delete_me(); + $tmp = $res->getParent(); + $tmp->removeChild($id); + } + } + + function insertNode(&$n) { + if($n->getParentID() != null) { + $res = $this->getNode($n->getParentID()); + if($res != null) { + $n->setParent($res); + $res->insertChild($n); + } + } + else { + $n->setParent($this); + $n->insert(); + $this->addChild($n); + } + } + + function updateNode($id,$data) { #MISSING: data handling... + $res = $this->getNode($id); + if($res != null) { + $res->setName($data['acl_name']); + $res->setImage($data['ac_image']); + $res->update(); + } + } + + function swapOrder($a,$b) { + $tmp_a = $this->getNode($a); + if($tmp_a != null) { + $tmp_b = $this->getNode($a); + if($tmp_b != null) { + $tmp = $tmp_b->getOrder(); + $tmp_b->setOrder($tmp_a->getOrder()); + $tmp_a->setOrder($tmp); + + if($tmp_a->getParentID() == $tmp_b->getParentID()) { + $tmp_a->getParent()->swapChild($a,$b); + } + } + } + } + + function getNode($id) { // try to find the MenuNode that has the given ID. Return null on failure. + $res = $this->getChildDataByID($id); + if($res != null) { + return $res; + } + + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + #echo $curr->getID(); + $tmp = $curr->getNode($id); + if($tmp != null) { + return $tmp; + } + } + + return null; + } + + function getNextOrder() { + if($this->isEmpty()) { + return 0; + } + + $val = array(); + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $val[] = $curr->getOrder(); + } + + return (max($val)+1); + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/AdmObjective_class.php b/code/web/app/app_achievements_admin/class/AdmObjective_class.php new file mode 100644 index 000000000..81d38a805 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/AdmObjective_class.php @@ -0,0 +1,152 @@ +setParent($this); + $n->insert(); + $this->addChild($n); + } + + function removeNode($id) { + $res = $this->getChildDataByID($id); + if($res != null) { + $res->delete_me(); + $this->removeChild($id); + } + } + + function updateNode($id) { // PROBABLY USELESS! + $res = $this->getChildDataByID($id); + if($res != null) { + $res->update(); + } + } + + function getPathID($path = "") { + if($path != "") { + $path = ";".$path; + } + $path = $this->getID().$path; + if($this->parent != null) { + return $this->parent->getPathID($path); + } + + return $path; + } + + function getElementByPath($pid) { + $tmp = explode(";",$pid); + if($tmp[0] == $this->getID()) { + if(sizeof($tmp) > 1) { + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { + unset($tmp[0]); + return $c->getElementByPath(implode(";",$tmp)); + } + return null; + } + else { + return $this; + } + } + return null; + } + ######################### + + function AdmObjective($data,$parent) { + parent::__construct($data,$parent); + + global $DBc; + + $res = $DBc->sqlQuery("SELECT * FROM ach_atom WHERE atom_objective='".$this->getID()."'"); + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + $this->addChild($this->makeChild($res[$i])); + } + } + + protected function makeChild($d) { + return new AdmAtom($d,$this); + } + + function getLang($lang) { // load language + global $DBc; + + $res = $DBc->sqlQuery("SELECT * FROM ach_objective_lang WHERE aol_objective='".$this->getID()."' AND aol_lang='".$lang."'"); + + return $res[0]['aol_name']; + } + + function setLang($lang,$txt) { // write language + global $DBc,$_USER; + + $DBc->sqlQuery("INSERT INTO ach_objective_lang (aol_objective,aol_lang,aol_name) VALUES ('".$this->getID()."','".$DBc->sqlEscape($lang)."','".$DBc->sqlEscape($txt)."') ON DUPLICATE KEY UPDATE aol_name='".$DBc->sqlEscape($txt)."'"); + + if($_USER->getLang() == $lang) { + $this->name = $txt; + } + } + + function delete_me() { + global $DBc; + + $DBc->sqlQuery("DELETE FROM ach_objective WHERE ao_id='".$this->getID()."'"); + $DBc->sqlQuery("DELETE FROM ach_player_objective WHERE apo_objective='".$this->getID()."'"); + + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $curr->delete_me(); + $this->removeChild($curr->getID()); + } + } + + function update() { + global $DBc; + + $DBc->sqlQuery("UPDATE ach_objective SET ao_condition='".$DBc->sqlEscape($this->getCondition())."',ao_value=".mkn($this->getValue()).",ao_display='".$DBc->sqlEscape($this->getDisplay())."',ao_metalink=".mkn($this->getMetalink())." WHERE ao_id='".$this->getID()."'"); + + $DBc->sqlQuery("INSERT INTO ach_objective_lang (aol_objective,aol_lang,aol_name) VALUES ('".$this->getID()."','en','".$DBc->sqlEscape($this->getName())."') ON DUPLICATE KEY UPDATE aol_name='".$DBc->sqlEscape($this->getName())."'"); + } + + function insert() { + global $DBc; + + $DBc->sqlQuery("INSERT INTO ach_objective (ao_task,ao_condition,ao_value,ao_display,ao_metalink) VALUES ('".$this->getTask()."','".$DBc->sqlEscape($this->getCondition())."',".mkn($this->getValue()).",'".$DBc->sqlEscape($this->getDisplay())."',".mkn($this->getMetalink()).")"); + $id = $DBc->insertID(); + $this->setID($id); + + $DBc->sqlQuery("INSERT INTO ach_objective_lang (aol_objective,aol_lang,aol_name) VALUES ('".$this->getID()."','en','".$DBc->sqlEscape($this->getName())."')"); + } + + function setCondition($c) { + $this->condition = $c; + } + + function setDisplay($d) { + $this->display = $d; + } + + function setName($n) { + $this->name = $n; + } + + function setValue($v) { + $this->value = $v; + } + + function setMetalink($m) { + $this->metalink = $m; + if($this->getDisplay() == "meta") { + $this->name = "name and image will load on refresh only!"; + } + } + + function setTask($t) { + $this->task = $t; + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/AdmTask_class.php b/code/web/app/app_achievements_admin/class/AdmTask_class.php new file mode 100644 index 000000000..26d050740 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/AdmTask_class.php @@ -0,0 +1,245 @@ +setParent($this); + $n->insert(); + $this->addChild($n); + } + + function removeNode($id) { + $res = $this->getChildDataByID($id); + if($res != null) { + $res->delete_me(); + $this->removeChild($id); + } + } + + function updateNode($id) { // PROBABLY USELESS! + $res = $this->getChildDataByID($id); + if($res != null) { + $res->update(); + } + } + + function getPathID($path = "") { + if($path != "") { + $path = ";".$path; + } + $path = $this->getID().$path; + if($this->parent != null) { + return $this->parent->getPathID($path); + } + + return $path; + } + + function getElementByPath($pid) { + $tmp = explode(";",$pid); + if($tmp[0] == $this->getID()) { + if(sizeof($tmp) > 1) { + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { + unset($tmp[0]); + return $c->getElementByPath(implode(";",$tmp)); + } + return null; + } + else { + return $this; + } + } + return null; + } + ######################### + + protected $condition; + protected $condition_value; + protected $torder; + + function AdmTask($data,$parent) { + parent::__construct($data,$parent); + + $this->condition = $data["at_condition"]; + $this->condition_value = $data["at_condition_value"]; + $this->torder = $data["at_torder"]; + } + + protected function makeChild($d) { + return new AdmObjective($d,$this); + } + + function getLang($lang) { // load language + global $DBc; + + $res = $DBc->sqlQuery("SELECT * FROM ach_task_lang WHERE atl_task='".$this->getID()."' AND atl_lang='".$lang."'"); + + return array(0=>$res[0]['atl_name'],1=>$res[0]['atl_template']); + } + + function setLang($lang,$txt,$tpl) { // write language + global $DBc,$_USER; + + $DBc->sqlQuery("INSERT INTO ach_task_lang (atl_task,atl_lang,atl_name,atl_template) VALUES ('".$this->getID()."','".$DBc->sqlEscape($lang)."','".$DBc->sqlEscape($txt)."',".mkn($tpl).") ON DUPLICATE KEY UPDATE atl_name='".$DBc->sqlEscape($txt)."',atl_template=".mkn($tpl).""); + + if($_USER->getLang() == $lang) { + $this->name = $txt; + $this->template = $tpl; + } + } + + function delete_me() { + global $DBc; + + $DBc->sqlQuery("DELETE FROM ach_task WHERE at_id='".$this->getID()."'"); + $DBc->sqlQuery("DELETE FROM ach_player_task WHERE apt_task='".$this->getID()."'"); + $DBc->sqlQuery("DELETE FROM ach_task_tie_align WHERE atta_task='".$this->getID()."'"); + $DBc->sqlQuery("DELETE FROM ach_task_tie_race WHERE attr_task='".$this->getID()."'"); + + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $curr->delete_me(); + $this->removeChild($curr->getID()); + } + } + + function update() { + global $DBc; + + $DBc->sqlQuery("UPDATE ach_task SET at_parent=".mkn($this->getParentID()).",at_value='".$DBc->sqlEscape($this->getValue())."',at_condition='".$DBc->sqlEscape($this->getCondition())."',at_condition_value=".mkn($this->getConditionValue()).",at_dev='".$this->getDev()."',at_torder='".$this->torder."', at_inherit='".$this->inherit_obj."' WHERE at_id='".$this->getID()."'"); + + $DBc->sqlQuery("INSERT INTO ach_task_lang (atl_task,atl_lang,atl_name,atl_template) VALUES ('".$this->getID()."','en','".$DBc->sqlEscape($this->getName())."',".mkn($this->getTemplate()).") ON DUPLICATE KEY UPDATE atl_name='".$DBc->sqlEscape($this->getName())."',atl_template=".mkn($this->getTemplate()).""); + + $DBc->sqlQuery("DELETE FROM ach_task_tie_align WHERE atta_task='".$this->getID()."'"); + $DBc->sqlQuery("DELETE FROM ach_task_tie_race WHERE attr_task='".$this->getID()."'"); + + foreach($this->tie_race as $elem) { + $DBc->sqlQuery("INSERT INTO ach_task_tie_race (attr_task,attr_race) VALUES ('".$this->getID()."','".$DBc->sqlEscape($elem)."')"); + } + + foreach($this->tie_align as $elem) { + $DBc->sqlQuery("INSERT INTO ach_task_tie_align (atta_task,atta_alignment) VALUES ('".$this->getID()."','".$DBc->sqlEscape($elem)."')"); + } + } + + function insert() { + global $DBc; + + $this->dev = 1; + + $DBc->sqlQuery("INSERT INTO ach_task (at_achievement,at_parent,at_value,at_condition,at_condition_value,at_dev,at_torder,at_inherit) VALUES ('".$this->getAchievement()."',".mkn($this->getParentID()).",'".$DBc->sqlEscape($this->getValue())."','".$DBc->sqlEscape($this->getCondition())."',".mkn($this->getConditionValue()).",'1','".$this->torder."','".$this->inherit_obj."')"); + $id = $DBc->insertID(); + $this->setID($id); + + $DBc->sqlQuery("INSERT INTO ach_task_lang (atl_task,atl_lang,atl_name,atl_template) VALUES ('".$this->getID()."','en','".$DBc->sqlEscape($this->getName())."',".mkn($this->getTemplate()).")"); + + foreach($this->tie_race as $elem) { + $DBc->sqlQuery("INSERT INTO ach_task_tie_race (attr_task,attr_race) VALUES ('".$this->getID()."','".$DBc->sqlEscape($elem)."')"); + } + + foreach($this->tie_align as $elem) { + $DBc->sqlQuery("INSERT INTO ach_task_tie_align (atta_task,atta_alignment) VALUES ('".$this->getID()."','".$DBc->sqlEscape($elem)."')"); + } + } + + function setAchievement($a) { + $this->achievement = $a; + } + + function setName($name) { + $this->name = $name; + } + + function setTemplate($t) { + $this->template = $t; + } + + function setValue($v) { + $this->value = $v; + } + + function setTieRace($t) { + $this->tie_race = $t; + } + + function setTieAlign($t) { + $this->tie_align = $t; + } + + function getCondition() { + return $this->condition; + } + + function getConditionValue() { + return $this->condition_value; + } + + function setCondition($c) { + $this->condition = $c; + } + + function setConditionValue($v) { + $this->condition_value = $v; + } + + function getTorder() { + return $this->torder; + } + + function setTorder($t) { + $this->torder = $t; + } + + function setHeritage($i) { + $this->inherit_obj = $i; + } + + function setParentID($p,$order = true) { #reordering must happen A) after insert B) when updating + if($p == null || $p == "null") { + + $this->parent_id = null; + + } + else { + + $this->parent_id = $p; + + } + + if($order == true) { + + $iter = $this->parent->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + if($curr->getID() == $this->id) { + continue; + } + if($curr->getParentID() == $this->parent_id) { + $curr->setParentID($this->id,false); + $curr->update(); + + break; + } + } + } + } + + function isTiedRace($r) { + if(sizeof($this->tie_race) == 0) { + return false; + } + return in_array($r,$this->tie_race); + } + + function isTiedAlign($cult,$civ) { + if(sizeof($this->tie_align) == 0) { + return false; + } + return in_array(($cult.'|'.$civ),$this->tie_align); + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/CSRAchievement_class.php b/code/web/app/app_achievements_admin/class/CSRAchievement_class.php new file mode 100644 index 000000000..1cbd7ada8 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/CSRAchievement_class.php @@ -0,0 +1,125 @@ +getID()."
"; + if(is_numeric($path)) { + //it's me (id == numeric) + if($this->getID() == $path) { + $this->grant($player); + #echo "grant()
"; + } + } + else { + //get child with the next level id and dispatch + $tmp = explode(";",$path); + + $c = $this->getChildDataByID($tmp[1]); + #echo "...".$tmp[1]; + if($c != null) { // check if it's really own child + unset($tmp[0]); + $c->grantNode(implode(";",$tmp),$player); + #echo "grantNode()
"; + } + } + #echo "end
"; + } + + function denyNode($path,$player) { + if(is_numeric($path)) { + //it's me (id == numeric) + if($this->getID() == $path) { + $this->deny($player); + } + } + else { + //get child with the next level id and dispatch + $tmp = explode(";",$path); + + if($tmp[0] == $this->getID()) { // it's my id! + + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { // check if it's really own child + unset($tmp[0]); + $c->denyNode(implode(";",$tmp),$player); + } + } + } + } + + function getPath($path = "") { + if($path != "") { + $path = ";".$path; + } + + $path = $this->getID().$path; + + if($this->hasParent()) { + $path = $this->parent->getPath($path); + } + + return $path; + } + + private function hasParent() { + return ($this->parent != null); + } + ######################### + + function CSRAchievement($data,$parent) { + parent::__construct($data,$parent); + } + + protected function makeChild($d) { + return new CSRTask($d,$this); + } + + function grant($pid) { + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $curr->grant($pid); + $this->setChildDone($curr->getID()); + } + + $this->parent->setChildDone($this->id); + } + + function deny($pid) { + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $curr->deny($pid); + $this->setChildOpen($curr->getID()); + } + + $this->parent->setChildOpen($this->id); + } + + function setTaskDone($id) { + $this->setChildDone($id); + + + $this->parent->addChildDone($this->id); + + if(!$this->hasOpen()) { + $this->parent->removeChildOpen($this->id); + } + } + + function setTaskOpen($id) { + + $this->setChildOpen($id); + + + $this->parent->addChildOpen($this->id); + + if(!$this->hasDone()) { + $this->parent->removeChildDone($this->id); + } + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/CSRAtom_class.php b/code/web/app/app_achievements_admin/class/CSRAtom_class.php new file mode 100644 index 000000000..398b7f283 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/CSRAtom_class.php @@ -0,0 +1,22 @@ +id = $data['atom_id']; + $this->parent = $parent; + } + + function grant($pid) { + $this->clear_all($pid); #empty database + } + + function deny($pid) { + $this->clear_all($pid); #empty database + } + + private function clear_all($pid) { + global $DBc; + $DBc->sqlQuery("DELETE FROM ach_player_atom WHERE apa_atom='".$this->getID()."' AND apa_player='".$pid."'"); + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/CSRCategory_class.php b/code/web/app/app_achievements_admin/class/CSRCategory_class.php new file mode 100644 index 000000000..b2f1eac7d --- /dev/null +++ b/code/web/app/app_achievements_admin/class/CSRCategory_class.php @@ -0,0 +1,89 @@ +getID()."
"; + if(is_numeric($path)) { + //it's me (id == numeric) + if($this->getID() == $path) { + $this->grant($player); + #echo "grant()
"; + } + } + else { + //get child with the next level id and dispatch + $tmp = explode(";",$path); + + $c = $this->getChildDataByID($tmp[1]); + #echo "...".$tmp[1]; + if($c != null) { // check if it's really own child + unset($tmp[0]); + $c->grantNode(implode(";",$tmp),$player); + #echo "grantNode()
"; + } + } + #echo "end
"; + } + + function denyNode($path,$player) { + if(is_numeric($path)) { + //it's me (id == numeric) + if($this->getID() == $path) { + $this->deny($player); + } + } + else { + //get child with the next level id and dispatch + $tmp = explode(";",$path); + + if($tmp[0] == $this->getID()) { // it's my id! + + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { // check if it's really own child + unset($tmp[0]); + $c->denyNode(implode(";",$tmp),$player); + } + } + } + } + + function getPath($path = "") { + if($path != "") { + $path = ";".$path; + } + + $path = $this->getID().$path; + + if($this->hasParent()) { + $path = $this->parent->getPath($path); + } + + return $path; + } + + private function hasParent() { + return ($this->parent != null); + } + ######################### + + function CSRCategory($id,$race,$cult = null,$civ = null) { + parent::__construct($id,$race,$cult,$civ); + } + + protected function makeChild($d) { + return new CSRAchievement($d,$this); + } + + function grant($id) { + return false; // category can't grant! + } + + function deny($id) { + return false; // category can't deny! + } + + } +?> diff --git a/code/web/app/app_achievements_admin/class/CSRDispatcher_trait.php b/code/web/app/app_achievements_admin/class/CSRDispatcher_trait.php new file mode 100644 index 000000000..65e8e43f2 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/CSRDispatcher_trait.php @@ -0,0 +1,65 @@ +getID() == $path) { + $this->grant($player); + } + } + else { + //get child with the next level id and dispatch + $tmp = explode(";",$path); + + $c = $this->getChildDataByID($tmp[1]); + + if($c != null) { // check if it's really own child + unset($tmp[0]); + $c->grantNode(implode(";",$tmp),$player); + + } + } + + } + + function denyNode($path,$player) { + if(is_numeric($path)) { + //it's me (id == numeric) + if($this->getID() == $path) { + $this->deny($player); + } + } + else { + //get child with the next level id and dispatch + $tmp = explode(";",$path); + + if($tmp[0] == $this->getID()) { // it's my id! + + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { // check if it's really own child + unset($tmp[0]); + $c->denyNode(implode(";",$tmp),$player); + } + } + } + } + + function getPath($path = "") { + if($path != "") { + $path = ";".$path; + } + + $path = $this->getID().$path; + + if($this->hasParent()) { + $path = $this->parent->getPath($path); + } + + return $path; + } + + private function hasParent() { + return ($this->parent != null); + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/CSRObjective_class.php b/code/web/app/app_achievements_admin/class/CSRObjective_class.php new file mode 100644 index 000000000..254824b0a --- /dev/null +++ b/code/web/app/app_achievements_admin/class/CSRObjective_class.php @@ -0,0 +1,116 @@ +getID()."
"; + if(is_numeric($path)) { + //it's me (id == numeric) + if($this->getID() == $path) { + $this->grant($player); + #echo "grant()
"; + } + } + else { + //get child with the next level id and dispatch + $tmp = explode(";",$path); + + $c = $this->getChildDataByID($tmp[1]); + #echo "...".$tmp[1]; + if($c != null) { // check if it's really own child + unset($tmp[0]); + $c->grantNode(implode(";",$tmp),$player); + #echo "grantNode()
"; + } + } + #echo "end
"; + } + + function denyNode($path,$player) { + if(is_numeric($path)) { + //it's me (id == numeric) + if($this->getID() == $path) { + $this->deny($player); + } + } + else { + //get child with the next level id and dispatch + $tmp = explode(";",$path); + + if($tmp[0] == $this->getID()) { // it's my id! + + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { // check if it's really own child + unset($tmp[0]); + $c->denyNode(implode(";",$tmp),$player); + } + } + } + } + + function getPath($path = "") { + if($path != "") { + $path = ";".$path; + } + + $path = $this->getID().$path; + + if($this->hasParent()) { + $path = $this->parent->getPath($path); + } + + return $path; + } + + private function hasParent() { + return ($this->parent != null); + } + ######################### + + function CSRObjective($data,$parent) { + parent::__construct($data,$parent); + + global $DBc; + + $res = $DBc->sqlQuery("SELECT atom_id FROM ach_atom WHERE atom_objective='".$this->getID()."'"); + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + $this->addChild($this->makeChild($res[$i])); + } + } + + protected function makeChild($d) { + return new CSRAtom($d,$this); + } + + function grant($pid) { + global $DBc; + + $DBc->sqlQuery("INSERT INTO ach_player_objective (apo_objective,apo_player,apo_date) VALUES ('".$this->getID()."','".$pid."','".time()."')"); + $this->done = 1; + $this->progress = $this->value; + + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $curr->grant($pid); + } + } + + function deny($pid) { + global $DBc; + + $DBc->sqlQuery("DELETE FROM ach_player_objective WHERE apo_objective='".$this->getID()."' AND apo_player='".$pid."'"); + $this->done = 0; + $this->progress = 0; + + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $curr->deny($pid); + } + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/CSRTask_class.php b/code/web/app/app_achievements_admin/class/CSRTask_class.php new file mode 100644 index 000000000..5680877a7 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/CSRTask_class.php @@ -0,0 +1,109 @@ +getID()."
"; + if(is_numeric($path)) { + //it's me (id == numeric) + if($this->getID() == $path) { + $this->grant($player); + #echo "grant()
"; + } + } + else { + //get child with the next level id and dispatch + $tmp = explode(";",$path); + + $c = $this->getChildDataByID($tmp[1]); + #echo "...".$tmp[1]; + if($c != null) { // check if it's really own child + unset($tmp[0]); + $c->grantNode(implode(";",$tmp),$player); + #echo "grantNode()
"; + } + } + #echo "end
"; + } + + function denyNode($path,$player) { + if(is_numeric($path)) { + //it's me (id == numeric) + if($this->getID() == $path) { + $this->deny($player); + } + } + else { + //get child with the next level id and dispatch + $tmp = explode(";",$path); + + if($tmp[0] == $this->getID()) { // it's my id! + + $c = $this->getChildDataByID($tmp[1]); + if($c != null) { // check if it's really own child + unset($tmp[0]); + $c->denyNode(implode(";",$tmp),$player); + } + } + } + } + + function getPath($path = "") { + if($path != "") { + $path = ";".$path; + } + + $path = $this->getID().$path; + + if($this->hasParent()) { + $path = $this->parent->getPath($path); + } + + return $path; + } + + private function hasParent() { + return ($this->parent != null); + } + ######################### + + function CSRTask($data,$parent) { + parent::__construct($data,$parent); + } + + protected function makeChild($d) { + return new CSRObjective($d,$this); + } + + function grant($pid) { + global $DBc; + + $DBc->sqlQuery("INSERT INTO ach_player_task (apt_task,apt_player,apt_date) VALUES ('".$this->getID()."','".$pid."','".time()."')"); + $this->done = time(); + #echo $this->idx."
"; + $this->parent->setTaskDone($this->id); + + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $curr->grant($pid); + } + } + + function deny($pid) { + global $DBc; + + $DBc->sqlQuery("DELETE FROM ach_player_task WHERE apt_task='".$this->getID()."' AND apt_player='".$pid."'"); + $this->done = 0; + $this->parent->setTaskOpen($this->id); + + $iter = $this->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + $curr->deny($pid); + } + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/CSR_inter.php b/code/web/app/app_achievements_admin/class/CSR_inter.php new file mode 100644 index 000000000..67b64149e --- /dev/null +++ b/code/web/app/app_achievements_admin/class/CSR_inter.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/RyzomAdmin_class.php b/code/web/app/app_achievements_admin/class/RyzomAdmin_class.php new file mode 100644 index 000000000..e7361364f --- /dev/null +++ b/code/web/app/app_achievements_admin/class/RyzomAdmin_class.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/class/mySQL_class.php b/code/web/app/app_achievements_admin/class/mySQL_class.php new file mode 100644 index 000000000..36baa1774 --- /dev/null +++ b/code/web/app/app_achievements_admin/class/mySQL_class.php @@ -0,0 +1,161 @@ +$elem) { + $in[$key] = mysql_real_escape_string(stripslashes($elem)); + } + } + else { + $in = mysql_real_escape_string(stripslashes($in)); + } + return $in; + } + + function mySQL($err=false) { + $this->DBstats = array(); + $this->DBc = false; + if($err === "DIE" || $err === "PRINT" || $err === "ALERT" || $err === "HIDE" || $err === "LOG") { + $this->DBerror = $err; + } + else { + $this->DBerror = "HIDE"; + } + $this->resetStats(); + $this->cached = false; + } + + function connect($ip,$user,$pass,$db=false) { + $this->DBc = mysql_pconnect($ip,$user,$pass) or $this->error(mysql_error()); + if($this->DBc && $db) { + $this->database($db); + } + $this->resetStats(); + } + + function database($db) { + if(!$this->DBc) { + return false; + } + mysql_select_db($db,$this->DBc) or $this->error(mysql_error()); + return true; + } + + function resetStats() { + $this->DBstats['query'] = 0; + $this->DBstats['error'] = 0; + } + + function getStats() { + return $this->DBstats; + } + + function sendSQL($query,$handling="PLAIN",$buffer=false) { // can be INSERT, DELETE, UPDATE, ARRAY, NONE, PLAIN + #if($this->cached !== false) { + #$this->unlinkSql($this->cached); + #} + if(!$this->DBc) { + return false; + } + + if($buffer === false && $handling !== "PLAIN") { + $res = mysql_unbuffered_query($query,$this->DBc) or $this->error(mysql_error(),$query); + } + else { + $res = mysql_query($query,$this->DBc) or $this->error(mysql_error(),$query); + } + + #$this->cached = $res; + + $this->DBstats['query']++; + + if($res) { + if($handling === "INSERT") { + $tmp = mysql_insert_id($this->DBc) or $this->error(mysql_error());; + $this->unlinkSql($res); + return $tmp; + } + elseif($handling === "DELETE" || $handling === "UPDATE") { + $tmp = mysql_affected_rows($this->DBc) or $this->error(mysql_error()); + $this->unlinkSql($res); + return $tmp; + } + elseif($handling === "ARRAY") { + $tmp = $this->parseSql($res); + $this->unlinkSql($res); + return $tmp; + } + elseif($handling === "NONE") { + $this->unlinkSql($res); + return true; + } + else { + return $res; + } + //mysql_free_result($res); + } + else { + return false; + } + } + + function unlinkSql($res) { + @mysql_free_result($res); + } + + private function parseSql($res) { + $data = array(); + $k = 0; + while($tmp = mysql_fetch_array($res,MYSQL_ASSOC)) { + $data[$k] = $tmp; + $k++; + } + + return $data; + } + + function getNext($res) { + if($res) { + if($tmp = mysql_fetch_array($res,MYSQL_ASSOC)) { + return $tmp; + } + else { + return false; + } + } + else { + return false; + } + } + + private function error($error,$query = false) { + $this->DBstats['error']++; + + if($query != false) { + $error .= " -->|".$query."|<--"; + } + + switch($this->DBerror) { + case 'DIE': + die($error); + break; + case 'PRINT': + echo "
".$error."
"; + break; + case 'ALERT': + echo ""; + break; + case 'LOG': + logf("MySQL ERROR: ".$error); + break; + default: + flush(); + break; + } + } + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/conf.php b/code/web/app/app_achievements_admin/conf.php new file mode 100644 index 000000000..1f20ac5a7 --- /dev/null +++ b/code/web/app/app_achievements_admin/conf.php @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/favicon.png b/code/web/app/app_achievements_admin/favicon.png new file mode 100644 index 000000000..0e26ec6e2 Binary files /dev/null and b/code/web/app/app_achievements_admin/favicon.png differ diff --git a/code/web/app/app_achievements_admin/include/adm_render_ach.php b/code/web/app/app_achievements_admin/include/adm_render_ach.php new file mode 100644 index 000000000..4b8c1a2d7 --- /dev/null +++ b/code/web/app/app_achievements_admin/include/adm_render_ach.php @@ -0,0 +1,997 @@ + + .ach_menu { + display:block; + padding:2px; + border:1px solid #000000; + margin-bottom:2px; + color:#FFFFFF; + } + .ach_menu:hover { + color:orange; + } + + .ach_mspan a { + text-decoration:none; + } + "; + + return $html.adm_render_mnode($menu,$sub); + } + + function adm_render_mnode(&$menu,$sub) { + global $_CONF; + + $html = ""; + + $iter = $menu->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + $html .= " + "; + if($sub == 0) { + $html .= ""; + } + $html .= " + +
getImage()."' />".$curr->getName()."
"; + if($curr->hasOpenCat() != 0) { + $html .= "
".adm_render_mnode($curr,($sub+4))."
"; + } + } + + return $html; + } + + function adm_render_category(&$cat) { + global $menu,$metalist,$DBc,$_USER; + + $html = ""; + + $m = $menu->getIterator(); + while($m->hasNext()) { + $n = $m->getNext(); + $html .= ""; + + $m2 = $n->getIterator(); + while($m2->hasNext()) { + $n2 = $m2->getNext(); + $html .= ""; + + //db + $res = $DBc->sqlQuery("SELECT aa_id,aal_name FROM ach_achievement LEFT JOIN (ach_achievement_lang) ON (aal_lang='".$_USER->getLang()."' AND aal_achievement=aa_id) WHERE aa_category='".$n2->getID()."' ORDER by aa_sticky DESC, aal_name ASC"); + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + $html .= ""; + } + } + + //db + $res = $DBc->sqlQuery("SELECT aa_id,aal_name FROM ach_achievement LEFT JOIN (ach_achievement_lang) ON (aal_lang='".$_USER->getLang()."' AND aal_achievement=aa_id) WHERE aa_category='".$n->getID()."' ORDER by aa_sticky DESC, aal_name ASC"); + $sz = sizeof($res); + for($i=0;$i<$sz;$i++) { + $html .= ""; + } + } + + $metalist = $html; + + + + $html = ""; + + if($_REQUEST['confirm'] == "delete") { + $tmp = $cat->getElementByPath($_REQUEST['id']); + if($tmp != null) { + $html .= "
+
+ Delete + Are you sure you want to delete ".$tmp->getName()."

+ Any nested Tasks/Objective/Atoms will be removed, as well as any player progress connected! +

+ delete +

+
"; + } + } + + $html .= "
+
+ + + +
+ +
"; + + if($cat->hasTieAlignDev()) { + $html .= ach_render_tiebar($cat->getCurrentCult(),$cat->getCurrentCiv(),$cat); + } + + + $iter = $cat->getOpen(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + if(!$curr->isTiedAlign_open($cat->getCurrentCult(),$cat->getCurrentCiv())) { + #continue; + } + + $html .= ach_render_achievement_open($curr,$cat); + } + + return $html; + } + + function ach_render_achievement_open(&$ach,&$cat) { + global $_CONF,$menu; + + $html = '
+ + + + + + + + + + + + + + + +
+
+ + + +
'; + + $html .= " +
[ach:]'.$ach->getName().''; + if($ach->getParentID() != null && $ach->getParentID() != "null") { + #echo $ach->getParentID(); + $c = $ach->getParent(); + $p = $c->getChildDataByID($ach->getParentID()); + $html .= "
child of ".$p->getName().""; + } + + $html .= '
getDev()."&id=".$ach->getPathID()."#ach_".$ach->getID()."'> "; + + $html .= " "; + + $html .= " "; + + $html .= "   getPathID()."'>
"; + + $html .= '
+
'; + + $html .= ""; + + $html .= ""; + + $html .= ""; + + $html .= ach_render_task_open($ach,$cat); + $html .= '
+
'; + + return $html; + } + + function ach_render_task_open(&$ach,&$cat) { + global $metalist; + + + + $html = ""; + + $task_list = $ach->getOpen(); + while($task_list->hasNext()) { + + $task = $task_list->getNext(); + + if(!$task->isTiedAlign($cat->getCurrentCult(),$cat->getCurrentCiv())) { + #continue; + } + + + $html .= ""; + + $html .= " +
[task:]".$task->getDisplayName()." (".$task->getValue().")getDev()."&id=".$task->getPathID()."#task_".$task->getID()."'> "; + + $html .= " "; + + $html .= "   getPathID()."'>
"; + + $html .= ""; + + $html .= ""; + + $html .= ach_render_obj_list($task->getIterator(),$task); + } + + return $html; + } + + function ach_render_obj_list($obj,$task) { + #return null; + global $metalist; + $html = "
"; + + #$i = 0; + #$skip = false; + + while($obj->hasNext()) { + #foreach($obj as $elem) { + $inh = ""; + $elem = $obj->getNext(); + + if($task->isInherited($elem->getID())) { + $inh = "inherited: "; + } + + #if(($i%2) == 0) { + $html .= ""; + #} + + + #if(!$skip) { + # $i++; + #} + #$skip = false; + } + + #if(($i%2) == 1) { + # $html .= ""; + #} + + $html .= "
"; + #} + + switch($elem->getDisplay()) { + case "meta": + $html .= ""; + #} + $html .= ""; + #$i++; + break; + case "simple": + $html .= ""; + break; + case "hidden": + default: + //do nothing + #$skip = true; + #if(($i%2) == 1) { + # $html .= ""; + #} + $html .= ""; + #$i++; + break; + } + + $html .= " +
".$inh.ach_render_obj_meta($elem).""; + break; + case "value": + #if(($i%2) == 1) { + # $html .= "
".$inh.ach_render_obj_value($elem)."".$inh.ach_render_obj_simple($elem)."
".$inh.ach_render_obj_hidden($elem).""; + + #$html .= " "; + + $html .= "   getPathID()."'>
"; + + + + $html .= ""; + + #if(($i%2) == 1) { + $html .= "
"; + + return $html; + } + + function ach_render_obj_simple(&$obj) { + global $_CONF; + $html = ""; + if($obj->isdone()) { + $html .= " "; + } + else { + $html .= " "; + } + + $html .= "[obj:]".$obj->getDisplayName().""; + + return $html; + } + + function ach_render_obj_meta(&$obj) { + global $_CONF; + + if($obj->isdone()) { + $col = "#71BE02"; + $grey = ""; + } + else { + $col = "#999999"; + $grey = "grey/"; + } + + return " + + + + +
getMetaImage()."' width='20px' /> [obj:]".$obj->getDisplayName()."
"; + } + + function ach_render_obj_value(&$obj) { + $html = ""; + #if($obj->getName() != null) { + if($obj->isdone()) { + $col = "#71BE02"; + } + else { + $col = "#999999"; + } + $html .= "
[obj:]".$obj->getDisplayName()."
"; + #} + + $html .= ach_render_progressbar($obj->getProgress(),$obj->getValue(),350); + + return $html; + } + + function ach_render_obj_hidden(&$obj) { + $html = ""; + #if($obj->getName() != null) { + if($obj->isdone()) { + $col = "#71BE02"; + } + else { + $col = "#999999"; + } + $html .= ""; + #} + + #$html .= ach_render_progressbar($obj->getProgress(),$obj->getValue(),350); + + return $html; + } + + function ach_render_progressbar($prog,$val,$width) { + $val = max(1,$val); + $left = floor($width*(100*($prog/$val))/100); + + $html = " + + + + + +
"; + if(($prog/$val) > 0.85) { + $html .= " ".nf($prog)." / ".nf($val)." "; + } + $html .= ""; + if(($prog/$val) <= 0.85) { + $html .= " ".nf($prog)." / ".nf($val)." "; + } + $html .= "
"; + + return $html; + } + + function ach_render_tiebar($cult = "c_neutral", $civ = "c_neutral",&$cat) { + global $_USER; + + $html = " + +
+ + "; + if($cat->isAllowedCult()) { + $html.= ""; + } + $html.= " +
+ +
+
+ +
"; + + /*if($cat->isTiedCult() && !$cat->isTiedCiv() && $cult == "c_neutral") { // neutral / xx + #While being of neutral allegiance with the higher powers + $html .= get_translation('ach_allegiance_neutral_cult',$_USER->getLang(),array("".get_translation('ach_c_neutral',$_USER->getLang())."")); + } + elseif($cat->isTiedCiv() && !$cat->isTiedCult() && $civ == "c_neutral") { // xx / neutral + #While being of neutral allegiance with the homin civilizations + $html .= get_translation('ach_allegiance_neutral_civ',$_USER->getLang(),array("".get_translation('ach_c_neutral',$_USER->getLang())."")); + }*/ + if(($cult == "c_neutral" || !$cat->isAllowedCult()) && ($civ == "c_neutral" || !$cat->isAllowedCiv())) { // neutral / neutral + #While being of neutral allegiance + $html .= get_translation('ach_allegiance_neutral',$_USER->getLang(),array("".get_translation('ach_c_neutral',$_USER->getLang())."")); + } + else { //other + #While being aligned with the + $html .= get_translation('ach_allegiance_start',$_USER->getLang()); + if($cat->isAllowedCult() && $cult != "c_neutral") { + #CULT + $html .= "".ach_translate_cc($cult).""; + if($cat->isAllowedCiv() && $civ != "c_neutral") { + #and the CIV + $html .= get_translation('ach_allegiance_and',$_USER->getLang())." ".ach_translate_cc($civ).""; + } + } + elseif($cat->isAllowedCiv() && $civ != "c_neutral") { + #CIV + $html .= "".ach_translate_cc($civ).""; + } + } + #, accomplish the following achievements: + $html .= get_translation('ach_allegiance_end',$_USER->getLang())."
"; + + return $html; + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/include/adm_render_atom.php b/code/web/app/app_achievements_admin/include/adm_render_atom.php new file mode 100644 index 000000000..ccf5d2366 --- /dev/null +++ b/code/web/app/app_achievements_admin/include/adm_render_atom.php @@ -0,0 +1,256 @@ + + .ach_menu { + display:block; + padding:2px; + border:1px solid #000000; + margin-bottom:2px; + color:#FFFFFF; + } + .ach_menu:hover { + color:orange; + } + + .ach_mspan a { + text-decoration:none; + } + "; + + return $html.adm_render_mnode($menu,$sub); + } + + function adm_render_mnode(&$menu,$sub) { + global $_CONF; + + $html = ""; + + $iter = $menu->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + $html .= " + "; + if($sub == 0) { + $html .= ""; + } + $html .= " + +
getImage()."' />".$curr->getName()."
"; + if($curr->hasOpenCat() != 0) { + $html .= "
".adm_render_mnode($curr,($sub+4))."
"; + } + } + + return $html; + } + + function atom_render_category(&$cat) { + $html = " + + + + "; + + $iter = $cat->getOpen(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + $html .= ach_render_achievement_open($curr); + } + + return $html; + } + + function ach_render_achievement_open(&$ach) { + + $open = explode(";",$_REQUEST['id']); + + $o = "none"; + if($open[1] == $ach->getID()) { + $o = "block"; + } + + $html = "
+
[+] ".$ach->getName()."
+
".ach_render_task_open($ach)."
+
"; + + return $html; + } + + function ach_render_task_open(&$ach) { + $html = ""; + + $open = explode(";",$_REQUEST['id']); + + $task_list = $ach->getOpen(); + while($task_list->hasNext()) { + + $task = $task_list->getNext(); + + $o = "none"; + if($open[2] == $task->getID()) { + $o = "block"; + } + + $html .= "
+
[+] ".$task->getDisplayName()." (condition= ".$task->getCondition().": ".$task->getConditionValue().")
+
".ach_render_obj_list($task->getIterator(),$task)."
+
"; + } + + return $html; + } + + function ach_render_obj_list($obj,$task) { + $html = ""; + + + while($obj->hasNext()) { + $elem = $obj->getNext(); + + if($task->isInherited($elem->getID()) || $elem->getDisplay() == "meta") { + continue; + } + + $o = "block"; + + + $html .= "
+
[+] ".$elem->getDisplayName()." (condition= ".$elem->getCondition().": ".$elem->getValue().")
+
+ + + ".ach_render_atom_list($elem->getIterator())." +
+
"; + } + + return $html; + } + + function ach_render_atom_list($atom) { + $html = ""; + + while($atom->hasNext()) { + $elem = $atom->getNext(); + + $html .= "
getPathID()."#obj_".$elem->getObjective()."'> + + + + + + + + + + + + + + +
getPathID()."#obj_".$elem->getObjective()."'>[X]
".$elem->getRulesetParsed()."
getMandatory() == 1) { + $html .= " checked='checked'"; + } + $html .= " /> mandatory
+

"; + } + + return $html; + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/include/adm_render_csr.php b/code/web/app/app_achievements_admin/include/adm_render_csr.php new file mode 100644 index 000000000..143d20dd2 --- /dev/null +++ b/code/web/app/app_achievements_admin/include/adm_render_csr.php @@ -0,0 +1,578 @@ +sqlQuery("SELECT count(*) as anz FROM players WHERE id='".$DBc_char->sqlEscape($id)."'"); + + if($res[0]['anz'] > 0) { + return true; + } + return false; + } + + function user_get_name($id) { + global $DBc_char; + + $res = $DBc_char->sqlQuery("SELECT name FROM players WHERE id='".$DBc_char->sqlEscape($id)."'"); + + return $res[0]['name']; + } + + function user_get_data($id) { + global $_CONF,$DBc_char; + $DBc_align = new mySQL($_CONF['mysql_error']); + $DBc_align->connect($_CONF['char_mysql_server'],$_CONF['char_mysql_user'],$_CONF['char_mysql_pass'],$_CONF['char_mysql_database']); + + $res = $DBc_char->sqlQuery("SELECT cid FROM players WHERE id='".$DBc_char->sqlEscape($id)."'"); + + $res = $DBc_align->sendSQL("SELECT race,civilisation,cult FROM characters WHERE char_id='".$res[0]['cid']."'","ARRAY"); + + return $res[0]; + } + + function csr_render_yubopoints() { + global $DBc,$_USER,$_CONF; + + $res = $DBc->sqlQuery("SELECT sum(at_value) as anz FROM ach_task,ach_player_task WHERE at_id=apt_task AND apt_player='".$_USER->getID()."'"); + + $html = "
".$_USER->getName()."  ".max(0,$res[0]['anz'])."
"; + + return $html; + } + + function csr_render_find_player() { + global $DBc_char; + + $html = "
+
+ Search for a player + + + + + + + + +
Name: 
+
+
"; + + if($_REQUEST['pname'] != "") { + $html .= "
"; + + $res = $DBc_char->sqlQuery("SELECT * FROM players WHERE (name LIKE '".$DBc_char->sqlEscape(strtolower($_REQUEST['pname']))."%' OR id='".$DBc_char->sqlEscape(strtolower($_REQUEST['pname']))."') AND deleted='0' LIMIT 0,100"); + $sz = sizeof($res); + + if($sz == 0) { + $html .= "no characters found"; + } + + $cols = 1; + if($sz > 8) { + $cols = 3; + } + + $html .= ""; + + for($i=0;$i<$sz;$i++) { + if($cols != 1 && ($i%$cols) == 0) { + $html .= ""; + } + + $html .= ""; + } + + $html .= "
".$res[$i]['name']."
"; + + $html .= "
"; + } + + return $html; + } + + function csr_render_menu(&$menu,$sub = 0) { + $html = ""; + + return $html.adm_render_mnode($menu,$sub); + } + + function adm_render_mnode(&$menu,$sub) { + global $_CONF; + + $html = ""; + + $iter = $menu->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + #$sz = $menu->getSize(); + #for($i=0;$i<$sz;$i++) { + # $curr = $menu->getChild($i); + if($curr->inDev()) { + #continue; + } + $html .= " + "; + if($sub == 0) { + $html .= ""; + } + $html .= " + +
getImage()."' />".$curr->getName()."
"; + if($curr->hasOpenCat() != 0) { + $html .= "
".adm_render_mnode($curr,($sub+4))."
"; + } + } + + return $html; + } + + function csr_render_category(&$cat) { + $html = ""; + + if($cat->hasTieAlign_done() || $cat->hasTieAlign_open()) { + $html .= ach_render_tiebar($cat->getCurrentCult(),$cat->getCurrentCiv(),$cat); + } + + $iter = $cat->getDone(); + + while($iter->hasNext()) { + $curr = $iter->getNext(); + + #$sz = sizeof($tmp); + #for($i=0;$i<$sz;$i++) { + #echo "A"; + if($curr->inDev()) { + continue; + } + $html .= ach_render_achievement_done($curr); + } + + $iter = $cat->getOpen(); + + while($iter->hasNext()) { + $curr = $iter->getNext(); + + #$sz = sizeof($tmp); + #for($i=0;$i<$sz;$i++) { + #echo "B"; + if($curr->inDev()) { + continue; + } + $html .= ach_render_achievement_open($curr); + } + + return $html; + } + + function ach_render_achievement_done(&$ach) { + global $_CONF; + + $html = '
+ + + + + + + + + + + + + + + +
+
+ + + + +
'.$ach->getName().'
+ '.$ach->getValueDone().'
+
'; + $html .= ach_render_task_done($ach); + $html .= '
+
'; + + return $html; + } + + function ach_render_achievement_open(&$ach) { + global $_CONF; + + $html = '
+ + + + + + + + + + + + + + + +
+
+ + + + +
'.$ach->getName().'
+ '.$ach->getValueOpen().'
+
'; + $html .= ach_render_task_open($ach); + $html .= '
+
'; + + return $html; + } + + function ach_render_task_open(&$ach) { + $html = ""; + + $task_list = $ach->getOpen(); + $task = $task_list->getNext(); + + + if($task->inDev()) { + return $html; + } + + $html .= ""; + + if($task->getName() != null) { + $html .= $task->getDisplayName(); + } + else { + $html .= "[untitled]"; + } + $html .= " Task: grant"; + + if($task->objDrawable()) { + $html .= ach_render_obj_list($task->getIterator()); + } + + return $html; + } + + function ach_render_task_done(&$ach) { + global $_CONF; + $html = ""; + + $task_list = $ach->getDone(); + while($task_list->hasNext()) { + $task = $task_list->getNext(); + + if($task->inDev()) { + continue; + } + $html .= "
".$task->getDisplayName()." ( ".date('d.m.Y',$task->getDone())." ) ".$task->getValue()." Task: deny
"; + } + + return $html; + } + + function ach_render_obj_list($obj) { + $html = "
"; + + $i = 0; + $skip = false; + + while($obj->hasNext()) { + #foreach($obj as $elem) { + $elem = $obj->getNext(); + if(($i%2) == 0) { + $html .= ""; + } + + switch($elem->getDisplay()) { + case "meta": + $html .= ""; + break; + case "value": + if(($i%2) == 1) { + $html .= ""; + } + $html .= ""; + $i++; + break; + case "simple": + $html .= ""; + break; + case "hidden": + default: + //do nothing + $skip = true; + break; + } + + if(($i%2) == 1) { + $html .= ""; + } + + + if(!$skip) { + $i++; + } + $skip = false; + } + + if(($i%2) == 1) { + $html .= ""; + } + + $html .= "
".ach_render_obj_meta($elem)."
".ach_render_obj_value($elem)."
".ach_render_obj_simple($elem)."
"; + + return $html; + } + + function ach_render_obj_simple(&$obj) { + global $_CONF; + $html = ""; + if($obj->isdone()) { + $html .= " "; + } + else { + $html .= " "; + } + + $html .= $obj->getDisplayName(); + if($obj->isdone()) { + $html .= " Obj: deny"; + } + else { + $html .= " Obj: grant"; + } + $html .= ""; + + return $html; + } + + function ach_render_obj_meta(&$obj) { + global $_CONF; + $html = ""; + if($obj->isdone()) { + $col = "#71BE02"; + $grey = ""; + } + else { + $col = "#999999"; + $grey = "grey/"; + } + + $html .= " + + + + +
getMetaImage()."' width='20px' /> ".$obj->getDisplayName(); + if($obj->isdone()) { + $html .= " Obj: deny"; + } + else { + $html .= " Obj: grant"; + } + $html .= "
"; + + return $html; + } + + function ach_render_obj_value(&$obj) { + $html = ""; + if($obj->getName() != null) { + if($obj->isdone()) { + $col = "#71BE02"; + } + else { + $col = "#999999"; + } + $html .= "
".$obj->getDisplayName()."
"; + } + + $html .= " + + + + +
".ach_render_progressbar($obj->getProgress(),$obj->getValue(),350).""; + if($obj->isdone()) { + $html .= " Obj: deny"; + } + else { + $html .= " Obj: grant"; + } + $html .= "
"; + + return $html; + } + + function ach_render_progressbar($prog,$val,$width) { + $val = max(1,$val); + $left = floor($width*(100*($prog/$val))/100); + + $html = " + + + + + +
"; + if(($prog/$val) > 0.85) { + $html .= " ".nf($prog)." / ".nf($val)." "; + } + $html .= ""; + if(($prog/$val) <= 0.85) { + $html .= " ".nf($prog)." / ".nf($val)." "; + } + $html .= "
"; + + return $html; + } + + function ach_render_summary_header() { + global $_USER; + + return "
".get_translation('ach_summary_header',$_USER->getLang())."
"; + } + + function ach_render_summary_footer(&$summary) { + global $_USER; + + $nodes = $summary->getSummary(); + $html = ""; + + $sum_done = 0; + $sum_total = 0; + + $i = 0; + foreach($nodes as $elem) { + if(($i%3) == 0) { + $html .= ""; + } + + $html .= "".$elem[0]."
".ach_render_progressbar($elem[1],$elem[2],200).""; + $sum_done += $elem[1]; + $sum_total += $elem[2]; + + if(($i%3) == 2) { + $html .= ""; + } + + $i++; + } + + if(($i%3) == 2) { + $html .= ""; + } + + $html = "

+

".get_translation('ach_summary_stats',$_USER->getLang())."
+ + + + + ".$html." +
".get_translation('ach_summary_stats_total',$_USER->getLang())."
".ach_render_progressbar($sum_done,$sum_total,450)."
"; + + return $html; + } + + function ach_render_tiebar($cult = "c_neutral", $civ = "c_neutral",&$cat) { + global $_USER; + + $html = " + +
+ + "; + if($cat->isAllowedCult()) { + $html.= "
+ + + "; + if($sub == 0) { + $html .= ""; + } + $html .= " + +
getImage()."' />"; + if($curr->inDev()) { + $html .= "".$curr->getName().""; + } + else { + $html .= $curr->getName(); + } + $html .= "
"; + + if($curr->hasOpenCat() != 0) { + $html .= "
".adm_render_mnode($curr,($sub+4))."
"; + } + } + + return $html; + } + + function atom_render_category(&$cat) { + global $_CONF; + + $html = ""; + + + $html .= "
+
Category:getID()."'> + + + + + "; + + foreach($_CONF['langs'] as $elem) { + + $html .= " + + + "; + } + + $html .= " + + + +
 name
".$elem."
 
+
"; + + $iter = $cat->getOpen(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + + $html .= ach_render_achievement_open($curr); + } + + return $html; + } + + function ach_render_achievement_open(&$ach) { + global $_CONF; + + $open = explode(";",$_REQUEST['id']); + + $o = "none"; + if($open[1] == $ach->getID()) { + $o = "block"; + } + + $html = "
+
[+] ".$ach->getName()." + +
+
getPathID()."#jach_".$ach->getID()."'> + + + + + + "; + + foreach($_CONF['langs'] as $elem) { + $tmp = $ach->getLang($elem); + + $html .= " + + + + "; + } + + $html .= " + + + +
 nametemplate
".$elem."
 
+
+
+ +
+
".ach_render_task_open($ach)."
+
"; + + return $html; + } + + function ach_render_task_open(&$ach) { + global $_CONF; + + $html = ""; + + $open = explode(";",$_REQUEST['id']); + + $task_list = $ach->getOpen(); + while($task_list->hasNext()) { + + $task = $task_list->getNext(); + + $o = "none"; + if($open[2] == $task->getID()) { + $o = "block"; + } + + $tmp = $task->getLang('en'); + + if($tmp[0] != "" || $tmp[1] != '') { + + $html .= "
+
[+] ".$task->getDisplayName()." + +
+
getPathID()."#jtask_".$task->getID()."'> + + + + + + "; + + foreach($_CONF['langs'] as $elem) { + $tmp = $task->getLang($elem); + + $html .= " + + + + "; + } + + $html .= " + + + +
 nametemplate
".$elem."
 
+
+
+ +
+
".ach_render_obj_list($task->getIterator(),$task)."
+
"; + } + else { + $html .= "
".ach_render_obj_list($task->getIterator(),$task)."
"; + } + } + + return $html; + } + + function ach_render_obj_list($obj,$task) { + global $_CONF; + + $html = ""; + + + while($obj->hasNext()) { + $elem = $obj->getNext(); + + if($task->isInherited($elem->getID()) || $elem->getDisplay() == 'hidden' || $elem->getDisplay() == "meta" || $elem->getLang('en') == "") { + continue; + } + + + + $html .= "
+
  ".$elem->getDisplayName()." + +
+
getPathID()."#jobj_".$elem->getID()."'> + + + + + "; + + foreach($_CONF['langs'] as $lang) { + $tmp = $elem->getLang($lang); + + $html .= " + + + "; + } + + $html .= " + + + +
 name
".$lang."
 
+
+
+ +
+ + +
"; + } + + return $html; + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/include/adm_render_menu.php b/code/web/app/app_achievements_admin/include/adm_render_menu.php new file mode 100644 index 000000000..68cf34e1c --- /dev/null +++ b/code/web/app/app_achievements_admin/include/adm_render_menu.php @@ -0,0 +1,171 @@ + + .ach_menu { + display:block; + padding:2px; + border:1px solid #000000; + margin-bottom:2px; + color:#FFFFFF; + } + .ach_menu:hover { + color:orange; + } + + .ach_mspan a { + text-decoration:none; + } + "; + + $html .= "
+
+ + "; + + if($_REQUEST['ac_id'] > 0 && $_REQUEST['confirm'] == "delete") { + $curr = $menu->getNode($_REQUEST['ac_id']); + $html .= "
+
+ Are you sure you want to delete this category?"; + if($curr->hasAchievements()) { + $html .= "You may NOT DELETE this category since there are still achievements tied to it or one of its sub-categories!"; + } + else { + $html .= "".$curr->getName()."

"; + + if($curr->getParentID() == null) { + $html .= "WARNING: Deleting this category will also delete ALL sub-categories!
"; + } + $html .= "delete"; + } + $html .= "

+
"; + } + + $html .= "
"; + + return $html.ach_render_mnode($menu,$sub); + } + + function ach_render_mnode(&$menu,$sub) { + global $_CONF; + + # echo "1"; + + $iter = $menu->getIterator(); + while($iter->hasNext()) { + $curr = $iter->getNext(); + #$sz = $menu->getSize(); + #for($i=0;$i<$sz;$i++) { + # $curr = $menu->getChild($i); + + $html .= " + "; + if($sub == 0) { + $html .= ""; + } + $html .= " + + +
getImage()."' />"; + if($curr->inDev()) { + $html .= ""; + } + + $html .= $curr->getName(); + + if($curr->inDev()) { + $html .= ""; + } + $html .= " "; + + if($sub == 0) { + $html .= " "; + } + + $html .= "   
"; + if($sub == 0) { + $html .= ""; + } + + $html .= ""; + + if(!$curr->isEmpty()) { + $html .= "
".ach_render_mnode($curr,($sub+4))."
"; + } + } + + return $html; + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/include/adm_render_stats.php b/code/web/app/app_achievements_admin/include/adm_render_stats.php new file mode 100644 index 000000000..758c477c6 --- /dev/null +++ b/code/web/app/app_achievements_admin/include/adm_render_stats.php @@ -0,0 +1,24 @@ +sqlQuery("SELECT SUM(sp_money) as all_money, AVG(sp_money) as avg_money, COUNT(*) as playercount FROM app_achievements.stat_players as s, webig.players as p, ring_live.characters as c, nel.user as n WHERE s.sp_char = p.id AND p.cid = c.char_id AND c.user_id = n.uid AND n.privilege=''"); + + $html .= "Total characters: ".nf($res[0]['playercount'])."

"; + + #$res = $DBc->sqlQuery("SELECT SUM(sp_money) as anz FROM stat_players"); + $html .= "Total money: ".nf($res[0]['all_money'])."

"; + + #$res = $DBc->sqlQuery("SELECT AVG(sp_money) as anz FROM stat_players"); + $html .= "Average money: ".nf($res[0]['avg_money'])."

"; + + $res = $DBc->sqlQuery("SELECT sp_money FROM app_achievements.stat_players as s, webig.players as p, ring_live.characters as c, nel.user as n WHERE s.sp_char = p.id AND p.cid = c.char_id AND c.user_id = n.uid AND n.privilege='' ORDER by sp_money ASC LIMIT ".floor($res[0]['playercount']/2).",1"); + $html .= "Mean money: ".nf($res[0]['sp_money'])."

"; + + + + return $html; + } +?> \ No newline at end of file diff --git a/code/web/app/app_achievements_admin/index.php b/code/web/app/app_achievements_admin/index.php new file mode 100644 index 000000000..b7c677ff7 --- /dev/null +++ b/code/web/app/app_achievements_admin/index.php @@ -0,0 +1,755 @@ +isIG()) { + die("IG disabled for admin tool!"); +} + +require_once("class/mySQL_class.php"); + +require_once($_CONF['app_achievements_path']."include/ach_render_common.php"); + +require_once($_CONF['app_achievements_path']."class/DLL_class.php"); +require_once($_CONF['app_achievements_path']."class/Node_abstract.php"); +require_once($_CONF['app_achievements_path']."class/AVLTree_class.php"); +require_once($_CONF['app_achievements_path']."class/Parentum_abstract.php"); +require_once($_CONF['app_achievements_path']."class/AchList_abstract.php"); +require_once($_CONF['app_achievements_path']."class/Tieable_inter.php"); +require_once($_CONF['app_achievements_path']."class/NodeIterator_class.php"); +#require_once($_CONF['app_achievements_path']."class/InDev_trait.php"); + +require_once($_CONF['app_achievements_path']."class/AchMenu_class.php"); +require_once($_CONF['app_achievements_path']."class/AchMenuNode_class.php"); +require_once($_CONF['app_achievements_path']."class/AchCategory_class.php"); +require_once($_CONF['app_achievements_path']."class/AchAchievement_class.php"); +require_once($_CONF['app_achievements_path']."class/AchTask_class.php"); +require_once($_CONF['app_achievements_path']."class/AchObjective_class.php"); +require_once($_CONF['app_achievements_path']."class/AchSummary_class.php"); + +require_once("class/ADM_inter.php"); +#require_once("class/AdmDispatcher_trait.php"); +require_once("class/AdmMenu_class.php"); +require_once("class/AdmMenuNode_class.php"); +require_once("class/AdmCategory_class.php"); +require_once("class/AdmAchievement_class.php"); +require_once("class/AdmTask_class.php"); +require_once("class/AdmObjective_class.php"); +require_once("class/AdmAtom_class.php"); + +#require_once("class/CSRDispatcher_trait.php"); +require_once("class/CSR_inter.php"); +require_once("class/CSRCategory_class.php"); +require_once("class/CSRAchievement_class.php"); +require_once("class/CSRTask_class.php"); +require_once("class/CSRObjective_class.php"); +require_once("class/CSRAtom_class.php"); + +$DBc = ryDB::getInstance("app_achievements"); + +function mkn($x) { // make NULL function for SQL + global $DBc; + if($x == null || strtolower($x) == "null" || $x == "") { + return "NULL"; + } + else { + return "'".$DBc->sqlEscape($x)."'"; + } +} + + +$c = " + + + +

+ + + + +
"; + + if($_ADMIN->isAdmin()) { + $c .= "Admin
+

"; + } + if($_ADMIN->isCSR()) { + $c .= "CSR
+

"; + } + + + +$c .= "

"; + + /*if($_REQUEST['mode'] == "insert_fame" && $_ADMIN->isAdmin()) { + $ftpl = 'ENTITY fame AS $fame { + if($fame->faction == ".faction" && ceil($fame->fame/6000) >= [0]) { + GRANT; + FINAL ENTITY; + } +}'; + + $res = $DBc->sqlQuery("SELECT at_id,atl_name FROM ach_achievement,ach_task,ach_task_lang WHERE at_achievement=aa_id AND ((aa_category<'24' AND aa_category>'15') OR aa_category='56') AND atl_task=at_id AND atl_lang='en'"); + + for($i=0;$isqlQuery("INSERT INTO ach_objective (ao_task,ao_condition,ao_value,ao_display,ao_metalink) VALUES ('".$res[$i]['at_id']."','all',NULL,'hidden',NULL)"); + $nid = $DBc->insertID(); + $DBc->sqlQuery("INSERT INTO ach_atom (atom_objective,atom_mandatory,atom_ruleset) VALUES ('".$nid."','0','".$DBc->sqlEscape(str_replace('[0]',$res[$i]['atl_name'],$ftpl))."')"); + + $c .= "INSERT INTO ach_objective (ao_task,ao_condition,ao_value,ao_display,ao_metalink) VALUES ('".$res[$i]['at_id']."','all',NULL,'hidden',NULL)
"; + + $c .= "INSERT INTO ach_atom (atom_objective,atom_mandatory,atom_ruleset) VALUES ('".$nid."','0','".$DBc->sqlEscape(str_replace('[0]',$res[$i]['atl_name'],$ftpl))."')

"; + } + } + + if($_REQUEST['mode'] == "enable_fame" && $_ADMIN->isAdmin()) { + $res = $DBc->sqlQuery("SELECT aa_id FROM ach_achievement WHERE (aa_category<'24' AND aa_category>'14') OR aa_category='56'"); + + for($i=0;$isqlQuery("UPDATE ach_achievement SET aa_dev='0' WHERE aa_id='".$res[$i]['aa_id']."'"); + + $DBc->sqlQuery("UPDATE ach_task SET at_dev='0' WHERE at_achievement='".$res[$i]['aa_id']."'"); + } + }*/ + + /* + * translation + */ + if($_REQUEST['mode'] == "lang" && $_ADMIN->isAdmin()) { + $c .= "

Language Editor

"; + + $user = array(); + $user['id'] = 0; + $user['lang'] = 'en'; + $user['name'] = 'Talvela'; + $user['race'] = "matis"; + $user['civ'] = "neutral"; + $user['cult'] = "neutral"; + + $_USER = new RyzomUser($user); + + //menu + require_once("include/adm_render_lang.php"); + $menu = new AdmMenu($_REQUEST['cat']); + + $c .= "
+ + + + +
"; + + + $c .= adm_render_menu($menu); + + $c .= "
"; + + $open = $menu->getOpenCat(); + + if($open != 0) { + $cat = new AdmCategory($open,'%','%','%'); + + if($_REQUEST['act'] == "cat_save") { + if(is_array($_REQUEST['c_name'])) { + foreach($_REQUEST['c_name'] as $key=>$elem) { + $cat->setLang($key,$_REQUEST['c_name'][$key]); + } + } + } + + if($_REQUEST['act'] == "ach_save") { + $ach = $cat->getElementByPath($_REQUEST['id']); + + if(is_array($_REQUEST['a_name'])) { + foreach($_REQUEST['a_name'] as $key=>$elem) { + $ach->setLang($key,$_REQUEST['a_name'][$key],$_REQUEST['a_tpl'][$key]); + } + } + } + + if($_REQUEST['act'] == "task_save") { + $task = $cat->getElementByPath($_REQUEST['id']); + + if(is_array($_REQUEST['t_name'])) { + foreach($_REQUEST['t_name'] as $key=>$elem) { + $task->setLang($key,$_REQUEST['t_name'][$key],$_REQUEST['t_tpl'][$key]); + } + } + } + + if($_REQUEST['act'] == "obj_save") { + $obj = $cat->getElementByPath($_REQUEST['id']); + + if(is_array($_REQUEST['o_name'])) { + foreach($_REQUEST['o_name'] as $key=>$elem) { + $obj->setLang($key,$_REQUEST['o_name'][$key]); + } + } + } + + + + $c .= atom_render_category($cat); + } + + + $c .= "
"; + + } + + /* + * Trigger settings + */ + + if($_REQUEST['mode'] == "atom" && $_ADMIN->isAdmin()) { + $c .= "

Trigger Settings

"; + + $user = array(); + $user['id'] = 0; + $user['lang'] = 'en'; + $user['name'] = 'Talvela'; + $user['race'] = "matis"; + $user['civ'] = "neutral"; + $user['cult'] = "neutral"; + + $_USER = new RyzomUser($user); + + //menu + require_once("include/adm_render_atom.php"); + $menu = new AdmMenu($_REQUEST['cat']); + + $c .= "
+ + + + +
"; + + + $c .= adm_render_menu($menu); + + $c .= "
"; + + $open = $menu->getOpenCat(); + + if($open != 0) { + $cat = new AdmCategory($open,'%','%','%'); + + if($_REQUEST['act'] == "insert_atom") { + $obj = $cat->getElementByPath($_REQUEST['id']); + + if($obj != null) { + $atom = new AdmAtom(array(),$obj); + $atom->setRuleset($_REQUEST['atom_ruleset']); + $atom->setMandatory($_REQUEST['atom_mandatory']); + $atom->setObjective($obj->getID()); + + $obj->insertNode($atom); + } + } + + if($_REQUEST['act'] == "update_atom") { + $atom = $cat->getElementByPath($_REQUEST['id']); + + if($atom != null) { + $atom->setRuleset($_REQUEST['atom_ruleset']); + $atom->setMandatory($_REQUEST['atom_mandatory']); + + $atom->update(); + } + } + + if($_REQUEST['act'] == "delete") { + $elem = $cat->getElementByPath($_REQUEST['id']); + $par = $elem->getParent(); + $par->removeNode($elem->getID()); + } + + $c .= atom_render_category($cat); + } + + $c .= "
"; + + } + + /* + * Menu settings + */ + + if($_REQUEST['mode'] == "menu" && $_ADMIN->isAdmin()) { + $c .= "

Menu Settings

"; + + $user = array(); + $user['id'] = 1; + $user['lang'] = 'en'; + $user['name'] = 'Talvela'; + $user['race'] = "matis"; + $user['civ'] = "neutral"; + $user['cult'] = "neutral"; + + $_USER = new RyzomUser($user); + + require_once("include/adm_render_menu.php"); + $menu = new AdmMenu(false); + + if($_REQUEST['act'] == "insert") { + $n = new AdmMenuNode(array(),null); + $n->setID(null); + $n->setInDev(true); + $n->setName($_REQUEST['acl_name']); + $n->setImage($_REQUEST['ac_image']); + $n->setParentID($_REQUEST['ac_parent']); + + $menu->insertNode($n); + } + + if($_REQUEST['act'] == "delete") { + $menu->removeNode($_REQUEST['ac_id']); + } + + if($_REQUEST['act'] == "update") { + $menu->updateNode($_REQUEST['ac_id'],array("acl_name"=>$_REQUEST['acl_name'],"ac_image"=>$_REQUEST['ac_image'])); + } + + if($_REQUEST['act'] == "dev") { + $curr = $menu->getNode($_REQUEST['ac_id']); + $curr->setInDev(($_REQUEST['state'] != 1)); + } + + + $c .= adm_render_menu($menu); + } + + /* + * Achievement settings + */ + + if($_REQUEST['mode'] == "ach" && $_ADMIN->isAdmin()) { + $c .= "

Achievement Settings

"; + + $user = array(); + $user['id'] = 0; + $user['lang'] = 'en'; + $user['name'] = 'Talvela'; + $user['race'] = "matis"; + $user['civ'] = "neutral"; + $user['cult'] = "neutral"; + + $_USER = new RyzomUser($user); + + //menu + require_once("include/adm_render_ach.php"); + $menu = new AdmMenu($_REQUEST['cat']); + + $c .= "
+ + + + +
"; + + + $c .= adm_render_menu($menu); + + $c .= "
"; + + $open = $menu->getOpenCat(); + + if($open != 0) { + if($_REQUEST['cult']) { + $cult = $_REQUEST['cult']; + $_SESSION['cult'] = $cult; + } + elseif($_SESSION['cult']) { + $cult = $_SESSION['cult']; + } + else { + $cult = $_USER->getCult(); + } + + if($_REQUEST['civ']) { + $civ = $_REQUEST['civ']; + $_SESSION['civ'] = $civ; + } + elseif($_SESSION['civ']) { + $civ = $_SESSION['civ']; + } + else { + $civ = $_USER->getCiv(); + } + + echo $civ.$cult; + + $cat = new AdmCategory($open,$_USER->getRace(),$cult,$civ); + + $microstop = explode(' ',microtime()); + $stop_time = $microstop[0] + $microstop[1]; + + echo "
loading: ".round($stop_time - $start_time,3); + + $start_time = $stop_time; + + if($_REQUEST['act'] == "ach_move") { + $ach = $cat->getChildDataByID($_REQUEST['id']); + if($ach != null) { + $ach->setCategory($_REQUEST['new_cat']); + $ach->update(); + $cat->removeChild($ach->getID()); + + $iter = $cat->getOpen(); + while($iter->hasNext()) { + $item = $iter->getNext(); + + if($ach->getID() == $item->getParentID()) { + $item->setCategory($_REQUEST['new_cat']); + $item->update(); + $cat->removeChild($item->getID()); + } + } + } + } + + if($_REQUEST['act'] == "ach_insert") { + $ach = new AdmAchievement(array(),$cat); + $ach->setCategory($cat->getID()); + $ach->setName($_REQUEST['aal_name']); + $ach->setTemplate($_REQUEST['aal_template']); + $ach->setImage($_REQUEST['aa_image']); + $ach->setParentID($_REQUEST['aa_parent']); + $ach->setSticky($_REQUEST['aa_sticky']); + + $cat->insertNode($ach); + + $task = new AdmTask(array(),$ach); + $task->setAchievement($ach->getID()); + $task->setName($_REQUEST['atl_name']); + $task->setTemplate($_REQUEST['atl_template']); + $task->setValue($_REQUEST['at_value']); + $task->setCondition($_REQUEST['at_condition']); + $task->setConditionValue($_REQUEST['at_condition_value']); + $task->setHeritage(0); + + if(is_array($_REQUEST['at_tie_allegiance'])) { + $task->setTieAlign($_REQUEST['at_tie_allegiance']); + } + + $ach->insertNode($task); + } + + if($_REQUEST['act'] == "ach_update") { + $ach = $cat->getChildDataByID($_REQUEST['id']); + + if($ach != null) { + $ach->setName($_REQUEST['aal_name']); + $ach->setTemplate($_REQUEST['aal_template']); + #$ach->setTieCult($_REQUEST['aa_tie_cult']); + #$ach->setTieCiv($_REQUEST['aa_tie_civ']); + $ach->setImage($_REQUEST['aa_image']); + $ach->setParentID($_REQUEST['aa_parent']); + $ach->setSticky($_REQUEST['aa_sticky']); + + $ach->update(); + } + } + + if($_REQUEST['act'] == "task_insert") { + $ach = $cat->getChildDataByID($_REQUEST['id']); + if($ach != null) { + $task = new AdmTask(array(),$ach); + $task->setAchievement($ach->getID()); + $task->setName($_REQUEST['atl_name']); + $task->setTemplate($_REQUEST['atl_template']); + $task->setValue($_REQUEST['at_value']); + $task->setCondition($_REQUEST['at_condition']); + $task->setConditionValue($_REQUEST['at_condition_value']); + $task->setHeritage($_REQUEST['at_inherit']); + + if(is_array($_REQUEST['at_tie_allegiance'])) { + $task->setTieAlign($_REQUEST['at_tie_allegiance']); + } + + $ach->insertNode($task); + $task->setParentID($_REQUEST['at_parent']); + $ach->orderTasks(); + $task->update(); + } + } + + if($_REQUEST['act'] == "task_update") { + $task = $cat->getElementByPath($_REQUEST['id']); + + if($task != null) { + $task->setName($_REQUEST['atl_name']); + $task->setTemplate($_REQUEST['atl_template']); + $task->setValue($_REQUEST['at_value']); + $task->setCondition($_REQUEST['at_condition']); + $task->setConditionValue($_REQUEST['at_condition_value']); + $task->setHeritage($_REQUEST['at_inherit']); + + if(is_array($_REQUEST['at_tie_allegiance'])) { + $task->setTieAlign($_REQUEST['at_tie_allegiance']); + } + + $task->setParentID($_REQUEST['at_parent']); + + $ach = $task->getParent(); + $ach->orderTasks(); + + $task->update(); + } + } + + if($_REQUEST['act'] == "obj_insert") { + $task = $cat->getElementByPath($_REQUEST['id']); + + if($task != null) { + $obj = new AdmObjective(array(),$task); + $obj->setName($_REQUEST['aol_name']); + $obj->setCondition($_REQUEST['ao_condition']); + $obj->setValue($_REQUEST['ao_value']); + $obj->setDisplay($_REQUEST['ao_display']); + $obj->setMetalink($_REQUEST['ao_metalink']); + $obj->setTask($task->getID()); + + $task->insertNode($obj); + } + } + + if($_REQUEST['act'] == "obj_update") { + $obj = $cat->getElementByPath($_REQUEST['id']); + + if($obj != null) { + $obj->setName($_REQUEST['aol_name']); + $obj->setCondition($_REQUEST['ao_condition']); + $obj->setValue($_REQUEST['ao_value']); + $obj->setDisplay($_REQUEST['ao_display']); + $obj->setMetalink($_REQUEST['ao_metalink']); + + $obj->update(); + } + } + + if($_REQUEST['act'] == "delete") { + $elem = $cat->getElementByPath($_REQUEST['id']); + if($elem != null) { + $par = $elem->getParent(); + $par->removeNode($elem->getID()); + + if(get_class($elem) == "AdmAchievement") { + $iter = $cat->getOpen(); + while($iter->hasNext()) { + $item = $iter->getNext(); + + if($elem->getID() == $item->getParentID()) { + $item->setParentID(null); + $item->update(); + } + } + } + } + } + + if($_REQUEST['act'] == "dev") { + $curr = $cat->getElementByPath($_REQUEST['id']); + $curr->setInDev(($_REQUEST['state'] != 1)); + } + + $microstop = explode(' ',microtime()); + $stop_time = $microstop[0] + $microstop[1]; + + echo "
manipulation: ".round($stop_time - $start_time,3); + + $start_time = $stop_time; + + $c .= adm_render_category($cat); + + $microstop = explode(' ',microtime()); + $stop_time = $microstop[0] + $microstop[1]; + + echo "
rendering: ".round($stop_time - $start_time,3); + } + + $c .= "
"; + + } + + /* + * Statistics page + */ + + if($_REQUEST['mode'] == "stats" && $_ADMIN->isCSR()) { + require_once("include/adm_render_stats.php"); + + $c .= "

Statistics

"; + + $c .= stats_render(); + } + + /* + * CSR player manager + */ + if($_REQUEST['mode'] == "player" && $_ADMIN->isCSR()) { + $c .= "

Player Administration

"; + + #$DBc_char = new mySQL($_CONF['mysql_error']); + #$DBc_char->connect($_CONF['char_mysql_server'],$_CONF['char_mysql_user'],$_CONF['char_mysql_pass'],$_CONF['char_mysql_database']); + + $DBc_char = ryDB::getInstance("webig"); + //menu + require_once("include/adm_render_csr.php"); + + if(!is_user($_REQUEST['pid'])) { // no user ID + $c .= csr_render_find_player(); + } + else { + $user = array(); + $user['id'] = $_REQUEST['pid']; + $user['lang'] = 'en'; + $dta = user_get_data($_REQUEST['pid']); + $user['char_name'] = user_get_name($_REQUEST['pid']); + $user['race'] = substr($dta['race'],2); + $user['civ'] = substr($dta['civilisation'],2); + $user['cult'] = substr($dta['cult'],2); + + $_USER = new RyzomUser($user); + + $menu = new AchMenu($_REQUEST['cat']); + + $open = $menu->getOpenCat(); + + if($open != 0) { + if($_REQUEST['cult']) { + $cult = $_REQUEST['cult']; + $_SESSION['cult'] = $cult; + } + elseif($_SESSION['cult']) { + $cult = $_SESSION['cult']; + } + else { + $cult = $_USER->getCult(); + } + + if($_REQUEST['civ']) { + $civ = $_REQUEST['civ']; + $_SESSION['civ'] = $civ; + } + elseif($_SESSION['civ']) { + $civ = $_SESSION['civ']; + } + else { + $civ = $_USER->getCiv(); + } + + $cat = new CSRCategory($open,$_USER->getRace(),$cult,$civ); + + if($_REQUEST['grant'] != "") { + $cat->grantNode($_REQUEST['grant'],$_USER->getID()); + } + + if($_REQUEST['deny'] != "") { + $cat->denyNode($_REQUEST['deny'],$_USER->getID()); + } + } + + + $c .= "
+ + + + + + + +
".csr_render_yubopoints($user['id'])."
"; + + + $c .= csr_render_menu($menu); + + $c .= "
"; + + + if($open != 0) { + $c .= csr_render_category($cat); + } + else { + $cat = new AchSummary($menu,3); + $c .= ach_render_summary_header(); + } + + if($open == 0) { + $c .= ach_render_summary_footer($cat); + } + + $c .= "
"; + } + + } + +$c .= "
"; + +#$c = var_export($_USER).$c; + +echo ryzom_app_render("achievements admin", $c, $_ADMIN->isIG()); + +?> diff --git a/code/web/app/app_achievements_admin/lang.php b/code/web/app/app_achievements_admin/lang.php new file mode 100644 index 000000000..1c642ae62 --- /dev/null +++ b/code/web/app/app_achievements_admin/lang.php @@ -0,0 +1,84 @@ + + array ( + 'en' => 'Summary', + 'fr' => 'Résumé ', + 'de' => 'Übersicht', + 'ru' => 'Резюме', + ), + 'ach_summary_header' => + array ( + 'en' => 'Recent Achievements', + 'fr' => 'Derniers Accomplissements', + 'de' => 'Aktuelle Erfolge', + 'ru' => 'недавние достижения', + ), + 'ach_summary_stats' => + array ( + 'en' => 'Statistics', + 'fr' => 'Statistiques', + 'de' => 'Statistiken', + 'ru' => '', + ), + 'ach_summary_stats_total' => + array ( + 'en' => 'Total', + 'fr' => 'Total', + 'de' => 'Gesamt', + 'ru' => '', + ), + 'ach_c_neutral' => + array ( + 'en' => 'Neutral', + 'fr' => 'Neutre', + 'de' => 'Neutral', + 'ru' => '', + ), + 'ach_allegiance_neutral_cult' => + array ( + 'en' => 'While being of %s allegiance with the higher powers', + 'fr' => 'En ayant %s de renommée envers les Puissances', + 'de' => '', + 'ru' => '', + ), + 'ach_allegiance_neutral_civ' => + array ( + 'en' => 'While being of %s allegiance with the homin civilizations', + 'fr' => 'En ayant %s de renommée envers les nations homines', + 'de' => '', + 'ru' => '', + ), + 'ach_allegiance_neutral' => + array ( + 'en' => 'While being of %s allegiance', + 'fr' => 'En ayant %s de réputation', + 'de' => '', + 'ru' => '', + ), + 'ach_allegiance_start' => + array ( + 'en' => 'While being aligned with the ', + 'fr' => 'En appartenant à', + 'de' => '', + 'ru' => '', + ), + 'ach_allegiance_and' => + array ( + 'en' => ' and the ', + 'fr' => ' et le', + 'de' => 'und', + 'ru' => '', + ), + 'ach_allegiance_end' => + array ( + 'en' => ', accomplish the following achievements:', + 'fr' => ', effectuez les accomplissements suivants : ', + 'de' => ', erfüllen die folgenden Leistungen:', + 'ru' => '', + ), +); +if(isset($ryzom_texts)) + $ryzom_texts = array_merge ($__texts, $ryzom_texts); +else + $ryzom_texts = $__texts; diff --git a/code/web/app/app_achievements_admin/pic/b_drop.png b/code/web/app/app_achievements_admin/pic/b_drop.png new file mode 100644 index 000000000..6fc4d3b20 Binary files /dev/null and b/code/web/app/app_achievements_admin/pic/b_drop.png differ diff --git a/code/web/app/app_achievements_admin/pic/b_insrow.png b/code/web/app/app_achievements_admin/pic/b_insrow.png new file mode 100644 index 000000000..3913b4a65 Binary files /dev/null and b/code/web/app/app_achievements_admin/pic/b_insrow.png differ diff --git a/code/web/app/app_achievements_admin/pic/b_tblops.png b/code/web/app/app_achievements_admin/pic/b_tblops.png new file mode 100644 index 000000000..153b267b7 Binary files /dev/null and b/code/web/app/app_achievements_admin/pic/b_tblops.png differ diff --git a/code/web/app/app_achievements_admin/pic/green.gif b/code/web/app/app_achievements_admin/pic/green.gif new file mode 100644 index 000000000..fa6957d51 Binary files /dev/null and b/code/web/app/app_achievements_admin/pic/green.gif differ diff --git a/code/web/app/app_achievements_admin/pic/icon_edit.gif b/code/web/app/app_achievements_admin/pic/icon_edit.gif new file mode 100644 index 000000000..9036904dc Binary files /dev/null and b/code/web/app/app_achievements_admin/pic/icon_edit.gif differ diff --git a/code/web/app/app_achievements_admin/pic/red.gif b/code/web/app/app_achievements_admin/pic/red.gif new file mode 100644 index 000000000..e8f675b74 Binary files /dev/null and b/code/web/app/app_achievements_admin/pic/red.gif differ diff --git a/code/web/app/app_test/create.sql b/code/web/app/app_test/create.sql new file mode 100644 index 000000000..ca90eade0 --- /dev/null +++ b/code/web/app/app_test/create.sql @@ -0,0 +1,27 @@ +-- -------------------------------------------------------- +-- Host: 178.33.225.92 +-- Server version: 5.5.28-0ubuntu0.12.04.2-log - (Ubuntu) +-- Server OS: debian-linux-gnu +-- HeidiSQL version: 7.0.0.4053 +-- Date/time: 2013-02-12 16:31:42 +-- -------------------------------------------------------- + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET FOREIGN_KEY_CHECKS=0 */; + +-- Dumping database structure for app_test +CREATE DATABASE IF NOT EXISTS `app_test` /*!40100 DEFAULT CHARACTER SET utf8 */; +USE `app_test`; + + +-- Dumping structure for table app_test.test +CREATE TABLE IF NOT EXISTS `test` ( + `id` INT(32) NOT NULL, + `num_access` INT(10) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- Data exporting was unselected. +/*!40014 SET FOREIGN_KEY_CHECKS=1 */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; + diff --git a/code/web/create_webig.sql b/code/web/create_webig.sql new file mode 100644 index 000000000..fd49dcf9b --- /dev/null +++ b/code/web/create_webig.sql @@ -0,0 +1,40 @@ +-- -------------------------------------------------------- +-- Host: 178.33.225.92 +-- Server version: 5.5.28-0ubuntu0.12.04.2-log - (Ubuntu) +-- Server OS: debian-linux-gnu +-- HeidiSQL version: 7.0.0.4053 +-- Date/time: 2013-02-12 16:14:54 +-- -------------------------------------------------------- + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET FOREIGN_KEY_CHECKS=0 */; + +-- Dumping database structure for webig +CREATE DATABASE IF NOT EXISTS `webig` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */; +USE `webig`; + + +-- Dumping structure for table webig.players +CREATE TABLE IF NOT EXISTS `players` ( + `id` INT(32) NOT NULL AUTO_INCREMENT, + `cid` INT(32) NOT NULL DEFAULT '0', + `name` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '0', + `gender` INT(1) NOT NULL DEFAULT '0', + `creation_date` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', + `deleted` tinyint(1) NOT NULL DEFAULT '0', + `last_login` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', + `dev_shard` tinyint(4) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Dumping structure for table webig.accounts +CREATE TABLE IF NOT EXISTS `accounts` ( + `uid` INT(10) DEFAULT NULL, + `web_privs` VARCHAR(255) COLLATE utf8_bin DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- Data exporting was unselected. +/*!40014 SET FOREIGN_KEY_CHECKS=1 */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +