From 2b781bddef707ddf0e95aa81099b0384104aa5bf Mon Sep 17 00:00:00 2001 From: sfb Date: Mon, 12 Mar 2012 08:12:23 -0500 Subject: [PATCH] merge from default --- .hgignore | 2 + code/CMakeModules/FindDirectXSDK.cmake | 15 +- code/CMakeModules/nel.cmake | 106 +- code/nel/include/nel/misc/common.h | 2 + code/nel/include/nel/misc/eid_translator.h | 2 + code/nel/include/nel/misc/event_emitter.h | 2 +- code/nel/include/nel/net/transport_class.h | 3 +- .../3d/driver/direct3d/driver_direct3d.cpp | 2 +- .../3d/driver/opengl/driver_opengl_light.cpp | 2 +- .../3d/driver/opengl/driver_opengl_vertex.cpp | 2 +- .../driver/opengl/mac/cocoa_event_emitter.cpp | 20 +- code/nel/src/3d/driver/opengl/mac/glext.h | 2 + code/nel/src/3d/nelu.cpp | 3 +- code/nel/src/3d/patchdlm_context.cpp | 4 +- code/nel/src/ligo/primitive.cpp | 2 +- code/nel/src/misc/common.cpp | 26 + code/nel/src/misc/eid_translator.cpp | 11 + code/nel/src/misc/events.cpp | 2 +- code/nel/src/misc/noise_value.cpp | 13 +- code/nel/src/misc/rgba.cpp | 8 + code/nel/src/misc/win_event_emitter.cpp | 7 + code/nel/src/net/transport_class.cpp | 3 +- .../src/plugins/CMakeLists.txt | 1 + .../src/plugins/bnp_manager/CMakeLists.txt | 47 + .../bnp_manager/bnp_dirtree_dialog.cpp | 93 + .../plugins/bnp_manager/bnp_dirtree_dialog.h | 83 + .../plugins/bnp_manager/bnp_dirtree_form.ui | 58 + .../src/plugins/bnp_manager/bnp_file.cpp | 313 ++++ .../src/plugins/bnp_manager/bnp_file.h | 139 ++ .../bnp_manager/bnp_filelist_dialog.cpp | 145 ++ .../plugins/bnp_manager/bnp_filelist_dialog.h | 83 + .../bnp_manager/bnp_filelist_dialog.ui | 70 + .../bnp_manager/bnp_filesystem_model.cpp | 51 + .../bnp_manager/bnp_filesystem_model.h | 49 + .../src/plugins/bnp_manager/bnp_manager.qrc | 9 + .../bnp_manager/bnp_manager_constants.h | 37 + .../bnp_manager/bnp_manager_plugin.cpp | 89 + .../plugins/bnp_manager/bnp_manager_plugin.h | 130 ++ .../bnp_manager/bnp_manager_window.cpp | 291 ++++ .../plugins/bnp_manager/bnp_manager_window.h | 145 ++ .../plugins/bnp_manager/bnp_manager_window.ui | 50 + .../plugins/bnp_manager/bnp_proxy_model.cpp | 56 + .../src/plugins/bnp_manager/bnp_proxy_model.h | 44 + .../bnp_manager/images/ic_nel_add_item.png | Bin 0 -> 3270 bytes .../bnp_manager/images/ic_nel_bnp_make.png | Bin 0 -> 25705 bytes .../bnp_manager/images/ic_nel_delete_item.png | Bin 0 -> 1496 bytes .../bnp_manager/images/ic_nel_export.png | Bin 0 -> 27878 bytes .../bnp_manager/images/ic_nel_reset_all.png | Bin 0 -> 30281 bytes .../bnp_manager/ovqt_plugin_bnp_manager.xml | 10 + .../src/plugins/object_viewer/attrib_form.ui | 2 +- .../plugins/object_viewer/attrib_widget.cpp | 11 +- .../src/plugins/object_viewer/attrib_widget.h | 3 +- .../plugins/object_viewer/particle_editor.cpp | 3 + .../plugins/object_viewer/particle_node.cpp | 1 + .../particle_workspace_dialog.cpp | 7 +- .../object_viewer/scheme_bank_dialog.cpp | 149 +- .../object_viewer/scheme_bank_dialog.h | 57 +- .../plugins/object_viewer/scheme_bank_form.ui | 36 +- .../plugins/object_viewer/scheme_manager.cpp | 26 +- .../translation_manager/CMakeLists.txt | 26 +- .../translation_manager/editor_phrase.cpp | 100 +- .../translation_manager/editor_phrase.h | 185 +- .../translation_manager/editor_worksheet.cpp | 734 ++++---- .../translation_manager/editor_worksheet.h | 93 +- .../translation_manager/extract_bot_names.cpp | 181 +- .../translation_manager/extract_bot_names.h | 64 +- .../extract_new_sheet_names.cpp | 206 ++- .../extract_new_sheet_names.h | 29 +- .../translation_manager/ftp_selection.cpp | 373 ++-- .../translation_manager/ftp_selection.h | 57 +- .../translation_manager/source_selection.cpp | 51 +- .../translation_manager/source_selection.h | 39 +- .../translation_manager_constants.h | 47 +- .../translation_manager_editor.h | 50 +- .../translation_manager_main_window.cpp | 869 +++++----- .../translation_manager_main_window.h | 130 +- .../translation_manager_plugin.cpp | 27 +- .../translation_manager_plugin.h | 16 +- .../translation_manager_settings_page.cpp | 114 +- .../translation_manager_settings_page.h | 28 +- .../translation_manager_settings_page.ui | 308 ++-- .../zone_painter/zone_painter_model.cpp | 40 + .../plugins/zone_painter/zone_painter_model.h | 42 + .../zone_painter/zone_painter_plugin.cpp | 20 + .../zone_painter/zone_painter_plugin.h | 5 + code/nel/tools/build_gamedata/8_upload.py | 26 +- code/nel/tools/sound/CMakeLists.txt | 5 + .../sound/build_samplebank/CMakeLists.txt | 13 + .../tools/sound/build_sound/CMakeLists.txt | 13 + .../sound/build_soundbank/CMakeLists.txt | 13 + code/ryzom/client/client_default.cfg | 23 +- code/ryzom/client/client_default.cfg.in | 23 +- .../new_texture_interfaces_dxtc.tga | Bin 4194322 -> 4194322 bytes .../new_texture_interfaces_dxtc.txt | 1282 +++++++------- .../data/gamedev/interfaces_v3/commands.xml | 11 +- .../data/gamedev/interfaces_v3/config.xml | 65 +- .../gamedev/interfaces_v3/encyclopedia.xml | 2 +- .../gamedev/interfaces_v3/game_config.xml | 178 +- .../data/gamedev/interfaces_v3/guild.xml | 53 +- .../gamedev/interfaces_v3/info_player.lua | 134 +- .../gamedev/interfaces_v3/info_player.xml | 278 ++- .../gamedev/interfaces_v3/interaction.xml | 28 +- .../data/gamedev/interfaces_v3/interface.txt | 1 + .../gamedev/interfaces_v3/out_v2_select.xml | 16 +- .../gamedev/interfaces_v3/out_v2_widgets.xml | 2 +- .../data/gamedev/interfaces_v3/player.lua | 41 +- .../data/gamedev/interfaces_v3/player.xml | 14 +- .../gamedev/interfaces_v3/player_trade.xml | 58 +- .../data/gamedev/interfaces_v3/reset.xml | 6 + .../interfaces_v3/texture_interfaces_v3.tga | Bin 2117952 -> 4194322 bytes .../data/gamedev/interfaces_v3/widgets.xml | 129 +- code/ryzom/client/src/app_bundle_utils.cpp | 1 + code/ryzom/client/src/cdb_branch.cpp | 2 +- code/ryzom/client/src/cdb_branch.h | 2 +- code/ryzom/client/src/character_cl.cpp | 88 +- code/ryzom/client/src/character_cl.h | 55 +- code/ryzom/client/src/client.cpp | 15 +- code/ryzom/client/src/client_cfg.cpp | 19 +- code/ryzom/client/src/client_cfg.h | 4 + code/ryzom/client/src/client_chat_manager.cpp | 61 +- code/ryzom/client/src/commands.cpp | 39 +- code/ryzom/client/src/connection.cpp | 35 +- code/ryzom/client/src/cursor_functions.cpp | 3 + code/ryzom/client/src/entity_cl.cpp | 76 +- code/ryzom/client/src/entity_cl.h | 27 +- .../src/interface_v3/action_handler_help.cpp | 49 +- .../src/interface_v3/action_handler_help.h | 9 + .../src/interface_v3/action_handler_item.cpp | 140 +- .../src/interface_v3/action_handler_ui.cpp | 2 +- .../src/interface_v3/action_phrase_faber.cpp | 103 +- .../src/interface_v3/action_phrase_faber.h | 5 +- .../src/interface_v3/bot_chat_page_trade.cpp | 17 +- .../client/src/interface_v3/chat_filter.cpp | 2 +- .../src/interface_v3/chat_text_manager.cpp | 27 +- .../client/src/interface_v3/chat_window.cpp | 26 +- .../src/interface_v3/ctrl_base_button.h | 2 + .../client/src/interface_v3/ctrl_button.cpp | 9 +- .../client/src/interface_v3/dbctrl_sheet.cpp | 171 +- .../client/src/interface_v3/dbctrl_sheet.h | 29 +- .../interface_v3/dbgroup_list_sheet_trade.cpp | 25 +- .../client/src/interface_v3/dbview_number.cpp | 28 +- .../client/src/interface_v3/group_compas.cpp | 10 + .../client/src/interface_v3/group_html.cpp | 531 ++++-- .../client/src/interface_v3/group_html.h | 46 +- .../client/src/interface_v3/group_html_cs.cpp | 14 +- .../client/src/interface_v3/group_html_cs.h | 4 +- .../src/interface_v3/group_html_forum.cpp | 11 +- .../src/interface_v3/group_html_forum.h | 4 +- .../src/interface_v3/group_html_mail.cpp | 11 +- .../client/src/interface_v3/group_html_mail.h | 4 +- .../src/interface_v3/group_html_webig.cpp | 153 +- .../src/interface_v3/group_html_webig.h | 30 +- .../interface_v3/group_in_scene_bubble.cpp | 126 ++ .../src/interface_v3/group_in_scene_bubble.h | 3 + .../interface_v3/group_in_scene_user_info.cpp | 209 +-- .../client/src/interface_v3/group_table.cpp | 97 +- .../client/src/interface_v3/group_table.h | 11 + .../client/src/interface_v3/guild_manager.cpp | 61 +- .../client/src/interface_v3/interface_group.h | 18 +- .../src/interface_v3/interface_manager.cpp | 43 +- .../src/interface_v3/interface_manager.h | 1 + .../src/interface_v3/interface_parser.cpp | 22 +- .../src/interface_v3/inventory_manager.cpp | 80 +- .../src/interface_v3/inventory_manager.h | 17 +- .../ryzom/client/src/interface_v3/lua_ihm.cpp | 406 ++++- code/ryzom/client/src/interface_v3/lua_ihm.h | 53 +- .../src/interface_v3/people_interraction.cpp | 82 +- .../client/src/interface_v3/people_list.cpp | 30 +- .../client/src/interface_v3/player_trade.cpp | 1 + .../client/src/interface_v3/skill_manager.cpp | 2 +- .../ryzom/client/src/interface_v3/view_base.h | 4 + .../client/src/interface_v3/view_bitmap.h | 2 + .../client/src/interface_v3/view_link.cpp | 18 + .../ryzom/client/src/interface_v3/view_link.h | 3 + .../client/src/interface_v3/view_pointer.cpp | 82 +- .../client/src/interface_v3/view_pointer.h | 1 + .../client/src/interface_v3/view_renderer.cpp | 9 +- .../client/src/interface_v3/view_renderer.h | 1 + code/ryzom/client/src/libwww.cpp | 9 +- code/ryzom/client/src/libwww.h | 7 +- code/ryzom/client/src/login.cpp | 21 +- code/ryzom/client/src/main_loop.cpp | 3 + code/ryzom/client/src/net_manager.cpp | 16 +- code/ryzom/client/src/player_cl.cpp | 189 +-- .../client/src/string_manager_client.cpp | 41 +- code/ryzom/client/src/string_manager_client.h | 7 +- code/ryzom/client/src/user_entity.cpp | 47 +- code/ryzom/client/src/user_entity.h | 10 + .../common/src/game_share/bot_chat_types.h | 2 + .../game_share/deployment_configuration.cpp | 1507 +++++++++++++++++ .../src/game_share/deployment_configuration.h | 255 +++ .../common/src/game_share/entity_types.h | 2 +- .../src/game_share/generate_client_db.xslt | 4 +- .../common/src/game_share/item_infos.cpp | 2 + code/ryzom/common/src/game_share/item_infos.h | 1 + .../src/game_share/persistent_data_template.h | 12 +- code/ryzom/common/src/game_share/pvp_mode.cpp | 2 + code/ryzom/common/src/game_share/pvp_mode.h | 4 +- .../src/game_share/ryzom_mirror_properties.h | 2 +- code/ryzom/common/src/game_share/send_chat.h | 2 +- code/ryzom/server/src/CMakeLists.txt | 3 +- .../src/patchman_service/CMakeLists.txt | 20 +- .../deployment_configuration_synchroniser.cpp | 1 + .../patchman_service/log_report_module.cpp | 1 + .../pam_patchman_admin_module.cpp | 4 +- .../src/patchman_service/service_main.cpp | 7 +- .../spa_server_patch_applier.cpp | 5 +- .../spm_server_patch_manager.cpp | 2 +- .../spt_server_patch_terminal.cpp | 3 +- .../client/client_patcher/CMakeLists.txt | 6 + .../tools/patch_gen/patch_gen_common.cpp | 11 +- .../server/admin/crons/cron_harddisk.php | 2 +- code/ryzom/tools/server/admin/index.php | 42 +- .../server/admin/tool_administration.php | 290 ++-- code/ryzom/tools/server/admin/tool_graphs.php | 10 +- .../tools/server/admin/tool_guild_locator.php | 6 +- .../server/admin/tool_player_locator.php | 6 +- code/snowballs2/CMakeLists.txt | 6 +- 218 files changed, 10707 insertions(+), 3909 deletions(-) create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/CMakeLists.txt create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_form.ui create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.ui create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager.qrc create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_constants.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.ui create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_add_item.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_bnp_make.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_delete_item.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_export.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_reset_all.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.h create mode 100644 code/nel/tools/sound/build_samplebank/CMakeLists.txt create mode 100644 code/nel/tools/sound/build_sound/CMakeLists.txt create mode 100644 code/nel/tools/sound/build_soundbank/CMakeLists.txt create mode 100644 code/ryzom/common/src/game_share/deployment_configuration.cpp create mode 100644 code/ryzom/common/src/game_share/deployment_configuration.h diff --git a/.hgignore b/.hgignore index 4a0311dcc..fcc548cd0 100644 --- a/.hgignore +++ b/.hgignore @@ -144,6 +144,8 @@ external external_stlport 3rdParty .svn +thumbs.db +Thumbs.db # build code/nel/build/* diff --git a/code/CMakeModules/FindDirectXSDK.cmake b/code/CMakeModules/FindDirectXSDK.cmake index 1f832cf95..9947778db 100644 --- a/code/CMakeModules/FindDirectXSDK.cmake +++ b/code/CMakeModules/FindDirectXSDK.cmake @@ -14,17 +14,22 @@ FIND_PATH(DXSDK_DIR "Include/dxsdkver.h" PATHS "$ENV{DXSDK_DIR}" + "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)" + "C:/Program Files/Microsoft DirectX SDK (June 2010)" + "C:/Program Files (x86)/Microsoft DirectX SDK (February 2010)" + "C:/Program Files/Microsoft DirectX SDK (February 2010)" + "C:/Program Files (x86)/Microsoft DirectX SDK (November 2007)" + "C:/Program Files/Microsoft DirectX SDK (November 2007)" + "C:/Program Files (x86)/Microsoft DirectX SDK" + "C:/Program Files/Microsoft DirectX SDK" ) MACRO(FIND_DXSDK_LIBRARY MYLIBRARY MYLIBRARYNAME) FIND_LIBRARY(${MYLIBRARY} NAMES ${MYLIBRARYNAME} PATHS - "${DXSDK_LIBRARY_DIR}" - "$ENV{DXSDK_DIR}" - "$ENV{DXSDK_DIR}/Lib" - "$ENV{DXSDK_DIR}/Lib/x86" - ) + "${DXSDK_LIBRARY_DIR}" + ) ENDMACRO(FIND_DXSDK_LIBRARY MYLIBRARY MYLIBRARYNAME) IF(DXSDK_DIR) diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index 5c5efc4a9..7dd43e8b4 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -37,7 +37,9 @@ ENDMACRO(NL_TARGET_DRIVER) # Argument: ### MACRO(NL_DEFAULT_PROPS name label) - SET_TARGET_PROPERTIES(${name} PROPERTIES PROJECT_LABEL ${label}) + IF(NOT MSVC10) + SET_TARGET_PROPERTIES(${name} PROPERTIES PROJECT_LABEL ${label}) + ENDIF(NOT MSVC10) GET_TARGET_PROPERTY(type ${name} TYPE) IF(${type} STREQUAL SHARED_LIBRARY) # Set versions only if target is a shared library @@ -302,27 +304,66 @@ MACRO(NL_SETUP_BUILD) ENDIF(CMAKE_BUILD_TYPE MATCHES "Release") ENDIF(CMAKE_BUILD_TYPE MATCHES "Debug") + SET(HOST_CPU ${CMAKE_SYSTEM_PROCESSOR}) + # Determine target CPU -# IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86") - IF(NOT CMAKE_SIZEOF_VOID_P) - INCLUDE (CheckTypeSize) - CHECK_TYPE_SIZE("void*" CMAKE_SIZEOF_VOID_P) - ENDIF(NOT CMAKE_SIZEOF_VOID_P) + IF(NOT TARGET_CPU) + SET(TARGET_CPU $ENV{DEB_HOST_GNU_CPU}) + ENDIF(NOT TARGET_CPU) - # Using 32 or 64 bits libraries + # If not specified, use the same CPU as host + IF(NOT TARGET_CPU) + SET(TARGET_CPU ${CMAKE_SYSTEM_PROCESSOR}) + ENDIF(NOT TARGET_CPU) + + IF(TARGET_CPU MATCHES "amd64") + SET(TARGET_CPU "x86_64") + ELSEIF(TARGET_CPU MATCHES "i.86") + 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 target and host CPU are the same + IF("${HOST_CPU}" STREQUAL "${TARGET_CPU}") + # x86-compatible CPU + IF(HOST_CPU MATCHES "x86") + IF(NOT CMAKE_SIZEOF_VOID_P) + INCLUDE (CheckTypeSize) + CHECK_TYPE_SIZE("void*" CMAKE_SIZEOF_VOID_P) + ENDIF(NOT CMAKE_SIZEOF_VOID_P) + + # Using 32 or 64 bits libraries + IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + SET(TARGET_CPU "x86_64") + ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) + SET(TARGET_CPU "x86") + ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) + ENDIF(HOST_CPU MATCHES "x86") + # TODO: add checks for ARM and PPC + ELSE("${HOST_CPU}" STREQUAL "${TARGET_CPU}") + 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 "-DHAVE_X86_64") + ELSEIF(TARGET_CPU STREQUAL "x86") SET(TARGET_X86 1) - IF(CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(ARCH "x86_64") - SET(TARGET_X64 1) - ADD_DEFINITIONS(-DHAVE_X86_64) - ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(ARCH "x86") - ADD_DEFINITIONS(-DHAVE_X86) - ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) -# ADD_DEFINITIONS(-DHAVE_IA64) -# ENDIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86") + SET(PLATFORM_CFLAGS "-DHAVE_X86") + ENDIF(TARGET_CPU STREQUAL "x86_64") - IF(WIN32) + # Fix library paths suffixes for Debian MultiArch + IF(NOT CMAKE_LIBRARY_ARCHITECTURE) + SET(CMAKE_LIBRARY_ARCHITECTURE $ENV{DEB_HOST_MULTIARCH}) + ENDIF(NOT CMAKE_LIBRARY_ARCHITECTURE) + + IF(CMAKE_LIBRARY_ARCHITECTURE) + SET(CMAKE_LIBRARY_PATH "/lib/${CMAKE_LIBRARY_ARCHITECTURE};/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE};${CMAKE_LIBRARY_PATH}") + ENDIF(CMAKE_LIBRARY_ARCHITECTURE) + + IF(MSVC) IF(MSVC10) # /Ox is working with VC++ 2010, but custom optimizations don't exist SET(SPEED_OPTIMIZATIONS "/Ox /GF /GS-") @@ -364,8 +405,17 @@ MACRO(NL_SETUP_BUILD) SET(NL_RELEASE_CFLAGS "/MD /D NDEBUG ${SPEED_OPTIMIZATIONS}") SET(NL_DEBUG_LINKFLAGS "/NODEFAULTLIB:msvcrt /INCREMENTAL:YES") SET(NL_RELEASE_LINKFLAGS "/OPT:REF /OPT:ICF /INCREMENTAL:NO") - ELSE(WIN32) - SET(PLATFORM_CFLAGS "-g -pipe -ftemplate-depth-48 -D_REENTRANT -Wall -ansi -W -Wpointer-arith -Wsign-compare -Wno-deprecated-declarations -Wno-multichar -Wno-unused -fno-strict-aliasing") + ELSE(MSVC) + IF(HOST_CPU STREQUAL "x86_64" AND TARGET_CPU STREQUAL "x86") + SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -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") + ENDIF(HOST_CPU STREQUAL "x86" AND TARGET_CPU STREQUAL "x86_64") + + SET(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -g -D_REENTRANT -pipe -ftemplate-depth-48 -Wall -ansi -W -Wpointer-arith -Wsign-compare -Wno-deprecated-declarations -Wno-multichar -Wno-unused -fno-strict-aliasing") + IF(WITH_COVERAGE) SET(PLATFORM_CFLAGS "-fprofile-arcs -ftest-coverage ${PLATFORM_CFLAGS}") ENDIF(WITH_COVERAGE) @@ -382,12 +432,12 @@ MACRO(NL_SETUP_BUILD) SET(PLATFORM_CXXFLAGS ${PLATFORM_CFLAGS}) IF(NOT APPLE) - SET(PLATFORM_LINKFLAGS "-Wl,--no-undefined -Wl,--as-needed") + SET(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,--no-undefined -Wl,--as-needed") ENDIF(NOT APPLE) SET(NL_DEBUG_CFLAGS "-DNL_DEBUG -D_DEBUG") SET(NL_RELEASE_CFLAGS "-DNL_RELEASE -DNDEBUG -O6") - ENDIF(WIN32) + ENDIF(MSVC) ENDMACRO(NL_SETUP_BUILD) MACRO(NL_SETUP_BUILD_FLAGS) @@ -451,7 +501,11 @@ MACRO(NL_SETUP_PREFIX_PATHS) IF(WIN32) SET(NL_LIB_PREFIX "../lib" CACHE PATH "Installation path for libraries.") ELSE(WIN32) - SET(NL_LIB_PREFIX "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation path for libraries.") + 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) ENDIF(NOT NL_LIB_PREFIX) @@ -460,7 +514,11 @@ MACRO(NL_SETUP_PREFIX_PATHS) IF(WIN32) SET(NL_DRIVER_PREFIX "../lib" CACHE PATH "Installation path for drivers.") ELSE(WIN32) - SET(NL_DRIVER_PREFIX "${CMAKE_INSTALL_PREFIX}/lib/nel" CACHE PATH "Installation path for drivers.") + 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) ENDIF(WIN32) ENDIF(NOT NL_DRIVER_PREFIX) diff --git a/code/nel/include/nel/misc/common.h b/code/nel/include/nel/misc/common.h index 42bf56d3b..fa9272386 100644 --- a/code/nel/include/nel/misc/common.h +++ b/code/nel/include/nel/misc/common.h @@ -342,6 +342,8 @@ std::string secondsToHumanReadable (uint32 time); /// Get a bytes or time in string format and convert it in seconds or bytes uint32 fromHumanReadable (const std::string &str); +/// Add digit grouping seperator to if value >= 10 000. Assumes input is numerical string. +std::string formatThousands(const std::string& s); /// This function executes a program in the background and returns instantly (used for example to launch services in AES). /// The program will be launched in the current directory diff --git a/code/nel/include/nel/misc/eid_translator.h b/code/nel/include/nel/misc/eid_translator.h index 695f7724e..9937b72fd 100644 --- a/code/nel/include/nel/misc/eid_translator.h +++ b/code/nel/include/nel/misc/eid_translator.h @@ -146,6 +146,8 @@ public: TAdditionalInfoCb EntityInfoCallback; + static void removeShardFromName(ucstring& name); + private: // get all eid for a user using the user name or the user id void getByUser (uint32 uid, std::vector &res); diff --git a/code/nel/include/nel/misc/event_emitter.h b/code/nel/include/nel/misc/event_emitter.h index e678c2674..5c547d07f 100644 --- a/code/nel/include/nel/misc/event_emitter.h +++ b/code/nel/include/nel/misc/event_emitter.h @@ -49,7 +49,7 @@ public: * \param server */ virtual void submitEvents(CEventServer & server, bool allWindows) = 0; - + /** * Instruct the event emitter to send CGDMouseMove instead of CEventMouseMove. * diff --git a/code/nel/include/nel/net/transport_class.h b/code/nel/include/nel/net/transport_class.h index 11161d7cd..2517da64b 100644 --- a/code/nel/include/nel/net/transport_class.h +++ b/code/nel/include/nel/net/transport_class.h @@ -75,7 +75,7 @@ public: enum TProp { PropUInt8, PropUInt16, PropUInt32, PropUInt64, PropSInt8, PropSInt16, PropSInt32, PropSInt64, - PropBool, PropFloat, PropDouble, PropString, PropDataSetRow, PropSheetId, PropUKN }; + PropBool, PropFloat, PropDouble, PropString, PropDataSetRow, PropSheetId, PropUCString, PropUKN }; // PropBool, PropFloat, PropDouble, PropString, PropDataSetRow, PropEntityId, PropSheetId, PropUKN }; @@ -160,6 +160,7 @@ public: case PropString: nlassert(sizeof(T) == sizeof (std::string)); break; // case PropEntityId: nlassert(sizeof(T) == sizeof (NLMISC::CEntityId)); break; case PropSheetId: nlassert(sizeof(T) == sizeof (NLMISC::CSheetId)); break; + case PropUCString: nlassert(sizeof(T) == sizeof (ucstring)); break; default: nlerror ("property %s have unknown type %d", name.c_str(), type); } diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp index 5ac1d2906..bfbd3fdb7 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp @@ -1228,7 +1228,7 @@ bool CDriverD3D::init (uint windowIcon, emptyProc exitFunc) ExitFunc = exitFunc; createCursors(); - + // Register a window class WNDCLASSW wc; diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_light.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_light.cpp index e5c3cff6e..2fc25f94a 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_light.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_light.cpp @@ -138,7 +138,7 @@ void CDriverGL::setLightInternal(uint8 num, const CLight& light) } else { - // Deactivate spot properties + // Disable spot properties #ifdef USE_OPENGLES glLightf (lightNum, GL_SPOT_CUTOFF, 180.f); glLightf (lightNum, GL_SPOT_EXPONENT, 0.f); diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_vertex.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_vertex.cpp index 502c971f1..7241d499b 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_vertex.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_vertex.cpp @@ -978,7 +978,7 @@ void CDriverGL::setupGlArraysStd(CVertexBufferInfo &vb) // Check type nlassert (vb.Type[CVertexBuffer::Normal]==CVertexBuffer::Float3); _DriverGLStates.enableNormalArray(true); - nglArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::Normal]); + nglArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::Normal]); } else { diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp index 95c713021..15bb40d28 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.cpp @@ -149,14 +149,28 @@ static NLMISC::TKey virtualKeycodeToNelKey(unsigned short keycode) bool CCocoaEventEmitter::pasteTextFromClipboard(ucstring &text) { -#warning "OpenGL Driver: Missing Mac Implementation for pasteTextFromClipboard" + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; + NSDictionary *options = [NSDictionary dictionary]; + + BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; + if (ok) + { + NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options]; + NSString *nstext = [objectsToPaste objectAtIndex:0]; + text.fromUtf8([nstext UTF8String]); + return true; + } return false; } bool CCocoaEventEmitter::copyTextToClipboard(const ucstring &text) { -#warning "OpenGL Driver: Missing Mac Implementation for copyTextToClipboard" - return false; + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard clearContents]; + NSArray *copiedObjects = [NSArray arrayWithObject:[NSString stringWithUTF8String:text.toUtf8().c_str()]]; + [pasteboard writeObjects:copiedObjects]; + return true; } /// convert modifier key state to nel internal modifier key state diff --git a/code/nel/src/3d/driver/opengl/mac/glext.h b/code/nel/src/3d/driver/opengl/mac/glext.h index 7d222aa19..6bcd8c238 100644 --- a/code/nel/src/3d/driver/opengl/mac/glext.h +++ b/code/nel/src/3d/driver/opengl/mac/glext.h @@ -4851,8 +4851,10 @@ typedef ptrdiff_t GLsizeiptrARB; #ifndef GL_ARB_shader_objects /* GL types for program/shader text and shader object handles */ typedef char GLcharARB; +#if !defined(MAC_OS_X_VERSION_10_7) typedef unsigned int GLhandleARB; #endif +#endif /* GL type for "half" precision (s10e5) float data in host memory */ #ifndef GL_ARB_half_float_pixel diff --git a/code/nel/src/3d/nelu.cpp b/code/nel/src/3d/nelu.cpp index 80ef89ec4..3d143bce1 100644 --- a/code/nel/src/3d/nelu.cpp +++ b/code/nel/src/3d/nelu.cpp @@ -58,7 +58,7 @@ bool CNELU::initDriver (uint w, uint h, uint bpp, bool windowed, nlWindow syst CNELU::Driver = NULL; // Init driver. -#if defined(NL_OS_WINDOWS) +#ifdef NL_OS_WINDOWS if (direct3d) { CNELU::Driver= CDRU::createD3DDriver(); @@ -75,6 +75,7 @@ bool CNELU::initDriver (uint w, uint h, uint bpp, bool windowed, nlWindow syst nlwarning ("CNELU::initDriver: no driver found"); return false; } + if (!CNELU::Driver->init()) { nlwarning ("CNELU::initDriver: init() failed"); diff --git a/code/nel/src/3d/patchdlm_context.cpp b/code/nel/src/3d/patchdlm_context.cpp index f5a5b578d..e50f1befe 100644 --- a/code/nel/src/3d/patchdlm_context.cpp +++ b/code/nel/src/3d/patchdlm_context.cpp @@ -1018,8 +1018,8 @@ void CPatchDLMContext::computeTextureFar() // compute src pixel const CRGBA *srcPixel= pTile->getPixels(CTileFarBank::diffuse, CTileFarBank::order1); // compute src info, for this tile rot and 256x256 context. - sint srcDeltaX; - sint srcDeltaY; + sint srcDeltaX = 0; + sint srcDeltaY = 0; srcPixel= computeTileFarSrcDeltas(nRot, is256x256, uvOff, srcPixel, srcDeltaX, srcDeltaY); // compute dst coordinate. start writing at pixel (1,1) diff --git a/code/nel/src/ligo/primitive.cpp b/code/nel/src/ligo/primitive.cpp index ff8c71c18..62c4ab9d6 100644 --- a/code/nel/src/ligo/primitive.cpp +++ b/code/nel/src/ligo/primitive.cpp @@ -2118,7 +2118,7 @@ bool CPrimAlias::read (xmlNodePtr xmlNode, const char *filename, uint version, C xmlNodePtr ptNode = CIXml::getFirstChildNode (xmlNode, "ALIAS"); if (ptNode) { - int val; + sint val = 0; if (ReadInt ("VALUE", val, filename, ptNode)) { _Alias = uint32(val); diff --git a/code/nel/src/misc/common.cpp b/code/nel/src/misc/common.cpp index fb9a9c6f5..19be95367 100644 --- a/code/nel/src/misc/common.cpp +++ b/code/nel/src/misc/common.cpp @@ -30,6 +30,7 @@ #include "nel/misc/command.h" #include "nel/misc/path.h" +#include "nel/misc/i18n.h" using namespace std; @@ -526,6 +527,31 @@ void toUpper(char *str) } } +std::string formatThousands(const std::string& s) +{ + int i, k; + int remaining = s.length() - 1; + static std::string separator = NLMISC::CI18N::get("uiThousandsSeparator").toUtf8(); + + // Don't add separator if the number is < 10k + if (remaining < 4) return s; + + std::string ns; + + do + { + for (i = remaining, k = 0; i >= 0 && k < 3; --i, ++k ) + { + ns = s[i] + ns; // New char is added to front of ns + if ( i > 0 && k == 2) ns = separator + ns; // j > 0 means still more digits + } + + remaining -= 3; + } + while (remaining >= 0); + + return ns; +} // // Exceptions diff --git a/code/nel/src/misc/eid_translator.cpp b/code/nel/src/misc/eid_translator.cpp index 36ea84247..e254831c4 100644 --- a/code/nel/src/misc/eid_translator.cpp +++ b/code/nel/src/misc/eid_translator.cpp @@ -417,6 +417,17 @@ void CEntityIdTranslator::checkEntity (const CEntityId &eid, const ucstring &ent } } +void CEntityIdTranslator::removeShardFromName(ucstring& name) +{ + // The string must contain a '(' and a ')' + ucstring::size_type p0= name.find('('); + ucstring::size_type p1= name.find(')'); + if (p0 == ucstring::npos || p1 == ucstring::npos || p1 <= p0) + return; + + name = name.substr(0, p0) + name.substr(p1 + 1); +} + // this callback is call when the file is changed void cbInvalidEntityNamesFilename(const std::string &invalidEntityNamesFilename) { diff --git a/code/nel/src/misc/events.cpp b/code/nel/src/misc/events.cpp index 4d3979416..7cef02f44 100644 --- a/code/nel/src/misc/events.cpp +++ b/code/nel/src/misc/events.cpp @@ -178,7 +178,7 @@ static const CStringConversion::CPair stringTable [] = { "KeyZOOM", KeyZOOM }, { "KeyNONAME", KeyNONAME }, { "KeyPA1", KeyPA1 }, - { "KeyOEM_CLEAR", KeyOEM_CLEAR }, + { "KeyOEM_CLEAR", KeyOEM_CLEAR } }; diff --git a/code/nel/src/misc/noise_value.cpp b/code/nel/src/misc/noise_value.cpp index 89b9a8ad4..4b7cade1f 100644 --- a/code/nel/src/misc/noise_value.cpp +++ b/code/nel/src/misc/noise_value.cpp @@ -18,7 +18,7 @@ #include "nel/misc/noise_value.h" #include "nel/misc/fast_floor.h" - +#include "nel/misc/random.h" namespace NLMISC @@ -45,7 +45,8 @@ public: CRandomGrid3D() { //seed - srand(0); + CRandom Random; + Random.srand(0); // init the grid for(uint z=0; z> 5; + uint v= Random.rand() >> 5; _Texture3d[id]= v&255; } } @@ -80,9 +81,9 @@ public: // init LevelPhases. for(i=0; ipostEvent (new CEventKeyDown ((NLMISC::TKey)wParam, getKeyButton(_AltButton, _ShiftButton, _CtrlButton), true, this)); + } + // Post the message if (wParam < KeyCount) server->postEvent (new CEventKeyUp ((NLMISC::TKey)wParam, getKeyButton(_AltButton, _ShiftButton, _CtrlButton), this)); diff --git a/code/nel/src/net/transport_class.cpp b/code/nel/src/net/transport_class.cpp index a5f826728..dca866916 100644 --- a/code/nel/src/net/transport_class.cpp +++ b/code/nel/src/net/transport_class.cpp @@ -77,7 +77,7 @@ string typeToString (CTransportClass::TProp type) string conv[] = { "PropUInt8", "PropUInt16", "PropUInt32", "PropUInt64", "PropSInt8", "PropSInt16", "PropSInt32", "PropSInt64", - "PropBool", "PropFloat", "PropDouble", "PropString", "PropDataSetRow", "PropSheetId", "PropUKN" }; + "PropBool", "PropFloat", "PropDouble", "PropString", "PropDataSetRow", "PropSheetId", "PropUCString", "PropUKN" }; // "PropBool", "PropFloat", "PropDouble", "PropString", "PropDataSetRow", "PropEntityId", "PropSheetId", "PropUKN" }; if (type > CTransportClass::PropUKN) @@ -352,6 +352,7 @@ void CTransportClass::init () // nlassert (PropDataSetRow < PropUKN); DummyProp[PropDataSetRow] = new CTransportClass::CRegisteredProp; // nlassert (PropEntityId < PropUKN); DummyProp[PropEntityId] = new CTransportClass::CRegisteredProp; nlassert (PropSheetId < PropUKN); DummyProp[PropSheetId] = new CTransportClass::CRegisteredProp; + nlassert (PropUCString < PropUKN); DummyProp[PropUCString] = new CTransportClass::CRegisteredProp; // we have to know when a service comes, so add callback (put the callback before all other one because we have to send this message first) CUnifiedNetwork::getInstance()->setServiceUpCallback("*", cbTCUpService, NULL, false); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt index 51d44137a..9e4342d2f 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt @@ -8,6 +8,7 @@ ADD_SUBDIRECTORY(object_viewer) ADD_SUBDIRECTORY(georges_editor) ADD_SUBDIRECTORY(translation_manager) ADD_SUBDIRECTORY(tile_editor) +ADD_SUBDIRECTORY(bnp_manager) # Note: Temporarily disabled until development continues. #ADD_SUBDIRECTORY(zone_painter) # Ryzom Specific Plugins diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/CMakeLists.txt new file mode 100644 index 000000000..7ecfd7396 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/CMakeLists.txt @@ -0,0 +1,47 @@ +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${QT_INCLUDES}) + +FILE(GLOB SRC *.cpp *.h) +SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + +SET(OVQT_PLUG_BNP_MANAGER_HDR bnp_manager_plugin.h + bnp_manager_window.h + bnp_dirtree_dialog.h + bnp_filesystem_model.h + bnp_file.h + bnp_filelist_dialog.h + bnp_proxy_model.h + ) +SET(OVQT_PLUG_BNP_MANAGER_UIS bnp_dirtree_form.ui + bnp_filelist_dialog.ui + ) + +SET(OVQT_PLUGIN_BNP_MANAGER_RCS bnp_manager.qrc) + +SET(QT_USE_QTGUI TRUE) + +QT4_ADD_RESOURCES(OVQT_PLUGIN_BNP_MANAGER_RC_SRCS ${OVQT_PLUGIN_BNP_MANAGER_RCS}) +QT4_WRAP_CPP(OVQT_PLUG_BNP_MANAGER_MOC_SRC ${OVQT_PLUG_BNP_MANAGER_HDR}) +QT4_WRAP_UI(OVQT_PLUG_BNP_MANAGER_UI_HDRS ${OVQT_PLUG_BNP_MANAGER_UIS}) + +SOURCE_GROUP(QtResources FILES ${OVQT_PLUG_BNP_MANAGER_UIS} ${OVQT_PLUGIN_BNP_MANAGER_RCS}) +SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_PLUG_BNP_MANAGER_UI_HDRS}) +SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_BNP_MANAGER_MOC_SRC}) +SOURCE_GROUP("BNP Manager Plugin" FILES ${SRC}) +SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) + +ADD_LIBRARY(ovqt_plugin_bnp_manager MODULE ${SRC} ${OVQT_PLUG_BNP_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_BNP_MANAGER_RC_SRCS} ${OVQT_PLUG_BNP_MANAGER_UI_HDRS}) + +TARGET_LINK_LIBRARIES(ovqt_plugin_bnp_manager ovqt_plugin_core nelmisc nelgeorges ${QT_LIBRARIES}) + +NL_DEFAULT_PROPS(ovqt_plugin_bnp_manager "NeL, Tools, 3D: Object Viewer Qt Plugin: BNP Manager") +NL_ADD_RUNTIME_FLAGS(ovqt_plugin_bnp_manager) +NL_ADD_LIB_SUFFIX(ovqt_plugin_bnp_manager) + +ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) + +INSTALL(TARGETS ovqt_plugin_bnp_manager LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp new file mode 100644 index 000000000..78cc2f3cd --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp @@ -0,0 +1,93 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 . + +// Project includes +#include "bnp_dirtree_dialog.h" +#include "bnp_filesystem_model.h" +#include "bnp_proxy_model.h" + +// Qt includes +#include + +// NeL includes +#include + +namespace BNPManager +{ + +CBnpDirTreeDialog::CBnpDirTreeDialog(QString bnpPath, QWidget *parent) + : QDockWidget(parent), + m_DataPath(bnpPath) +{ + // Setup the dialog + m_ui.setupUi(this); + + // Filter settings to only display files with bnp extension. + // Could be changed to display all files and react according to the extension: + // Bnp file: opened and displayed + // all other files: added to the currently opened bnp file + QStringList filter; + //filter << tr("*.bnp"); + + // Setup the directory tree model + m_dirModel= new BNPFileSystemModel(); + m_proxyModel = new BNPSortProxyModel(); + m_dirModel->setRootPath(m_DataPath); + m_dirModel->setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::AllEntries); + m_dirModel->setNameFilters(filter); + m_dirModel->setNameFilterDisables(0); + + m_proxyModel->setSourceModel(m_dirModel); + + m_ui.dirTree->setModel(m_proxyModel); + + m_ui.dirTree->setRootIndex( m_proxyModel->mapFromSource (m_dirModel->index(m_DataPath) ) ); + m_ui.dirTree->setSortingEnabled(true); + + // Trigger if one filename is activated + // In future drag&drop should be also possible + connect(m_ui.dirTree, SIGNAL(activated(QModelIndex)), + this, SLOT(fileSelected(QModelIndex))); +} +// *************************************************************************** +CBnpDirTreeDialog::~CBnpDirTreeDialog() +{ + +} +// *************************************************************************** +void CBnpDirTreeDialog::fileSelected(QModelIndex index) +{ + QModelIndex source = m_proxyModel->mapToSource(index); + if (source.isValid() && !m_dirModel->isDir(source)) + { + // emit the according signal to BNPManagerWindow class + Q_EMIT selectedFile(m_dirModel->fileInfo(source).filePath()); + } +} +// *************************************************************************** +void CBnpDirTreeDialog::changeFile(QString file) +{ + +} +// *************************************************************************** +void CBnpDirTreeDialog::BnpPathChanged(QString path) +{ + +} +// *************************************************************************** +} + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.h new file mode 100644 index 000000000..737085185 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.h @@ -0,0 +1,83 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 BNP_DIRTREE_DIALOG_H +#define BNP_DIRTREE_DIALOG_H + +// Qt includes +#include + +// STL includes + +// NeL includes + +// Project includes +#include "ui_bnp_dirtree_form.h" + +namespace BNPManager +{ + +class BNPFileSystemModel; +class BNPSortProxyModel; + +class CBnpDirTreeDialog : public QDockWidget +{ + Q_OBJECT +public: + + /** + * Constructor + * \param path to root directory, which should be displayed + */ + CBnpDirTreeDialog(QString bnpPath, QWidget *parent = 0); + + /** + * Destructor + */ + ~CBnpDirTreeDialog(); + + /** + * Change the root path for the dir tree view + * \param data path to the new directory + */ + void BnpPathChanged(QString); + +private: + + Ui::CBnpDirTreeDialog m_ui; + + // path ro data root directory + QString m_DataPath; + + BNPFileSystemModel *m_dirModel; + + BNPSortProxyModel *m_proxyModel; + +Q_SIGNALS: + void selectedFile(const QString); + +private Q_SLOTS: + /** + * Triggered if the user activates (double klick on windows) + * a file name in the dir tree view + * \param selected ModelIndex (filename) + */ + void fileSelected(QModelIndex index); + + void changeFile(QString file); +}; +} +#endif \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_form.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_form.ui new file mode 100644 index 000000000..751c4f055 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_form.ui @@ -0,0 +1,58 @@ + + + CBnpDirTreeDialog + + + + 0 + 0 + 400 + 300 + + + + + 0 + 0 + + + + + 200 + 141 + + + + QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable + + + BNP Datapath + + + + + 50 + 0 + + + + + + + + 0 + 0 + + + + + + + + + + + + + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.cpp new file mode 100644 index 000000000..d9b2f45c1 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.cpp @@ -0,0 +1,313 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 . + +// Project includes +#include "bnp_file.h" + +// Nel includes +#include +#include +#include +#include +#include + +// Qt includes + +using namespace NLMISC; +using namespace std; + + +namespace BNPManager +{ + +PackedFile::PackedFile() +{ + m_size = 0; + m_pos = 0; +} + +NLMISC_SAFE_SINGLETON_IMPL(BNPFileHandle); + +BNPFileHandle::BNPFileHandle() +{ + m_offsetFromBeginning = 0; +} +// *************************************************************************** +BNPFileHandle::~BNPFileHandle() +{ + // Erase the list + m_packedFiles.clear(); +} +// *************************************************************************** +void BNPFileHandle::releaseInstance() +{ + if (_Instance) + { + NLMISC::INelContext::getInstance().releaseSingletonPointer("BNPFileHandle", _Instance); + delete _Instance; + _Instance = NULL; + } +} +// *************************************************************************** +bool BNPFileHandle::unpack(const string &dirName, const vector& fileList) +{ + CIFile bnp; + bnp.open(m_openedBNPFile); + + TPackedFilesList::iterator it_files = m_packedFiles.begin(); + + for (it_files; it_files != m_packedFiles.end(); it_files++) + { + // Check if the file should be unpacked or not + if (find(fileList.begin(), fileList.end(), it_files->m_name) != fileList.end()) + { + string filename = dirName + "/" + it_files->m_name; + + COFile out; + if ( out.open(filename) ) + { + bnp.seek(it_files->m_pos, IStream::begin); + uint8 *ptr = new uint8[it_files->m_size]; + bnp.serialBuffer(ptr,it_files->m_size); + out.serialBuffer(ptr,it_files->m_size); + delete [] ptr; + } + out.close(); + } + } + + bnp.close(); + return true; +} +// *************************************************************************** +// Read the header from a big file +bool BNPFileHandle::readHeader(const std::string &filePath) +{ + m_packedFiles.clear(); + + m_openedBNPFile = filePath; + + CIFile bnp; + bnp.open (filePath); + + bnp.seek(0, IStream::end); + uint32 nFileSize = bnp.getFileSize(); + bnp.seek(nFileSize-sizeof(uint32), IStream::begin); + + uint32 nOffsetFromBegining; + + bnp.serial(nOffsetFromBegining); + + if ( !bnp.seek (nOffsetFromBegining, IStream::begin) ) + { + nlwarning("Could not read offset from begining"); + bnp.close(); + return false; + } + + uint32 nNbFile; + bnp.serial(nNbFile); + + for (uint32 i = 0; i < nNbFile; ++i) + { + uint8 nStringSize; + char sName[256]; + + bnp.serial(nStringSize); + bnp.serialBuffer( (uint8*)sName, nStringSize); + sName[nStringSize] = 0; + + PackedFile tmpPackedFile; + tmpPackedFile.m_name = sName; + tmpPackedFile.m_path = m_openedBNPFile; + + bnp.serial(tmpPackedFile.m_size); + bnp.serial(tmpPackedFile.m_pos); + + m_packedFiles.push_back (tmpPackedFile); + } + + bnp.close(); + return true; +} +// *************************************************************************** +void BNPFileHandle::list(TPackedFilesList& FileList) +{ + PackedFile tmpFile; + TPackedFilesList::iterator it = m_packedFiles.begin(); + while (it != m_packedFiles.end() ) + { + tmpFile.m_name = it->m_name; + tmpFile.m_pos = it->m_pos; + tmpFile.m_size = it->m_size; + tmpFile.m_path = it->m_path; + FileList.push_back(tmpFile); + it++; + } +} +// *************************************************************************** +bool BNPFileHandle::writeHeader( const std::string &filePath, uint32 offset ) +{ + COFile bnp; + bnp.open(filePath, true); + if ( !bnp.isOpen() ) + return false; + + uint32 nNbFile = (uint32)m_packedFiles.size(); + bnp.serial(nNbFile); + + for (uint32 i = 0; i < nNbFile; ++i) + { + uint8 nStringSize = (uint8)m_packedFiles[i].m_name.size(); + bnp.serial( nStringSize ); + bnp.serialBuffer( (uint8*)m_packedFiles[i].m_name.c_str(), nStringSize ); + bnp.serial(m_packedFiles[i].m_size); + bnp.serial(m_packedFiles[i].m_pos); + } + + bnp.serial(offset); + + bnp.close(); + + return true; +} +// *************************************************************************** +void BNPFileHandle::fileNames(std::vector &fileNames) +{ + TPackedFilesList::iterator it = m_packedFiles.begin(); + while (it != m_packedFiles.end() ) + { + fileNames.push_back(it->m_name); + it++; + } +} +// *************************************************************************** +void BNPFileHandle::addFiles( const vector &filePathes) +{ + uint32 OffsetFromBegining = 0; + + // create packed files and add them to the private vector + vector::const_iterator it_vec = filePathes.begin(); + while (it_vec != filePathes.end() ) + { + PackedFile tmpFile; + tmpFile.m_name = CFile::getFilename (*it_vec); + // Leave position to 0 and set the value during the new bnp file is creating + // We need the position only for the header at the end + tmpFile.m_pos = 0; + tmpFile.m_size = CFile::getFileSize(*it_vec); + tmpFile.m_path = *it_vec; + m_packedFiles.push_back( tmpFile ); + + it_vec++; + } + + // sort packed files alphabetic + std::sort ( m_packedFiles.begin(), m_packedFiles.end(), compare ); + + // create a new temporary bnp file with extension *.tmp + TPackedFilesList::iterator it_packed = m_packedFiles.begin(); + while (it_packed != m_packedFiles.end() ) + { + append(m_openedBNPFile + ".tmp", *it_packed); + // Set now the new offset for the new header + it_packed->m_pos = OffsetFromBegining; + OffsetFromBegining += it_packed->m_size; + + it_packed++; + } + + writeHeader(m_openedBNPFile + ".tmp", OffsetFromBegining); + + CFile::deleteFile( m_openedBNPFile ); + string src = m_openedBNPFile + ".tmp"; + CFile::moveFile( m_openedBNPFile.c_str(), src.c_str() ); +} +// *************************************************************************** +void BNPFileHandle::deleteFiles( const vector& fileNames) +{ + vector::const_iterator it_vec; + TPackedFilesList::iterator it_packed; + uint32 OffsetFromBegining = 0; + string tmpFile = m_openedBNPFile + ".tmp"; + + // create a new temporary bnp file with extension *.tmp + it_packed = m_packedFiles.begin(); + while (it_packed != m_packedFiles.end() ) + { + // check each packed file if it should be deleted + it_vec = find (fileNames.begin(), fileNames.end(), it_packed->m_name ); + if ( it_vec != fileNames.end() ) + { + nlinfo("Deleting file %s.", it_packed->m_name.c_str() ); + it_packed = m_packedFiles.erase(it_packed); + } + else + { + append(tmpFile, *it_packed); + // Set now the new offset for the new header + it_packed->m_pos = OffsetFromBegining; + OffsetFromBegining += it_packed->m_size; + + it_packed++; + } + } + + writeHeader(tmpFile, OffsetFromBegining); + + CFile::deleteFile( m_openedBNPFile ); + string src = m_openedBNPFile + ".tmp"; + CFile::moveFile( m_openedBNPFile.c_str(), src.c_str() ); +} +// *************************************************************************** +void BNPFileHandle::append(const string &destination, const PackedFile &source) +{ + // check if the file exists and create one if not + if ( !CFile::fileExists(destination) ) + CFile::createEmptyFile( destination ); + + COFile bnpfile; + CIFile packedfile; + bnpfile.open(destination, true); + packedfile.open(source.m_path); + if ( !bnpfile.isOpen() ) return; + + + uint8 *ptr = new uint8[source.m_size]; + + // check if the source is a bnp file. + if ( nlstricmp( CFile::getExtension(source.m_path), "bnp" ) == 0 ) + { + // Jump to the file position inside the bnp + packedfile.seek(source.m_pos, IStream::begin); + } + // Read the source + packedfile.serialBuffer(ptr, source.m_size); + + // Append the data to the destination + bnpfile.serialBuffer(ptr, source.m_size); + + delete [] ptr; + + packedfile.close(); + bnpfile.close(); +} +// *************************************************************************** +bool BNPFileHandle::compare(const PackedFile &left, const PackedFile &right) +{ + return nlstricmp (left.m_name.c_str(), right.m_name.c_str()) < 0; +} +} // namespace BNPManager \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.h new file mode 100644 index 000000000..e03d0e664 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.h @@ -0,0 +1,139 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 BNP_FILE_H +#define BNP_FILE_H + +// Project includes + +// Nel includes +#include "nel/misc/types_nl.h" +#include + +// Qt includes +#include + + +namespace BNPManager +{ + +struct PackedFile +{ + PackedFile(); + std::string m_name; + uint32 m_size; + uint32 m_pos; + std::string m_path; +}; + +typedef std::vector TPackedFilesList; + +class BNPFileHandle +{ + NLMISC_SAFE_SINGLETON_DECL(BNPFileHandle) + + /** + * Private constructor + */ + BNPFileHandle(); + + /** + * Private destructor + */ + ~BNPFileHandle(); + +public: + // release memory + static void releaseInstance(); + + /*void append (const QString destFilename, const QString origFilename, uint32 sizeToRead); + void packRecurse();*/ + + /** + * Read the header from the bnp file and create a filelist + * \param filename (consisting the whole path) + */ + bool readHeader (const std::string &filePath); + + bool writeHeader (const std::string &filePath, uint32 offset); + + /** + * Append the header to a created bnp file + * \param filename (consisting the whole path) + */ + void appendHeader (const std::string &filename) {}; + + /** + * Create a vector of all packed files inside the bnp file + * \param reference to the vector, which has to be filled + */ + void list (TPackedFilesList& FileList); + + /** + * Create a vector of all file names inside the bnp file + * \param reference to the vector, which has to be filled + */ + void fileNames( std::vector& fileNames ); + + /** + * Add files to the current aktive bnp file + * \param vector of file pathes to add + */ + void addFiles( const std::vector& filePathes ); + + /** + * Delete files from the current aktive bnp file + * \param vector of files names + */ + void deleteFiles (const std::vector& fileNames); + + /** + * Unpack the selected packed files into user defined dir + * \param directory path, where the files should be unpacked + * \param list of files, which has to be unpacked + */ + bool unpack (const std::string &dirName, const std::vector& fileList); + + /** + * Compares two filenames + * \param left: left packed file + * \param right: right packed file + * \return: TODO + */ + static bool compare(const PackedFile &left, const PackedFile &right); + +private: + + /** + * Append one file to an existing bnp file + * \param destination: the active bnp file to append the file + * \param source: the source file to pack + */ + void append( const std::string& destination, const PackedFile& source ); + + TPackedFilesList m_packedFiles; + + // currently opened and displayed bnp file + std::string m_openedBNPFile; + + // offset where the header of the bnp file begins + uint32 m_offsetFromBeginning; + +}; + +} + +#endif \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.cpp new file mode 100644 index 000000000..418d7fa04 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.cpp @@ -0,0 +1,145 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 . + +// Project includes +#include "bnp_filelist_dialog.h" +#include "bnp_file.h" + +// Qt includes +#include +#include +#include +#include +#include + +// NeL includes +#include + +using namespace std; + +namespace BNPManager +{ + +BnpFileListDialog::BnpFileListDialog(QString bnpPath, QWidget *parent) + : QDockWidget(parent), + m_DataPath(bnpPath) +{ + m_ui.setupUi(this); + setAcceptDrops(true); +} +// *************************************************************************** +BnpFileListDialog::~BnpFileListDialog() +{ + +} +// *************************************************************************** +void BnpFileListDialog::setupTable(int nbrows) +{ + // delete all old entries + m_ui.tableWidget->clear(); + + // set 2 colums: filename and size + m_ui.tableWidget->setColumnCount(2); + + // set number of rows according to the number of files in the bnp file + m_ui.tableWidget->setRowCount(nbrows); + + // only entire rows can be selected + m_ui.tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + + // set the horizontal headers + QStringList labels; + labels << tr("Filename") << tr("Size"); + m_ui.tableWidget->setHorizontalHeaderLabels(labels); + + m_ui.tableWidget->horizontalHeader()->setResizeMode(0, QHeaderView::Interactive); + m_ui.tableWidget->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch ); + m_ui.tableWidget->verticalHeader()->hide(); + + // set vertical size a little bit smaller + m_ui.tableWidget->verticalHeader()->setDefaultSectionSize(15); + m_ui.tableWidget->setShowGrid(false); + m_ui.tableWidget->setObjectName("tablewidget"); +} +// *************************************************************************** +bool BnpFileListDialog::loadTable(const QString filePath) +{ + // reference to the BNPFileHandle singletone instance + BNPFileHandle& myBNPFileHandle = BNPFileHandle::getInstance(); + // string vector of all packed files inside a bnp + TPackedFilesList filelist; + int row = 0; + + // read the header from the bnp file + if (!myBNPFileHandle.readHeader( filePath.toStdString()) ) + { + return false; + } + myBNPFileHandle.list( filelist ); + + // create table with number of rows + setupTable(filelist.size()); + + // fill the table items + TPackedFilesList::iterator it = filelist.begin(); + while (it != filelist.end() ) + { + QTableWidgetItem *nameItem = new QTableWidgetItem (it->m_name.c_str() ); + QTableWidgetItem *sizeItem = new QTableWidgetItem (tr("%1 KB").arg(it->m_size)); + m_ui.tableWidget->setItem(row, 0, nameItem); + m_ui.tableWidget->setItem(row, 1, sizeItem); + it++; + row++; + } + + // Set the file path as the widgets title + setWindowTitle(filePath); + + return true; +} +// *************************************************************************** +void BnpFileListDialog::getSelections(TSelectionList& SelectionList) +{ + QModelIndex index; + QAbstractItemModel *model = m_ui.tableWidget->model(); + QItemSelectionModel *selection = m_ui.tableWidget->selectionModel(); + QModelIndexList indexes = selection->selectedRows(); + + Q_FOREACH(index, indexes) + { + QVariant data = model->data(index); + QString filename = data.toString(); + SelectionList.push_back( filename.toStdString() ); + } +} +// *************************************************************************** +void BnpFileListDialog::dragEnterEvent(QDragEnterEvent *event) +{ + // Accept only one file + // In the future a tabbed FileListDialog would accept more + if ( event->mimeData()->hasUrls() && event->mimeData()->urls().count() == 1) + event->acceptProposedAction(); +} +// *************************************************************************** +void BnpFileListDialog::dropEvent(QDropEvent *event) + { + // Excraft the local file url from the drop object and fill the table + const QMimeData *mimeData = event->mimeData(); + QList urlList = mimeData->urls(); + loadTable( urlList.first().toLocalFile() ); + } + +} // namespace BNPManager \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.h new file mode 100644 index 000000000..5b5491d8f --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.h @@ -0,0 +1,83 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 BNP_FILELIST_DIALOG_H +#define BNP_FILELIST_DIALOG_H + +// Qt includes +#include + +// STL includes +#include +#include + +// NeL includes + +// Project includes +#include "ui_bnp_filelist_dialog.h" + +namespace BNPManager +{ + +typedef std::vector TSelectionList; + +class BnpFileListDialog : public QDockWidget +{ + Q_OBJECT + +public: + + // Constructor + BnpFileListDialog(QString bnpPath, QWidget *parent = 0); + + // Destructor + ~BnpFileListDialog(); + + /** + * Load the bnp file and setup the table view + * \param Filename + * \return true if everything went well + */ + bool loadTable(const QString filePath); + + /** + * Set the dimension of the table + * \param number of rows + */ + void setupTable(int nbrows); + + /** + * Fill the files selected in the table view to + * unpack them. + * \param reference to a vector of filenames. + * \return true if everything went well + */ + void getSelections(TSelectionList& SelectionList); + +protected: + void dragEnterEvent (QDragEnterEvent *event); + void dropEvent(QDropEvent *event); +private: + Ui::BnpFileListDialog m_ui; + + // common data path as root folder for the dirtree view + QString m_DataPath; + +}; + +} + +#endif diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.ui new file mode 100644 index 000000000..9f62ff7c0 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.ui @@ -0,0 +1,70 @@ + + + BnpFileListDialog + + + + 0 + 0 + 400 + 300 + + + + + 0 + 0 + + + + + 200 + 141 + + + + true + + + QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable + + + BNP File List + + + + + 50 + 0 + + + + + + + true + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SelectRows + + + false + + + 15 + + + + + + + + + + + + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.cpp new file mode 100644 index 000000000..75ef031ff --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.cpp @@ -0,0 +1,51 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 + +#include "bnp_filesystem_model.h" + +#include +#include + +namespace BNPManager +{ + +BNPFileSystemModel::BNPFileSystemModel(QObject *parent) + : QFileSystemModel(parent) +{ +} +// *************************************************************************** +BNPFileSystemModel::~BNPFileSystemModel() +{ + +} +// *************************************************************************** +int BNPFileSystemModel::columnCount(const QModelIndex &) const +{ + return 1; +} +// *************************************************************************** +QVariant BNPFileSystemModel::data(const QModelIndex& index, int role) const +{ + + if (role == Qt::DecorationRole) + { + if (isDir(index)) + return QApplication::style()->standardIcon(QStyle::SP_DirIcon); + } + return QFileSystemModel::data(index, role); +} +// *************************************************************************** +} // namespace BNPManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.h new file mode 100644 index 000000000..2ca086b39 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.h @@ -0,0 +1,49 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 BNP_FILESYSTEM_MODEL_H +#define BNP_FILESYSTEM_MODEL_H + +#include + +namespace BNPManager +{ + +class BNPFileSystemModel : public QFileSystemModel +{ + Q_OBJECT + +public: + + /** + * Constructor + */ + BNPFileSystemModel(QObject *parent = 0); + + /** + * Destructor + */ + ~BNPFileSystemModel(); + + int columnCount(const QModelIndex &) const; + + QVariant data(const QModelIndex& index, int role) const ; + +}; + +} + +#endif \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager.qrc b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager.qrc new file mode 100644 index 000000000..bf32595d6 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager.qrc @@ -0,0 +1,9 @@ + + + images/ic_nel_bnp_make.png + images/ic_nel_delete_item.png + images/ic_nel_add_item.png + images/ic_nel_export.png + images/ic_nel_reset_all.png + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_constants.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_constants.h new file mode 100644 index 000000000..7ec5eecd0 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_constants.h @@ -0,0 +1,37 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 BNP_MANAGER_CONSTANTS_H +#define BNP_MANAGER_CONSTANTS_H + +namespace BNPManager +{ +namespace Constants +{ +//settings +const char * const BNP_MANAGER_SECTION = "BNPManager"; + +//resources +const char *const ICON_ADD = ":/images/ic_nel_add_item.png"; +const char *const ICON_DELETE = ":/images/ic_nel_delete_item.png"; +const char *const ICON_UNPACK = ":/images/ic_nel_export.png"; +const char *const ICON_CLOSE = ":/images/ic_nel_reset_all.png"; + + +} // namespace Constants +} // namespace Plugin + +#endif diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.cpp new file mode 100644 index 000000000..70015773b --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.cpp @@ -0,0 +1,89 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 . + +// Project includes +#include "bnp_manager_plugin.h" +#include "bnp_manager_window.h" + +#include "../core/icore.h" +#include "../core/core_constants.h" +#include "../core/menu_manager.h" + +// NeL includes +#include "nel/misc/debug.h" + +// Qt includes +#include +#include + +namespace BNPManager +{ + + BNPManagerPlugin::BNPManagerPlugin() + { + } + + BNPManagerPlugin::~BNPManagerPlugin() + { + Q_FOREACH(QObject *obj, m_autoReleaseObjects) + { + m_plugMan->removeObject(obj); + } + qDeleteAll(m_autoReleaseObjects); + m_autoReleaseObjects.clear(); + } + +bool BNPManagerPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) +{ + Q_UNUSED(errorString); + m_plugMan = pluginManager; + + addAutoReleasedObject(new BNPManagerContext(this)); + return true; +} + +void BNPManagerPlugin::extensionsInitialized() +{ +} + +void BNPManagerPlugin::shutdown() +{ + +} + +void BNPManagerPlugin::setNelContext(NLMISC::INelContext *nelContext) +{ +#ifdef NL_OS_WINDOWS + // Ensure that a context doesn't exist yet. + // This only applies to platforms without PIC, e.g. Windows. + nlassert(!NLMISC::INelContext::isContextInitialised()); +#endif // NL_OS_WINDOWS + m_libContext = new NLMISC::CLibraryContext(*nelContext); +} + +void BNPManagerPlugin::addAutoReleasedObject(QObject *obj) +{ + m_plugMan->addObject(obj); + m_autoReleaseObjects.prepend(obj); +} + +/*void BNPManagerContext::open() +{ + m_BnpManagerWindow->open(); +}*/ +} + +Q_EXPORT_PLUGIN(BNPManager::BNPManagerPlugin) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.h new file mode 100644 index 000000000..55e2e8444 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.h @@ -0,0 +1,130 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 BNP_MANAGER_PLUGIN_H +#define BNP_MANAGER_PLUGIN_H + +// Project includes +#include "../../extension_system/iplugin.h" +#include "../core/icontext.h" +#include "bnp_manager_window.h" + +// NeL includes +#include "nel/misc/app_context.h" +#include + +// Qt includes +#include +#include + +namespace NLMISC +{ +class CLibraryContext; +} + +namespace ExtensionSystem +{ +class IPluginSpec; +} + +namespace BNPManager +{ +class m_BnpManagerWindow; + +class BNPManagerPlugin : public QObject, public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_INTERFACES(ExtensionSystem::IPlugin) + +public: + BNPManagerPlugin(); + virtual ~BNPManagerPlugin(); + + virtual bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); + virtual void extensionsInitialized(); + virtual void shutdown(); + virtual void setNelContext(NLMISC::INelContext *nelContext); + + void addAutoReleasedObject(QObject *obj); + +protected: + + NLMISC::CLibraryContext *m_libContext; + +private: + + ExtensionSystem::IPluginManager *m_plugMan; + QList m_autoReleaseObjects; +}; + +/** + * Implementation of the IContext interface + * + * \date 2011 + */ + +class BNPManagerContext : public Core::IContext +{ + Q_OBJECT + +public: + // Constructor + BNPManagerContext(QObject *parent = 0) : IContext(parent) + { + // run new manager window app + m_BnpManagerWindow = new BNPManagerWindow(); + } + + // Destructor + virtual ~BNPManagerContext() {} + + virtual QString id() const + { + return QLatin1String("BNPManagerContext"); + } + virtual QString trName() const + { + return tr("BNP Manager"); + } + virtual QIcon icon() const + { + return QIcon(":/images/ic_nel_bnp_make.png"); + } + + virtual void open() + { + m_BnpManagerWindow->open(); + } + + virtual QUndoStack *undoStack() + { + return m_BnpManagerWindow->m_undoStack; + } + + virtual QWidget *widget() + { + return m_BnpManagerWindow; + } + + BNPManagerWindow *m_BnpManagerWindow; + +}; + +} // namespace Plugin + + + +#endif // BNP_MANAGER_PLUGIN_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.cpp new file mode 100644 index 000000000..4022931d1 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.cpp @@ -0,0 +1,291 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 . + +// Project includes +#include "bnp_manager_window.h" +#include "bnp_manager_constants.h" +#include "bnp_dirtree_dialog.h" +#include "bnp_filelist_dialog.h" +#include "bnp_file.h" + +#include "../core/icore.h" +#include "../core/menu_manager.h" +#include "../core/core_constants.h" +#include "../../extension_system/iplugin_spec.h" + +// NeL includes +#include +#include + +// Qt includes +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace NLMISC; + + +namespace BNPManager +{ + +BNPManagerWindow::BNPManagerWindow(QWidget *parent) + : QMainWindow(parent) +{ + // add new mainwindow for sheet dockwidgets + QTableWidget* hideWidget = new QTableWidget(0,0,this); + setCentralWidget(hideWidget); + hideWidget->hide(); + + // Read the settings + readSettings(); + + // create main dialogs and display them + createDialogs(); + + // create actions like open, close, add etc. + createActions(); + + // create a toolbar with icons + createToolBars(); + + // this SLOT is triggered if the user activates a bnp files in the + // dirtree view + connect(m_BnpDirTreeDialog, SIGNAL(selectedFile(const QString)), + this, SLOT(loadFile(const QString))); + + // not used + m_undoStack = new QUndoStack(this); +} +// *************************************************************************** +BNPManagerWindow::~BNPManagerWindow() +{ + writeSettings(); +} +// *************************************************************************** +void BNPManagerWindow::createDialogs() +{ + // create dialog to list the contents of the specified + // bnp data file directory + m_BnpDirTreeDialog = new CBnpDirTreeDialog(tr(m_DataPath.toStdString().c_str()),this); + addDockWidget(Qt::LeftDockWidgetArea, m_BnpDirTreeDialog); + m_BnpDirTreeDialog->setVisible(true); + restoreDockWidget(m_BnpDirTreeDialog); + + // create dialog to list the packed file contents of bnp files on + // the right hand side + m_BnpFileListDialog = new BnpFileListDialog(m_DataPath,this); + addDockWidget(Qt::RightDockWidgetArea, m_BnpFileListDialog); + m_BnpFileListDialog->setVisible(true); + restoreDockWidget(m_BnpFileListDialog); +} +// *************************************************************************** +void BNPManagerWindow::createActions() +{ + // open action + m_openAction = new QAction(tr("&Open..."), this); + m_openAction->setIcon(QIcon(Core::Constants::ICON_OPEN)); + m_openAction->setStatusTip(tr("Open file")); + connect(m_openAction, SIGNAL(triggered()), this, SLOT( open() )); + + // close action + m_closeAction = new QAction(tr("&Close..."), this); + m_closeAction->setIcon(QIcon(Constants::ICON_CLOSE)); + m_closeAction->setStatusTip(tr("Close the BNP File")); + connect(m_closeAction, SIGNAL(triggered()), this, SLOT( close() )); + + // add files into the bnp file + m_addFilesAction = new QAction(tr("&Add..."), this); + m_addFilesAction->setIcon(QIcon(Constants::ICON_ADD)); + m_addFilesAction->setStatusTip(tr("Add Files to BNP")); + connect(m_addFilesAction, SIGNAL(triggered()), this, SLOT( addFiles() )); + + // delete files from the bnp file + m_deleteFilesAction = new QAction(tr("&Delete..."), this); + m_deleteFilesAction->setIcon(QIcon(Constants::ICON_DELETE)); + m_deleteFilesAction->setStatusTip(tr("Delete Files")); + connect(m_deleteFilesAction, SIGNAL(triggered()), this, SLOT( deleteFiles() )); + + // unpack selected files into user defined dir + m_unpackFilesAction = new QAction(tr("&Unpack..."), this); + m_unpackFilesAction->setIcon(QIcon(Constants::ICON_UNPACK)); + m_unpackFilesAction->setStatusTip(tr("Unpack Files")); + connect(m_unpackFilesAction, SIGNAL(triggered()), this, SLOT( unpackFiles() )); +} +// *************************************************************************** +void BNPManagerWindow::createToolBars() +{ + m_fileToolBar = addToolBar(tr("&File")); + m_fileToolBar->addAction(m_openAction); + m_fileToolBar->addAction(m_closeAction); + + m_toolsBar = addToolBar(tr("&Tools")); + m_toolsBar->addAction(m_addFilesAction); + m_toolsBar->addAction(m_deleteFilesAction); + m_toolsBar->addAction(m_unpackFilesAction); +} +// *************************************************************************** +bool BNPManagerWindow::loadFile(const QString fileName) +{ + m_BnpFileListDialog->loadTable(fileName); + return true; +} +// *************************************************************************** +void BNPManagerWindow::open() +{ + QString fileName; + // file dialog to select with file should be opened + fileName = QFileDialog::getOpenFileName(this, + tr("Open BNP file"), tr(m_DataPath.toStdString().c_str()), tr("BNP Files (*.bnp)")); + + // Check if filename is empty + if (fileName.isNull()) + return; + + m_openedBNPFile = fileName; + loadFile(fileName); +} +// *************************************************************************** +void BNPManagerWindow::close() +{ + //TODO +} +// *************************************************************************** +void BNPManagerWindow::addFiles() +{ + // reference to the BNPFileHandle singletone instance + BNPFileHandle& myBNPFileHandle = BNPFileHandle::getInstance(); + + // vector of all current packed filenames + vector currentFiles; + + // vector of files to add + vector addFiles; + + // open a file dialog and to add files + QStringList FileList; + + FileList = QFileDialog::getOpenFileNames(this,tr("Add Files..."), + QDir::currentPath(), tr("All Files (*.*)") ); + + // get all current filenames from the opened bnp file + myBNPFileHandle.fileNames(currentFiles); + + QStringList::iterator it_list = FileList.begin(); + while (it_list != FileList.end() ) + { + string fileName = CFile::getFilename (it_list->toStdString() ); + if ( std::find(currentFiles.begin(), currentFiles.end(), fileName ) != currentFiles.end() ) + { + // Ask the user if he wants to override the existing file + // atm only warn the user and do not override + QMessageBox::warning(this, tr("BNP Manager"), + tr("File is already in the list!"), + QMessageBox::Ok, + QMessageBox::Ok); + } + else + { + addFiles.push_back( it_list->toStdString() ); + // log it + nlinfo("Add file %s", fileName.c_str() ); + } + it_list++; + } + + if ( !addFiles.empty() ) + { + myBNPFileHandle.addFiles( addFiles ); + } + loadFile(m_openedBNPFile); +} +// *************************************************************************** +void BNPManagerWindow::deleteFiles() +{ + QFileDialog filedialog(this); + BNPFileHandle& myBNPFileHandle = BNPFileHandle::getInstance(); + vector selectedRows; + + m_BnpFileListDialog->getSelections(selectedRows); + + // Check if files were selected. If not, inform the user. + if (selectedRows.empty()) + { + QMessageBox::information(this, tr("BNP Manager"), + tr("No files selected!"), + QMessageBox::Ok, + QMessageBox::Ok); + return; + } + + myBNPFileHandle.deleteFiles(selectedRows); + loadFile(m_openedBNPFile); +} +// *************************************************************************** +void BNPManagerWindow::unpackFiles() +{ + QFileDialog filedialog(this); + BNPFileHandle& myBNPFileHandle = BNPFileHandle::getInstance(); + vector selectedrows; + + m_BnpFileListDialog->getSelections(selectedrows); + + // Check if files were selected. If not, inform the user. + // TODO: Ask the user if nothing was selected, if he wants to unpack all + // files. This is more like Winzip. + if (selectedrows.empty()) + { + QMessageBox::information(this, tr("BNP Manager"), + tr("No files selected!"), + QMessageBox::Ok, + QMessageBox::Ok); + return; + } + + QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), + tr(m_DataPath.toStdString().c_str()), + QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks); + + // If anything went wrong or the user pressed "cancel" + if ( dir.isEmpty() ) + return; + + if (myBNPFileHandle.unpack(dir.toStdString(),selectedrows)) + { + QMessageBox::information(this, tr("BNP Manager"), + tr("All files has been exported successfully."), + QMessageBox::Ok, + QMessageBox::Ok); + } +} +// *************************************************************************** +void BNPManagerWindow::readSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + m_DataPath = settings->value(Core::Constants::ASSETS_PATH, "w:/database").toString(); + settings->endGroup(); +} +// *************************************************************************** +void BNPManagerWindow::writeSettings() +{ +} +} // namespace BNPManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.h new file mode 100644 index 000000000..b31d17a09 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.h @@ -0,0 +1,145 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 BNP_MANAGER_WINDOW_H +#define BNP_MANAGER_WINDOW_H + +// Project includes +//#include "ui_bnp_manager_window.h" + +// Qt includes +#include +#include +#include +#include + + +namespace BNPManager +{ + +class CBnpDirTreeDialog; +class BnpFileListDialog; +class BNPFileHandle; + +/** + * Main window class. Derived from QMainWindow and implements + * the basic layout like menue, toolbars and dialogs. + * + * \date 2011 + */ + +class BNPManagerWindow : public QMainWindow +{ + Q_OBJECT + +public: + + // Constructor + BNPManagerWindow(QWidget *parent = 0); + + //Destructor + ~BNPManagerWindow(); + + + QUndoStack *m_undoStack; + +public Q_SLOTS: + + /** + * Open a file dialog to choose which file should be opened. + * \return Filename string + */ + void open(); + + /** + * Load a certain bnp file into the manager + * \param Filename + * \return true if everything went well + */ + bool loadFile(const QString fileName); + + /** + * close an opened bnp file and reset all views + */ + void close(); + + /** + * Add files into an opened bnp file. + * \param Filelist + */ + void addFiles(); + + /** + * Unpack the files marked in the filelist dialog into user defined + * directory. + * \param TBD + * \return true if everything went well + */ + void unpackFiles(); + + /** + * Delete marked files from the bnp file + * \param TBD + */ + void deleteFiles(); + +private: + + /** + * Read plugin settings and set the window accordingly + */ + void readSettings(); + + /** + * Write plugin settings + */ + void writeSettings(); + + /** + * Create all plugin dialogs + */ + void createDialogs(); + + /** + * Create all plugin actions + */ + void createActions(); + + /** + * Create the plugin toolbar + */ + void createToolBars(); + + QToolBar *m_fileToolBar; + QToolBar *m_toolsBar; + + QAction *m_openAction; + QAction *m_closeAction; + QAction *m_addFilesAction; + QAction *m_unpackFilesAction; + QAction *m_deleteFilesAction; + + CBnpDirTreeDialog *m_BnpDirTreeDialog; + BnpFileListDialog *m_BnpFileListDialog; + + QString m_DataPath; + QString m_openedBNPFile; + +}; /* class BNPManagerWindow */ + +} /* namespace Plugin */ + +#endif diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.ui new file mode 100644 index 000000000..4e695f72c --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.ui @@ -0,0 +1,50 @@ + + + BNPManagerWindow + + + + 0 + 0 + 800 + 600 + + + + BNP Manager + + + + + + + QWidget#centralwidget { + image: url(:/images/ic_nel_georges_editor.png); + } + + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.cpp new file mode 100644 index 000000000..d3657d13b --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.cpp @@ -0,0 +1,56 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 + +// NeL includes +#include + +// project includes +#include "bnp_proxy_model.h" + +namespace BNPManager +{ + +bool BNPSortProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + if ( sourceModel()->hasChildren(left) ) + { + if ( !sourceModel()->hasChildren(right) ) + { + return true; + } + else + { + QString leftString = sourceModel()->data( left ).toString(); + QString rightString = sourceModel()->data( right ).toString(); + return QString::localeAwareCompare(leftString, rightString) < 0; + } + } + else + { + if ( sourceModel()->hasChildren(right) ) + return false; + else + { + QString leftString = sourceModel()->data( left ).toString(); + QString rightString = sourceModel()->data( right ).toString(); + return QString::localeAwareCompare(leftString, rightString) < 0; + } + } +} + +} /* namespace Plugin */ + +/* end of file */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.h new file mode 100644 index 000000000..ed2da5966 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.h @@ -0,0 +1,44 @@ +// Object Viewer Qt - BNP Manager Plugin - MMORPG Framework +// Copyright (C) 2011 Roland Winklmeier +// +// 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 BNP_PROXY_MODEL_H +#define BNP_PROXY_MODEL_H + +// Qt includes +#include + +namespace BNPManager +{ + + class BNPSortProxyModel : public QSortFilterProxyModel + { + + public: + BNPSortProxyModel(QObject *parent = 0): QSortFilterProxyModel(parent) + { + } + ~BNPSortProxyModel() + { + } + + protected: + virtual bool lessThan ( const QModelIndex & left, const QModelIndex & right ) const; + + };/* class BNPSortProxyModel */ + +} // BNPManager + +#endif // BNP_PROXY_MODEL_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_add_item.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_add_item.png new file mode 100644 index 0000000000000000000000000000000000000000..bde338f7851d2675b29272c7dcf9471196a8f6cc GIT binary patch literal 3270 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 Eg5p97)c^nh literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_bnp_make.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_bnp_make.png new file mode 100644 index 0000000000000000000000000000000000000000..19b749b1da76ec5ae8a7f063c7127f5672915ef6 GIT binary patch literal 25705 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 literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_delete_item.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_delete_item.png new file mode 100644 index 0000000000000000000000000000000000000000..a5a1787d593591f855be9a7eb8da271cc8d8f214 GIT binary patch literal 1496 zcmaKs{XY{30LC|C-c2!W(h#B2QhA@kOt{brn;~tK$;-mn#DM?-zdb>=i zu*@RTd8@_pvUxpuxyoG1>Bsxw?uX}jKHujL_-0@|T~w8{l>h*Ms+%k3&``sHb<81=-~(e+|N^9C&_KHVw5X^3IM3J{S1(sAHJ}8!egC%W4+FY#L`JIX8~B! zIZ7C+< z6bcMhk7Jz$z zt<~^Npzeyeat^;b(tkMW#bRkwb5S`|-P(cZ{!1geIKC7Tzpi^Q9XhN7r*| zh)Tmw?h}4)r(e%EPx*~jbiDn>W9k_F^gyx#1J1b!&uZuD!J$Duh_I|$-B|3)pjcABT`DZr@@$gnJ?g*7niqC zPg~-q=_uM61|+bWZC}wlE4;C-L;LVrU6J(R@D0Z4=p`kt`4==LnW(d8wXiBZND)3NugXyk}j`B>QSp`rx>7I47#1U z_C?Zqn_!w_iq*Q=7#33$KOO+R;CW!bcdn#k;~tqqg>*o8s|#;{%M1@^2B=`1X*QOW z`~~EL<8YMd;Wk~hP%ln9+T{3weTCGPC>#3IdbbgtfSL(^;<-$(&+()%CWY(ZY}rUs zYZ^=Sws7E+dDpj6e_>>!qz;jFg;SMzWx6GvaM=_CJv#h+^qF(IggsR{8BYMQlBT|c zLR(J;=NJUkn>YRLcdDtY?zXt@zIEUuTe=1hEndEU6|7%)i#=`5cs5S}P9Mh=PcJfo z{ZbSwueq|yZyG~GMGk&1;XI&33fgfyu~6eIQgk!Fkv4<^W8F=|9U5oXINb+#fCen_ z{sB?u3Xfi@SxqMAC%ZI%1BJIf0uMiCx!yXz62rndMv z$=6toP8$LinV$s7C|ZjMS5+@W1rn4NxN=o7bmp|tGx-1vXy7V6(LK7Owl1b<1|o_O z>bY9rcsZ;+(mT(U8Vqy|@K*SC7Xeg!@WG?ntw{ZC`G3Vh1-90Bf1vJ=9f)jI$P4Q6YBQ@Z8;^^H#>9pe+1$q6DXU$-5VbBeJ(3kUiuh943T}3C$!G=4Zw&rX zIZx;etQ%$b10W;H`0fD|-g&n~Eq? zJZ zC}pc4u@0qD`7mQX=zMD+8o3Hi#&31p7{mxJ*6-KkigeYIgt}@Xn1a05YyE6U8VHU~ z8PL=CTn*0W$(#-|89Sz`9P!(hY?pOfm^ZQVXfjUeBhD+B#yUg0vkok?_%`$Xq0`=> g{}tB1bjDO$2a)_&SEAML{IoE@&Dj&vfF`E?18{b*hyVZp literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_export.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_export.png new file mode 100644 index 0000000000000000000000000000000000000000..9fc71c09dab0615021bb5c813d47e3f5b2a72623 GIT binary patch literal 27878 zcmd3N^;Z<{7ys z0WyN%hU|jrKzzv=GlD{c;CTPv-gsb7(7KdorPuT77Iu55^M(5eBJES%_Xhm7$0=xvle_<3!QemzH!4%-**^)^{@c{w$FS=kIm?vk&z>7WP_iw+60@z z4*OI;YU9A*3lE>&G7egkY8e?A@(?q!CVbZMjn{R|)#k)<+vR#kA zmX9^wtb>&~Zo0lhKCH3|hxdNYoBgOw>iSe?pgcz5Y&r3K@7{KzYE^rau21&`t<5{ybDf^^=*0i~{rq(1)yJQ_t4}NYbDc!n%gU~cL#MEF|C^6d@g(Vp zFl_y^FUC&>l>AR7+a`>vkx#6Grhv}t1d)Qxc|DEi_lOS-6&*GQrG7Ap*qN>(wJO6>9^OEE0HeEJ_kZ75pfr+cHY_Y<| z78E(ZF3zi0~O^V{N;0Kf=#3xmP+LikFtNNb|3F6GQZw) z=u6P8NN+ad)JGwUP%2^q$1iOqP7`ZKt+3O=2Ddb#PFewL>6Vg!2HteNX@l8P1)?q2 zC|d*{?g=sh9l17ySsK=kvXeI!$xAf%`!4NzFbwzqVffEpC|f`OZdB67SV&ksUZB zxK+VlWqK{#YUsu}H!Nr4v4CteZ`#f^58h&L@Eg0QYkZ?y>cU~rmy~44bm(?d_4Uq; z4zH@U)2bp!kB=V`t%oFZH}|Ig&V)_8(%xF9Gp-&ic$(ai>*RP?2cvuLU+z4{s91+=${5xx6+T46kV*muFC5l%orC>wQ>Vk}bdCDX6-37rmGQIx?q6OjPGI`L_? zuT$wEDW9=I9EKNkEDus7)*C>MDeINST8A0QpKY~mZ8j;mh>A+2X$0Mfdm&5Mk-PGh zh4Z&3+FOl%ITPlj4Jq1QEv8o9x4TZ7CPLRt?<1BY}txKBAoR z*Ar{mHKp(cY`>$p2((#_k@exb!TYiZNRWJikvrLTUQ~htU%H5KwuEz0rdh2Sosb2c zCPXM1Dy{#=rVdNn;C}qV+;xl=YUe&1Xy!&GLG$p>xwZEzNw$ZFBj2u^Jf7&2Hs73G z!{VyH?Tc1&QcefTpXN<6$GDeh*2hTX4U0CU$fCm(uhlMCO0q5emb1-erTu0at^&~k zXR5?T&J$1#W$lw3WrqLYYB6dg8ahFt!P zf(p)bOd|K3p_gQ2M0-;ZU@1|~D~p8Sdp}fTJ=Y1~Vw`=3e?K&e=yiFO^o;A)KUaK{ z#u*jLLPgf<5e-Sm$Uj&X?C+>t?nq>evJHWz^YX%%dhwK=FSiw>65fH?p>NJiciIjf zazRaB=%>UCw`}o}zoe!D>2VMaY;0sxl$GxXt5_j%%UivKXq_Z#T}D^-yC0dV{K3t( zIZZHR*f@FocH~=;W<2x2^QMJj;&)Eu1Bo4Pd3B;F|DB6+%;8V)PY6-&A3c%BQb4>R z%$-rqdbvhN$QpRp2x6Qp33zx4x;pvNC`k!u+L9IEJ}B}rx=?o2c=Gi#SA?vL7^Nse zE*plXh~6nz-TM*S1MbshAVHzVcG4IVf(aV18zls7&DtvtqjD z%RC}ZrhcQ#uT)e$noBEVBgUqGLORSpm=>k_?;ek>;LMOQ=tyHHTZDHx(7uoL7e)On z$;1N(=_LB^%T=wV5b-%lCZTwvszk`u%Ic$7VQvG41JHzdN%faV>b{7l0~iTHdZ>(I z@m83li_j;V(jOsbC*}ygktR6r0NDve6$9pc_Dh)}UM@Z51C+m)eA#6CW!%41huKr- za@*cfg1lTbN+F8LVS+p6UVOSTr8du#;4o^0-l^;p2xkG;W&XQoL>;}^iSXj5?lYxp zQ<0D#X&AO8+znZM009Ak=?gHh6uMXC1qJrX2Mk!CmsZg#A{z-Q@8Jmb&*=mrq?DqJ zDAuS?nRJh$;dFT#bYJ_fo0l~SDtSOM&_F0*)Vt2)*{f}f>+19MYbM)>nL_*XVm7n6 zX-LVC2Lzk47@kMWBoK1sL`SPDQV&W39TPd}=+n>(8LGafM`?9;*xt}*1a$PCturDC zJ^r?-Hk{hv6NjOuy#9S*Aa#4H@XYet5$J12eoZS@(lg%m>4J%w5t71skpZ`(_z5Sn z0RM02TVK4Zsr)lbBbx&)*+yQrTCcdIE0>2Ni zCJ=~pZj39d`}v_V;uB~^{>FXQQoH98>szrH{`!fMx$kU*JfmI7Vn8c9nUC0(KB4AN z=R?R?QO2d&x4*`0871aTCb5LljO>+W4F(i%z)60Vj-89c?mEXT!5qd8-ndg?)k9HW|#1Cq94RPuIc!|{Z40VwW1=0+5AOG-`9 z+oVWs1F2c;JmX2~qRFIn-S!eHweqhoaGD4X`o=Le+Z$CdhYrGSHg#OFopv_io`zq> z;&QQ9`^eAjxOkjC96NzC!ksK4jd3?~@NzV+1HS1oz9hQl&F03D^26V1>hk+OHt(@J zHFQRVFba#RD=bGQBC(p4NZ^J}=8Wuw^qw0S@Q%&#)p7uvrB<_{?3_^FY~1j8QkXx* zM5ikQ5B?UscSUGMX0{dVHD}`Yb^Ag4)5S3bY`pvWT}Gt20f@@TXVDA`-my<^>;}=q z8VQHujW}Aq2WZ?p!^F1DjoayhRC}?))!t%hHFm>!YYunewH1rIvf0|lEeF2UP$uGH zn(1FREYsUuc#7-@SZ#(BAYiznu-HA{tjV{!Om7k=r3m$4)&wLHe zB64WFem&@lXoLGxa;aMCN0=C?A?WZ>ZY}7VXvfbbZ3KlWyc(G$=DiuMusxzMxf;1W zJ*VNeqrn@(w;*j^&q!-{(Rq8R{dC0T7H_F~wAMM-#=Gn>Nc~fX{MslDH2{iv0Z2ZY zj?q8t(G~STu*S$B0cJ%fIGv+jG&1)n<^^8;;j>(o7dZ)XPiQ#{w&V(UIWbMTL{}8< zVB7b!w^Z|qp%$aH9M;J5N_1pIrz_|yFY0g2pI5+B`Um5W4*(pemv5lajw%?jEs+!ybF?lX;F5QSx&00+pKQQ_4oo+u#Yg!| z+*N@5Rw-0NJNG!&>mH{-*iEll0YZ%Ixh(j3f5~H3E9-a3%O)iE+SQ_MSKB91t*~`= zFD38ypm5Sg0_gtcNs4a_ky#qXMXe&SD>Iz!`tNDr;uVtyDak9KepjK$6c1D(F~@jwy+J+c6(L9QCg?H?I5-V7@S>i( zy=(lxipr)7L2`{E`_4U}DA=mzePD(6<7d*)}D!>TWAs0|VDxI)q4OCrGA4Y+v8Yh_$5wju{v~#$5uF^K<`qO4(gRsG3GXcg#zp29kR1tE;oo z9{|f=z%Otf7yjFN5H+Gp0MYQbhwP)Z<&FetGL^EMF?KB{R4xv+I$*~PbibDbiDX<;N6gU;NFb{zB|6U+yiT;h?Vp<-h>r?i*ysX8*Z9Y3ef=mr z1t9J1KFKxDF+TTC-of@$FkON+DQA?~bdCBRtHdL#nSMCJ;$kMSgOXX>>xqmf~G0p(oMquWl95O*l0ZXF0{Xo; zJx;Crwrr8{U#G?Ohs8Bf<^<)0E&DXq`MJ?}h2It;I+kRa4+@P;^xttRfN1ev1z&a> zUpYSNDs?5kJhxmJO&ryMilxNyI+t`3v1B@dv_p|6KNlrx_u+3`6|!iths(HMm$)K_ zU#bw{cHAoOX9U)|QKTvH!Nv=4O;39D`cvZ*x9Y^gj%q#EyKUQMG*_6hI7;;kGf{4c zwIMko4$5~jWoT%2`Qujfi%J-E#e+C?0sHLuzbq(C#3IJ8!ihTvIk}EJF2?=VsC-g5 zF15p$c9~S>75RIX?wLrW;3;qh+qCqfBA81#X4eG783eU(1?)69`Cb3J@w^}cf3mYm z=TJOA?9|CxQ*S4Ozh~KIPpg{U!w57bs7Z-HKqOC7B(yHG85q)B-t0-B{EDmOc-=c~ z1Ufh@!4*dfKf49pG6)_0WqvCJwq;DhSL8+o$8W1OO!fUGy7C9u5@znmyL*# zMGG@fNPj&uU5w)fWQ43BO8;I`0j3Y_ z#i=5m8n)RF|35ZAe2>$E1N0;l-1?H*yTSV}?r@UmPYHH3h;&IxdaxY3Q;cQX(WZsN zi=IXsREJdxM&nO-+|N&>#5M17sG?{xXqLcY7SWsIf086O-NjrPAcr!R_JgVbSzw(N z6P&-o%4*b_LmO#xhs#_+yB1{4;tF{v@Nc8~qS}c-XB61+5<9{PqzpdkgR(IMP~3i8 zFq>c(dSmp9sEa$at{~62p2%8xO8De$7KGRr`UJe8`q)!JhK7Y3GyKgd20^cvis43!sl6VH-GWs=bwR zXQ2*HKj=Q^QoU4IfEw@r95O7%K%f_!gmK{2H$-?vN?lMi)i!vslKnH^~j zT!(3#Mgy1kfzu{YY>D{Qj$)Fd-7h`*TSS+XVSXW*84+iwaTk`snN>H^IC93&&_$E} zZ?dzek>bL15w{4n8?BC;S*=DrD5|f5v!?AxMf%iSi7c_>%$ggNKA`{ zlH|?I5+gU${87KSpgBu!%jS2>ENGd^+{G$+7qm}dyK@D7itM*(dkbPel zJv$vyw|)s}pjn(J*GvXe-|1D-*Rkir`Art@-A2qa3b8y`V0adoTf zW3MGhZd<~Dq1sg=O%g3NW}!+YoAb(`>z5UFj}y52%)tw!O%jC7=2WdzZ5k*l@FZnD zH*IEMQgFNI96Wf1@p;@KJd-tj zVIU)x_xqE?+J|BISNv-WA@A?Gxpn{p?+xA>+!`0Rn3WP`qBa><+!_~OPEgjz(CWnI zd>Wy2G}ac6`hyiZWAT0gSoS6iAY{nm=#pmPv@*Zh0!Vqm7lC*uNEfiB%(RI=;;7o>GupFMd#(FoFn!)j8AKNHadg)hk6xzK}T5#jrv-jm3@ou>}97xrr0v zSBcX9DstkT{cXAr85&^GNY(7$gWGW*9B6yN-ax({7JA7Lqqga-!$0Uiyuz=RRUF~Xv`FPfR8NF_rC8I8mp(BBh4GoAG$N$wr=F;K=zX_N{LP*B>D5`V z0hVyUIN=4jmaNy`OKx6YU&X@(vgS7X_@gv3f<_Rff;q9<6dPwfD5fSUNTr$_OWMYp zey5&^FGP;=2dGU@#NKMx_^Q_(U#gPMvi{Xx5I~JQvSrJtHbQrw6@n`!Sq53@t0tw= zh%V%d=xyB~`Jn|nhk88d4xV7hkS2TG7drn9>h{Q?X#$pVW=C0!zJ0AAZr~|{2Yhe>^>WLY)=R25)Q2fEjVWUf0yD5#|?2jCbnHI4fV^cIRlMX zw6@-M72eK2d(g9^=SJNgojEcsSNN?eIJSQBbE{)6T1-RgU`5)!(nDJ*$^du(d{IpG zUFSLY@4nHnB;Mfu>+?^xb%dekK17VGx4+l-4cAJ-_nv&W+Ye;B-^VL!Jq$}+-_CU2 z*9c>N>N1J8@-A9wMuK&^{_3aDp8QstA zdA``bkNXFwjxMlG?6|zF&fH0H2oegtd_@IxD8F0vf83=52t6N`u%iaT0I3F!^!h&8 zO?sWE9-RGs{rjYe@!pgdtvEJ^6T5}bvbFka#d~CjR0m)U@Cd&Cu`lRBljMOP`?nY1 z>1xG$lA{oJuo#W|TJ75UM4zXrT{Ke|Y@`R^@0M#MLC2C$!P1u6QZd&f_MFzC14fKj zvYtlTqNyBhMwMNRwQl6~s0G)93xSW>M!7HJ8A`w|;P24Le`Tw>^`N!wu}A8*5$9;E zRrtDdhr3wwBD>s^vu~HHUazPTtFwYvA#0Z$;ph9G29$3E6PSC#fYZQ6_38T9&@GZB zn>){Y1d1rRN|>R!Fdr(;A1MqmBGKEa_BhYGuJ(%((V?CN$nn?}O}zK%en9{wB0LUI zZ|y~?1-0^7VV%{<%1{|~^k*4xJ&8p`TDb1%i(d)_1X-_I1^Mf)Y_Z;;IM8xk!U} ziMp+6P*t2$<_RNi=&vS~uTN}FPj<^l7L|9^hX1?U~5a;M`qPR+rs1^kf?+I(6Utde|?_6rK8#Csg9gl78eyn zKWOn6WO~PK8sYaXFkCqCKC~R@NkKO&?}l7iHyjSkO&C%GDE_5}>b~1E+iFDU#&M0! zyHyy29Qb7yR+Vw$B8M*VPoAVgM4QZd>Gk;ZqZA2{PP&9<3NRF@l!O4)1JsdcqynC< z)H~8IGpzY`%HdZT0n|le>E9Wg2t?SX+tsFPxq(dXSFqFSdIq9~iR%qA;7=+b)$L|x zBK3D>-JXR^b_N=~?6ttgAoV_-*VYgunn;0X&u3_CN~lJOSoo8+xt*1};>O}9W-nqk}6JoGtTNr~W~yjBSno%5MEz z@x^|jD19+ABMQdc(TRDPGU1Is9wDSYC#z;c{+rfAX(~$)R=6thu8vA;Tra>h?ycEg z3lG3*I){#Ith?nDa`xt8B!UEVBl9vpdNr9W)yFRWDK@wg`p=g!{=tPmKKoA}5AV-% zY4W=&&jUcy_(jGAc4CyRDA~;|<@XSg^+r+{^tl8mQyENy5(0eDVZFOb39I@8Q+OBU z?5~Ut>@@ZWt4+RBSWaxnuC}$F6u_kP&_D%4dGy!{#f)A=|a z5&p0iCCUXX?mYbT^0LsI?5T@*E+sP}k{9)w-oc3+B!6bd4ZVIbX5=PPZI_IR7XJEc zh56XDBG8p=M;L(w6a9-m0}2`gDdeNcf-XCQ~Yt++xHRiz~l{!-XxR1q73{Asg58^2*DPdE8C@rCI+Hl zbL=}MGSJBjR8np1f7LQs3U%XXeNq{E;nc9cw>|OjF-R3}DS&!Gk3(K1^r?M3TyDS`cjj>6dcI*;iq7go3d zHP8i<4obL5{-FNUW}ZJC4}~iyz{Ls8c8@TAd(!k=rkXs0drzl*Z7}8}-q6bkU%#xc z1?2^Pc_z57P7Qn^@Bm(aW6_GzE z0d~q7OP|U;NqA5!9AR|>mnPedGQ>;2OcxB?JqT!)vOL(Hcx<1a6K_E;k=30PeG9qb zQZEkNyjp)w_FaX9Jvwyh|0~Mo#@w(#QBC~(l?8qnD9Jlj-Y?obbibkOIz|UZFo2-xOEgXC zefKsJIW1z64tqv7@~N1_SKGl(@d7wnW(J5+WzuQ4VxSQb>*=KB;f_7YVkSi;yGm5J z!W7^q4W1EBx&&Uq_&XLGf$>zNpzNmBfWXsV&w~<`(^h8_+fhZ^k8Xp?pkt^Z*eO@1v|C2O+8R?vtW=uXe9XZ0S-=l^=27=HiaYocj= z=LVNDT$nsgFgiLM@7=fK_g4q9@ZZV^Z8+*ObAQ)ortxepZvOZAMO$?LOH(QN=GA}$umHfAHV~^ihn#h(@B2v>C%IOva z|Cl4HGsLK1_?&_%kK{F(sVYrT=|Abw+1#r!>=X>_4Uk-9e8F8Y;LK|c^@uP8(u#xO zM=dR@e2PNqT<5>!M2J!AwQpOr@t`2@TjfvZ$Bp2;#w*!tu9o#|l|Nxtkpvx8BhE9G zu8+cs!w!A)MvYy_3!y1(rK)&$8M<9jtlN~AnT=(fd#MaA0 zOr+!f4l8GJShVrceiRexdW;)2RXCj*2|21(ggL6&P+|aB_!8pdTwpFAlbG>Goy?;D z*63YIZ7j)3M;xKbyNh3O?x(|3?d6?b)F^Vl%lU@q_Y+0HwoNwIvu;o3_PGIiyjos> z7t_&XV%zX)@sHqwzf@{#{BY~+g8F9Fp15-qI^M`#>Dh~UWx)VXKHD^hJVXjvKiG)@ z+RY719BMy}(g53@e|}i{b3{j9jV+7p;B39Z%uVs39~4UkXeaLaO6^FmaHFo#p}Mu-89$*on((0w-xsHelW|PsFN;pNs;WCjdf3(D zggq9`EBWG?Gs}kf`gri3`4)IhH&|jaUhY1755cH>cEpgUjM@Q`ip&HdSG;+zQyBlP zZ;W^nQZ31=W7*QmloIM>4Q`Ahol2Ek%j+ZLO`e?RxOQUvOk{jyFgB3V#JVNwk{ba6 zu8T*vcE=nFA?MQ6L8U&;hNJsu+{ ztGf~dFtOli z>U4`%m*Vm%1dkPTMofxxhDJmb zx(q3bSv+0&5hSR_0Bg`@fOSY2BXpI&;0j^uP#WyHK-!~_;tqJ(9@@0xGXeP3cVBn(N zm3gutz7DDT$TLb(D~|+`%tpie{5eugu6{`EY+#U z5ku}0?8UJUh9`b>^A-fCfrd!SBqjDiKnqvz;r}L-^;cy)-;Y{a>bIw?7;R*9FIYfaF(caU8Q z0YoX7`KIEZuSUe|u)*&ch%TRPfc%afG(gjz#<<8BR{fWY(5jRX9I@xzkh|T~QqV}+ zf97Lnn|2HNLUwHCi_CXO8Ym%NqIaP_^tcy?x=-P-#6FLHGP+ejaJE(S-^M|ff;wI2 zUsGcd_|t=Edkzqs)P34x{ZBRSEqf_o{qA`ThPCQA15T+1=$v%As!WV>qn=(I@CU3WqIXCJ*K#j*n)=A`*e;ar15wCH z+gR6Xny}`QBJv1{Uye?eT{DiaO3nZExIRMBxK?*7(h~&G#DSqzVt1g6!8hI9 zt;At8UkwmX0^Vs7ysXf`Nkai9X=tP!VXZke1A*>-Apyl+`BBn}k(~cKz8upsj|eSn z-lf3Nn@IHU52qKrfE9usL%K0^UbXxjoz(4yJbkMVw(aR`C-B9yoQNiSAg0+*gV=r+ z|3+bP!j=%@pE5izs@s{!g%(ZQ^O32@+wm|Wr3{_mAy)Nhf)S1N>J}+vVFF9Xg<$5@ zY?O9jZ=Sy*z+Cd5_K5M|BER+R8V9SsS|y*}x9fbKm%)wf3?(g$A8t0UrJ#Cv$w)I{ znBORLgU8b9C;{65t8Rrvy8m7-xQD^} zSQA>B_maZ59q#m``1oGIY>4IkXDuRZ@OPPUhA)?#m&>kjhkc!0*hJu5QB&vOxe}O{ zDxLezcWcP9|%x<>c>(u)H7jT)REf?D`qJYmet+u z%G}5(iG%AFVU}6M*;{qvjz3WEC}dD3vzT8}W}2uPUHlNm0mF+1=^&rm(-;0lkzR*A{S%P7#sj!SiGsAc zA>NVG{_jf9VzZTZdsxM*;HDkxEngmQNR5`^F3Uy&BqX1=N@CDCqDn)m(q5evEkviC zb0aUUY0tcWB}P5IXjwy(&I^r_l<1ba=eXrKP@}eCBg?Je-}*hO5X+;Va%ntWRm*0^ zDvS88pom3#GQVk>P{M84#iK*JWrC7jue_`L!8D3u!S5c4&DveFlGWilA7T;>ky-gd zb6bt%Dvb}c`EI4vUEDmQ4Nxw4GuV4m!9};8ixeYGBX)HYCoK223;6F*gNP9lDE8ui z3XJQqv+$4;7ns95#N=^k4j*u_dBE?e*U`Mv$HgquCafbfXE;xQq*aWGw5igZL-*-_ zPvin-&*Yw}nc+~|`$)@L&e8{{wK}tETSoR9+$06ubj^-&kZRAN0#4Fj8dB>)>?PBo zqZc4HH%nle{=?lyeVE4f@Y@sbyq<)*+f{K|cnfMqLq-k|9I+&f*V5$GkD!L2_%YseLh3)MU( zOm8Lz?Cz8J(jx6#TTc z`v>c1bLDx+Xfnq#H?7MHa!+rmkCI`{nX)hbOTAGQ*a2OT#&ce30{Yh(fBFcRg${nS zJ8rcF3q`u$%hJ#RNDo$nCJ#wL&3765gCi@s2NjY16X&)AzLY>_6!voqe zUBt#8j^@_$f1P!^Sdm9LWwcM$0N83eh8~RabGtN6ao0?&kOF|Tvuhzh zf;tnuZFJ?@MhNU_nbHevqka*D*SSrrbe;?Rd&322g-It$gQgbF(~a<;qBS9-G>9!f zNoor0{z>iH)>Cw6Rzpo28MD%=2|Xd_VM@AfA%3epAFG~5L@%CBDT=~BqAas!f-f11w) zO!U9~b^{*yAQqS8$%6zi1O6Ay9x6c1n~a_Nn!MFL6pI%Lg8FTO_N$dT8F^>$@6gK>&4{}gwU0^-;-{oW1?U3DVKVqu z?O^skCr&5|r@48#KT7y(TX_3uVx{NldP5TxKMRwy@K>o)5QLqHWV_K_*NuoJ#)u7RcF@wNotxU5LObT7)3 zeE#~!&*8`>^pG6ovJ|G{cC=+{^}M4Z((zuD7~OzJlvIYw`svPcetX&*c>@SyVnGgG z@hbfRYMg1eK;`pDO^W?i&7TgALvJ=4HFs$NwQMp>sZ6`OCWn8{^hjf+N3@2q>(jkL z+BvUxYA6ljDFTsLVt1DQBa0p1m2k#KaXsrkMm3g9iP{?2=dWsUGc{OOM(z&l?^1+A zvZZJFIcQCV4>y*5`w67NUf?hbE>bEYZx2i>z^XrN`B74wk2g=){$sLmLwF8z( z)53gY2LT*~j`zPlsk36-SyOJn^?#I-eBWyT-0?Uc<(a7Z*VlrDUWzJuS*NVmzIUbt ziIBPEbdNs&a2LVddX?#K#P#_{mEmfio^#&LG=F(>Linh;Ae8T2>sk!PvhQ{20e7lM zn*}C0c)*ix^phg5gCXVe0-m2#-izE@u;q86N9`dBF85U517Sor!y@FlJgC6;0K=oz z2#<3I{VT$WmRk0Rn#Syot0&+CzU+(xGXo`?a{|BW1eX!WK$S|p_F9GNQ2KACl1#s{eka+zfIigqc0M11NJ22*4_6)#T z7M!i!?-qu$uM4a4S7%Z3iGwx`r>s!*ovcMv&F|u6rc$q73KX`G-Zc1|W^b6SsV9eWRy4mvTLxaMTOCzeTUXhKL45j!kOTi3Z zSNtw!Tw4Tx>0(Hl2R&%}t@?^Xs)DWPp@mAoT0?hcoS0?*L!j!sFSRrO8ya>{5Y2qR z3IP=&zm8Q-f+^1&0?{HP;bp)7G|uS8S`~Ej$I$Nh5^=FL))zKudnDr7IA06KE+_1d z)%@qPztoy*AyPQdAt!i2zpms)kDV8=`oa%06Mzz)^u?bOu~z>B^Z4n4!9@4#6tg1=*^nQw#eE*g6d-BY(|HU= zc+wcFKynelI5Y|9jAj`c3Cn3YTZyT&5$nn@`c81kK&~Nh{DUdG5SiGQ;pX1xcFCb= z{INfac=nVBYNglU4H5gLb*|l2v-b5v2#!07fOwS0P_ zxV3I4P-#=06XVM26dV6m4@#VFnHw0H)%V5G^tCQnXzAy9bE90&Tg0;V6Vt=%*LefZ%28h=TYPX?6YP9WP0sql1^#%h8FeaPlSGH*Wd5{;IAv=@hyri6G-RLIPN-?k7JJe@dWcjgeUBS zq-~Bv2Ynk7EFo%@UI_bARdzjX;7VeD^CkZ0gr(!@s_lxM_s6@+X^Q=6xBZ@RZ1a{^ zbQXpf&p~XH1K%lPO^hc-V$he^QfTpebBA@eaC@Eic)(qcif)7yES4K`P+WjpzZZxI zN!;(_)_ed%HNyE92Yb**rJw1X0|wvCk2g_SdD{eSA8+w!xXAy@2@7Q*uutoenh3v^ zYg`Z6nF#b3$dSGj7?Q`e&W%4awXAL<-hCYQxv_gDBUb)uW-==~yj$*eKm%nJ;XxjA zizf#vxKSZgtbX5J7VT%;b{NSQYi>b&n(Am4FNz>+K5e>OBaZ6fZh-?ZZEZ~>G^KHNCy2U6+84CGB9rp1>BX?E9$=gJpknF9It`p zW)5$@72zVQgN1ptO{IQ;sh?nY__6b4IAo}dw7k4Le?La~`zN26>W~_f4=0y2vL<5W8u9@U@I+Jqj&v?UK&xfACapV%_0Rq1|PIvoL!3! za0G6NetzwLnvh}h@>qT=LA%<(QaRD;rP2HO0o0#QBPo$G6C4NUVH>pa>gN{_ow9+99^ zzY>TVld@uIfkjYEpo#m{z#&L5@7A;GlIWnYzQ+$Jq_GF=6Vn0L*C2tm!gj0 z!j4c2pDTl-L^;CB{&X+IfsuCf3OeC&N5BQuh53>4?i577wCR%6)nxDA^S21xGfq^h z%(Vv5$py#P71!_MHkl6-&W&c<2pTf=!6nw0Y2&z=-3twg7}hx?+0I6%e&V`QFSGiA z9X%n`rn@a?a3RoSfd?gI8AFM1+$v%EIVzgjJ z=iWstOs00Y1?xkD_*)K_NCWsy6{BuQ`#$46kfe?L4;i408g1cyh2#R(>KrS>P zeHLX>>mjACz=tKv%QSPce4+%tQDV&+am)T!3YXSrGu#OBP8vjVF`S=&dnY18BNGJj zn9H}6{;&}vf?vcACTI4agHmIsFiO~AF&wMY*CT8dyHCRJtDgS#9*c))D)UtZrMS=3|-~BQl-+)?qq>c7FdO9)In& zWcc?9$XontMQng;Q0eP!fV-C8aoDATbZkdtbqg$(RsHuNgfcQ}aBxs``Hm{Y`z63- z7WWk?nIvL*`GyAI@iq%&83@!X+AB6(vVT2Lg5CPCP@!PF%JTZp`#6llM-FZO7JGy9 zyM7LE$KQWDA4?*u=U(04aZUk_c_9~{l;1fntslymDjqRQTo9J|$c&qQE>w`m)?X5b z$Y4v3Xl_3ASXQRxg!isLGT4_t`!Dqa1iy3TD7~0OgJsaJvB?ct=WE0XrnvxL)Eqa% z+sT6NQ){Sz%1lGZf!{a*GF2Me8|#v+Zd@;=-h@t`aO?>t=Mk%ezr&K2pcnx)Yr zJYG36eg>839Xz{qkD$Zg8fu}a_cLS0lM$3Cx3}<>wz;hiwyePS2u9I#6OXDoGcBw@ z*)0v_eo+h^#^@-^Rg#B0bY7f6fqqUeryKbdNB-jQmEi`&uYglr^C1%`9qopDRd2P7 zvsdAO*$=bAWZAdIT;bfx^XAV0CC48FkeT7z71lU?J^7utIw z#o5~-N8$CCmsbN)3e^qFlEj4)aF)NrV155_qR%KrK*9b@tJ*R^4*39Y%;9nMAY? z6}9BCWAw=VsfDsLs~}_1p|tqm-x(SY9E?qKOTH^-Q370?k8tR@<;Wzgb23mTB59Mr z{?Z#P`5RcVQ_FDYyS%6}L-LhHcNVKf9l=`2x;LAdpPn*V1`Z#&SAg3k9Uu7YQOwRTrX|pLumK6<@fXn zo%?XhF&Hi&$U(=H1?Y+UUP~;T`7qYVXEN7^V4UNo(j#YO2AiY)Op@gIP0G_ zMto-H#Fx@`&jl^9)o)Ae++0;xboG)1sEwfOx`D_KbJAh^v&zUX4KDjFM8u3`e}kbn zl7|5z5-dY`Y`R$p)emB8UilS1x@vBJ{JrG@hNa$voWm4G(fr408Vc3^PYE228>SY@ z13Vm&dqoeb9#Sj&2We%dzxO&}9(H_6LEp^y+pjS7r)!hX@ha7+%zvo(yUi^nQQFdT zC$lOkY|VF6AH=t$Qz{d97BdQZJAs(}IYlr{$}OXDw9@&85*bxRf{C~$HNbd zHC$4bI0J+hR#z1hom3s7csi+chNW>1tO~~u0qdLr*zpPPP?(_PDlNq04r_mNgig0M zHq=QrLM;F2wP>ZzI~JTpwmf?@HoGe)WvEjakOdEk zL>2ppoJ4isHwRK!;9l%$PAcsm$CLzYqXYo;%W-u;(C9O&Dq7#Cs91N8<_+#+V1#d3 zoag2B(r|ZkMEDN|eVu8cU~*OHeCpYcLwzr8%e+QM$}`u{9N3`jL^&L|2S~il;Daib zijH1HbkO)*iLtAhLITc6ia^^qIr5N#Bf9gH^8k}1 zMuBo7%a!ER)rYxK$|!M-m;ywo)^NmH`@XctHEZX)Bd@58piBxu ze!>VGr#i5bgKo{xk0#-}&vhw$v#{WIoP@D)QQ7q`pUpqz?w!5MRYNM`jK*$1&%fE; zHYeVQy)|3^;D9xG_s>Ae663W`FDi^Ma!Wg@1u)DG7aZd@LWeKU7)H!4nJ;pvwJncR zW9vr>hqdJ{4bD^#+^JR*98cZFzF>TgHOU;Vi1d-koTX){RE4ES?e7d59RJej z+P7jjB#(ajRfGkF7?#U>+FosA88yD>v*u#`Q&gNS)8&e{35YqxzQzx{{Nlfs|E}cC zqE4?8h!C!xs0_NR`)Ha?gEN15x=)n+GFvks?~@}pT`6s)LkkCA`0L9O&*1<`K9^oc z`g6X}EyV@|X6v4HITMVGGgKQKq)3{eQlVYp%$7IqQ?a4h4BkB)o)o|lsz*YKn?G(2 zu!Ssd4UeO+!1Y_=RKl%m&o;H|ciRMN%0uzjqnZ0Z5<z>p*&YM#;&M62?I)*1+x*Apo$MsKZU)!(r zHHxCs68mB48Spue4Ey3ntuk$-io0x?g?6%i_sz_aA`SZ1!}OH%e>8s?G#?fHd%ZY4 ziE%Pa1+dk|D>H|AlYrr9oGWC)UMMHbDgHnD} z#|hV8`nqxI=ND8Z3a+d7BQv9P`W%7*7m`(xPn|iBluG^>3=|hk2Vb~SaW|HsPqrya zjLrr7Pt0cKjQ_nGX^A`P{8wr;lZmxI@c}md{SAErcP^J^em;@(zgF|zOK{zx*UVh{ zR$WPn@a47l3L59t2ixng1HwCcfky_$?I+T#G`al1XSTnZU^|^@_mrWUWGm%$vXV=4 zcOB{KjaL;M|1KsIBg`=9@BR8CuV?%@X*lGLlQlQpx(U9hFktmpoiW4xYx$3!3bD;u zb0E$~0{G)~hsi@WcU&rtv|@5fIubA+ujcQ?>SY{?jk-QqndU@4Djly*zL|gX4LqP^ zfiHB^(PB`YMc=3JN{(jV%F4-GA2g{5nhJj@k2}@6$`-6p?s*dHN6-l|{M|QUX@KPgAgGDGkFFqP18u))F26E&`n2~bsGiobtHK4h>+ zdhV}gNbO?PDK0;)#JRvGzO<#bVUxl+C~S>r&$Fhv-;WM9+>66;R_!e&aZ)3Vw$pzH z7QGs->VvU7c(x1~oKzKH8huvKsdufgPt!wRY0s}@!uzu-MCMYS@D^+TU7O1dd&L_2 zrq2Fk5!k&0?33J!eYaI`Dp&6L_FZTs#BEBAEsMgCog*K+4tt<$t4~UQ{ULRkSld>+;mOaI zWLE2@|M9DsyPLTFdxmo*XjbgY{>~wD2O-R3ZuOnmeYLLx)gQ#%_Bz{xb`FPoIFAm+ zH{bTy44s|{@Qv;X_;QKfHpC^+jG4qw|^lVxc0~B;$q+Bg_S5$)rK$;<}Gnx*|aq8N*D>l0uaPc3EGiolXfr-43Ye z{x>%Wn!I-?*I*Nu}WyN%}G7?stj`zA(&X_;>bt7)S&cs{@vqcpeV6fa zc1dK%HL5x?4LZvS24D^8njq=c3*dvo6DUSlo?hZ$^!ACKGb4Uw+4Uv&VI<)?k_EB@tF zasc!$jl>V#=>SQL!Up`tBUCt$Hk0&#TbpUeXW*=7{vrxqv2zY}RvBa3^uk*U@Wi`` zs4?6&$rbC2zX+I4)B0;H#(r05?I0lBTx8^#ec1O0XQREwj=#NG=`4*1%<O8QAtF&F0JJFBgfOFj(uV&dn8 z9Y{r?g;+VZ;cHwvnKhka#Rv73Q%4*OF^XOvDPCXw^|6tcwvj$(YMFohyzOaQog_r_ zzJ~C-orQ(>9RWqO)8j?^-zf}?Y`R6+w)Bmr_mK@$m&a?$k+Tx=yvkp!ObZ`PHydhU zU}L--V9MqW0Y*&7$!r3xePet-J=B6p?hUU=mB zb~7#SNL)2iKub?wOnmfHrCnws<`J2%6F>=#dhb>Wa;CP>^b%kYGA|nY z{J0|;$2m2-VT!G{@-P^%k||+P<7yJ6U=QO@(0%Ilb&gr$sh(*j7Kw(sxs!UHeUg7W z?2ehLseiCpVo~5g!&>0*nyt9t^-qK3d2ew^$b0JEsCUkv=gH;PMoa}D5qF%{O!s+k zo))GuAI5U>kTKxkP5IBNL``sAv7QBM%m1=5vck?9q&Wn7PrToondLe6@j3C~3Z@JG|_es7|LOb#`tLQ=j zd<|->$s%I?Bjwp|eod01LbA5O$BKhUUL0Kxt@SO6uu`H(Y3S>uOuXY0%04RoCvKYx z&le^Z{S47JkBoMHh?E!3`` zsL-~N2Xy3@AYLMqpo2GP$xXXXPXl~94abXQg_=z)Uh!XVdhl@cRc~bp$S1`K(_tf% zRTK)xG4AxZJQG}iu0@>g`R)iG)Da!hYM8si8_j+7R_1PFmOc}mjpQp13~F-Kgbk;@ zyt_r3X3bF4TpjW%B(x!%RFPgi>K>;3>Rr-KNOU9LI6okBLV$!kh7ZX&E@S= z+LfFo$RL?0t!Y>9FT0UG4?P6{^xMeV8__4DDRw;KG#J>NEwr4eF>a~9kT}>+)gRGk zl`0i5E;rWxY+6{SUH%<)fvY4onjNKG2dC{O>Zpz$fp~Sd<#XK-(y2De+mtfD&1t=L zuL=0*j^8QPE!4{T{8M|q;Ahi;&ItJfMN+sMpn`IQ(?QN?$jLPr{f4lQpwX9588+VVm+zZyIg|VWVi1auUho&` z*Ca}O-%zvUuJpDz*DVJGBCTuLP&q`4Be_&$k) zWqsuE^{>Q80SK1>ME$*uY-hA}$jX)}?~U&WH%tbRRI1K<4n_;Z3;IHLgOke~-Ivez zY95`xc`2j|dDoWsG2IU~iWVCQNuriaG*=P4(s-na$?;VP~(JF(y9*B5GD??EaOYQR%^p)|I0hJFAfAEHi?31kt!*Cg}NKWR+EJ^SBLp2@Nn?Ky? z2ITW)+WHh@gvwvS>JyHBercAH#IWwg(&t>ylqNI~cbg~_===+7ONA(pg!>$@aDi-e zkSIhbKNJD$#;E9kJh@ULRBys^kqpZfNuiOPlVd6r6~@iix^uVy1Dq&PAoufi@#(|A zqC^gcHa+p1lZrxgA#4b(fYydh-0agzjE!KVOT3fN1cg-)l{%XX4TsWirYOBZK!KmU z|GkX9MY>thsFnVMB+6%&=3laBy(=T%pJXBi8mQL|m!q8H0u zT5;hh&quyO-)CLNs-wsFMHoX(JCnGTN8c=X`q&wM39$cj>tN zpr_j()V%oSL`A*Dd()$d;!NQMUh`nKt*Tnh;?vCi>IoH;q7ZN>Y_4*=qzi=IStrcE!*;Dw)c>H~{MvLFF&B1!8_(*2pVQHOjcG>J? zrCCeVE;Tu3(IT;}$*ivQ2*KPoD zuBDk6yx;uN9UXMj>NwFTP?qtI?shVOutJCI6~}F?q&*$fI3r(fqc4{Ps$>ykUnycQ zVt)$b$Ei`bZwIL02cxgz4bulX=B(+LJ^rQ`-$wf*TXLW!Ygof5zw(J#GziEMHRCnXD2 zlzeQ7g{_@jwu;l)QGEakQn_d&Je{CjjoJp=PkD$ETLUNp-{XtVi>vgqAyoC5w4X!` zvb9;s2gV01EIb_bTH(+wXS@5bCA1!SoiP1;2TMk_yn+J0Ua+a-_h!`SCcbJVU}~Ly6aAvf0YIUntmnqu69bsIQLPND>0ISe0dv45bbT+7rX-kG zob@UBf{NW;H+uoVL}u!nEQy!D;JdmU3abo0gva%)yAVp{O)LUu&v((QL_0KpI=XIR zeu||YCAit2w)8+iKljf5h!KIECpxFZY$t4rTdOzbh6DzZG0aSm-*HMG2Qm)WPQs^& zfZ`JJQ?;x}P>OFF{P;;AU`+sW2_6HG0|inm&WJmARJhG53w2FPE4G4P!#)|_T{u+& z3Wf*9fG}n!;YT2D$aq7P>kuhVsM0}u49s4v=T{9FmS;aNFuItFnZDRY{nS5TjL|M0 z*i}Gj6E%!QBwh6ZryKWSI#F}C7yH}wYT&fg+JM`B=pnMnUmO4ksd_tEmGmQ2{;F^@ zlaa;Jm8B9IZDb-7CvM)CR6P{OIQqCNj1PBLPG($k4E$Lr#RIS&^O3Zi*GMp^!mMvI zuyI2MFLNR}V3Rw?ND%ZRR^sC}@y#R$gx?k^=S?+J1b-(045ABFC-NQ{lp@(BmZ^YT z=rd|M97BY(JVavq-aoavHfF%&Y*$eLVlLyB+Sr@)8g^(`)5A&+ymD0sYA;-!!PPR_ zVem#@F^To0%kW=!dSK3rx$@htiJJ)>hF_81dNtuW;jeLd+(Ux+h-}kQ=}{2`HRO_s zEIV|`%&A2h66#OOH_>;6529Vb(%X0ncp^~S&Plwor&1Wa6p(f&Wdg5)^&Go|y-qD> zTUPO)!}+q{bttgaAs={fh|mO*0TosRU78lS8qZA&NdkHS#+{c;VLvw_o!fPlS$Kdh zlC=08PW|{7ZE*Ez;$}KT<`eJiw>z}}Ef~-MSg>JiuOu?nyR&{}a$6fX;=}0coG-z1 z{Rfheja2;rs#yi)VY~+VAa+BBZ{APr#L!HmS7u?fY;37{a7^cwl8b`Oy(s#~Xn&!S1Hk_ zC7h|lrUQ=jIosBbxHm3oay`9z6m1byD3owP1fqlQ7uXvOd;JBfM1a!jg*RubrSu(=u}Yc7mae9w^X*gLv!Pcd7gtSLuh&%WXG_uFIJ0GhA(>Y zSw<$~1HhJ}x{gqXE02rPeCK{3AyNptIxu-7n1+P2^A zFH^V}wHvf$0XT=rHH+O_LlE2pBAhs1r@KTa6ziu)#EmG=ZyiFFIe1@=;l%EH~dE00Mo0q#s(&St%T$sW-EC*h! zE%;uBT@auxE59MeL0Vy+l)U1mLLvH#ocw{rUt?u;u$RL6m52t01#_E+Cr0V(%a}ou zhjCS~dPQiLirPY3BP(rB()A(S-)XFJYvvgZB?}7?IfrJy6c^Qm-u+^1r44X!Y@$hl z4|OCv?j8EAJdXhIHS5YB7w}j;p(P-YHR)yQ;@xpSpWpXu?r|uu_^eT82~sOMgA!!+ zqh`-3lPDvu;sH%gC6x6%+RD#8l3V~!j1<4-(MN*#y50Kk%EV=%3ti&#t8ir@dd!($FKf{a`xF#T zT_1?`DpF*6Zz3?*_kfONNQ1-`Xos9xv0*Y`xo}Oj6{|?#vFGhttlP6RVwYg$MOA^7 z7@_yeG5Ku!HYG1`N-qcT_VcSIz;Vi#ZecHT{mJxnalAlbP$A@DJwd|!u9pJ4~5O(te)=tL1O|zIW1*AAO3>X1S#&q!k zkn&?r%{5L{Ac+;FhluOst8UVztY&>5CjY;6a{S|@hgDxZ1=F16Av-rro$2?h3CQ+T zJI<-dm+1iK!d+(A)FU7U|6!^>X@00)Dlx{*>X<~PGPKM3c4W-R9MF%QwNq<{FzFN0 z$yMlyL=wZtZ7w*94fEkLc1hX|4cS{qP~kMGKcrf_i1PtP6rSiPH0m5yz0FKqv@mRs zh4O(LJtbdc;TsR-L3Dla3nlsq(9t{%ZY@J`a>{;};V5^Y6-ZIR*>clCN=Y4k)<69? z*ebsNiN+vYOzi^!efv_F8drP++OJ3jFbZ&orcudh9$1vQJBv_Ky`n*Rg09IJL$nY$ z!AiWrJi~5pmvsyP9G7zl372^bG&{9im?h~EvMK1=KOhmfDh;joDeeP#L?PZcpUHWm z5L@AD+2g!U`NN1{C||f(B8vKy(z8LdOvaTCClLX7=|XY7c0)g7xp5Eqwa2lW_asDG zuEqvUtpDfDFa@(NBo&|C<^i1VSwdHLcAN&PPSCIevsA%Ne#TK0d0n}j0T3Tp+f7;3f3q}hz0*mKr8iZLWn{7P`fPZCzzc$dfp|-a(iW0c<%Z0l#(stm{;t4=PI@H3DHVE_@JVR5b5^Q0)bo^J4 zj$TQ1aYERIk&pb=z9-y%#Sp}5?UHmip68sJ5fbe%_&ghiE@by4-Ps|eVhW_s^G|EE z$T9dBRfz4pJj0;GJ3v!RB=A7A&jjb5dXD`4fE`5~;qrAr3OghL-`>X94i{7Q3Oi!BBLxJ4l**!@^U(m|nB(UO& z_AS^>o0L8Ek4(=8s+J!EF8q4RGV_L}C;f)35}%_pVCH!yY?yMlsSk|ji3OZPCx!Vi z5BAh6FKBV;9wq_wx#6LCyt6{6OBXu8xIGW{$Avm92PF{w61dU5jr;l^8$38yOx5x1 z+Z#V&eh4lItDE|8Py-txb768JFpu0qv-!gVMsxhUwAT&>?p)9>yW8>Tq>$pgo{>N% zk2+L{8kSum&ZnlLLe}IccaG)5r_*-M_(8BvApfxj;9cE7j*8|rlDJyRIw*fy`xR;R zSuJM??^Rj@{%#T;Yu>v#aoBrbLJRb=p_?L{Yi3~_3ax&VkXt*1)9lslN?#X;n6tzo zfb!8c4l;BTyBjI6Z-uzwoz~Lw+=ZSVWq^LOE^RMOl8(tSONuzA__iy6Vx&Xd;Zg*j zdtq$4zH}Ya-@#cnM8R-cCa2AXJhMGJw-meGfoui0`GfWdYGK@*;Du}>HkHJ`sRzyES1Gp28r-ETeEjtv0vF_u?u^n5Up9o^EH;ZvL zAu%^V>xl3?<#LGkH-Wjis%(hdIr1t|bDDe88Z^ZTJIlK{=tC=FFmEF6+hF|)XJK%r zOTdgC(PXIknK_zsr51(c%$Uhff~@jKi?;dCelI%!`+V9 zXM->nO~|yaz+sCM$QND*Oh8S#l*v&jm(1Hz%oBQ61E?HrNnk35^elTMF1kNzx{fLiqCNCIy@g_6{KFn4T zc%V_FlZ;#5tc>7v0^+K{OE zPIhO~+{^!2`GqP$6xUl9!~(rZ_&yQ(c6IzMZ^}n6f!;=9 zbt!Hmkj-ixNoJR!7?kdA7dZK?xQ`#;hVdi(!JV|#L~#H#(RiB^-eWu58b1US!7Gd` z<11q@@4d}o)=}qt!N#xri?*72A>IELpHI;Mo$PR&<#vM0iRx3Jc3*nV>l&9f!2XX| z2*wSXHcXt4^LE6;rMk&6rRy1;Y4$i5(Q1Z#l8IQKu2-#mkazbIqe+=yTq-Ce&fiI& z;}0}3F((%0r@;P-_!}8ymMAfR133h7&Ih5N5fYfabC2W^n7C)6A+R#3f;TNLth@&l zTFHH{dqYG{F!gX0UMwMJNVb=ayXYfMI0Cm!Jgv(tEpEHB82W~Phvo7;X()dP6^X$F zLo8S@4GDZWUt1y2WAbc9AOq7Qfa=4H^RAxArdM43^EzeV+a%)?aHlQ++%Z|LAbyx* z?IhqjH+!fOdD#uj)#HlyzG8G->T3qg+_Gx&)z*~(uFq@ACLOConZq?%3-|<%;X193 zX>ao6%hXlGK6oXBkVxIG9FEt&juF{;csDVGX3zA9XD_h@3}&k6Q2Jo^`z}CG4a*i> zpbJt0W*UiCJL@hE_5#;2_Ar}}El?auQ?=QEt$}fU!^we+5D%-)0J`(vzFo|~;FiF| zBx54ATr#jBHOB{|1Frjc0kbo9@YY2|pxYUu4(glLWZQ4(WDa_{u>WMDH#n{Y+@EBc2iT2$f&2QVE7iWZWR*LN?I~QvGjZd(SWn>g8yO3FF$? z!HvjNYthj;Ht*Tzv|5=kO#xe%7%pZ=goPE**QIDeg>eGv{ty|E9g)>RaSu9jJX#%u zAvJJPkaoJj)rOVR02@B*Eq6FGU-G~1>Ueuv;`ywUKunQ&IcW4AK#*1kD7QuFaN}%4 zvpsKrx+H=5P9-XXYX%fhjPYR%t^}#m!G7~zGkg_+ zQER!-5ateX%!+B$4(1BK*%*j{>{U4JCK(lV6FF7$UVgYQfAFj5^jmo+Bx%!&g;LmzTo&k zi)~J;@5UvN24SPiX@i5h=^)yT4d%2ft6HN(AGvPrY~XxvZr;&)J6AFJJ7q3|$4!P+ zb=5!8vgcDir^O|NWwBY%w*rdfYjujgk}GnS1=L z-ihu9R6vy32C$~WH5_Ja~Nn6bqF686RMS>_65FIAW&FyafW34@x46uFOa z_t`hD@VyPwWV0pZ5MQ4#*{6^ZR=Y&f%iN5s%VF zY9*;31fH2dTK`rV)If-@L!8RAAP#VSA@gXZvcBl{&7y6FNtBYMllJz@!(_}{MJ?XF z_Z4E3Rdk`?gF1kg^1-!RvVQcb%!TMs`}UW2C)Q)(>It|RKQ_}J^oBJuicx~Jx@TPT zA`;zK=ZuZY$A5>{C+XU9rF44CK0MZRU+ml^wy6~YcQOvGueQlTn-a0BJM#cr^24|};*H#uSdO`K|X%+)tUP%6Hdp9F|$v59_K5EzWA z2&UggCTyxPS^fB1Zg+O)^)_T59eadqJLD7%3Eh2|wZ}PeG&ga{v6%4TM^jdu(5O{> zvQrq_aE49+q4Vtji=kE_{|}Ad3OW_vAwUML&BvJf5hujiWPpb1Bb72G>#+X=1rxIt literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_reset_all.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_reset_all.png new file mode 100644 index 0000000000000000000000000000000000000000..c6728740865db94a38a7d740accd930a9c8326d5 GIT binary patch literal 30281 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 + ovqt_plugin_bnp_manager + BNPManager + 0.1 + Krolock + Edit BNP Files + + + + \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_form.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_form.ui index 77c4b895f..404444fc0 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_form.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_form.ui @@ -91,7 +91,7 @@ - false + true diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_widget.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_widget.cpp index 648e0e1a5..e00d07cec 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_widget.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_widget.cpp @@ -186,12 +186,11 @@ void CAttribWidget::changeUseScheme(int index) void CAttribWidget::openSchemeBankDialog() { - CSchemeBankDialog *dialog = new CSchemeBankDialog(this); - dialog->setModal(true); - dialog->show(); - dialog->exec(); - delete dialog; - //updateUi(); + CSchemeBankDialog dialog(this); + dialog.setModal(true); + dialog.show(); + dialog.exec(); + updateUi(); } void CAttribWidget::inputValueUpdate(void) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_widget.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_widget.h index 7bd929d72..da308aba7 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_widget.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/attrib_widget.h @@ -58,7 +58,7 @@ public: /// Force to update dialog content void updateUi(); - /// Сonnects all the slots with signals + /// Connects all the slots with signals void init(); /// Sets the pointer CWorkspaceNode* in the wrappers. @@ -192,6 +192,7 @@ protected: QDialog *_SchemeWidget; Ui::CAttribWidget _ui; + friend class CSchemeBankDialog; }; /* class CAttribWidget */ /** diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_editor.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_editor.cpp index d03cdab3d..12ea96c8a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_editor.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_editor.cpp @@ -73,11 +73,14 @@ void CParticleEditor::release() { stop(); closeWorkspace(); + delete _SchemeManager; } void CParticleEditor::setActiveNode(CWorkspaceNode *node) { if (node == _ActiveNode) return; + if (node == 0) + _ActiveNode->getPSModel()->hide(); _ActiveNode = node; bool wasRunning = _State == State::RunningSingle; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_node.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_node.cpp index 3dfc1ce2c..15761c505 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_node.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_node.cpp @@ -378,6 +378,7 @@ void CParticleWorkspace::removeNode(uint index) { nlassert(index < _Nodes.size()); _Nodes[index] = NULL; // delete the smart-ptr target + delete _Nodes[index]; _Nodes.erase(_Nodes.begin() + index); touch(); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_workspace_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_workspace_dialog.cpp index cb49def05..74182120c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_workspace_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_workspace_dialog.cpp @@ -305,6 +305,8 @@ void CParticleWorkspaceDialog::customContextMenu() _instanciateAction->setEnabled(stopped); _savePSAction->setEnabled(stopped); _saveAsPSAction->setEnabled(stopped); + _removeFromWSAction->setEnabled(stopped); + _clearContentAction->setEnabled(stopped); popurMenu->exec(QCursor::pos()); delete popurMenu; @@ -369,13 +371,14 @@ void CParticleWorkspaceDialog::clearContent() void CParticleWorkspaceDialog::removePS() { - if (_treeModel->getOwnerNode(_currentItem) == Modules::psEdit().getActiveNode()) + CWorkspaceNode *node = _currentItem->getNode(); + if (node == Modules::psEdit().getActiveNode()) Modules::psEdit().setActiveNode(NULL); QModelIndex index = _ui.treeView->currentIndex(); _ui.treeView->setCurrentIndex(index.parent()); clickedItem(index.parent()); - Modules::psEdit().getParticleWorkspace()->removeNode(static_cast(index.internalPointer())->getNode()); + Modules::psEdit().getParticleWorkspace()->removeNode(node); _treeModel->removeRows(index.row(), index.parent()); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_dialog.cpp index 66deb2a17..bca0f4879 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_dialog.cpp @@ -1,24 +1,33 @@ -// NeL - 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 +// NeL - 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 . // Project includes #include "stdpch.h" #include "scheme_bank_dialog.h" +#include "scheme_manager.h" #include "modules.h" +// NeL includes +#include + +// Qt includes +#include +#include +#include + namespace NLQT { @@ -27,6 +36,16 @@ CSchemeBankDialog::CSchemeBankDialog(CAttribWidget *attribWidget, QWidget *paren { _ui.setupUi(this); _attribWidget = attribWidget; + + connect(_ui.createButton, SIGNAL(clicked()), this, SLOT(createScheme())); + connect(_ui.currentButton, SIGNAL(clicked()), this, SLOT(setCurrentScheme())); + connect(_ui.removeButton, SIGNAL(clicked()), this, SLOT(removeScheme())); + connect(_ui.loadButton, SIGNAL(clicked()), this, SLOT(loadBank())); + connect(_ui.saveButton, SIGNAL(clicked()), this, SLOT(saveBank())); + connect(_ui.listWidget, SIGNAL(itemSelectionChanged()), this, SLOT(enableButtons())); + connect(_ui.listWidget, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(changeNameScheme(QListWidgetItem *))); + + buildList(); } CSchemeBankDialog::~CSchemeBankDialog() @@ -35,27 +54,125 @@ CSchemeBankDialog::~CSchemeBankDialog() void CSchemeBankDialog::createScheme() { + bool ok; + QString text = QInputDialog::getText(this, tr("Insert new scheme"), + tr("Set name:"), QLineEdit::Normal, + "new scheme", &ok); + if (ok && !text.isEmpty()) + { + NL3D::CPSAttribMakerBase *attribMakerBase = _attribWidget->getCurrentSchemePtr()->clone(); + Modules::psEdit().getSchemeManager()->insertScheme(text.toStdString(), attribMakerBase); + + CSchemeItem *item = new CSchemeItem(text, _ui.listWidget); + item->setUserData(attribMakerBase); + item->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled); + } } void CSchemeBankDialog::setCurrentScheme() { - //SchemeManager.insertScheme(cn.getName(), getCurrentSchemePtr()->clone()); + CSchemeItem *item = dynamic_cast(_ui.listWidget->currentItem()); + + NL3D::CPSAttribMakerBase *attrib = item->getUserData(); + nlassert(attrib); + + _attribWidget->setCurrentSchemePtr(attrib->clone()); + _attribWidget->updateUi(); } void CSchemeBankDialog::removeScheme() { + CSchemeItem *item = dynamic_cast(_ui.listWidget->currentItem()); + + NL3D::CPSAttribMakerBase *attrib = item->getUserData(); + nlassert(attrib); + Modules::psEdit().getSchemeManager()->remove(attrib); + _ui.listWidget->removeItemWidget(item); + delete item; + + if (_ui.listWidget->count() == 0) + { + _ui.currentButton->setEnabled(false); + _ui.removeButton->setEnabled(false); + } } void CSchemeBankDialog::saveBank() { + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save scheme bank file"), ".", + tr("Scheme bank files (*.scb)")); + + if (!fileName.isEmpty()) + { + try + { + NLMISC::COFile iF; + iF.open(fileName.toStdString()); + NLQT::CSchemeManager *schemeManager = Modules::psEdit().getSchemeManager(); + iF.serial(*schemeManager); + } + catch (std::exception &e) + { + QMessageBox::critical(this, "Scheme manager", tr("Error saving scheme bank : %1").arg(e.what())); + return; + } + } } void CSchemeBankDialog::loadBank() { + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open scheme bank file"), ".", + tr("Scheme bank files (*.scb)")); + + if (!fileName.isEmpty()) + { + NLQT::CSchemeManager sm; + try + { + NLMISC::CIFile iF; + iF.open(fileName.toStdString()); + iF.serial(sm); + Modules::psEdit().getSchemeManager()->swap(sm); + } + catch (std::exception &e) + { + QMessageBox::critical(this, "Scheme manager", tr("Error loading scheme bank : %1").arg(e.what())); + return; + } + buildList(); + } } -void CSchemeBankDialog::buildList() +void CSchemeBankDialog::changeNameScheme(QListWidgetItem *item) { + CSchemeItem *schemeItem = dynamic_cast(item); + + NL3D::CPSAttribMakerBase *attrib = schemeItem->getUserData(); + nlassert(attrib); + + Modules::psEdit().getSchemeManager()->rename(attrib, item->text().toStdString()); +} + +void CSchemeBankDialog::enableButtons() +{ + _ui.currentButton->setEnabled(true); + _ui.removeButton->setEnabled(true); +} + +void CSchemeBankDialog::buildList() +{ + _ui.listWidget->clear(); + typedef std::vector TSchemeVect; + static TSchemeVect schemes; + Modules::psEdit().getSchemeManager()->getSchemes(_attribWidget->getCurrentSchemePtr()->getType(), schemes); + for (TSchemeVect::const_iterator it = schemes.begin(); it != schemes.end(); ++it) + { + CSchemeItem *item = new CSchemeItem(it->first.c_str(), _ui.listWidget); + item->setUserData(it->second); + item->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled); + } } } /* namespace NLQT */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_dialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_dialog.h index a02406468..8f9f300b8 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_dialog.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_dialog.h @@ -1,17 +1,17 @@ -// NeL - 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 +// NeL - 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 SCHEME_BANK_DIALOG_H @@ -27,12 +27,37 @@ #include "nel/3d/particle_system.h" // Project includes +#include "attrib_widget.h" #include "ps_wrapper.h" namespace NLQT { class CAttribWidget; +/** +@class CSchemeItem +@brief Contain pointer to NL3D::CPSAttribMakerBase. +*/ +class CSchemeItem: public QListWidgetItem +{ +public: + CSchemeItem(const QString &text, QListWidget *parent = 0, int type = UserType ): + QListWidgetItem(text, parent, type), _attrib(NULL) {} + + void setUserData(NL3D::CPSAttribMakerBase *attrib) + { + _attrib = attrib; + } + NL3D::CPSAttribMakerBase *getUserData() const + { + return _attrib; + } + +private: + + NL3D::CPSAttribMakerBase *_attrib; +}; /* class CSchemeItem */ + class CSchemeBankDialog: public QDialog { Q_OBJECT @@ -47,9 +72,11 @@ private Q_SLOTS: void removeScheme(); void saveBank(); void loadBank(); + void enableButtons(); + void changeNameScheme(QListWidgetItem *item); private: - void buildList(); + void buildList(); CAttribWidget *_attribWidget; Ui::CSchemeBankDialog _ui; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_form.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_form.ui index e7dd281f8..f8fa10865 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_form.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_bank_form.ui @@ -14,31 +14,27 @@ Sceme bank - + - Create + Put current - - - Rename - - - - + + false + Remove - + Qt::Vertical @@ -51,24 +47,33 @@ - + + + true + Load bank - + + + true + Save bank - + + + false + 0 @@ -105,7 +110,10 @@ - + + + false + Set current diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_manager.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_manager.cpp index 62e847a73..c00422af5 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_manager.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scheme_manager.cpp @@ -18,7 +18,7 @@ #include "scheme_manager.h" #include "nel/3d/ps_attrib_maker.h" -namespace NLQT +namespace NLQT { CSchemeManager::~CSchemeManager() @@ -34,7 +34,7 @@ void CSchemeManager::insertScheme(const std::string &name, NL3D::CPSAttribMakerB { nlassert(scheme); TSchemeInfo si(std::string(name), scheme); - _SchemeMap.insert(TSchemeMap::value_type(std::string(scheme->getType()), si)); + _SchemeMap.insert(TSchemeMap::value_type(std::string(scheme->getType()), si)); } void CSchemeManager::getSchemes(const std::string &type, std::vector &dest) @@ -49,30 +49,30 @@ void CSchemeManager::getSchemes(const std::string &type, std::vectorsecond.first); // name f.serialPolyPtr(smIt->second.second); // scheme - } + } } else { _SchemeMap.clear(); - + std::string name; NL3D::CPSAttribMakerBase *scheme = NULL; sint32 size; f.serial(size); for (sint32 k = 0; k < size; ++k) - { + { f.serial(name); f.serialPolyPtr(scheme); insertScheme(name, scheme); @@ -80,12 +80,12 @@ void CSchemeManager::serial(NLMISC::IStream &f) throw(NLMISC::EStream) } } -void CSchemeManager::swap(CSchemeManager &other) +void CSchemeManager::swap(CSchemeManager &other) { this->_SchemeMap.swap(other._SchemeMap); } -void CSchemeManager::remove(NL3D::CPSAttribMakerBase *am) +void CSchemeManager::remove(NL3D::CPSAttribMakerBase *am) { TSchemeMap::iterator smIt; for (smIt = _SchemeMap.begin(); smIt != _SchemeMap.end(); ++smIt) @@ -101,7 +101,7 @@ void CSchemeManager::remove(NL3D::CPSAttribMakerBase *am) } // rename a scheme, given a pointer on it -void CSchemeManager::rename(NL3D::CPSAttribMakerBase *am, const std::string &newName) +void CSchemeManager::rename(NL3D::CPSAttribMakerBase *am, const std::string &newName) { TSchemeMap::iterator smIt; for (smIt = _SchemeMap.begin(); smIt != _SchemeMap.end(); ++smIt) @@ -110,7 +110,7 @@ void CSchemeManager::rename(NL3D::CPSAttribMakerBase *am, const std::string &ne } if (smIt != _SchemeMap.end()) { - smIt->second.first = newName; + smIt->second.first = newName; } } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/CMakeLists.txt index 0f520c9d8..272c7b962 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/CMakeLists.txt @@ -10,25 +10,23 @@ SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin. ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) SET(OVQT_PLUG_TRANSLATION_MANAGER_HDR translation_manager_plugin.h - translation_manager_main_window.h - translation_manager_settings_page.h - translation_manager_editor.h - source_selection.h - ftp_selection.h - editor_worksheet.h - editor_phrase.h - extract_new_sheet_names.h - extract_bot_names.h) + translation_manager_main_window.h + translation_manager_settings_page.h + translation_manager_editor.h + source_selection.h + ftp_selection.h + editor_worksheet.h + editor_phrase.h +) SET(OVQT_PLUG_TRANSLATION_MANAGER_UIS translation_manager_settings_page.ui - translation_manager_main_window.ui - source_selection.ui - ftp_selection.ui) + translation_manager_main_window.ui + source_selection.ui + ftp_selection.ui) SET(OVQT_PLUG_TRANSLATION_MANAGER_RCS ftp_selection.qrc) SET(QT_USE_QTGUI TRUE) -SET(QT_USE_QTOPENGL TRUE) SET(QT_USE_QTNETWORK TRUE) QT4_WRAP_CPP(OVQT_PLUG_TRANSLATION_MANAGER_MOC_SRC ${OVQT_PLUG_TRANSLATION_MANAGER_HDR}) @@ -42,7 +40,7 @@ SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) ADD_LIBRARY(ovqt_plugin_translation_manager MODULE ${SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_translation_manager ovqt_plugin_core nelmisc nel3d nelligo nelgeorges ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) +TARGET_LINK_LIBRARIES(ovqt_plugin_translation_manager ovqt_plugin_core nelmisc nelligo nelgeorges ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) NL_DEFAULT_PROPS(ovqt_plugin_translation_manager "NeL, Tools, 3D: Object Viewer Qt Plugin: Translation Manager") NL_ADD_RUNTIME_FLAGS(ovqt_plugin_translation_manager) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.cpp index c1633c3be..a1c59a11f 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.cpp @@ -1,5 +1,4 @@ // Translation Manager Plugin - OVQT Plugin -// Copyright (C) 2010 Winch Gate Property Limited // Copyright (C) 2011 Emanuel Costea // // This program is free software: you can redistribute it and/or modify @@ -15,32 +14,32 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +// Project includes +#include "editor_phrase.h" +#include "translation_manager_constants.h" + // Nel includes #include "nel/misc/path.h" #include "nel/misc/diff_tool.h" // Qt includes +#include +#include +#include +#include +#include #include -#include #include #include -#include -#include -#include -#include -#include - -// Project includes -#include "editor_phrase.h" -#include "translation_manager_constants.h" using namespace std; -namespace TranslationManager { +namespace TranslationManager +{ void CEditorPhrase::open(QString filename) { - vector phrases; + std::vector phrases; if(readPhraseFile(filename.toStdString(), phrases, false)) { text_edit = new CTextEdit(this); @@ -53,26 +52,28 @@ void CEditorPhrase::open(QString filename) QFile file(filename); file.open(QIODevice::ReadOnly | QIODevice::Text); QTextStream in(&file); - // set the file content to the text edit + // set the file content to the text edit QString data = in.readAll(); text_edit->append(data); // window settings setCurrentFile(filename); - setAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_DeleteOnClose); editor_type = Constants::ED_PHRASE; current_file = filename; connect(text_edit->document(), SIGNAL(contentsChanged()), this, SLOT(docContentsChanged())); connect(text_edit->document(), SIGNAL(undoCommandAdded()), this, SLOT(newUndoCommandAdded())); - } else { - QErrorMessage error; - error.showMessage("This file is not a phrase file."); - error.exec(); - } + } + else + { + QErrorMessage error; + error.showMessage("This file is not a phrase file."); + error.exec(); + } } void CEditorPhrase::newUndoCommandAdded() { - current_stack->push(new CUndoPhraseNewCommand(text_edit)); + current_stack->push(new CUndoPhraseNewCommand(text_edit)); } void CEditorPhrase::docContentsChanged() @@ -97,44 +98,37 @@ void CEditorPhrase::saveAs(QString filename) QTextStream out(&file); out.setCodec("UTF-8"); out.setGenerateByteOrderMark(true); - out<toPlainText(); + out << text_edit->toPlainText(); current_file = filename; setCurrentFile(current_file); } - - void CEditorPhrase::closeEvent(QCloseEvent *event) { - if(isWindowModified()) - { - QMessageBox msgBox; - msgBox.setText("The document has been modified."); - msgBox.setInformativeText("Do you want to save your changes?"); - msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Save); - int ret = msgBox.exec(); - switch (ret) - { - case QMessageBox::Save: - save(); - event->accept(); - close(); - break; - case QMessageBox::Discard: - event->accept(); - close(); - break; - case QMessageBox::Cancel: - event->ignore(); - break; - default: - break; - } - } else { - event->accept(); - close(); - } + if(isWindowModified()) + { + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Question); + msgBox.setText(tr("The document has been modified.")); + msgBox.setInformativeText(tr("Do you want to save your changes?")); + msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Save); + + int ret = msgBox.exec(); + switch (ret) + { + case QMessageBox::Save: + save(); + break; + case QMessageBox::Discard: + break; + case QMessageBox::Cancel: + event->ignore(); + return; + } + } + event->accept(); + close(); } } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.h index f26dec73e..b9955fa48 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.h @@ -18,6 +18,9 @@ #ifndef EDITOR_PHRASE_H #define EDITOR_PHRASE_H +// Project includes +#include "translation_manager_editor.h" + // Qt includes #include #include @@ -32,23 +35,23 @@ #include #include -// Project includes -#include "translation_manager_editor.h" - -namespace TranslationManager { +namespace TranslationManager +{ class CTextEdit : public QTextEdit { Q_OBJECT + private: - QUndoStack* m_undoStack; + QUndoStack *m_undoStack; + public: - CTextEdit(QWidget* parent = 0) : QTextEdit(parent) - { + CTextEdit(QWidget *parent = 0) : QTextEdit(parent) + { setUndoRedoEnabled(true); } //void keyPressEvent(QKeyEvent *event); - void setUndoStack(QUndoStack* undoStack) + void setUndoStack(QUndoStack *undoStack) { m_undoStack = undoStack; } @@ -57,20 +60,22 @@ public: class CEditorPhrase : public CEditor { Q_OBJECT + public: - CTextEdit *text_edit; -public: - CEditorPhrase(QMdiArea* parent) : CEditor(parent) {} - CEditorPhrase() : CEditor() {} - void open(QString filename); - void save(); - void saveAs(QString filename); - void activateWindow(); + CEditorPhrase(QMdiArea *parent) : CEditor(parent) {} + CEditorPhrase() : CEditor() {} + void open(QString filename); + void save(); + void saveAs(QString filename); + void activateWindow(); void closeEvent(QCloseEvent *event); + public Q_SLOTS: void docContentsChanged(); void newUndoCommandAdded(); +private: + CTextEdit *text_edit; }; class CUndoPhraseNewCommand : public QUndoCommand @@ -79,7 +84,7 @@ public: CUndoPhraseNewCommand(CTextEdit *textEdit, QUndoCommand *parent = 0) : QUndoCommand("Inserting/Removing characters", parent), m_textEdit(textEdit) - { } + {} ~CUndoPhraseNewCommand() {} @@ -92,96 +97,102 @@ public: { m_textEdit->redo(); } + private: - CTextEdit* m_textEdit; + CTextEdit *m_textEdit; }; class SyntaxHighlighter : public QSyntaxHighlighter { public: SyntaxHighlighter(QTextEdit *parent) : QSyntaxHighlighter(parent) - { - HighlightingRule rule; + { + HighlightingRule rule; - translateStringFormat.setFontWeight(QFont::Bold); - translateStringFormat.setForeground(Qt::darkMagenta); - rule.pattern = QRegExp("\\[.+\\]"); - rule.format = translateStringFormat; - highlightingRules.append(rule); + translateStringFormat.setFontWeight(QFont::Bold); + translateStringFormat.setForeground(Qt::darkMagenta); + rule.pattern = QRegExp("\\[.+\\]"); + rule.format = translateStringFormat; + highlightingRules.append(rule); + singleLineCommentFormat.setForeground(Qt::red); + rule.pattern = QRegExp("//[^\n]*"); + rule.format = singleLineCommentFormat; + highlightingRules.append(rule); - singleLineCommentFormat.setForeground(Qt::red); - rule.pattern = QRegExp("//[^\n]*"); - rule.format = singleLineCommentFormat; - highlightingRules.append(rule); + multiLineCommentFormat.setForeground(Qt::red); - multiLineCommentFormat.setForeground(Qt::red); + quotationFormat.setForeground(Qt::darkGreen); + rule.pattern = QRegExp("\".*\""); + rule.format = quotationFormat; + highlightingRules.append(rule); - quotationFormat.setForeground(Qt::darkGreen); - rule.pattern = QRegExp("\".*\""); - rule.format = quotationFormat; - highlightingRules.append(rule); + functionFormat.setFontItalic(true); + functionFormat.setForeground(Qt::blue); + rule.pattern = QRegExp("\\(.+\\)"); + rule.format = functionFormat; + highlightingRules.append(rule); - functionFormat.setFontItalic(true); - functionFormat.setForeground(Qt::blue); - rule.pattern = QRegExp("\\(.+\\)"); - rule.format = functionFormat; - highlightingRules.append(rule); - - commentStartExpression = QRegExp("/\\*"); - commentEndExpression = QRegExp("\\*/"); + commentStartExpression = QRegExp("/\\*"); + commentEndExpression = QRegExp("\\*/"); } - void highlightBlock(const QString &text) - { - Q_FOREACH(const HighlightingRule &rule, highlightingRules) { - QRegExp expression(rule.pattern); - int index = expression.indexIn(text); - while (index >= 0) { - int length = expression.matchedLength(); - setFormat(index, length, rule.format); - index = expression.indexIn(text, index + length); - } - } - setCurrentBlockState(0); + void highlightBlock(const QString &text) + { + Q_FOREACH(const HighlightingRule &rule, highlightingRules) + { + QRegExp expression(rule.pattern); + int index = expression.indexIn(text); + while (index >= 0) + { + int length = expression.matchedLength(); + setFormat(index, length, rule.format); + index = expression.indexIn(text, index + length); + } + } + setCurrentBlockState(0); - int startIndex = 0; - if (previousBlockState() != 1) - startIndex = commentStartExpression.indexIn(text); + int startIndex = 0; + if (previousBlockState() != 1) + startIndex = commentStartExpression.indexIn(text); - while (startIndex >= 0) { - int endIndex = commentEndExpression.indexIn(text, startIndex); - int commentLength; - if (endIndex == -1) { - setCurrentBlockState(1); - commentLength = text.length() - startIndex; - } else { - commentLength = endIndex - startIndex - + commentEndExpression.matchedLength(); - } - setFormat(startIndex, commentLength, multiLineCommentFormat); - startIndex = commentStartExpression.indexIn(text, startIndex + commentLength); - } - } + while (startIndex >= 0) + { + int endIndex = commentEndExpression.indexIn(text, startIndex); + int commentLength; + if (endIndex == -1) + { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } + else + { + commentLength = endIndex - startIndex + + commentEndExpression.matchedLength(); + } + setFormat(startIndex, commentLength, multiLineCommentFormat); + startIndex = commentStartExpression.indexIn(text, startIndex + commentLength); + } + } - private: - struct HighlightingRule - { - QRegExp pattern; - QTextCharFormat format; - }; - QVector highlightingRules; +private: + struct HighlightingRule + { + QRegExp pattern; + QTextCharFormat format; + }; + QVector highlightingRules; - QRegExp commentStartExpression; - QRegExp commentEndExpression; + QRegExp commentStartExpression; + QRegExp commentEndExpression; - QTextCharFormat keywordFormat; - QTextCharFormat classFormat; - QTextCharFormat singleLineCommentFormat; - QTextCharFormat multiLineCommentFormat; - QTextCharFormat quotationFormat; - QTextCharFormat functionFormat; - QTextCharFormat translateStringFormat; + QTextCharFormat keywordFormat; + QTextCharFormat classFormat; + QTextCharFormat singleLineCommentFormat; + QTextCharFormat multiLineCommentFormat; + QTextCharFormat quotationFormat; + QTextCharFormat functionFormat; + QTextCharFormat translateStringFormat; }; } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.cpp index c8a101e0f..7041a5178 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.cpp @@ -15,6 +15,11 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +// Project includes +#include "editor_worksheet.h" +#include "extract_bot_names.h" +#include "translation_manager_constants.h" + // Qt includes #include #include @@ -24,97 +29,103 @@ #include #include -// Project includes -#include "editor_worksheet.h" -#include "extract_bot_names.h" -#include "translation_manager_constants.h" -#include - using namespace std; -namespace TranslationManager { +namespace TranslationManager +{ void CEditorWorksheet::open(QString filename) { - STRING_MANAGER::TWorksheet wk_file; - if(loadExcelSheet(filename.toStdString(), wk_file, true) == true) - { - bool hasHashValue = false; - table_editor = new QTableWidget(); - if(wk_file.getData(0, 0) == ucstring("*HASH_VALUE")) - { - table_editor->setColumnCount(wk_file.ColCount - 1); - hasHashValue = true; - } else { - table_editor->setColumnCount(wk_file.ColCount); - } - table_editor->setRowCount(wk_file.size() - 1); - - // read columns name - for(unsigned int i = 0; i < wk_file.ColCount; i++) - { - if(hasHashValue && i == 0) - { - // we don't show the column with hash value - } else { - QTableWidgetItem *col = new QTableWidgetItem(); - ucstring col_name = wk_file.getData(0, i); - col->setText(QString(col_name.toString().c_str())); - if(hasHashValue) - { - table_editor->setHorizontalHeaderItem(i - 1, col); - } else { - table_editor->setHorizontalHeaderItem(i, col); - } - } - } - - // read rows - for(unsigned int i = 1; i < wk_file.size(); i++) - { - for(unsigned int j = 0; j < wk_file.ColCount; j++) - { - if(hasHashValue && j == 0) - { - // we don't show the column with hash value - } else { - QTableWidgetItem *row = new QTableWidgetItem(); - ucstring row_value = wk_file.getData(i, j); - row->setText(QString::fromUtf8(row_value.toUtf8().c_str())); - if(hasHashValue) - { - table_editor->setItem(i - 1, j - 1, row); - } else { - table_editor->setItem(i - 1, j, row); - } - } - } - } - setCurrentFile(filename); - setAttribute(Qt::WA_DeleteOnClose); - setWidget(table_editor); - editor_type = Constants::ED_SHEET; - table_editor->resizeColumnsToContents(); - table_editor->resizeRowsToContents(); - // set editor signals - connect(table_editor, SIGNAL(itemChanged(QTableWidgetItem*) ), this, SLOT(worksheetEditorChanged(QTableWidgetItem*))); - connect(table_editor, SIGNAL(itemDoubleClicked(QTableWidgetItem*) ), this, SLOT(worksheetEditorCellEntered(QTableWidgetItem*))); - connect (table_editor,SIGNAL(customContextMenuRequested(const QPoint &)), this,SLOT(contextMenuEvent(QContextMenuEvent*))); - } else { - QErrorMessage error; - error.showMessage("This file is not a worksheet file."); - error.exec(); - } - + STRING_MANAGER::TWorksheet wk_file; + if(loadExcelSheet(filename.toStdString(), wk_file, true) == true) + { + bool hasHashValue = false; + table_editor = new QTableWidget(); + if(wk_file.getData(0, 0) == ucstring("*HASH_VALUE")) + { + table_editor->setColumnCount(wk_file.ColCount - 1); + hasHashValue = true; + } + else + { + table_editor->setColumnCount(wk_file.ColCount); + } + table_editor->setRowCount(wk_file.size() - 1); + + // read columns name + for(uint i = 0; i < wk_file.ColCount; i++) + { + if(hasHashValue && i == 0) + { + // we don't show the column with hash value + } + else + { + QTableWidgetItem *col = new QTableWidgetItem(); + ucstring col_name = wk_file.getData(0, i); + col->setText(QString(col_name.toString().c_str())); + if(hasHashValue) + { + table_editor->setHorizontalHeaderItem(i - 1, col); + } + else + { + table_editor->setHorizontalHeaderItem(i, col); + } + } + } + + // read rows + for(unsigned int i = 1; i < wk_file.size(); i++) + { + for(unsigned int j = 0; j < wk_file.ColCount; j++) + { + if(hasHashValue && j == 0) + { + // we don't show the column with hash value + } + else + { + QTableWidgetItem *row = new QTableWidgetItem(); + ucstring row_value = wk_file.getData(i, j); + row->setText(QString::fromUtf8(row_value.toUtf8().c_str())); + if(hasHashValue) + { + table_editor->setItem(i - 1, j - 1, row); + } + else + { + table_editor->setItem(i - 1, j, row); + } + } + } + } + setCurrentFile(filename); + setAttribute(Qt::WA_DeleteOnClose); + setWidget(table_editor); + editor_type = Constants::ED_SHEET; + table_editor->resizeColumnsToContents(); + table_editor->resizeRowsToContents(); + // set editor signals + connect(table_editor, SIGNAL(itemChanged(QTableWidgetItem *) ), this, SLOT(worksheetEditorChanged(QTableWidgetItem *))); + connect(table_editor, SIGNAL(itemDoubleClicked(QTableWidgetItem *) ), this, SLOT(worksheetEditorCellEntered(QTableWidgetItem *))); + connect(table_editor,SIGNAL(customContextMenuRequested(const QPoint &)), this,SLOT(contextMenuEvent(QContextMenuEvent *))); + } + else + { + QErrorMessage error; + error.showMessage(tr("This file is not a worksheet file.")); + error.exec(); + } } void CEditorWorksheet::contextMenuEvent(QContextMenuEvent *e) { - QAction *insertRowAct = new QAction("Insert new row", this); - connect(insertRowAct, SIGNAL(triggered()), this, SLOT(insertRow())); - QAction *deleteRowAct = new QAction("Delete row", this); - connect(deleteRowAct, SIGNAL(triggered()), this, SLOT(deleteRow())); + QAction *insertRowAct = new QAction(tr("Insert new row"), this); + connect(insertRowAct, SIGNAL(triggered()), this, SLOT(insertRow())); + QAction *deleteRowAct = new QAction(tr("Delete row"), this); + connect(deleteRowAct, SIGNAL(triggered()), this, SLOT(deleteRow())); QMenu *contextMenu = new QMenu(this); contextMenu->addAction(insertRowAct); @@ -127,7 +138,7 @@ void CEditorWorksheet::contextMenuEvent(QContextMenuEvent *e) void CEditorWorksheet::activateWindow() { - showMaximized(); + showMaximized(); } void CEditorWorksheet::save() @@ -137,372 +148,377 @@ void CEditorWorksheet::save() void CEditorWorksheet::saveAs(QString filename) { - STRING_MANAGER::TWorksheet new_file, wk_file; - loadExcelSheet(current_file.toStdString(), wk_file, true); - // set columns - new_file.resize(new_file.size() + 1); - for(unsigned int i = 0; i < wk_file.ColCount; i++) - { - ucstring col_name = wk_file.getData(0, i); - new_file.insertColumn(new_file.ColCount); - new_file.setData(0, new_file.ColCount - 1, col_name); - } - // read all the rows from table - uint rowIdx; - uint colIdx = 0; - bool hasHashValue = false; - if(wk_file.getData(0, 0) == ucstring("*HASH_VALUE")) - { - hasHashValue = true; - colIdx = 1; - } - for(int i = 0; i < table_editor->rowCount(); i++) - { - rowIdx = new_file.size(); - new_file.resize(new_file.size() + 1); - ucstring tvalue; - for(int j = 0; j < table_editor->columnCount(); j++) - { - QTableWidgetItem* item = table_editor->item(i, j); - tvalue.fromUtf8(std::string(item->text().toUtf8())); - new_file.setData(rowIdx, j + colIdx, tvalue); - } - } - if(hasHashValue) - { - // rewrite the hash codes - makeHashCode(wk_file, true); - } - ucstring s = prepareExcelSheet(new_file); - NLMISC::CI18N::writeTextFile(filename.toStdString(), s, false); - current_file = filename; - setCurrentFile(filename); + STRING_MANAGER::TWorksheet new_file, wk_file; + loadExcelSheet(current_file.toStdString(), wk_file, true); + // set columns + new_file.resize(new_file.size() + 1); + for(unsigned int i = 0; i < wk_file.ColCount; i++) + { + ucstring col_name = wk_file.getData(0, i); + new_file.insertColumn(new_file.ColCount); + new_file.setData(0, new_file.ColCount - 1, col_name); + } + // read all the rows from table + uint rowIdx; + uint colIdx = 0; + bool hasHashValue = false; + if(wk_file.getData(0, 0) == ucstring("*HASH_VALUE")) + { + hasHashValue = true; + colIdx = 1; + } + for(int i = 0; i < table_editor->rowCount(); i++) + { + rowIdx = new_file.size(); + new_file.resize(new_file.size() + 1); + ucstring tvalue; + for(int j = 0; j < table_editor->columnCount(); j++) + { + QTableWidgetItem *item = table_editor->item(i, j); + tvalue.fromUtf8(std::string(item->text().toUtf8())); + new_file.setData(rowIdx, j + colIdx, tvalue); + } + } + if(hasHashValue) + { + // rewrite the hash codes + makeHashCode(wk_file, true); + } + ucstring s = prepareExcelSheet(new_file); + NLMISC::CI18N::writeTextFile(filename.toStdString(), s, false); + current_file = filename; + setCurrentFile(filename); } void CEditorWorksheet::insertRow() { - int last_row = table_editor->rowCount(); + int last_row = table_editor->rowCount(); current_stack->push(new CUndoWorksheetNewCommand(table_editor, last_row)); } void CEditorWorksheet::deleteRow() { - int selected_row = table_editor->currentRow(); - QMessageBox msgBox; - msgBox.setText(tr("The row will be deleted.")); - msgBox.setInformativeText(tr("Do you want to delete the selected row ?")); - msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); - msgBox.setDefaultButton(QMessageBox::No); - int ret = msgBox.exec(); - if(ret == QMessageBox::Yes) - { - current_stack->push(new CUndoWorksheetDeleteCommand(table_editor, selected_row)); - } + int selected_row = table_editor->currentRow(); + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Question); + msgBox.setText(tr("The row will be deleted.")); + msgBox.setInformativeText(tr("Do you want to delete the selected row ?")); + msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); + msgBox.setDefaultButton(QMessageBox::No); - table_editor->clearFocus(); - table_editor->clearSelection(); - return; + int ret = msgBox.exec(); + if(ret == QMessageBox::Yes) + { + current_stack->push(new CUndoWorksheetDeleteCommand(table_editor, selected_row)); + } + table_editor->clearFocus(); + table_editor->clearSelection(); + return; } -void CEditorWorksheet::worksheetEditorCellEntered(QTableWidgetItem * item) +void CEditorWorksheet::worksheetEditorCellEntered(QTableWidgetItem *item) { temp_content = item->text(); current_stack->push(new CUndoWorksheetCommand(table_editor, item, temp_content)); } -void CEditorWorksheet::worksheetEditorChanged(QTableWidgetItem * item) +void CEditorWorksheet::worksheetEditorChanged(QTableWidgetItem *item) { if(temp_content != item->text()) { //current_stack->push(new CUndoWorksheetCommand(table_editor, item, temp_content)); } - if(!isWindowModified()) - setWindowModified(true); + if(!isWindowModified()) + setWindowModified(true); } void CEditorWorksheet::extractBotNames(list filters, string level_design_path, NLLIGO::CLigoConfig ligoConfig) { - bool modified = false; + bool modified = false; QList new_items; - ExtractBotNames ebn; - ebn.setRequiredSettings(filters, level_design_path); - ebn.extractBotNamesFromPrimitives(ligoConfig); - // get SimpleNames - { - map SimpleNames = ebn.getSimpleNames(); - map::iterator it(SimpleNames.begin()), last(SimpleNames.end()); + ExtractBotNames ebn; + ebn.setRequiredSettings(filters, level_design_path); + ebn.extractBotNamesFromPrimitives(ligoConfig); + // get SimpleNames + { + map SimpleNames = ebn.getSimpleNames(); + map::iterator it(SimpleNames.begin()), last(SimpleNames.end()); + + for (; it != last; ++it) + { + QList search_results = table_editor->findItems(QString(it->first.c_str()), Qt::MatchExactly); + if(search_results.size() == 0) + { + QList records; + records.push_back(QString(it->first.c_str())); + records.push_back(QString(it->first.c_str())); + records.push_back(QString(it->second.SheetName.c_str())); + insertTableRecords(records, new_items); + if(!modified) modified = true; + } + } + ebn.cleanSimpleNames(); + } + // get GenericNames + { + set GenericNames = ebn.getGenericNames(); + set::iterator it(GenericNames.begin()), last(GenericNames.end()); + for (; it != last; ++it) + { + string gnName = "gn_" + ebn.cleanupName(*it); + QList search_results = table_editor->findItems(QString((*it).c_str()), Qt::MatchExactly); + if(search_results.size() == 0) + { + QList records; + records.push_back(QString((*it).c_str())); + records.push_back(QString(gnName.c_str())); + records.push_back(" "); + insertTableRecords(records, new_items); + if(!modified) modified = true; + } + } + ebn.cleanGenericNames(); + } + + current_stack->push(new CUndoWorksheetExtraction(new_items, table_editor)); + if(modified) + { + setWindowModified(true); + table_editor->scrollToBottom(); + } - for (; it != last; ++it) - { - QList search_results = table_editor->findItems(QString(it->first.c_str()), Qt::MatchExactly); - if(search_results.size() == 0) - { - QList records; - records.push_back(QString(it->first.c_str())); - records.push_back(QString(it->first.c_str())); - records.push_back(QString(it->second.SheetName.c_str())); - insertTableRecords(records, new_items); - if(!modified) modified = true; - } - } - ebn.cleanSimpleNames(); - } - // get GenericNames - { - set GenericNames = ebn.getGenericNames(); - set::iterator it(GenericNames.begin()), last(GenericNames.end()); - for (; it != last; ++it) - { - string gnName = "gn_" + ebn.cleanupName(*it); - QList search_results = table_editor->findItems(QString((*it).c_str()), Qt::MatchExactly); - if(search_results.size() == 0) - { - QList records; - records.push_back(QString((*it).c_str())); - records.push_back(QString(gnName.c_str())); - records.push_back(" "); - insertTableRecords(records, new_items); - if(!modified) modified = true; - } - } - ebn.cleanGenericNames(); - } - - current_stack->push(new CUndoWorksheetExtraction(new_items, table_editor)); - if(modified) - { - setWindowModified(true); - table_editor->scrollToBottom(); - } - } -void CEditorWorksheet::extractWords(QString filename, QString columnId, IWordListBuilder& wordListBuilder) +void CEditorWorksheet::extractWords(QString filename, QString columnId, IWordListBuilder &wordListBuilder) { - uint i; + uint i; // **** Load the excel sheet // load - TWorksheet workSheet; + STRING_MANAGER::TWorksheet workSheet; if(!loadExcelSheet(filename.toStdString(), workSheet, true)) { nlwarning("Error reading '%s'. Aborted", filename.toStdString().c_str()); return; } // get the key column index - uint keyColIndex = 0; + uint keyColIndex = 0; if(!workSheet.findCol(columnId.toStdString(), keyColIndex)) { nlwarning("Error: Don't find the column '%s'. '%s' Aborted", columnId.toStdString().c_str(), filename.toStdString().c_str()); return; } // get the name column index - uint nameColIndex; + uint nameColIndex; if(!workSheet.findCol(ucstring("name"), nameColIndex)) { nlwarning("Error: Don't find the column 'name'. '%s' Aborted", filename.toStdString().c_str()); return; - } - - // **** List all words with the builder given - std::vector allWords; - if(!wordListBuilder.buildWordList(allWords, filename.toStdString())) - { - return; - } - bool modified = false; - QList new_items; - for(i = 0; i < allWords.size(); i++) - { - string keyName = allWords[i]; - QList search_results = table_editor->findItems(QString(keyName.c_str()), Qt::MatchExactly); - if(search_results.size() == 0) - { - int knPos = 0, nPos = 0; - if(workSheet.getData(0, 0) == ucstring("*HASH_VALUE")) - { - knPos = keyColIndex - 1; - nPos = nameColIndex - 1; - } else { - knPos = keyColIndex; - nPos = nameColIndex; - } + } - QList records; - records.push_back(QString(keyName.c_str())); - records.push_back(QString("") + QString(keyName.c_str())); - insertTableRecords(records, new_items); - if(!modified) modified = true; - } - } - current_stack->push(new CUndoWorksheetExtraction(new_items, table_editor)); - if(modified) - { - setWindowModified(true); - table_editor->scrollToBottom(); - } + // **** List all words with the builder given + std::vector allWords; + if(!wordListBuilder.buildWordList(allWords, filename.toStdString())) + { + return; + } + bool modified = false; + QList new_items; + for(i = 0; i < allWords.size(); i++) + { + string keyName = allWords[i]; + QList search_results = table_editor->findItems(QString(keyName.c_str()), Qt::MatchExactly); + if(search_results.size() == 0) + { + int knPos = 0, nPos = 0; + if(workSheet.getData(0, 0) == ucstring("*HASH_VALUE")) + { + knPos = keyColIndex - 1; + nPos = nameColIndex - 1; + } + else + { + knPos = keyColIndex; + nPos = nameColIndex; + } + + QList records; + records.push_back(QString(keyName.c_str())); + records.push_back(QString("") + QString(keyName.c_str())); + insertTableRecords(records, new_items); + if(!modified) modified = true; + } + } + current_stack->push(new CUndoWorksheetExtraction(new_items, table_editor)); + if(modified) + { + setWindowModified(true); + table_editor->scrollToBottom(); + } } void CEditorWorksheet::insertTableRecords(QList records, QList new_items) { - const int currentRow = table_editor->rowCount(); + const int currentRow = table_editor->rowCount(); table_editor->setRowCount(currentRow + 1); int n = 0; Q_FOREACH(QString record, records) { QTableWidgetItem *rec = new QTableWidgetItem(); rec->setBackgroundColor(QColor("#F75D59")); - table_editor ->setItem(currentRow, n, rec); + table_editor ->setItem(currentRow, n, rec); CTableWidgetItemStore rec_s(rec, currentRow, n); new_items.push_back(rec_s); n++; } - } bool CEditorWorksheet::compareWorksheetFile(QString filename) { - STRING_MANAGER::TWorksheet wk_file; - int colIndex = 0; - if(loadExcelSheet(filename.toStdString(), wk_file, true) == true) - { - if(wk_file.getData(0, 0) == ucstring("*HASH_VALUE")) - { - colIndex = 1; - } - if(wk_file.ColCount - colIndex != table_editor->columnCount()) - { - return false; - } - for(int i = 0; i < table_editor->columnCount(); i++) - { - QString item = table_editor->horizontalHeaderItem(i)->text(); - ucstring itemC = wk_file.getData(0, i+ colIndex); - if(item.toStdString() != itemC.toString()) - { - nlwarning(item.toStdString().c_str()); - nlwarning(itemC.toString().c_str()); - return false; - } - } - } else { - return false; - } - - return true; + STRING_MANAGER::TWorksheet wk_file; + int colIndex = 0; + if(loadExcelSheet(filename.toStdString(), wk_file, true) == true) + { + if(wk_file.getData(0, 0) == ucstring("*HASH_VALUE")) + { + colIndex = 1; + } + if(wk_file.ColCount - colIndex != table_editor->columnCount()) + { + return false; + } + for(int i = 0; i < table_editor->columnCount(); i++) + { + QString item = table_editor->horizontalHeaderItem(i)->text(); + ucstring itemC = wk_file.getData(0, i+ colIndex); + if(item.toStdString() != itemC.toString()) + { + nlwarning(item.toStdString().c_str()); + nlwarning(itemC.toString().c_str()); + return false; + } + } + } + else + { + return false; + } + return true; } void CEditorWorksheet::mergeWorksheetFile(QString filename) { - STRING_MANAGER::TWorksheet wk_file; - if(loadExcelSheet(filename.toStdString(), wk_file, true) == true) - { - bool hasHashValue = false; - int colIndex = 0; - if(wk_file.getData(0, 0) == ucstring("*HASH_VALUE")) - { - hasHashValue = true; - colIndex = 1; - } - // read rows - for(unsigned int i = 1; i < wk_file.size(); i++) - { - // search with the first column - ucstring rowId = wk_file.getData(i,colIndex); - QList search_results = table_editor->findItems(QString(rowId.toString().c_str()), Qt::MatchExactly); - if(search_results.size() == 0) - { - const int lastRow = table_editor->rowCount(); - table_editor->setRowCount(lastRow + 1); - for(unsigned int j = 0; j < table_editor->columnCount(); j++) - { - ucstring rowValue = wk_file.getData(i, j + colIndex); // get the value - QTableWidgetItem *row = new QTableWidgetItem(); - row->setText(QString(rowValue.toString().c_str())); // set the value in table item - table_editor->setItem(lastRow, j, row); - } - } - } - } else { - QErrorMessage error; - error.showMessage(tr("This file is not a worksheet file.")); - error.exec(); - } + STRING_MANAGER::TWorksheet wk_file; + if(loadExcelSheet(filename.toStdString(), wk_file, true) == true) + { + bool hasHashValue = false; + int colIndex = 0; + if(wk_file.getData(0, 0) == ucstring("*HASH_VALUE")) + { + hasHashValue = true; + colIndex = 1; + } + // read rows + for(unsigned int i = 1; i < wk_file.size(); i++) + { + // search with the first column + ucstring rowId = wk_file.getData(i,colIndex); + QList search_results = table_editor->findItems(QString(rowId.toString().c_str()), Qt::MatchExactly); + if(search_results.size() == 0) + { + const int lastRow = table_editor->rowCount(); + table_editor->setRowCount(lastRow + 1); + for(int j = 0; j < table_editor->columnCount(); j++) + { + ucstring rowValue = wk_file.getData(i, j + colIndex); // get the value + QTableWidgetItem *row = new QTableWidgetItem(); + row->setText(QString(rowValue.toString().c_str())); // set the value in table item + table_editor->setItem(lastRow, j, row); + } + } + } + } + else + { + QErrorMessage error; + error.showMessage(tr("This file is not a worksheet file.")); + error.exec(); + } } void CEditorWorksheet::closeEvent(QCloseEvent *event) { - if(isWindowModified()) - { - QMessageBox msgBox; - msgBox.setText(tr("The document has been modified.")); - msgBox.setInformativeText(tr("Do you want to save your changes?")); - msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Save); - int ret = msgBox.exec(); - switch (ret) - { - case QMessageBox::Save: - save(); - event->accept(); - close(); - break; - case QMessageBox::Discard: - event->accept(); - close(); - break; - case QMessageBox::Cancel: - event->ignore(); - break; - default: - break; - } - } else { - event->accept(); - close(); - } + if(isWindowModified()) + { + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Question); + msgBox.setText(tr("The document has been modified.")); + msgBox.setInformativeText(tr("Do you want to save your changes?")); + msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Save); + int ret = msgBox.exec(); + switch (ret) + { + case QMessageBox::Save: + save(); + break; + case QMessageBox::Discard: + break; + case QMessageBox::Cancel: + event->ignore(); + return; + } + } + event->accept(); + close(); } bool CEditorWorksheet::isBotNamesTable() { - bool status = true; - if(table_editor->horizontalHeaderItem(0)->text() != "bot name" - || table_editor->horizontalHeaderItem(1)->text() != "translated name" - || table_editor->horizontalHeaderItem(2)->text() != "sheet_name") - { - status = false; - } - - return status; + bool status = true; + if(table_editor->horizontalHeaderItem(0)->text() != "bot name" + || table_editor->horizontalHeaderItem(1)->text() != "translated name" + || table_editor->horizontalHeaderItem(2)->text() != "sheet_name") + { + status = false; + } + return status; } bool CEditorWorksheet::isSheetTable(QString type) { - QString column_name; - if(type.toAscii() == Constants::WK_ITEM) - { - column_name = "item ID"; - } else if(type.toAscii() == Constants::WK_CREATURE) { - column_name = "creature ID"; - } else if(type.toAscii() == Constants::WK_SBRICK) { - column_name = "sbrick ID"; - } else if(type.toAscii() == Constants::WK_SPHRASE) { - column_name = "sphrase ID"; - } else if(type.toAscii() == Constants::WK_PLACE) { - column_name = "placeId"; - } - bool status = true; - if(table_editor->horizontalHeaderItem(0)->text() != column_name - || table_editor->horizontalHeaderItem(1)->text() != "name") - { - status = false; - } - - return status; + QString column_name; + if(type.toAscii() == Constants::WK_ITEM) + { + column_name = "item ID"; + } + else if(type.toAscii() == Constants::WK_CREATURE) + { + column_name = "creature ID"; + } + else if(type.toAscii() == Constants::WK_SBRICK) + { + column_name = "sbrick ID"; + } + else if(type.toAscii() == Constants::WK_SPHRASE) + { + column_name = "sphrase ID"; + } + else if(type.toAscii() == Constants::WK_PLACE) + { + column_name = "placeId"; + } + bool status = true; + if(table_editor->horizontalHeaderItem(0)->text() != column_name + || table_editor->horizontalHeaderItem(1)->text() != "name") + { + status = false; + } + return status; } } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.h index 487a9eea8..b60c7a534 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.h @@ -18,6 +18,10 @@ #ifndef EDITOR_WORKSHEET_H #define EDITOR_WORKSHEET_H +// Project includes +#include "translation_manager_editor.h" +#include "extract_new_sheet_names.h" + // Nel includes #include "nel/misc/types_nl.h" #include "nel/misc/sheet_id.h" @@ -34,11 +38,9 @@ #include #include -// Project includes -#include "translation_manager_editor.h" -#include "extract_new_sheet_names.h" -namespace TranslationManager { +namespace TranslationManager +{ struct CTableWidgetItemStore { @@ -47,6 +49,7 @@ public: m_item(item), m_row(row), m_column(column) { } + QTableWidgetItem *m_item; int m_row; int m_column; @@ -54,39 +57,41 @@ public: class CEditorWorksheet : public CEditor { - Q_OBJECT -private: - QString temp_content; + Q_OBJECT + public: - CEditorWorksheet(QMdiArea* parent) : CEditor(parent) {} - CEditorWorksheet() : CEditor() {} - QTableWidget* table_editor; - void open(QString filename); - void save(); - void saveAs(QString filename); - void activateWindow(); - void mergeWorksheetFile(QString filename); - bool compareWorksheetFile(QString filename); - void extractBotNames(list filters, string level_design_path, NLLIGO::CLigoConfig ligoConfig); - void extractWords(QString filename, QString columnId, IWordListBuilder &wordListBuilder); + CEditorWorksheet(QMdiArea *parent) : CEditor(parent) {} + CEditorWorksheet() : CEditor() {} + QTableWidget *table_editor; + void open(QString filename); + void save(); + void saveAs(QString filename); + void activateWindow(); + void mergeWorksheetFile(QString filename); + bool compareWorksheetFile(QString filename); + void extractBotNames(std::list filters, std::string level_design_path, NLLIGO::CLigoConfig ligoConfig); + void extractWords(QString filename, QString columnId, IWordListBuilder &wordListBuilder); void insertTableRecords(QList records, QList new_items); - bool isBotNamesTable(); - bool isSheetTable(QString type); - void closeEvent(QCloseEvent *event); + bool isBotNamesTable(); + bool isSheetTable(QString type); + void closeEvent(QCloseEvent *event); + private Q_SLOTS: - void worksheetEditorCellEntered(QTableWidgetItem * item); - void worksheetEditorChanged(QTableWidgetItem * item); - void insertRow(); - void deleteRow(); + void worksheetEditorCellEntered(QTableWidgetItem *item); + void worksheetEditorChanged(QTableWidgetItem *item); + void insertRow(); + void deleteRow(); void contextMenuEvent(QContextMenuEvent *e); - + +private: + QString temp_content; }; class CUndoWorksheetCommand : public QUndoCommand { public: - CUndoWorksheetCommand(QTableWidget *table, QTableWidgetItem* item, const QString &ocontent, QUndoCommand *parent = 0) : QUndoCommand("Insert characters in cells", parent), m_table(table), m_item(item), m_ocontent(ocontent) - { + CUndoWorksheetCommand(QTableWidget *table, QTableWidgetItem *item, const QString &ocontent, QUndoCommand *parent = 0) : QUndoCommand("Insert characters in cells", parent), m_table(table), m_item(item), m_ocontent(ocontent) + { m_ccontent = m_ocontent; } @@ -98,16 +103,16 @@ public: } } void undo() - { + { if(m_item->text() != m_ocontent) { m_ccontent = m_item->text(); } m_item->setText(m_ocontent); - } + } private: - QTableWidget* m_table; - QTableWidgetItem* m_item; + QTableWidget *m_table; + QTableWidgetItem *m_item; QString m_ocontent; QString m_ccontent; }; @@ -123,7 +128,7 @@ public: m_table->setRowCount(m_rowID + 1); for(int j = 0; j < m_table->columnCount(); j++) { - QTableWidgetItem* item = new QTableWidgetItem(); + QTableWidgetItem *item = new QTableWidgetItem(); m_table->setItem(m_rowID, j, item); m_table->scrollToBottom(); } @@ -133,16 +138,16 @@ public: { m_table->removeRow(m_rowID); } -private: - QTableWidget* m_table; - int m_rowID; +private: + QTableWidget *m_table; + int m_rowID; }; class CUndoWorksheetExtraction : public QUndoCommand { public: - CUndoWorksheetExtraction(QList items, QTableWidget *table, QUndoCommand *parent = 0) : QUndoCommand("Word extraction", parent), + CUndoWorksheetExtraction(QList items, QTableWidget *table, QUndoCommand *parent = 0) : QUndoCommand("Word extraction", parent), m_items(items), m_table(table) { } @@ -153,7 +158,6 @@ public: { m_table->setItem(is.m_row, is.m_column, is.m_item); } - } void undo() @@ -161,14 +165,13 @@ public: Q_FOREACH(CTableWidgetItemStore is, m_items) { m_table->setItem(is.m_row, is.m_column, is.m_item); - m_table->takeItem(is.m_row, is.m_column); + m_table->takeItem(is.m_row, is.m_column); } - } private: QList m_items; - QTableWidget* m_table; + QTableWidget *m_table; }; class CUndoWorksheetDeleteCommand : public QUndoCommand @@ -181,8 +184,8 @@ public: { for(int i = 0; i < m_table->columnCount(); i++) { - QTableWidgetItem* item = new QTableWidgetItem(); - QTableWidgetItem* table_item = m_table->item(m_rowID, i); + QTableWidgetItem *item = new QTableWidgetItem(); + QTableWidgetItem *table_item = m_table->item(m_rowID, i); item->setText(table_item->text()); m_deletedItems.push_back(item); } @@ -203,8 +206,8 @@ public: } private: - QList m_deletedItems; - QTableWidget* m_table; + QList m_deletedItems; + QTableWidget *m_table; int m_rowID; }; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.cpp index e8ed68bbf..ee65ca73c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.cpp @@ -17,18 +17,14 @@ #include "extract_bot_names.h" - static bool RemoveOlds = false; - - - namespace TranslationManager { TCreatureInfo *ExtractBotNames::getCreature(const std::string &sheetName) { - CSheetId id(sheetName+".creature"); + NLMISC::CSheetId id(sheetName+".creature"); if (Creatures.find(id) != Creatures.end()) return &(Creatures.find(id)->second); @@ -36,18 +32,17 @@ TCreatureInfo *ExtractBotNames::getCreature(const std::string &sheetName) return NULL; } -string ExtractBotNames::cleanupName(const std::string &name) +std::string ExtractBotNames::cleanupName(const std::string &name) { - string ret; + std::string ret; - for (uint i=0; i= 2) { - if ( *ret.begin() == ucchar('$')) + if (*ret.begin() == ucchar('$')) { ret=ret.substr(1); } - if ( *ret.rbegin() == ucchar('$')) + if (*ret.rbegin() == ucchar('$')) { - ret = ret.substr(0, ret.size()-1); + ret = ret.substr(0, ret.size() - 1); } } ret = cleanupUcName(ret); - return ret; + return ret; } - - - - -set ExtractBotNames::getGenericNames() +std::set ExtractBotNames::getGenericNames() { - return GenericNames; + return GenericNames; } -map ExtractBotNames::getSimpleNames() +std::map ExtractBotNames::getSimpleNames() { - return SimpleNames; + return SimpleNames; } void ExtractBotNames::cleanSimpleNames() -{ - SimpleNames.clear(); +{ + SimpleNames.clear(); } void ExtractBotNames::cleanGenericNames() { - GenericNames.clear(); + GenericNames.clear(); } -string ExtractBotNames::removeAndStoreFunction(const std::string &fullName) +std::string ExtractBotNames::removeAndStoreFunction(const std::string &fullName) { - string::size_type pos = fullName.find("$"); - if (pos == string::npos) + std::string::size_type pos = fullName.find("$"); + if (pos == std::string::npos) + { return fullName; + } else { // extract and store the function name - string ret; + std::string ret; ret = fullName.substr(0, pos); - string::size_type pos2 = fullName.find("$", pos+1); + std::string::size_type pos2 = fullName.find("$", pos+1); - string fct = fullName.substr(pos+1, pos2-(pos+1)); + std::string fct = fullName.substr(pos + 1, pos2 - (pos + 1)); - ret += fullName.substr(pos2+1); + ret += fullName.substr(pos2 + 1); if (Functions.find(fct) == Functions.end()) { nldebug("Adding function '%s'", fct.c_str()); Functions.insert(fct); } - return ret; } } - void ExtractBotNames::addGenericName(const std::string &name, const std::string &sheetName) { TCreatureInfo *c = getCreature(sheetName); if (!c || c->ForceSheetName || !c->DisplayName) return; - + if (SimpleNames.find(name) != SimpleNames.end()) { nldebug("Name '%s' is now a generic name", name.c_str()); @@ -177,7 +167,7 @@ void ExtractBotNames::addSimpleName(const std::string &name, const std::string & else { nldebug("Adding simple name '%s'", name.c_str()); - + TEntryInfo ei; ei.SheetName = sheetName; @@ -185,75 +175,72 @@ void ExtractBotNames::addSimpleName(const std::string &name, const std::string & } } -void ExtractBotNames::setRequiredSettings(list filters, string level_design_path) +void ExtractBotNames::setRequiredSettings(std::list filters, std::string level_design_path) { - for (std::list::iterator it = filters.begin(); it != filters.end(); ++it) + for (std::list::iterator it = filters.begin(); it != filters.end(); ++it) { Filters.push_back(*it); } //------------------------------------------------------------------- // init the sheets - CSheetId::init(false); - const string PACKED_SHEETS_NAME = "bin/translation_tools_creature.packed_sheets"; + NLMISC::CSheetId::init(false); + const std::string PACKED_SHEETS_NAME = "bin/translation_tools_creature.packed_sheets"; loadForm("creature", PACKED_SHEETS_NAME, Creatures, false, false); if (Creatures.empty()) { - loadForm("creature", PACKED_SHEETS_NAME, Creatures, true); + loadForm("creature", PACKED_SHEETS_NAME, Creatures, true); } - } -void ExtractBotNames::extractBotNamesFromPrimitives(CLigoConfig ligoConfig) +void ExtractBotNames::extractBotNamesFromPrimitives(NLLIGO::CLigoConfig ligoConfig) { - //------------------------------------------------------------------- // ok, ready for the real work, // first, read the primitives files and parse the primitives - vector files; - CPath::getFileList("primitive", files); - + std::vector files; + NLMISC::CPath::getFileList("primitive", files); for (uint i=0; i ps; + NLLIGO::CPrimitiveSet ps; ps.buildSet(primDoc.RootNode, pred, result); - for (uint i=0; igetPropertyByName("name", name); result[i]->getPropertyByName("count", countStr); result[i]->getPropertyByName("bot_sheet_look", sheetStr); @@ -276,16 +263,16 @@ void ExtractBotNames::extractBotNamesFromPrimitives(CLigoConfig ligoConfig) } // look for bot template { - TPrimitiveClassPredicate pred("bot_template_npc"); - TPrimitiveSet result; + NLLIGO::TPrimitiveClassPredicate pred("bot_template_npc"); + NLLIGO::TPrimitiveSet result; - CPrimitiveSet ps; + NLLIGO::CPrimitiveSet ps; ps.buildSet(primDoc.RootNode, pred, result); - for (uint i=0; igetPropertyByName("name", name); result[i]->getPropertyByName("sheet_look", sheetStr); @@ -305,19 +292,19 @@ void ExtractBotNames::extractBotNamesFromPrimitives(CLigoConfig ligoConfig) } } } - // look for npc_group + // look for npc_group { - TPrimitiveClassPredicate pred("npc_group"); - TPrimitiveSet result; + NLLIGO::TPrimitiveClassPredicate pred("npc_group"); + NLLIGO::TPrimitiveSet result; - CPrimitiveSet ps; + NLLIGO::CPrimitiveSet ps; ps.buildSet(primDoc.RootNode, pred, result); - for (uint i=0; igetPropertyByName("name", name); result[i]->getPropertyByName("count", countStr); result[i]->getPropertyByName("bot_sheet_client", sheetStr); @@ -342,18 +329,18 @@ void ExtractBotNames::extractBotNamesFromPrimitives(CLigoConfig ligoConfig) } } } - // look for bot + // look for bot { - TPrimitiveClassPredicate pred("npc_bot"); - TPrimitiveSet result; + NLLIGO::TPrimitiveClassPredicate pred("npc_bot"); + NLLIGO::TPrimitiveSet result; - CPrimitiveSet ps; + NLLIGO::CPrimitiveSet ps; ps.buildSet(primDoc.RootNode, pred, result); - for (uint i=0; igetPropertyByName("name", name); result[i]->getPropertyByName("sheet_client", sheetStr); @@ -373,7 +360,7 @@ void ExtractBotNames::extractBotNamesFromPrimitives(CLigoConfig ligoConfig) } } } - } + } } - + } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.h index df1cb39ca..208b4db5c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.h @@ -30,22 +30,16 @@ #include "nel/ligo/primitive.h" #include "nel/ligo/primitive_utils.h" -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; -using namespace STRING_MANAGER; - namespace TranslationManager { struct TCreatureInfo { - CSheetId SheetId; - bool ForceSheetName; - bool DisplayName; + NLMISC::CSheetId SheetId; + bool ForceSheetName; + bool DisplayName; - - void readGeorges (const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId) + void readGeorges(const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId) { const NLGEORGES::UFormElm &item=form->getRootNode(); @@ -61,51 +55,45 @@ struct TCreatureInfo f.serial(DisplayName); } - - static uint getVersion () - { + static uint getVersion () + { return 1; } void removed() { } - }; struct TEntryInfo { - string SheetName; + std::string SheetName; }; struct ExtractBotNames { private: - vector Filters; - std::map Creatures; - set GenericNames; - map SimpleNames; - set Functions; + std::vector Filters; + std::map Creatures; + std::set GenericNames; + std::map SimpleNames; + std::set Functions; private: - TCreatureInfo *getCreature(const std::string &sheetName); - ucstring makeGroupName(const ucstring & translationName); - string removeAndStoreFunction(const std::string &fullName); - void addGenericName(const std::string &name, const std::string &sheetName); - void addSimpleName(const std::string &name, const std::string &sheetName); + TCreatureInfo *getCreature(const std::string &sheetName); + ucstring makeGroupName(const ucstring &translationName); + std::string removeAndStoreFunction(const std::string &fullName); + void addGenericName(const std::string &name, const std::string &sheetName); + void addSimpleName(const std::string &name, const std::string &sheetName); public: - void extractBotNamesFromPrimitives(CLigoConfig ligoConfig); - void setRequiredSettings(list filters, string level_design_path); - set getGenericNames(); - map getSimpleNames(); - string cleanupName(const std::string &name); - ucstring cleanupUcName(const ucstring &name); - void cleanSimpleNames(); - void cleanGenericNames(); - + void extractBotNamesFromPrimitives(NLLIGO::CLigoConfig ligoConfig); + void setRequiredSettings(std::list filters, std::string level_design_path); + std::set getGenericNames(); + std::map getSimpleNames(); + std::string cleanupName(const std::string &name); + ucstring cleanupUcName(const ucstring &name); + void cleanSimpleNames(); + void cleanGenericNames(); }; - } - -#endif /* EXTRACT_BOT_NAMES_H */ - +#endif /* EXTRACT_BOT_NAMES_H */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.cpp index 5d0b9b455..984f86d17 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.cpp @@ -16,139 +16,135 @@ #include "extract_new_sheet_names.h" -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; -using namespace STRING_MANAGER; - -namespace TranslationManager +namespace TranslationManager { - - // *************************************************************************** /* * Specialisation of IWordListBuilder to list sheets in a directory */ - -bool CSheetWordListBuilder::buildWordList(std::vector &allWords, string workSheetFileName) +bool CSheetWordListBuilder::buildWordList(std::vector &allWords, std::string workSheetFileName) +{ + SheetExt = NLMISC::toLower(SheetExt); + // verify the directory is correct + if(!NLMISC::CFile::isDirectory(SheetPath)) { - SheetExt= toLower(SheetExt); - // verify the directory is correct - if(!CFile::isDirectory(SheetPath)) - { - nlwarning("Error: Directory '%s' not found. '%s' Aborted", SheetPath.c_str(), workSheetFileName.c_str()); - return false; - } - - // list all files. - std::vector allFiles; - allFiles.reserve(100000); - CPath::getPathContent(SheetPath, true, false, true, allFiles, NULL); - - // Keep only the extension we want, and remove "_" (parent) - allWords.clear(); - allWords.reserve(allFiles.size()); - for(uint i=0;i allFiles; + allFiles.reserve(100000); + NLMISC::CPath::getPathContent(SheetPath, true, false, true, allFiles, NULL); + // Keep only the extension we want, and remove "_" (parent) + allWords.clear(); + allWords.reserve(allFiles.size()); + for(size_t i = 0; i < allFiles.size(); i++) + { + std::string fileNameWithoutExt = NLMISC::CFile::getFilenameWithoutExtension(allFiles[i]); + std::string extension = NLMISC::toLower(NLMISC::CFile::getExtension(allFiles[i])); + + // bad extension? + if(extension!=SheetExt) + continue; + + // parent? + if(fileNameWithoutExt.empty() || fileNameWithoutExt[0] == '_') + continue; + + // ok, add + allWords.push_back(NLMISC::toLower(fileNameWithoutExt)); + } + return true; +} // *************************************************************************** /* * Specialisation of IWordListBuilder to list new region/place name from .primitive */ -bool CRegionPrimWordListBuilder::buildWordList(std::vector &allWords, string workSheetFileName) +bool CRegionPrimWordListBuilder::buildWordList(std::vector &allWords, std::string workSheetFileName) +{ + // verify the directory is correct + if(!NLMISC::CFile::isDirectory(PrimPath)) { - // verify the directory is correct - if(!CFile::isDirectory(PrimPath)) + nlwarning("Error: Directory '%s' not found. '%s' Aborted", PrimPath.c_str(), workSheetFileName.c_str()); + return false; + } + + // list all files. + std::vector allFiles; + allFiles.reserve(100000); + NLMISC::CPath::getPathContent(PrimPath, true, false, true, allFiles, NULL); + + // parse all primitive that match the filter + allWords.clear(); + allWords.reserve(100000); + // to avoid duplicate + std::set allWordSet; + for(size_t i = 0; i < allFiles.size(); i++) + { + std::string fileName = NLMISC::CFile::getFilename(allFiles[i]); + // filter don't match? + bool oneMatch= false; + for(size_t filter = 0; filter < PrimFilter.size(); filter++) { - nlwarning("Error: Directory '%s' not found. '%s' Aborted", PrimPath.c_str(), workSheetFileName.c_str()); + if(NLMISC::testWildCard(fileName, PrimFilter[filter])) + oneMatch= true; + } + if(!oneMatch) + continue; + + // ok, read the file + NLLIGO::CPrimitives PrimDoc; + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = &PrimDoc; + if (!NLLIGO::loadXmlPrimitiveFile(PrimDoc, allFiles[i], LigoConfig)) + { + nlwarning("Error: cannot open file '%s'. '%s' Aborted", allFiles[i].c_str(), workSheetFileName.c_str()); + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; return false; } - - // list all files. - std::vector allFiles; - allFiles.reserve(100000); - CPath::getPathContent(PrimPath, true, false, true, allFiles, NULL); - - // parse all primitive that match the filter - allWords.clear(); - allWords.reserve(100000); - // to avoid duplicate - set allWordSet; - for(uint i=0;i setPlace; + NLLIGO::TPrimitiveSet placeRes; + setPlace.buildSet(PrimDoc.RootNode, predCont, placeRes); + + // for all found + for (size_t placeId = 0; placeId < placeRes.size(); ++placeId) { - nlwarning("Error: cannot open file '%s'. '%s' Aborted", allFiles[i].c_str(), workSheetFileName.c_str()); - CPrimitiveContext::instance().CurrentPrimitive = NULL; - return false; - } - CPrimitiveContext::instance().CurrentPrimitive = NULL; - - // For all primitives of interest - const char *listClass[]= {"continent", "region", "place", "stable", - "teleport_destination", "room_template"}; - const char *listProp[]= {"name", "name", "name", "name", - "place_name", "place_name"}; - const uint numListClass= sizeof(listClass)/sizeof(listClass[0]); - const uint numListProp= sizeof(listProp)/sizeof(listProp[0]); - nlctassert(numListProp==numListClass); - for(uint cid=0;cid setPlace; - TPrimitiveSet placeRes; - setPlace.buildSet(PrimDoc.RootNode, predCont, placeRes); - // for all found - for (uint placeId= 0; placeId < placeRes.size(); ++placeId) + std::string primName; + if(placeRes[placeId]->getPropertyByName(listProp[cid], primName) && !primName.empty()) { - string primName; - if(placeRes[placeId]->getPropertyByName(listProp[cid], primName) && !primName.empty()) + primName = NLMISC::toLower(primName); + // avoid duplicate + if(allWordSet.insert(primName).second) { - primName= toLower(primName); - // avoid duplicate - if(allWordSet.insert(primName).second) - { - allWords.push_back(primName); - } + allWords.push_back(primName); } } } } - - return true; } + return true; +} } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.h index ca7295f91..01d0f1a0a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.h @@ -30,43 +30,34 @@ #include "nel/ligo/primitive.h" #include "nel/ligo/primitive_utils.h" -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; -using namespace STRING_MANAGER; - -namespace TranslationManager +namespace TranslationManager { - // *************************************************************************** /* * Interface to build the whole list of words (key id) for a specific worksheet */ struct IWordListBuilder { - virtual bool buildWordList(std::vector &allWords, string workSheetFileName) =0; - + virtual bool buildWordList(std::vector &allWords, std::string workSheetFileName) =0; }; struct CSheetWordListBuilder : public IWordListBuilder { - string SheetExt; - string SheetPath; + std::string SheetExt; + std::string SheetPath; - virtual bool buildWordList(std::vector &allWords, string workSheetFileName); + virtual bool buildWordList(std::vector &allWords, std::string workSheetFileName); }; struct CRegionPrimWordListBuilder : public IWordListBuilder { - string PrimPath; - vector PrimFilter; - NLLIGO::CLigoConfig LigoConfig; - virtual bool buildWordList(std::vector &allWords, string workSheetFileName); + std::string PrimPath; + std::vector PrimFilter; + NLLIGO::CLigoConfig LigoConfig; + virtual bool buildWordList(std::vector &allWords, std::string workSheetFileName); }; } - -#endif /* EXTRACT_NEW_SHEET_NAMES_H */ - +#endif /* EXTRACT_NEW_SHEET_NAMES_H */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.cpp index 41a8072e2..876599b61 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.cpp @@ -1,191 +1,216 @@ +// Translation Manager Plugin - OVQT Plugin +// Copyright (C) 2011 Emanuel Costea +// +// 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 . #include "ftp_selection.h" #include #include + namespace TranslationManager { - CFtpSelection::CFtpSelection(QWidget *parent): QDialog(parent) - { - _ui.setupUi(this); - connect(_ui.connectButton, SIGNAL(clicked()), this, SLOT(ConnectButtonClicked())); - connect(_ui.doneButton, SIGNAL(clicked()), this, SLOT(DoneButtonClicked())); - connect(_ui.cdToParrent, SIGNAL(clicked()), this, SLOT(cdToParent())); - connect(_ui.cancelButton, SIGNAL(clicked()), this, SLOT(reject())); - - // file list - connect(_ui.fileList, SIGNAL(itemActivated(QTreeWidgetItem*,int)),this, SLOT(processItem(QTreeWidgetItem*,int))); - _ui.fileList->setEnabled(false); - _ui.fileList->setRootIsDecorated(false); - _ui.fileList->setHeaderLabels(QStringList() << tr("Name") << tr("Size") << tr("Owner") << tr("Group") << tr("Time")); - _ui.fileList->header()->setStretchLastSection(false); +CFtpSelection::CFtpSelection(QWidget *parent): QDialog(parent) +{ + _ui.setupUi(this); + connect(_ui.connectButton, SIGNAL(clicked()), this, SLOT(ConnectButtonClicked())); + connect(_ui.doneButton, SIGNAL(clicked()), this, SLOT(DoneButtonClicked())); + connect(_ui.cdToParrent, SIGNAL(clicked()), this, SLOT(cdToParent())); + connect(_ui.cancelButton, SIGNAL(clicked()), this, SLOT(reject())); - // buttons - _ui.cdToParrent->setEnabled(false); - _ui.doneButton->setEnabled(false); + // file list + connect(_ui.fileList, SIGNAL(itemActivated(QTreeWidgetItem *,int)),this, SLOT(processItem(QTreeWidgetItem *,int))); + _ui.fileList->setEnabled(false); + _ui.fileList->setRootIsDecorated(false); + _ui.fileList->setHeaderLabels(QStringList() << tr("Name") << tr("Size") << tr("Owner") << tr("Group") << tr("Time")); + _ui.fileList->header()->setStretchLastSection(false); - status = false; - } - - // Connection with the FTP Server. We retrieve the file list. - void CFtpSelection::ConnectButtonClicked() - { - conn = new QFtp(this); - connect(conn, SIGNAL(commandFinished(int,bool)), this, SLOT(FtpCommandFinished(int,bool))); - connect(conn, SIGNAL(listInfo(QUrlInfo)), this, SLOT(AddToList(QUrlInfo))); - #ifndef QT_NO_CURSOR - setCursor(Qt::WaitCursor); - #endif - QUrl url(_ui.url->text()); - if (!url.isValid() || url.scheme().toLower() != QLatin1String("ftp")) { - conn->connectToHost(_ui.url->text(), 21); - conn->login(); - } else { - conn->connectToHost(url.host(), url.port(21)); + // buttons + _ui.cdToParrent->setEnabled(false); + _ui.doneButton->setEnabled(false); - if (!url.userName().isEmpty()) - conn->login(QUrl::fromPercentEncoding(url.userName().toLatin1()), url.password()); - else - conn->login(); - if (!url.path().isEmpty()) - conn->cd(url.path()); - } - } - - // Get the user action. - void CFtpSelection::FtpCommandFinished(int, bool error) - { - #ifndef QT_NO_CURSOR - setCursor(Qt::ArrowCursor); - #endif - if (conn->currentCommand() == QFtp::ConnectToHost) - { - if (error) - { - QMessageBox::information(this, tr("FTP"), - tr("Unable to connect to the FTP server " - "at %1. Please check that the host " - "name is correct.") - .arg(_ui.url->text())); - return; - } + status = false; +} - return; - } - - if (conn->currentCommand() == QFtp::Login) - { - conn->list(); - } - - if (conn->currentCommand() == QFtp::Get) - { - if(error) - { - status = false; - file->close(); - file->remove(); - } else { - file->close(); - status = true; - } - _ui.cancelButton->setEnabled(true); - } +// Connection with the FTP Server. We retrieve the file list. +void CFtpSelection::ConnectButtonClicked() +{ + conn = new QFtp(this); + connect(conn, SIGNAL(commandFinished(int,bool)), this, SLOT(FtpCommandFinished(int,bool))); + connect(conn, SIGNAL(listInfo(QUrlInfo)), this, SLOT(AddToList(QUrlInfo))); - if (conn->currentCommand() == QFtp::List) - { - if (isDirectory.isEmpty()) { - _ui.fileList->addTopLevelItem(new QTreeWidgetItem(QStringList() << tr(""))); - _ui.fileList->setEnabled(false); - } - } - } - // Make the file list with directories and files - void CFtpSelection::AddToList(const QUrlInfo &urlInfo) - { - QTreeWidgetItem *item = new QTreeWidgetItem; - item->setText(0, urlInfo.name()); - item->setText(1, QString::number(urlInfo.size())); - item->setText(2, urlInfo.owner()); - item->setText(3, urlInfo.group()); - item->setText(4, urlInfo.lastModified().toString("MMM dd yyyy")); + setCursor(Qt::WaitCursor); - QPixmap pixmap(urlInfo.isDir() ? ":/translationManager/images/dir.png" : ":/translationManager/images/file.png"); - item->setIcon(0, pixmap); - - isDirectory[urlInfo.name()] = urlInfo.isDir(); - _ui.fileList->addTopLevelItem(item); - if (!_ui.fileList->currentItem()) { - _ui.fileList->setCurrentItem(_ui.fileList->topLevelItem(0)); - _ui.fileList->setEnabled(true); - } - } - - void CFtpSelection::processItem(QTreeWidgetItem* item, int) - { - QString name = item->text(0); - if (isDirectory.value(name)) - { - _ui.fileList->clear(); - isDirectory.clear(); - currentPath += '/'; - currentPath += name; - conn->cd(name); - conn->list(); - #ifndef QT_NO_CURSOR - setCursor(Qt::WaitCursor); - #endif - return; - } - _ui.doneButton->setEnabled(true); - } - - // Exit from a directory - void CFtpSelection::cdToParent() + QUrl url(_ui.url->text()); + if (!url.isValid() || url.scheme().toLower() != QLatin1String("ftp")) { - #ifndef QT_NO_CURSOR - setCursor(Qt::WaitCursor); - #endif - _ui.fileList->clear(); - isDirectory.clear(); - currentPath = currentPath.left(currentPath.lastIndexOf('/')); - if (currentPath.isEmpty()) { - _ui.cdToParrent->setEnabled(false); - conn->cd("/"); - } else { - conn->cd(currentPath); - } - conn->list(); + conn->connectToHost(_ui.url->text(), 21); + conn->login(); + } + else + { + conn->connectToHost(url.host(), url.port(21)); + + if (!url.userName().isEmpty()) + conn->login(QUrl::fromPercentEncoding(url.userName().toLatin1()), url.password()); + else + conn->login(); + if (!url.path().isEmpty()) + conn->cd(url.path()); + } +} + +// Get the user action. +void CFtpSelection::FtpCommandFinished(int, bool error) +{ + setCursor(Qt::ArrowCursor); + + if (conn->currentCommand() == QFtp::ConnectToHost) + { + if (error) + { + QMessageBox::information(this, tr("FTP"), + tr("Unable to connect to the FTP server " + "at %1. Please check that the host " + "name is correct.") + .arg(_ui.url->text())); + return; + } + + return; } - // Done action - void CFtpSelection::DoneButtonClicked() - { - QString fileName = _ui.fileList->currentItem()->text(0); - - if (QFile::exists(fileName)) { - QMessageBox::information(this, tr("FTP"), - tr("There already exists a file called %1 in " - "the current directory.") - .arg(fileName)); - return; - } - - file = new QFile(fileName); - #ifndef QT_NO_CURSOR - setCursor(Qt::WaitCursor); - #endif - if (!file->open(QIODevice::WriteOnly)) { - QMessageBox::information(this, tr("FTP"), - tr("Unable to save the file %1: %2.") - .arg(fileName).arg(file->errorString())); - delete file; - return; - } - _ui.cancelButton->setEnabled(false); - conn->get(_ui.fileList->currentItem()->text(0), file); - - reject(); - } - + if (conn->currentCommand() == QFtp::Login) + { + conn->list(); + } + + if (conn->currentCommand() == QFtp::Get) + { + if(error) + { + status = false; + file->close(); + file->remove(); + } + else + { + file->close(); + status = true; + } + _ui.cancelButton->setEnabled(true); + } + + if (conn->currentCommand() == QFtp::List) + { + if (isDirectory.isEmpty()) + { + _ui.fileList->addTopLevelItem(new QTreeWidgetItem(QStringList() << tr(""))); + _ui.fileList->setEnabled(false); + } + } +} +// Make the file list with directories and files +void CFtpSelection::AddToList(const QUrlInfo &urlInfo) +{ + QTreeWidgetItem *item = new QTreeWidgetItem; + item->setText(0, urlInfo.name()); + item->setText(1, QString::number(urlInfo.size())); + item->setText(2, urlInfo.owner()); + item->setText(3, urlInfo.group()); + item->setText(4, urlInfo.lastModified().toString("MMM dd yyyy")); + + QPixmap pixmap(urlInfo.isDir() ? ":/translationManager/images/dir.png" : ":/translationManager/images/file.png"); + item->setIcon(0, pixmap); + + isDirectory[urlInfo.name()] = urlInfo.isDir(); + _ui.fileList->addTopLevelItem(item); + if (!_ui.fileList->currentItem()) + { + _ui.fileList->setCurrentItem(_ui.fileList->topLevelItem(0)); + _ui.fileList->setEnabled(true); + } +} + +void CFtpSelection::processItem(QTreeWidgetItem *item, int) +{ + QString name = item->text(0); + if (isDirectory.value(name)) + { + _ui.fileList->clear(); + isDirectory.clear(); + currentPath += '/'; + currentPath += name; + conn->cd(name); + conn->list(); + + setCursor(Qt::WaitCursor); + return; + } + _ui.doneButton->setEnabled(true); +} + +// Exit from a directory +void CFtpSelection::cdToParent() +{ + setCursor(Qt::WaitCursor); + + _ui.fileList->clear(); + isDirectory.clear(); + currentPath = currentPath.left(currentPath.lastIndexOf('/')); + if (currentPath.isEmpty()) + { + _ui.cdToParrent->setEnabled(false); + conn->cd("/"); + } + else + { + conn->cd(currentPath); + } + conn->list(); +} + +// Done action +void CFtpSelection::DoneButtonClicked() +{ + QString fileName = _ui.fileList->currentItem()->text(0); + + if (QFile::exists(fileName)) + { + QMessageBox::information(this, tr("FTP"), + tr("There already exists a file called %1 in " + "the current directory.") + .arg(fileName)); + return; + } + + file = new QFile(fileName); + + setCursor(Qt::WaitCursor); + + if (!file->open(QIODevice::WriteOnly)) + { + QMessageBox::information(this, tr("FTP"), + tr("Unable to save the file %1: %2.") + .arg(fileName).arg(file->errorString())); + delete file; + return; + } + _ui.cancelButton->setEnabled(false); + conn->get(_ui.fileList->currentItem()->text(0), file); + + reject(); +} + } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.h index 47dcfdb57..9f8af85dd 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.h @@ -1,4 +1,4 @@ -/* +/* * File: ftp_selection.h * Author: cemycc * @@ -8,6 +8,8 @@ #ifndef FTP_SELECTION_H #define FTP_SELECTION_H +#include "ui_ftp_selection.h" + #include #include #include @@ -16,34 +18,33 @@ #include #include -#include "ui_ftp_selection.h" +namespace TranslationManager +{ -using namespace std; +class CFtpSelection : public QDialog +{ + Q_OBJECT -namespace TranslationManager { - - class CFtpSelection : public QDialog - { - Q_OBJECT - private: - Ui::FtpSelectionDialog _ui; - QFtp *conn; - QHash isDirectory; - QString currentPath; - private Q_SLOTS: - void cdToParent(); - void processItem(QTreeWidgetItem*,int); - void ConnectButtonClicked(); - void DoneButtonClicked(); - void FtpCommandFinished(int, bool error); - void AddToList(const QUrlInfo &urlInfo); - public: - bool status; - QFile *file; - CFtpSelection(QWidget* parent = 0); - ~CFtpSelection() {} - }; +public: + CFtpSelection(QWidget *parent = 0); + ~CFtpSelection() {} + bool status; + QFile *file; + +private Q_SLOTS: + void cdToParent(); + void processItem(QTreeWidgetItem *,int); + void ConnectButtonClicked(); + void DoneButtonClicked(); + void FtpCommandFinished(int, bool error); + void AddToList(const QUrlInfo &urlInfo); + +private: + Ui::FtpSelectionDialog _ui; + QFtp *conn; + QHash isDirectory; + QString currentPath; +}; } -#endif /* FTP_SELECTION_H */ - +#endif /* FTP_SELECTION_H */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.cpp index 3015b447d..518906db0 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.cpp @@ -1,39 +1,54 @@ - -#include +// Translation Manager Plugin - OVQT Plugin +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Emanuel Costea +// +// 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 . #include "source_selection.h" +#include + namespace TranslationManager { - CSourceDialog::CSourceDialog(QWidget *parent): QDialog(parent) { _ui.setupUi(this); - // Set signal and slot for "OK Button" + connect(_ui.ok_button, SIGNAL(clicked()), this, SLOT(OkButtonClicked())); - // Set signal and slot for "Cancel Button" - connect(_ui.cancel_button, SIGNAL(clicked()), this, SLOT(reject())); - _ui.sourceSelectionListWidget->setSortingEnabled(false); + connect(_ui.cancel_button, SIGNAL(clicked()), this, SLOT(reject())); + + _ui.sourceSelectionListWidget->setSortingEnabled(false); connect(_ui.sourceSelectionListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), - this, SLOT(itemDoubleClicked(QListWidgetItem *))); + this, SLOT(itemDoubleClicked(QListWidgetItem *))); } // Insert options in the source dialog. Options like: from FTP Server, from Local directory etc. -void CSourceDialog::setSourceOptions(map options) +void CSourceDialog::setSourceOptions(std::map &options) { - map::iterator it; - - for(it = options.begin(); it != options.end(); ++it) - { - _ui.sourceSelectionListWidget->addItem((*it).first); - } + std::map::iterator it; + + for(it = options.begin(); it != options.end(); ++it) + { + _ui.sourceSelectionListWidget->addItem((*it).first); + } } void CSourceDialog::OkButtonClicked() { - selected_item = _ui.sourceSelectionListWidget->currentItem(); - accept(); + selected_item = _ui.sourceSelectionListWidget->currentItem(); + accept(); } void CSourceDialog::itemDoubleClicked(QListWidgetItem *item) @@ -42,4 +57,4 @@ void CSourceDialog::itemDoubleClicked(QListWidgetItem *item) accept(); } -} +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.h index d32bfcb02..7b6fc2cb9 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.h @@ -1,16 +1,30 @@ - +// Translation Manager Plugin - OVQT Plugin +// Copyright (C) 2011 Emanuel Costea +// +// 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 SOURCE_SELECTION_H #define SOURCE_SELECTION_H +#include "ui_source_selection.h" + #include #include #include #include -#include "ui_source_selection.h" -#include -using namespace std; +#include namespace TranslationManager { @@ -18,16 +32,19 @@ namespace TranslationManager class CSourceDialog : public QDialog { Q_OBJECT -private: - Ui::SourceSelectionDialog _ui; + +public: + CSourceDialog(QWidget *parent = 0); + ~CSourceDialog() {} + void setSourceOptions(std::map &options); + QListWidgetItem *selected_item; + private Q_SLOTS: void OkButtonClicked(); void itemDoubleClicked(QListWidgetItem *item); -public: - CSourceDialog(QWidget *parent = 0); - ~CSourceDialog(){} - void setSourceOptions(map options); - QListWidgetItem *selected_item; + +private: + Ui::SourceSelectionDialog _ui; }; } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_constants.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_constants.h index dcb91676b..d72a2b223 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_constants.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_constants.h @@ -1,29 +1,38 @@ -/* - * File: translation_manager_constants.h - * Author: cemycc - * - * Created on July 5, 2011, 9:15 PM - */ +// Translation Manager Plugin - OVQT Plugin +// Copyright (C) 2011 Emanuel Costea +// +// 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 TRANSLATION_MANAGER_CONSTANTS_H #define TRANSLATION_MANAGER_CONSTANTS_H namespace TranslationManager { - namespace Constants - { - const int ED_SHEET = 1; - const int ED_PHRASE = 2; +namespace Constants +{ +const int ED_SHEET = 1; +const int ED_PHRASE = 2; - const char * const WK_BOTNAMES = "bot_names_wk.txt"; - const char * const WK_ITEM = "item_words_wk.txt"; - const char * const WK_CREATURE = "creature_words_wk.txt"; - const char * const WK_SBRICK = "sbrick_words_wk.txt"; - const char * const WK_SPHRASE = "sphrase_words_wk.txt"; - const char * const WK_PLACE = "place_words_wk.txt"; - const char * const WK_CONTINENT = "place_words_wk.txt"; - const char * const WK_STABLE = "place_words_wk.txt"; - } +const char *const WK_BOTNAMES = "bot_names_wk.txt"; +const char *const WK_ITEM = "item_words_wk.txt"; +const char *const WK_CREATURE = "creature_words_wk.txt"; +const char *const WK_SBRICK = "sbrick_words_wk.txt"; +const char *const WK_SPHRASE = "sphrase_words_wk.txt"; +const char *const WK_PLACE = "place_words_wk.txt"; +const char *const WK_CONTINENT = "place_words_wk.txt"; +const char *const WK_STABLE = "place_words_wk.txt"; +} } #endif /* TRANSLATION_MANAGER_CONSTANTS_H */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_editor.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_editor.h index bc46769c1..fd53ba863 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_editor.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_editor.h @@ -1,5 +1,4 @@ // Translation Manager Plugin - OVQT Plugin -// Copyright (C) 2010 Winch Gate Property Limited // Copyright (C) 2011 Emanuel Costea // // This program is free software: you can redistribute it and/or modify @@ -25,31 +24,30 @@ #include #include -namespace TranslationManager { - -class CEditor : public QMdiSubWindow { -Q_OBJECT -protected: - QUndoStack* current_stack; - QString current_file; - int editor_type; -public: - CEditor(QMdiArea* parent) : QMdiSubWindow(parent) {} - CEditor() : QMdiSubWindow() {} - virtual void open(QString filename) =0; - virtual void save() =0; - virtual void saveAs(QString filename) =0; - virtual void activateWindow() =0; +namespace TranslationManager +{ + +class CEditor : public QMdiSubWindow +{ + Q_OBJECT + public: + CEditor(QMdiArea *parent) : QMdiSubWindow(parent) {} + CEditor() : QMdiSubWindow() {} + virtual void open(QString filename) =0; + virtual void save() =0; + virtual void saveAs(QString filename) =0; + virtual void activateWindow() =0; + int eType() { return editor_type; } - QString subWindowFilePath() - { - return current_file; - } - void setUndoStack(QUndoStack* stack) + QString subWindowFilePath() + { + return current_file; + } + void setUndoStack(QUndoStack *stack) { current_stack = stack; } @@ -58,14 +56,16 @@ public: QFileInfo *file = new QFileInfo(filename); current_file = file->canonicalFilePath(); setWindowModified(false); - setWindowTitle(file->fileName() + "[*]"); + setWindowTitle(file->fileName() + "[*]"); setWindowFilePath(current_file); } +protected: + QUndoStack *current_stack; + QString current_file; + int editor_type; }; } - -#endif /* TRANSLATION_MANAGER_EDITOR_H */ - +#endif /* TRANSLATION_MANAGER_EDITOR_H */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.cpp index 23509bd20..46a0dd99f 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -1,4 +1,3 @@ - // Translation Manager Plugin - OVQT Plugin // Copyright (C) 2010 Winch Gate Property Limited // Copyright (C) 2011 Emanuel Costea @@ -16,32 +15,31 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -// Project system includes +// Plugin includes +#include "translation_manager_main_window.h" +#include "translation_manager_constants.h" +#include "ftp_selection.h" + +// Core includes #include "../core/icore.h" #include "../core/core_constants.h" #include "../core/menu_manager.h" #include "../../extension_system/iplugin_spec.h" // Qt includes -#include -#include +#include +#include #include -#include #include +#include +#include +#include #include #include #include #include -#include #include -#include -#include #include -// Plugin includes -#include "translation_manager_main_window.h" -#include "translation_manager_constants.h" -#include "ftp_selection.h" - namespace TranslationManager { @@ -49,122 +47,126 @@ namespace TranslationManager CMainWindow::CMainWindow(QWidget *parent) : QMainWindow(parent) { - _ui.setupUi(this); - - _ui.mdiArea->closeAllSubWindows(); - windowMapper = new QSignalMapper(this); - connect(windowMapper, SIGNAL(mapped(QWidget*)), this, SLOT(setActiveSubWindow(QWidget*))); - - initialize_settings["georges"] = false; - initialize_settings["ligo"] = false; + _ui.setupUi(this); - connect(Core::ICore::instance(), SIGNAL(changeSettings()), this, SLOT(readSettings())); - readSettings(); - createToolbar(); - m_undoStack = new QUndoStack(this); + _ui.mdiArea->closeAllSubWindows(); + windowMapper = new QSignalMapper(this); + connect(windowMapper, SIGNAL(mapped(QWidget *)), this, SLOT(setActiveSubWindow(QWidget *))); + + initialize_settings["georges"] = false; + initialize_settings["ligo"] = false; + + connect(Core::ICore::instance(), SIGNAL(changeSettings()), this, SLOT(readSettings())); + readSettings(); + createToolbar(); + m_undoStack = new QUndoStack(this); } // Functions that will insert the plugin buttons void CMainWindow::createToolbar() -{ - // File menu - openAct = new QAction(QIcon(Core::Constants::ICON_OPEN), "&Open file(s)...", this); - _ui.toolBar->addAction(openAct); - connect(openAct, SIGNAL(triggered()), this, SLOT(open())); - saveAct = new QAction(QIcon(Core::Constants::ICON_SAVE), "&Save...", this); - _ui.toolBar->addAction(saveAct); - connect(saveAct, SIGNAL(triggered()), this, SLOT(save())); - saveAsAct = new QAction(QIcon(Core::Constants::ICON_SAVE_AS), "&Save as...", this); - _ui.toolBar->addAction(saveAsAct); - connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); +{ + // File menu + openAct = new QAction(QIcon(Core::Constants::ICON_OPEN), "&Open file(s)...", this); + _ui.toolBar->addAction(openAct); + connect(openAct, SIGNAL(triggered()), this, SLOT(open())); + saveAct = new QAction(QIcon(Core::Constants::ICON_SAVE), "&Save...", this); + _ui.toolBar->addAction(saveAct); + connect(saveAct, SIGNAL(triggered()), this, SLOT(save())); + saveAsAct = new QAction(QIcon(Core::Constants::ICON_SAVE_AS), "&Save as...", this); + _ui.toolBar->addAction(saveAsAct); + connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); - // Tools menu - QMenu *wordsExtractionMenu = new QMenu("&Words extraction..."); - wordsExtractionMenu->setIcon(QIcon(Core::Constants::ICON_SETTINGS)); - _ui.toolBar->addAction(wordsExtractionMenu->menuAction()); - // extract bot names - QAction *extractBotNamesAct = wordsExtractionMenu->addAction("&Extract bot names..."); - extractBotNamesAct->setStatusTip(tr("Extract bot names from primitives.")); - connect(extractBotNamesAct, SIGNAL(triggered()), this, SLOT(extractBotNames())); - // Words extraction - // ----------------------------- - // signal mapper for extraction words - QSignalMapper *wordsExtractionMapper = new QSignalMapper(this); - connect(wordsExtractionMapper, SIGNAL(mapped(QString)), this, SLOT(extractWords(QString))); - // extract item words - QAction *extractItemWordsAct = wordsExtractionMenu->addAction("&Extract item words..."); - extractItemWordsAct->setStatusTip(tr("Extract item words")); - connect(extractItemWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map())); - wordsExtractionMapper->setMapping(extractItemWordsAct, QString(Constants::WK_ITEM)); - // extract creature words - QAction *extractCreatureWordsAct = wordsExtractionMenu->addAction("&Extract creature words..."); - extractCreatureWordsAct->setStatusTip(tr("Extract creature words")); - connect(extractCreatureWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map())); - wordsExtractionMapper->setMapping(extractCreatureWordsAct, QString(Constants::WK_CREATURE)); - // extract sbrick words - QAction *extractSbrickWordsAct = wordsExtractionMenu->addAction("&Extract sbrick words..."); - extractSbrickWordsAct->setStatusTip(tr("Extract sbrick words")); - connect(extractSbrickWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map())); - wordsExtractionMapper->setMapping(extractSbrickWordsAct, QString(Constants::WK_SBRICK)); - // extract sphrase words - QAction *extractSphraseWordsAct = wordsExtractionMenu->addAction("&Extract sphrase words..."); - extractSphraseWordsAct->setStatusTip(tr("Extract sphrase words")); - connect(extractSphraseWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map())); - wordsExtractionMapper->setMapping(extractSphraseWordsAct, QString(Constants::WK_SPHRASE)); - // extract place and region names - QAction *extractPlaceNamesAct = wordsExtractionMenu->addAction("&Extract place names..."); - extractPlaceNamesAct->setStatusTip(tr("Extract place names from primitives")); - connect(extractPlaceNamesAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map())); - wordsExtractionMapper->setMapping(extractPlaceNamesAct, QString(Constants::WK_PLACE)); - // Merge options - // ----------------------------- - QAction *mergeSingleFileAct = wordsExtractionMenu->addAction("&Merge worksheet file..."); - mergeSingleFileAct->setStatusTip(tr("Merge worksheet file from local or remote directory")); - connect(mergeSingleFileAct, SIGNAL(triggered()), this, SLOT(mergeSingleFile())); - // Windows menu - Core::ICore *core = Core::ICore::instance(); - Core::MenuManager *menuManager = core->menuManager(); - windowMenu = menuManager->menuBar()->addMenu("Window"); - updateWindowsList(); - connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowsList())); + // Tools menu + QMenu *wordsExtractionMenu = new QMenu("&Words extraction..."); + wordsExtractionMenu->setIcon(QIcon(Core::Constants::ICON_SETTINGS)); + _ui.toolBar->addAction(wordsExtractionMenu->menuAction()); - // Undo, Redo actions - // ----------------------------- - QAction* undoAction = menuManager->action(Core::Constants::UNDO); - if (undoAction != 0) - _ui.toolBar->addAction(undoAction); - - QAction* redoAction = menuManager->action(Core::Constants::REDO); - if (redoAction != 0) - _ui.toolBar->addAction(redoAction); + // extract bot names + QAction *extractBotNamesAct = wordsExtractionMenu->addAction("&Extract bot names..."); + extractBotNamesAct->setStatusTip(tr("Extract bot names from primitives.")); + connect(extractBotNamesAct, SIGNAL(triggered()), this, SLOT(extractBotNames())); + + // Words extraction + QSignalMapper *wordsExtractionMapper = new QSignalMapper(this); + connect(wordsExtractionMapper, SIGNAL(mapped(QString)), this, SLOT(extractWords(QString))); + // extract item words + + QAction *extractItemWordsAct = wordsExtractionMenu->addAction("&Extract item words..."); + extractItemWordsAct->setStatusTip(tr("Extract item words")); + connect(extractItemWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map())); + wordsExtractionMapper->setMapping(extractItemWordsAct, QString(Constants::WK_ITEM)); + + // extract creature words + QAction *extractCreatureWordsAct = wordsExtractionMenu->addAction(tr("&Extract creature words...")); + extractCreatureWordsAct->setStatusTip(tr("Extract creature words")); + connect(extractCreatureWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map())); + wordsExtractionMapper->setMapping(extractCreatureWordsAct, QString(Constants::WK_CREATURE)); + + // extract sbrick words + QAction *extractSbrickWordsAct = wordsExtractionMenu->addAction("&Extract sbrick words..."); + extractSbrickWordsAct->setStatusTip(tr("Extract sbrick words")); + connect(extractSbrickWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map())); + wordsExtractionMapper->setMapping(extractSbrickWordsAct, QString(Constants::WK_SBRICK)); + + // extract sphrase words + QAction *extractSphraseWordsAct = wordsExtractionMenu->addAction("&Extract sphrase words..."); + extractSphraseWordsAct->setStatusTip(tr("Extract sphrase words")); + connect(extractSphraseWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map())); + wordsExtractionMapper->setMapping(extractSphraseWordsAct, QString(Constants::WK_SPHRASE)); + + // extract place and region names + QAction *extractPlaceNamesAct = wordsExtractionMenu->addAction("&Extract place names..."); + extractPlaceNamesAct->setStatusTip(tr("Extract place names from primitives")); + connect(extractPlaceNamesAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map())); + wordsExtractionMapper->setMapping(extractPlaceNamesAct, QString(Constants::WK_PLACE)); + + // Merge options + QAction *mergeSingleFileAct = wordsExtractionMenu->addAction("&Merge worksheet file..."); + mergeSingleFileAct->setStatusTip(tr("Merge worksheet file from local or remote directory")); + connect(mergeSingleFileAct, SIGNAL(triggered()), this, SLOT(mergeSingleFile())); + + // Windows menu + Core::ICore *core = Core::ICore::instance(); + Core::MenuManager *menuManager = core->menuManager(); + windowMenu = menuManager->menuBar()->addMenu("Window"); + updateWindowsList(); + connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowsList())); + + // Undo, Redo actions + QAction *undoAction = menuManager->action(Core::Constants::UNDO); + if (undoAction != 0) + _ui.toolBar->addAction(undoAction); + + QAction *redoAction = menuManager->action(Core::Constants::REDO); + if (redoAction != 0) + _ui.toolBar->addAction(redoAction); } // Update the toolbar if the editor is worksheet void CMainWindow::updateToolbar(QMdiSubWindow *window) { - if(_ui.mdiArea->subWindowList().size() > 0) - if(QString(window->widget()->metaObject()->className()) == "QTableWidget") // Sheet Editor - { - QAction *insertRowAct = new QAction(tr("Insert new row"), this); - connect(insertRowAct, SIGNAL(triggered()), window, SLOT(insertRow())); - windowMenu->addAction(insertRowAct); - QAction *deleteRowAct = new QAction(tr("Delete row"), this); - connect(deleteRowAct, SIGNAL(triggered()), window, SLOT(deleteRow())); - windowMenu->addAction(deleteRowAct); - - } + if(_ui.mdiArea->subWindowList().size() > 0) + if(QString(window->widget()->metaObject()->className()) == "QTableWidget") // Sheet Editor + { + QAction *insertRowAct = new QAction(tr("Insert new row"), this); + connect(insertRowAct, SIGNAL(triggered()), window, SLOT(insertRow())); + windowMenu->addAction(insertRowAct); + QAction *deleteRowAct = new QAction(tr("Delete row"), this); + connect(deleteRowAct, SIGNAL(triggered()), window, SLOT(deleteRow())); + windowMenu->addAction(deleteRowAct); + } } // Set the active subwindow -void CMainWindow::setActiveSubWindow(QWidget* window) +void CMainWindow::setActiveSubWindow(QWidget *window) { - if (!window) - { - return; - } - QMdiSubWindow *cwindow = qobject_cast(window); - _ui.mdiArea->setActiveSubWindow(cwindow); + if (!window) + return; + + QMdiSubWindow *mdiWindow = qobject_cast(window); + if (mdiWindow != 0) + _ui.mdiArea->setActiveSubWindow(mdiWindow); } // Functions for updating the windows list @@ -172,148 +174,139 @@ void CMainWindow::updateWindowsList() { if(_ui.mdiArea->activeSubWindow()) { - windowMenu->clear(); - QMdiSubWindow *current_window = _ui.mdiArea->activeSubWindow(); - QList subWindows = _ui.mdiArea->subWindowList(); - - updateToolbar(current_window); - - for(int i = 0; i < subWindows.size(); ++i) - { - QString window_file = QFileInfo(subWindows.at(i)->windowFilePath()).fileName(); - QString action_text; - if (i < 9) { - action_text = QString("&%1 %2").arg(i + 1).arg(window_file); - } else { - action_text = QString("%1 %2").arg(i + 1).arg(window_file); - } - QAction *action = new QAction(action_text, this); - action->setCheckable(true); - action->setChecked(subWindows.at(i) == current_window); - connect(action, SIGNAL(triggered()), windowMapper, SLOT(map())); - windowMenu->addAction(action); - windowMapper->setMapping(action, subWindows.at(i)); - } - } else { - windowMenu->clear(); - } + windowMenu->clear(); + QMdiSubWindow *current_window = _ui.mdiArea->activeSubWindow(); + QList subWindows = _ui.mdiArea->subWindowList(); + + updateToolbar(current_window); + + for(int i = 0; i < subWindows.size(); ++i) + { + QString window_file = QFileInfo(subWindows.at(i)->windowFilePath()).fileName(); + QString action_text; + if (i < 9) + { + action_text = QString("&%1 %2").arg(i + 1).arg(window_file); + } + else + { + action_text = QString("%1 %2").arg(i + 1).arg(window_file); + } + QAction *action = new QAction(action_text, this); + action->setCheckable(true); + action->setChecked(subWindows.at(i) == current_window); + connect(action, SIGNAL(triggered()), windowMapper, SLOT(map())); + windowMenu->addAction(action); + windowMapper->setMapping(action, subWindows.at(i)); + } + } + else + { + windowMenu->clear(); + } } // Open signal void CMainWindow::open() { - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup("translationmanager"); - QString lastOpenLocation = settings->value("lastOpenLocation").toString(); - QString file_name = QFileDialog::getOpenFileName(this, tr("Open translation file"), lastOpenLocation, tr("Translation files (*txt)")); - QFileInfo* file_info = new QFileInfo(file_name); - settings->setValue("lastOpenLocation", file_info->absolutePath()); - settings->endGroup(); + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup("translationmanager"); + QString lastOpenLocation = settings->value("lastOpenLocation").toString(); + QString file_name = QFileDialog::getOpenFileName(this, tr("Open translation file"), lastOpenLocation, tr("Translation files (*txt)")); + QFileInfo *file_info = new QFileInfo(file_name); + settings->setValue("lastOpenLocation", file_info->absolutePath()); + settings->endGroup(); - if(!file_name.isEmpty()) - { - CEditor *editor = getEditorByWindowFilePath(file_name); - if(editor != NULL) - { - editor->activateWindow(); - return; - } - #ifndef QT_NO_CURSOR - QApplication::setOverrideCursor(Qt::WaitCursor); - #endif - // sheet editor - if(isWorksheetEditor(file_name)) - { - CEditorWorksheet *new_window = new CEditorWorksheet(_ui.mdiArea); - new_window->setUndoStack(m_undoStack); - new_window->open(file_name); - new_window->activateWindow(); - } - // phrase editor - if(isPhraseEditor(file_name)) - { - CEditorPhrase *new_window = new CEditorPhrase(_ui.mdiArea); - new_window->setUndoStack(m_undoStack); - new_window->open(file_name); - new_window->activateWindow(); - } - #ifndef QT_NO_CURSOR - QApplication::restoreOverrideCursor(); - #endif - } - + if(!file_name.isEmpty()) + { + CEditor *editor = getEditorByWindowFilePath(file_name); + if(editor != NULL) + { + editor->activateWindow(); + return; + } + QApplication::setOverrideCursor(Qt::WaitCursor); + + // sheet editor + if(isWorksheetEditor(file_name)) + { + CEditorWorksheet *new_window = new CEditorWorksheet(_ui.mdiArea); + new_window->setUndoStack(m_undoStack); + new_window->open(file_name); + new_window->activateWindow(); + } + // phrase editor + if(isPhraseEditor(file_name)) + { + CEditorPhrase *new_window = new CEditorPhrase(_ui.mdiArea); + new_window->setUndoStack(m_undoStack); + new_window->open(file_name); + new_window->activateWindow(); + } + QApplication::restoreOverrideCursor(); + } } // Open a work file. You can set the directory for work file in the settings dialog void CMainWindow::openWorkFile(QString file) { - QFileInfo* file_path = new QFileInfo(QString("%1/%2").arg(work_path).arg(file)); - if(file_path->exists()) - { - if(isWorksheetEditor(file_path->filePath())) - { - CEditorWorksheet *new_window = new CEditorWorksheet(_ui.mdiArea); - new_window->open(file_path->filePath()); - new_window->activateWindow(); - } - } else { - QErrorMessage error; - error.showMessage(QString("The %1 file don't exists.").arg(file_path->fileName())); - error.exec(); - } - + QFileInfo *file_path = new QFileInfo(QString("%1/%2").arg(work_path).arg(file)); + if(file_path->exists()) + { + if(isWorksheetEditor(file_path->filePath())) + { + CEditorWorksheet *new_window = new CEditorWorksheet(_ui.mdiArea); + new_window->open(file_path->filePath()); + new_window->activateWindow(); + } + } + else + { + QErrorMessage error; + error.showMessage(tr("The %1 file don't exists.").arg(file_path->fileName())); + error.exec(); + } } -// Save signal void CMainWindow::save() { - if(_ui.mdiArea->subWindowList().size() > 0) - { - CEditor* current_window = qobject_cast(_ui.mdiArea->currentSubWindow()); - #ifndef QT_NO_CURSOR - QApplication::setOverrideCursor(Qt::WaitCursor); - #endif + if(_ui.mdiArea->subWindowList().size() > 0) + { + CEditor *current_window = qobject_cast(_ui.mdiArea->currentSubWindow()); + QApplication::setOverrideCursor(Qt::WaitCursor); current_window->save(); - #ifndef QT_NO_CURSOR - QApplication::restoreOverrideCursor(); - #endif - } + QApplication::restoreOverrideCursor(); + } } -// Save as signal void CMainWindow::saveAs() { - QString file_name; - if (_ui.mdiArea->isActiveWindow()) - { - file_name = QFileDialog::getSaveFileName(this); - } - - if (!file_name.isEmpty()) - { - CEditor* current_window = qobject_cast(_ui.mdiArea->currentSubWindow()); - #ifndef QT_NO_CURSOR - QApplication::setOverrideCursor(Qt::WaitCursor); - #endif - current_window->saveAs(file_name); - #ifndef QT_NO_CURSOR - QApplication::restoreOverrideCursor(); - #endif - } + QString file_name; + if (_ui.mdiArea->isActiveWindow()) + { + file_name = QFileDialog::getSaveFileName(this); + } + if (!file_name.isEmpty()) + { + CEditor *current_window = qobject_cast(_ui.mdiArea->currentSubWindow()); + QApplication::setOverrideCursor(Qt::WaitCursor); + current_window->saveAs(file_name); + QApplication::restoreOverrideCursor(); + } } // This function is needed by extraction. void CMainWindow::initializeSettings(bool georges = false) -{ - if(georges == true && initialize_settings["georges"] == false) - { - CPath::addSearchPath(level_design_path.toStdString() + "/DFN", true, false); - CPath::addSearchPath(level_design_path.toStdString() + "/Game_elem/Creature", true, false); - initialize_settings["georges"] = true; - } +{ + if(georges == true && initialize_settings["georges"] == false) + { + NLMISC::CPath::addSearchPath(level_design_path.toStdString() + "/DFN", true, false); + NLMISC::CPath::addSearchPath(level_design_path.toStdString() + "/Game_elem/Creature", true, false); + initialize_settings["georges"] = true; + } - if(initialize_settings["ligo"] == false) - { + if(initialize_settings["ligo"] == false) + { try { // Search path of file world_editor_classes.xml @@ -328,252 +321,263 @@ void CMainWindow::initializeSettings(bool georges = false) { nlerror("Can't found path to world_editor_classes.xml"); } - } - + } } // Extracting words void CMainWindow::extractWords(QString typeq) { - if(verifySettings() == true) - { - CEditorWorksheet* editor_window = getEditorByWorksheetType(typeq); + if(verifySettings() == true) + { + CEditorWorksheet *editor_window = getEditorByWorksheetType(typeq); + if(editor_window != NULL) + { + editor_window->activateWindow(); + QString file_path = editor_window->windowFilePath(); + } + else + { + openWorkFile(typeq); + editor_window = getEditorByWorksheetType(typeq); if(editor_window != NULL) { - editor_window->activateWindow(); - QString file_path = editor_window->windowFilePath(); - } else { - openWorkFile(typeq); - editor_window = getEditorByWorksheetType(typeq); - if(editor_window != NULL) - { - editor_window->activateWindow(); - QString file_path = editor_window->windowFilePath(); - } else return; + editor_window->activateWindow(); + QString file_path = editor_window->windowFilePath(); } + else return; + } - QString column_name; - // Sheet extraction - CSheetWordListBuilder builderS; - // Primitives extraction - CRegionPrimWordListBuilder builderP; - bool isSheet = false; - if(typeq.toAscii() == Constants::WK_ITEM) { - column_name = "item ID"; - builderS.SheetExt = "sitem"; - builderS.SheetPath = level_design_path.append("/game_element/sitem").toStdString(); - isSheet = true; - } else if(typeq.toAscii() == Constants::WK_CREATURE) { - column_name = "creature ID"; - builderS.SheetExt = "creature"; - builderS.SheetPath = level_design_path.append("/Game_elem/Creature/fauna").toStdString(); - isSheet = true; - } else if(typeq.toAscii() == Constants::WK_SBRICK) { - column_name = "sbrick ID"; - builderS.SheetExt = "sbrick"; - builderS.SheetPath = level_design_path.append("/game_element/sbrick").toStdString(); - isSheet = true; - } else if(typeq.toAscii() == Constants::WK_SPHRASE) { - column_name = "sphrase ID"; - builderS.SheetExt = "sphrase"; - builderS.SheetPath = level_design_path.append("/game_element/sphrase").toStdString(); - isSheet = true; - } else if(typeq.toAscii() == Constants::WK_PLACE) { - column_name = "placeId"; - builderP.PrimPath = primitives_path.toStdString(); - builderP.PrimFilter.push_back("region_*.primitive"); - builderP.PrimFilter.push_back("indoors_*.primitive"); - isSheet = false; - } - #ifndef QT_NO_CURSOR - QApplication::setOverrideCursor(Qt::WaitCursor); - #endif - if(isSheet) - { - editor_window->extractWords(editor_window->windowFilePath(), column_name, builderS); - } else { - initializeSettings(false); - editor_window->extractWords(editor_window->windowFilePath(), column_name, builderP); - } - #ifndef QT_NO_CURSOR - QApplication::restoreOverrideCursor(); - #endif - } - + QString column_name; + // Sheet extraction + CSheetWordListBuilder builderS; + // Primitives extraction + CRegionPrimWordListBuilder builderP; + bool isSheet = false; + if(typeq.toAscii() == Constants::WK_ITEM) + { + column_name = "item ID"; + builderS.SheetExt = "sitem"; + builderS.SheetPath = level_design_path.append("/game_element/sitem").toStdString(); + isSheet = true; + } + else if(typeq.toAscii() == Constants::WK_CREATURE) + { + column_name = "creature ID"; + builderS.SheetExt = "creature"; + builderS.SheetPath = level_design_path.append("/Game_elem/Creature/fauna").toStdString(); + isSheet = true; + } + else if(typeq.toAscii() == Constants::WK_SBRICK) + { + column_name = "sbrick ID"; + builderS.SheetExt = "sbrick"; + builderS.SheetPath = level_design_path.append("/game_element/sbrick").toStdString(); + isSheet = true; + } + else if(typeq.toAscii() == Constants::WK_SPHRASE) + { + column_name = "sphrase ID"; + builderS.SheetExt = "sphrase"; + builderS.SheetPath = level_design_path.append("/game_element/sphrase").toStdString(); + isSheet = true; + } + else if(typeq.toAscii() == Constants::WK_PLACE) + { + column_name = "placeId"; + builderP.PrimPath = primitives_path.toStdString(); + builderP.PrimFilter.push_back("region_*.primitive"); + builderP.PrimFilter.push_back("indoors_*.primitive"); + isSheet = false; + } + QApplication::setOverrideCursor(Qt::WaitCursor); + if(isSheet) + { + editor_window->extractWords(editor_window->windowFilePath(), column_name, builderS); + } + else + { + initializeSettings(false); + editor_window->extractWords(editor_window->windowFilePath(), column_name, builderP); + } + QApplication::restoreOverrideCursor(); + } } // Extract bot names from primitives void CMainWindow::extractBotNames() { - if(verifySettings() == true) - { - CEditorWorksheet* editor_window = getEditorByWorksheetType(NULL); + if(verifySettings() == true) + { + CEditorWorksheet *editor_window = getEditorByWorksheetType(NULL); + if(editor_window != NULL) + { + editor_window->activateWindow(); + QString file_path = editor_window->windowFilePath(); + } + else + { + openWorkFile(Constants::WK_BOTNAMES); + editor_window = getEditorByWorksheetType(NULL); if(editor_window != NULL) { - editor_window->activateWindow(); - QString file_path = editor_window->windowFilePath(); - } else { - openWorkFile(Constants::WK_BOTNAMES); - editor_window = getEditorByWorksheetType(NULL); - if(editor_window != NULL) - { - editor_window->activateWindow(); - QString file_path = editor_window->windowFilePath(); - } else return; + editor_window->activateWindow(); + QString file_path = editor_window->windowFilePath(); } - #ifndef QT_NO_CURSOR - QApplication::setOverrideCursor(Qt::WaitCursor); - #endif - initializeSettings(true); - editor_window->extractBotNames(convertQStringList(filters), level_design_path.toStdString(), ligoConfig); - #ifndef QT_NO_CURSOR - QApplication::restoreOverrideCursor(); - #endif - } + else return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + initializeSettings(true); + editor_window->extractBotNames(convertQStringList(filters), level_design_path.toStdString(), ligoConfig); + QApplication::restoreOverrideCursor(); + } } // Merge the content for 2 worksheet files void CMainWindow::mergeSingleFile() { - CEditor* editor_window = qobject_cast(_ui.mdiArea->currentSubWindow()); - CSourceDialog *dialog = new CSourceDialog(this); - CFtpSelection* ftp_dialog; - map methods; + CEditor *editor_window = qobject_cast(_ui.mdiArea->currentSubWindow()); + CSourceDialog *dialog = new CSourceDialog(this); + CFtpSelection *ftp_dialog; + map methods; QString file_name; - if (_ui.mdiArea->subWindowList().size() == 0) - { + if (_ui.mdiArea->subWindowList().size() == 0) + { QErrorMessage error; - error.showMessage(QString("Open a work file in editor for merge operation.")); - error.exec(); + error.showMessage(tr("Open a work file in editor for merge operation.")); + error.exec(); return; } - if(editor_window->eType() != Constants::ED_SHEET) // Sheet Editor - { + if(editor_window->eType() != Constants::ED_SHEET) // Sheet Editor + { QErrorMessage error; - error.showMessage(QString("Please open or activate the window with a sheet file.")); - error.exec(); + error.showMessage(tr("Please open or activate the window with a sheet file.")); + error.exec(); return; } - // create items - QListWidgetItem* local_item = new QListWidgetItem(); - local_item->setText("Local directory"); - methods[local_item] = 0; - QListWidgetItem* ftp_item = new QListWidgetItem(); - ftp_item->setText("From a FTP server"); - methods[ftp_item] = 1; - - dialog->setSourceOptions(methods); - dialog->show(); - dialog->exec(); + // create items + QListWidgetItem *local_item = new QListWidgetItem(); + local_item->setText("Local directory"); + methods[local_item] = 0; + QListWidgetItem *ftp_item = new QListWidgetItem(); + ftp_item->setText("From a FTP server"); + methods[ftp_item] = 1; + + dialog->setSourceOptions(methods); + dialog->show(); + dialog->exec(); // get the file for merge - if(dialog->selected_item == local_item) // Local directory - { - file_name = QFileDialog::getOpenFileName(this); - } + if(dialog->selected_item == local_item) // Local directory + { + file_name = QFileDialog::getOpenFileName(this); + } else if(dialog->selected_item == ftp_item) // Ftp directory { - CFtpSelection* ftp_dialog = new CFtpSelection(this); - ftp_dialog->show(); + CFtpSelection *ftp_dialog = new CFtpSelection(this); + ftp_dialog->show(); if(ftp_dialog->exec() && ftp_dialog->status == true) - file_name = ftp_dialog->file->fileName(); + file_name = ftp_dialog->file->fileName(); delete ftp_dialog; - } + } else - return; - + return; + // Make sure we retrieved a file name if(file_name.isEmpty()) return; - editor_window->activateWindow(); - CEditorWorksheet* current_window = qobject_cast(editor_window); - if(current_window->windowFilePath() == file_name) + editor_window->activateWindow(); + CEditorWorksheet *current_window = qobject_cast(editor_window); + if(current_window->windowFilePath() == file_name) return; - if(current_window->compareWorksheetFile(file_name)) - { - current_window->mergeWorksheetFile(file_name); - } else { - QErrorMessage error; - error.showMessage(tr("The file: %1 has different columns from the current file in editor.").arg(file_name)); - error.exec(); - } - if(dialog->selected_item == ftp_item) + if(current_window->compareWorksheetFile(file_name)) { + current_window->mergeWorksheetFile(file_name); + } + else + { + QErrorMessage error; + error.showMessage(tr("The file: %1 has different columns from the current file in editor.").arg(file_name)); + error.exec(); + } + if(dialog->selected_item == ftp_item) + { + /* + // TODO: uninit ftp_dialog????? if(!ftp_dialog->file->remove()) { QErrorMessage error; error.showMessage(tr("Please remove the file from ftp server manually. The file is located on the same directory with OVQT application.")); - error.exec(); + error.exec(); } - + */ } } // Read the settings from QSettings void CMainWindow::readSettings() { - QSettings *settings = Core::ICore::instance()->settings(); - // translation manager settings - settings->beginGroup("translationmanager"); - filters = settings->value("filters").toStringList(); - languages = settings->value("trlanguages").toStringList(); - translation_path = settings->value("translation").toString(); - work_path = settings->value("work").toString(); - settings->endGroup(); - // core settings - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - level_design_path = settings->value(Core::Constants::LEVELDESIGN_PATH).toString(); - primitives_path = QString(Core::Constants::PRIMITIVES_PATH); //TODO - settings->endGroup(); + QSettings *settings = Core::ICore::instance()->settings(); + // translation manager settings + settings->beginGroup("translationmanager"); + filters = settings->value("filters").toStringList(); + languages = settings->value("trlanguages").toStringList(); + translation_path = settings->value("translation").toString(); + work_path = settings->value("work").toString(); + settings->endGroup(); + // core settings + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + level_design_path = settings->value(Core::Constants::LEVELDESIGN_PATH).toString(); + primitives_path = QString(Core::Constants::PRIMITIVES_PATH); //TODO + settings->endGroup(); } // Verify the settings bool CMainWindow::verifySettings() { - bool count_errors = false; - - if(level_design_path.isNull() || primitives_path.isNull() || work_path.isNull()) - { - QErrorMessage error_settings; - error_settings.showMessage(tr("Please write all the paths on the settings dialog.")); - error_settings.exec(); - count_errors = true; - } - - return !count_errors; - + bool count_errors = false; + + if(level_design_path.isNull() || primitives_path.isNull() || work_path.isNull()) + { + QErrorMessage error_settings; + error_settings.showMessage(tr("Please write all the paths on the settings dialog.")); + error_settings.exec(); + count_errors = true; + } + return !count_errors; } bool CCoreListener::closeMainWindow() const { bool okToClose = true; - Q_FOREACH(QMdiSubWindow *subWindow, m_MainWindow->_ui.mdiArea->subWindowList()) - { - CEditor *currentEditor = qobject_cast(subWindow); + Q_FOREACH(QMdiSubWindow *subWindow, m_MainWindow->_ui.mdiArea->subWindowList()) + { + CEditor *currentEditor = qobject_cast(subWindow); if(subWindow->isWindowModified()) { QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Question); msgBox.setText(tr("The document has been modified ( %1 ).").arg(currentEditor->windowFilePath())); - msgBox.setInformativeText("Do you want to save your changes?"); + msgBox.setInformativeText(tr("Do you want to save your changes?")); msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Save); int ret = msgBox.exec(); - if(ret == QMessageBox::Save) - { - currentEditor->save(); - } - else if(ret == QMessageBox::Cancel) - { - okToClose = false; - break; - } + if(ret == QMessageBox::Save) + { + currentEditor->save(); + } + else if(ret == QMessageBox::Cancel) + { + okToClose = false; + break; + } } - } + } return okToClose; } @@ -581,73 +585,68 @@ bool CCoreListener::closeMainWindow() const // Helper functions CEditor *CMainWindow::getEditorByWindowFilePath(const QString &fileName) { - Q_FOREACH(QMdiSubWindow *subWindow, _ui.mdiArea->subWindowList()) - { - CEditor *currentEditor = qobject_cast(subWindow); - if(currentEditor->subWindowFilePath() == fileName) - return currentEditor; - } - return NULL; + Q_FOREACH(QMdiSubWindow *subWindow, _ui.mdiArea->subWindowList()) + { + CEditor *currentEditor = qobject_cast(subWindow); + if(currentEditor->subWindowFilePath() == fileName) + return currentEditor; + } + return NULL; } CEditorWorksheet *CMainWindow::getEditorByWorksheetType(const QString &type) { - Q_FOREACH(QMdiSubWindow *subWindow, _ui.mdiArea->subWindowList()) - { - CEditor *currentEditor = qobject_cast(subWindow); + Q_FOREACH(QMdiSubWindow *subWindow, _ui.mdiArea->subWindowList()) + { + CEditor *currentEditor = qobject_cast(subWindow); if(currentEditor->eType() == Constants::ED_SHEET) { CEditorWorksheet *editor = qobject_cast(currentEditor); - if(type != NULL) { + if(type != NULL) + { if(editor->isSheetTable(type)) { return editor; } - } else { + } + else + { if(editor->isBotNamesTable()) { return editor; } } } - } - return NULL; + } + return NULL; } +std::list CMainWindow::convertQStringList(QStringList listq) +{ + std::list stdlist; -list CMainWindow::convertQStringList(QStringList listq) -{ - std::list stdlist; - - Q_FOREACH(QString text, listq) - { - stdlist.push_back(text.toStdString()); - } - - return stdlist; + Q_FOREACH(QString text, listq) + { + stdlist.push_back(text.toStdString()); + } + return stdlist; } bool CMainWindow::isWorksheetEditor(QString filename) { - STRING_MANAGER::TWorksheet wk_file; - if(loadExcelSheet(filename.toStdString(), wk_file, true) == true) - { + STRING_MANAGER::TWorksheet wk_file; + if(loadExcelSheet(filename.toStdString(), wk_file, true) == true) + { if(wk_file.ColCount > 1) return true; - } - + } return false; } bool CMainWindow::isPhraseEditor(QString filename) { vector phrases; - if(readPhraseFile(filename.toStdString(), phrases, false)) - { - return true; - } else { - return false; - } + return readPhraseFile(filename.toStdString(), phrases, false); } } /* namespace TranslationManager */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.h index 19c3c1976..c67f282e0 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.h @@ -1,5 +1,4 @@ // Translation Manager Plugin - OVQT Plugin -// Copyright (C) 2010 Winch Gate Property Limited // Copyright (C) 2011 Emanuel Costea // // This program is free software: you can redistribute it and/or modify @@ -15,20 +14,19 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . - #ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H +// Project includes +#include "ui_translation_manager_main_window.h" +#include "translation_manager_editor.h" +#include "source_selection.h" +#include "editor_worksheet.h" +#include "editor_phrase.h" + // Project system includes #include "../core/icore_listener.h" -// Nel includes -#include "nel/misc/types_nl.h" -#include "nel/misc/sheet_id.h" -#include "nel/misc/path.h" -#include "nel/misc/diff_tool.h" -#include "nel/ligo/ligo_config.h" - // Qt includes #include #include @@ -39,80 +37,82 @@ #include #include -// Plugin includes -#include "translation_manager_editor.h" -#include "source_selection.h" -#include "ui_translation_manager_main_window.h" +// STL includes #include -#include "editor_worksheet.h" -#include "editor_phrase.h" - -class QWidget; +// Nel includes +#include "nel/misc/types_nl.h" +#include "nel/misc/sheet_id.h" +#include "nel/misc/path.h" +#include "nel/misc/diff_tool.h" +#include "nel/ligo/ligo_config.h" using namespace std; namespace TranslationManager { - + class CMainWindow : public QMainWindow { Q_OBJECT + public: - CMainWindow(QWidget *parent = 0); - virtual ~CMainWindow() {} - QUndoStack *m_undoStack; + CMainWindow(QWidget *parent = 0); + virtual ~CMainWindow() {} + QUndoStack *m_undoStack; + public: - Ui::CMainWindow _ui; -private: - // actions - QAction *openAct; - QAction *saveAct; - QAction *saveAsAct; - QMenu *windowMenu; - QSignalMapper *windowMapper; - // config - QMap initialize_settings; - QList filters; - QList languages; - QString level_design_path; - QString primitives_path; - QString translation_path; - QString work_path; - NLLIGO::CLigoConfig ligoConfig; -private Q_SLOTS: - void extractBotNames(); - void extractWords(QString typeq); - void open(); - void save(); - void saveAs(); - void setActiveSubWindow(QWidget *window); - void updateWindowsList(); - void mergeSingleFile(); + Ui::CMainWindow _ui; + private: - void openWorkFile(QString file); - void updateToolbar(QMdiSubWindow *window); - bool verifySettings(); - void readSettings(); - void createMenus(); - void createToolbar(); - void initializeSettings(bool georges); - list convertQStringList(QStringList listq); - CEditor* getEditorByWindowFilePath(const QString &fileName); + // actions + QAction *openAct; + QAction *saveAct; + QAction *saveAsAct; + QMenu *windowMenu; + QSignalMapper *windowMapper; + // config + QMap initialize_settings; + QList filters; + QList languages; + QString level_design_path; + QString primitives_path; + QString translation_path; + QString work_path; + NLLIGO::CLigoConfig ligoConfig; + +private Q_SLOTS: + void extractBotNames(); + void extractWords(QString typeq); + void open(); + void save(); + void saveAs(); + void setActiveSubWindow(QWidget *window); + void updateWindowsList(); + void mergeSingleFile(); + +private: + void openWorkFile(QString file); + void updateToolbar(QMdiSubWindow *window); + bool verifySettings(); + void readSettings(); + void createMenus(); + void createToolbar(); + void initializeSettings(bool georges); + std::list convertQStringList(QStringList listq); + CEditor *getEditorByWindowFilePath(const QString &fileName); // Worksheet specific functions - CEditorWorksheet* getEditorByWorksheetType(const QString &type); - bool isWorksheetEditor(QString filename); + CEditorWorksheet *getEditorByWorksheetType(const QString &type); + bool isWorksheetEditor(QString filename); bool isPhraseEditor(QString filename); - - - }; class CCoreListener : public Core::ICoreListener { Q_OBJECT + public: - CCoreListener(CMainWindow* mainWindow, QObject *parent = 0): ICoreListener(parent) + CCoreListener(CMainWindow *mainWindow, QObject *parent = 0): ICoreListener(parent) { m_MainWindow = mainWindow; } @@ -124,10 +124,6 @@ public: CMainWindow *m_MainWindow; }; - - } // namespace TranslationManager - - -#endif // SIMPLE_VIEWER_H +#endif diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.cpp index a43311506..03aa06c87 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.cpp @@ -19,7 +19,8 @@ #include "translation_manager_plugin.h" #include "translation_manager_settings_page.h" #include "translation_manager_main_window.h" -// Project system includes + +// Core includes #include "../core/icore.h" #include "../core/core_constants.h" #include "../core/menu_manager.h" @@ -59,17 +60,14 @@ bool TranslationManagerPlugin::initialize(ExtensionSystem::IPluginManager *plugi addAutoReleasedObject(new CTranslationManagerSettingsPage(this)); addAutoReleasedObject(new CTranslationManagerContext(mainWindow, this)); addAutoReleasedObject(new CCoreListener(mainWindow, this)); - + return true; } void TranslationManagerPlugin::extensionsInitialized() { - } - - void TranslationManagerPlugin::setNelContext(NLMISC::INelContext *nelContext) { #ifdef NL_OS_WINDOWS @@ -86,23 +84,6 @@ void TranslationManagerPlugin::addAutoReleasedObject(QObject *obj) _autoReleaseObjects.prepend(obj); } -QObject* TranslationManagerPlugin::objectByName(const QString &name) const -{ - Q_FOREACH (QObject *qobj, _plugMan->allObjects()) - if (qobj->objectName() == name) - return qobj; - return 0; } -ExtensionSystem::IPluginSpec *TranslationManagerPlugin::pluginByName(const QString &name) const -{ - Q_FOREACH (ExtensionSystem::IPluginSpec *spec, _plugMan->plugins()) - if (spec->name() == name) - return spec; - return 0; - -} - -} - -Q_EXPORT_PLUGIN(TranslationManager::TranslationManagerPlugin) +Q_EXPORT_PLUGIN(TranslationManager::TranslationManagerPlugin) \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.h index f9cb6798c..fb03a49f1 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.h @@ -45,8 +45,8 @@ class IPluginSpec; namespace TranslationManager { - class CTranslationManagerContext; - +class CTranslationManagerContext; + class TranslationManagerPlugin : public QObject, public ExtensionSystem::IPlugin { Q_OBJECT @@ -58,12 +58,8 @@ public: void extensionsInitialized(); void setNelContext(NLMISC::INelContext *nelContext); - void addAutoReleasedObject(QObject *obj); - QObject *objectByName(const QString &name) const; - ExtensionSystem::IPluginSpec *pluginByName(const QString &name) const; - protected: NLMISC::CLibraryContext *_LibContext; @@ -75,8 +71,9 @@ private: class CTranslationManagerContext: public Core::IContext { Q_OBJECT + public: - CTranslationManagerContext(CMainWindow* mainWindow, QObject *parent = 0): IContext(parent) + CTranslationManagerContext(CMainWindow *mainWindow, QObject *parent = 0): IContext(parent) { m_MainWindow = mainWindow; } @@ -109,9 +106,8 @@ public: } CMainWindow *m_MainWindow; - }; -} // namespace Plugin +} -#endif // TRANSLATION_MANAGER_PLUGIN_H +#endif // TRANSLATION_MANAGER_PLUGIN_H \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.cpp index 09588da7d..e3dbd92df 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.cpp @@ -1,5 +1,4 @@ // Translation Manager Plugin - OVQT Plugin -// Copyright (C) 2010 Winch Gate Property Limited // Copyright (C) 2011 Emanuel Costea // // This program is free software: you can redistribute it and/or modify @@ -17,17 +16,15 @@ #include "translation_manager_settings_page.h" +// Core includes +#include "../core/icore.h" + // Qt includes #include #include #include #include -// NeL includes - -// Project includes -#include "../core/icore.h" - namespace TranslationManager { @@ -68,20 +65,20 @@ QWidget *CTranslationManagerSettingsPage::createPage(QWidget *parent) { _currentPage = new QWidget(parent); _ui.setupUi(_currentPage); - readSettings(); + readSettings(); connect(_ui.filter_add, SIGNAL(clicked()), this, SLOT(filterAdd())); connect(_ui.filter_del, SIGNAL(clicked()), this, SLOT(filterDel())); connect(_ui.lang_add, SIGNAL(clicked()), this, SLOT(languageAdd())); connect(_ui.lang_del, SIGNAL(clicked()), this, SLOT(languageDel())); - connect(_ui.translation_add, SIGNAL(clicked()), this, SLOT(translationAdd())); - connect(_ui.work_add, SIGNAL(clicked()), this, SLOT(workAdd())); - + connect(_ui.translation_add, SIGNAL(clicked()), this, SLOT(translationAdd())); + connect(_ui.work_add, SIGNAL(clicked()), this, SLOT(workAdd())); + return _currentPage; } void CTranslationManagerSettingsPage::filterAdd() -{ - QString newValue = _ui.filter_edit->text(); +{ + QString newValue = _ui.filter_edit->text(); if (!newValue.isEmpty()) { QListWidgetItem *newItem = new QListWidgetItem; @@ -95,113 +92,112 @@ void CTranslationManagerSettingsPage::filterDel() { QListWidgetItem *removeItem = _ui.filter_list->takeItem(_ui.filter_list->currentRow()); if (!removeItem) - delete removeItem; + delete removeItem; } void CTranslationManagerSettingsPage::languageAdd() { - QString newValue = _ui.lang_edit->text(); + QString newValue = _ui.lang_edit->text(); if (!newValue.isEmpty()) { QListWidgetItem *newItem = new QListWidgetItem; newItem->setText(newValue); newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); _ui.lang_list->addItem(newItem); - } + } } void CTranslationManagerSettingsPage::languageDel() { QListWidgetItem *removeItem = _ui.lang_list->takeItem(_ui.lang_list->currentRow()); if (!removeItem) - delete removeItem; + delete removeItem; } void CTranslationManagerSettingsPage::translationAdd() { - QString newPath = QFileDialog::getExistingDirectory(_currentPage, ""); - if (!newPath.isEmpty()) + QString newPath = QFileDialog::getExistingDirectory(_currentPage, ""); + if (!newPath.isEmpty()) { - _ui.translation_edit->setText(newPath); - } + _ui.translation_edit->setText(newPath); + } } void CTranslationManagerSettingsPage::workAdd() { - QString newPath = QFileDialog::getExistingDirectory(_currentPage, ""); - if (!newPath.isEmpty()) + QString newPath = QFileDialog::getExistingDirectory(_currentPage, ""); + if (!newPath.isEmpty()) { - _ui.work_edit->setText(newPath); - } + _ui.work_edit->setText(newPath); + } } void CTranslationManagerSettingsPage::apply() { - writeSettings(); + writeSettings(); } void CTranslationManagerSettingsPage::readSettings() { QStringList filters, languages; - QString ligo, translation, work; - + QString ligo, translation, work; + QSettings *settings = Core::ICore::instance()->settings(); settings->beginGroup("translationmanager"); - - filters = settings->value("filters").toStringList(); /* filters */ - languages = settings->value("trlanguages").toStringList(); /* languages */ - ligo = settings->value("ligo").toString(); - translation = settings->value("translation").toString(); - work = settings->value("work").toString(); - + + filters = settings->value("filters").toStringList(); /* filters */ + languages = settings->value("trlanguages").toStringList(); /* languages */ + ligo = settings->value("ligo").toString(); + translation = settings->value("translation").toString(); + work = settings->value("work").toString(); + settings->endGroup(); - // filter + // filter Q_FOREACH(QString filter, filters) { QListWidgetItem *newItem = new QListWidgetItem; newItem->setText(filter); newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); _ui.filter_list->addItem(newItem); - } - // languages + } + // languages Q_FOREACH(QString lang, languages) { QListWidgetItem *newItem = new QListWidgetItem; newItem->setText(lang); newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); _ui.lang_list->addItem(newItem); - } - // translation - _ui.translation_edit->setText(translation); - // work - _ui.work_edit->setText(work); - + } + // translation + _ui.translation_edit->setText(translation); + // work + _ui.work_edit->setText(work); + } void CTranslationManagerSettingsPage::writeSettings() { QStringList filters, languages; - QString ligo, translation, work; - // filters + QString ligo, translation, work; + // filters for (int i = 0; i < _ui.filter_list->count(); ++i) filters << _ui.filter_list->item(i)->text(); - // languages + // languages for (int i = 0; i < _ui.lang_list->count(); ++i) - languages << _ui.lang_list->item(i)->text(); - // translations path - translation = _ui.translation_edit->text(); - // work path - work = _ui.work_edit->text(); - + languages << _ui.lang_list->item(i)->text(); + // translations path + translation = _ui.translation_edit->text(); + // work path + work = _ui.work_edit->text(); + QSettings *settings = Core::ICore::instance()->settings(); settings->beginGroup("translationmanager"); - settings->setValue("filters", filters); - settings->setValue("trlanguages", languages); - settings->setValue("translation", translation); - settings->setValue("work", work); + settings->setValue("filters", filters); + settings->setValue("trlanguages", languages); + settings->setValue("translation", translation); + settings->setValue("work", work); settings->endGroup(); - settings->sync(); + settings->sync(); } - -} /* namespace Plugin */ +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.h index 34caea5e1..9b34d87ba 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.h @@ -24,13 +24,9 @@ #include "ui_translation_manager_settings_page.h" -class QWidget; - namespace TranslationManager { -/** -@class CTranslationManagerSettingsPage -*/ + class CTranslationManagerSettingsPage : public Core::IOptionsPage { Q_OBJECT @@ -44,23 +40,23 @@ public: virtual QString trCategory() const; virtual QIcon categoryIcon() const; virtual QWidget *createPage(QWidget *parent); - + virtual void apply(); virtual void finish() {} private Q_SLOTS: - void filterAdd(); - void filterDel(); - void languageAdd(); - void languageDel(); - void translationAdd(); - void workAdd(); + void filterAdd(); + void filterDel(); + void languageAdd(); + void languageDel(); + void translationAdd(); + void workAdd(); private: QWidget *_currentPage; Ui::CTranslationManagerSettingsPage _ui; - void writeSettings(); - void readSettings(); + void writeSettings(); + void readSettings(); }; -} // namespace Plugin +} -#endif // TRANSLATION_MANAGER_SETTINGS_H +#endif // TRANSLATION_MANAGER_SETTINGS_H \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.ui index aaa4337f4..bd377b6b9 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.ui @@ -6,178 +6,152 @@ 0 0 - 533 - 478 + 589 + 490 Form - - - - 0 - 10 - 531 - 421 - - - - Translation Manager Plugin - - - - - 0 - 30 - 521 - 232 - - - - - - - Filters - - - - - - - - - - - - - - :/core/icons/ic_nel_add_item.png:/core/icons/ic_nel_add_item.png - - - true - - - - - - - - - - - :/core/icons/ic_nel_delete_item.png:/core/icons/ic_nel_delete_item.png - - - true - - - - - - - Languages - - - - - - - - - - - - - - :/core/icons/ic_nel_add_item.png:/core/icons/ic_nel_add_item.png - - - true - - - - - - - - - - - :/core/icons/ic_nel_delete_item.png:/core/icons/ic_nel_delete_item.png - - - true - - - - - - - - - - - - - - - 0 - 340 - 521 - 60 - - - - - - - Translation directory - - - - - - - - - - ... - - - - - - - - - 0 - 270 - 521 - 60 - - - - - - - Work directory - - - - - - - - - - ... - - - - - - + + + + + Translation Manager Plugin + + + + + + + + Filters + + + + + + + + + + + + + + :/core/icons/ic_nel_add_item.png:/core/icons/ic_nel_add_item.png + + + true + + + + + + + + + + + :/core/icons/ic_nel_delete_item.png:/core/icons/ic_nel_delete_item.png + + + true + + + + + + + Languages + + + + + + + + + + + + + + :/core/icons/ic_nel_add_item.png:/core/icons/ic_nel_add_item.png + + + true + + + + + + + + + + + :/core/icons/ic_nel_delete_item.png:/core/icons/ic_nel_delete_item.png + + + true + + + + + + + + + + + + + + + + + Work directory + + + + + + + + + + ... + + + + + + + + + + + Translation directory + + + + + + + + + + ... + + + + + + + + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.cpp new file mode 100644 index 000000000..4ab93d62d --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.cpp @@ -0,0 +1,40 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// 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 . + +#include "zone_painter_model.h" + +// STL includes + +// Qt includes + +// NeL includes + +namespace Plugin +{ + +CZonePainterModel::CZonePainterModel() +{ + +} + +CZonePainterModel::~CZonePainterModel() +{ + +} + +} /* namespace Plugin */ + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.h new file mode 100644 index 000000000..259634b63 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.h @@ -0,0 +1,42 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// 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 ZONE_PAINTER_MODEL_H +#define ZONE_PAINTER_MODEL_H + +// NeL includes +#include +#include +#include + +// Qt includes + +namespace Plugin +{ + +class CZonePainterModel +{ +public: + CZonePainterModel(); + virtual ~CZonePainterModel(); + +}; /* class CZonePainterModel */ + +} /* namespace Plugin */ + + +#endif // ZONE_PAINTER_MODEL_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.cpp index ed7d601b9..37222cef2 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace Plugin { @@ -39,6 +40,7 @@ bool ZonePainterPlugin::initialize(ExtensionSystem::IPluginManager *pluginManage addAutoReleasedObject(new CZonePainterSettingsPage(this)); addAutoReleasedObject(new CZonePainterContext(this)); //addAutoReleasedObject(new CCoreListener(this)); + return true; } @@ -46,8 +48,26 @@ void ZonePainterPlugin::extensionsInitialized() { Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); + QAction *loadZoneAction = new QAction("Load Zone", this); + QAction *saveZoneAction = new QAction("Save Zone", this); + + QMenu *toolsMenu = menuManager->menu(Core::Constants::M_TOOLS); + QMenu *zoneMenu = toolsMenu->addMenu("Zone Painter"); + zoneMenu->addAction(loadZoneAction); + connect(loadZoneAction, SIGNAL(triggered()), this, SLOT(clickLoadZoneAction())); + zoneMenu->addAction(saveZoneAction); } +/****** SLOTS ******/ +void ZonePainterPlugin::clickLoadZoneAction() { + QString zoneFile = QFileDialog::getOpenFileName(NULL, tr("Open Zone File"), ".", tr("Zone Files (*.zone);;")); +} + +void ZonePainterPlugin::clickSaveZoneAction() { + +} +/****** END SLOTS ******/ + void ZonePainterPlugin::setNelContext(NLMISC::INelContext *nelContext) { #ifdef NL_OS_WINDOWS diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.h index dee4f3124..a3def41ba 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.h @@ -56,12 +56,17 @@ public: void addAutoReleasedObject(QObject *obj); +public Q_SLOTS: + void clickLoadZoneAction(); + void clickSaveZoneAction(); protected: NLMISC::CLibraryContext *m_LibContext; private: ExtensionSystem::IPluginManager *m_plugMan; QList m_autoReleaseObjects; + + NL3D::CLandscapeModel *m_Landscape; }; class CZonePainterContext: public Core::IContext diff --git a/code/nel/tools/build_gamedata/8_upload.py b/code/nel/tools/build_gamedata/8_upload.py index 3cfbd77ef..1b60aad68 100644 --- a/code/nel/tools/build_gamedata/8_upload.py +++ b/code/nel/tools/build_gamedata/8_upload.py @@ -57,7 +57,7 @@ printLog(log, "") Psftp = findFileMultiDir(log, ToolDirectories + WindowsExeDllCfgDirectories, UploadPsftpTool) printLog(log, "PSFTP " + Psftp) -def downloadVersionTag(server, user, dir): +def downloadVersionTag(server, user, sshkey, dir): if os.path.isfile("upload.tag"): os.remove("upload.tag") if os.path.isfile("upload.batch"): @@ -67,7 +67,7 @@ def downloadVersionTag(server, user, dir): ub.write("get upload.tag upload.tag\n") ub.write("quit\n") ub.close() - subprocess.call([ Psftp, "-b", "upload.batch", user + "@" + server ]) + subprocess.call([ Psftp, "-b", "upload.batch", "-i", sshkey, user + "@" + server ]) os.remove("upload.batch") if os.path.isfile("upload.tag"): ft = open("upload.tag") @@ -122,8 +122,8 @@ def listDirectoryUpload(ft, ub, udb, dir): printLog(log, "listDirectoryUpload: file not dir or file?!" + fileFull) return nft -def uploadSftp(server, user, dir_to, dir_from, addcmd): - ft = downloadVersionTag(server, user, dir_to) +def uploadSftp(server, user, sshkey, dir_to, dir_from, addcmd): + ft = downloadVersionTag(server, user, sshkey, dir_to) if isDirectoryNeeded(ft, dir_from): if os.path.isfile("upload_dir.batch"): os.remove("upload_dir.batch") @@ -146,8 +146,8 @@ def uploadSftp(server, user, dir_to, dir_from, addcmd): ub.close() udb.write("quit\n") udb.close() - subprocess.call([ Psftp, "-be", "-b", "upload_dir.batch", user + "@" + server ]) - subprocess.call([ Psftp, "-b", "upload.batch", user + "@" + server ]) + subprocess.call([ Psftp, "-be", "-b", "upload_dir.batch", "-i", sshkey, user + "@" + server ]) + subprocess.call([ Psftp, "-b", "upload.batch", "-i", sshkey, user + "@" + server ]) os.remove("upload_dir.batch") os.remove("upload.batch") os.remove("upload.tag") @@ -156,19 +156,23 @@ def uploadSftp(server, user, dir_to, dir_from, addcmd): printLog(log, ">>> Upload patch <<<") for target in UploadPatch: - uploadSftp(target[0], target[1], target[3], ClientPatchDirectory + "/patch", [ ]) + uploadSftp(target[0], target[1], target[2], target[3], ClientPatchDirectory + "/patch", [ ]) printLog(log, ">>> Upload data_shard <<<") for target in UploadShard: - uploadSftp(target[0], target[1], target[3], DataShardDirectory, [ "rm *.packed_sheets", "rm primitive_cache/*.binprim" ]) + uploadSftp(target[0], target[1], target[2], target[3], DataShardDirectory, [ "rm *.packed_sheets", "rm primitive_cache/*.binprim" ]) printLog(log, ">>> Upload data_common <<<") for target in UploadCommon: - uploadSftp(target[0], target[1], target[3], DataCommonDirectory, [ ]) + uploadSftp(target[0], target[1], target[2], target[3], DataCommonDirectory, [ ]) -printLog(log, ">>> Upload data_leveldesign <<<") +printLog(log, ">>> Upload data_leveldesign/leveldesign <<<") for target in UploadLeveldesign: - uploadSftp(target[0], target[1], target[3], LeveldesignDirectory, [ ]) + uploadSftp(target[0], target[1], target[2], target[3], LeveldesignDirectory, [ ]) + +printLog(log, ">>> Upload data_leveldesign/primitives <<<") +for target in UploadPrimitives: + uploadSftp(target[0], target[1], target[2], target[3], PrimitivesDirectory, [ ]) log.close() if os.path.isfile("8_upload.log"): diff --git a/code/nel/tools/sound/CMakeLists.txt b/code/nel/tools/sound/CMakeLists.txt index d3f5a12fa..a5d44bb50 100644 --- a/code/nel/tools/sound/CMakeLists.txt +++ b/code/nel/tools/sound/CMakeLists.txt @@ -1 +1,6 @@ +ADD_SUBDIRECTORY(build_samplebank) +ADD_SUBDIRECTORY(build_sound) +ADD_SUBDIRECTORY(build_soundbank) +# Deprecated tool - no longer useful, valid or buildable. +#ADD_SUBDIRECTORY(source_sounds_builder) diff --git a/code/nel/tools/sound/build_samplebank/CMakeLists.txt b/code/nel/tools/sound/build_samplebank/CMakeLists.txt new file mode 100644 index 000000000..b94d4d1bf --- /dev/null +++ b/code/nel/tools/sound/build_samplebank/CMakeLists.txt @@ -0,0 +1,13 @@ +FILE(GLOB SRC *.cpp *.h) + +ADD_EXECUTABLE(build_samplebank ${SRC}) + +ADD_DEFINITIONS( ${LIBXML2_DEFINITIONS}) + +INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + +TARGET_LINK_LIBRARIES(build_samplebank nelmisc nelsound) +NL_DEFAULT_PROPS(build_samplebank "NeL, Tools, Sound: build_samplebank") +NL_ADD_RUNTIME_FLAGS(build_samplebank) + +INSTALL(TARGETS build_samplebank RUNTIME DESTINATION bin COMPONENT toolssound) diff --git a/code/nel/tools/sound/build_sound/CMakeLists.txt b/code/nel/tools/sound/build_sound/CMakeLists.txt new file mode 100644 index 000000000..5cf651e42 --- /dev/null +++ b/code/nel/tools/sound/build_sound/CMakeLists.txt @@ -0,0 +1,13 @@ +FILE(GLOB SRC *.cpp *.h) + +ADD_EXECUTABLE(build_sound ${SRC}) + +ADD_DEFINITIONS( ${LIBXML2_DEFINITIONS}) + +INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + +TARGET_LINK_LIBRARIES(build_sound nelmisc nelsound) +NL_DEFAULT_PROPS(build_sound "NeL, Tools, Sound: build_sound") +NL_ADD_RUNTIME_FLAGS(build_sound) + +INSTALL(TARGETS build_sound RUNTIME DESTINATION bin COMPONENT toolssound) diff --git a/code/nel/tools/sound/build_soundbank/CMakeLists.txt b/code/nel/tools/sound/build_soundbank/CMakeLists.txt new file mode 100644 index 000000000..a9f556280 --- /dev/null +++ b/code/nel/tools/sound/build_soundbank/CMakeLists.txt @@ -0,0 +1,13 @@ +FILE(GLOB SRC *.cpp *.h) + +ADD_EXECUTABLE(build_soundbank ${SRC}) + +ADD_DEFINITIONS( ${LIBXML2_DEFINITIONS}) + +INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + +TARGET_LINK_LIBRARIES(build_soundbank nelmisc nelsound) +NL_DEFAULT_PROPS(build_soundbank "NeL, Tools, Sound: build_soundbank") +NL_ADD_RUNTIME_FLAGS(build_soundbank) + +INSTALL(TARGETS build_soundbank RUNTIME DESTINATION bin COMPONENT toolssound) diff --git a/code/ryzom/client/client_default.cfg b/code/ryzom/client/client_default.cfg index c29ca9b93..997699ca8 100644 --- a/code/ryzom/client/client_default.cfg +++ b/code/ryzom/client/client_default.cfg @@ -80,6 +80,9 @@ XMLOutGameInterfaceFiles = { "out_v2_keys.xml", }; +TexturesInterface = "texture_interfaces_v3"; +TexturesInterfaceDXTC = "texture_interfaces_dxtc"; + // The ligo primitive class file LigoPrimitiveClass = "world_editor_classes.xml"; @@ -351,8 +354,8 @@ SystemInfoColors = // NEW System Info Categories "SYS", "255 255 255 255 normal", // Default system messages -"BC", "255 255 255 255 center", // Broadcast messages -"TAGBC", "255 255 255 255 center", // Taged broadcast messages : color should remain white as some word are tagged +"BC", "255 255 255 255 centeraround", // Broadcast messages +"TAGBC", "255 255 255 255 centeraround", // Taged broadcast messages : color should remain white as some word are tagged "XP", "255 255 64 255 over", // XP Gain "SP", "255 255 64 255 over", // SP Gain "TTL", "255 255 64 255 over", // Title @@ -440,23 +443,24 @@ R2EDReloadFiles = { XMLInterfaceFiles = { "config.xml", "widgets.xml", + "webig_widgets.xml", "player.xml", "inventory.xml", "interaction.xml", - "phrase.xml", + "phrase.xml", "harvest.xml", "macros.xml", "info_player.xml", "outpost.xml", "guild.xml", "taskbar.xml", - "game_config.xml", + "game_config.xml", "game_context_menu.xml", "player_trade.xml", "bot_chat_v4.xml", "compass.xml", "map.xml", - "hierarchy.xml", + "hierarchy.xml", "reset.xml", "actions.xml", "help.xml", @@ -556,6 +560,15 @@ HelpPages = "de=http://forums.ryzom.com/forum/showthread.php?t=29131" }; +WebIgMainDomain = "atys.ryzom.com"; + +WebIgTrustedDomains = +{ + "atys.ryzom.com" +}; + +PatchletUrl = "http://atys.ryzom.com/start/app_patchlet.php?patch=preload"; + SelectedSlot = 0; BuildName = "RELEASE_HEAD"; diff --git a/code/ryzom/client/client_default.cfg.in b/code/ryzom/client/client_default.cfg.in index 8ae0117a5..41c3dd1de 100644 --- a/code/ryzom/client/client_default.cfg.in +++ b/code/ryzom/client/client_default.cfg.in @@ -80,6 +80,9 @@ XMLOutGameInterfaceFiles = { "out_v2_keys.xml", }; +TexturesInterface = "texture_interfaces_v3"; +TexturesInterfaceDXTC = "texture_interfaces_dxtc"; + // The ligo primitive class file LigoPrimitiveClass = "world_editor_classes.xml"; @@ -352,8 +355,8 @@ SystemInfoColors = // NEW System Info Categories "SYS", "255 255 255 255 normal", // Default system messages -"BC", "255 255 255 255 center", // Broadcast messages -"TAGBC", "255 255 255 255 center", // Taged broadcast messages : color should remain white as some word are tagged +"BC", "255 255 255 255 centeraround", // Broadcast messages +"TAGBC", "255 255 255 255 centeraround", // Taged broadcast messages : color should remain white as some word are tagged "XP", "255 255 64 255 over", // XP Gain "SP", "255 255 64 255 over", // SP Gain "TTL", "255 255 64 255 over", // Title @@ -441,23 +444,24 @@ R2EDReloadFiles = { XMLInterfaceFiles = { "config.xml", "widgets.xml", + "webig_widgets.xml", "player.xml", "inventory.xml", "interaction.xml", - "phrase.xml", + "phrase.xml", "harvest.xml", "macros.xml", "info_player.xml", "outpost.xml", "guild.xml", "taskbar.xml", - "game_config.xml", + "game_config.xml", "game_context_menu.xml", "player_trade.xml", "bot_chat_v4.xml", "compass.xml", "map.xml", - "hierarchy.xml", + "hierarchy.xml", "reset.xml", "actions.xml", "help.xml", @@ -557,6 +561,15 @@ HelpPages = "de=http://forums.ryzom.com/forum/showthread.php?t=29131" }; +WebIgMainDomain = "atys.ryzom.com"; + +WebIgTrustedDomains = +{ + "atys.ryzom.com" +}; + +PatchletUrl = "http://atys.ryzom.com/start/app_patchlet.php?patch=preload"; + SelectedSlot = 0; BuildName = "RELEASE_HEAD"; diff --git a/code/ryzom/client/data/gamedev/adds/interfaces/new_texture_interfaces_dxtc.tga b/code/ryzom/client/data/gamedev/adds/interfaces/new_texture_interfaces_dxtc.tga index bbeeab27b137f23de2ef17354622069d33f7c77c..91e87e2e7ca33bf8fcad0846b7f2d90a0849095f 100644 GIT binary patch delta 75237 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 wOzxN4!CoHX0h+d&k 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
{Fb24wo2>~lVm~rbn zRGcgKe-m%l)rl8itI|(PUe11R%s+Fs>}<;YpcIGe{KSsgotpB8^?%XPV1I9TqRY4M zx3k~5y+v;~a*SwQ#ccCa< zxHKxM#l0>=C%%m8*hkd*IzR88q<%Cg&F{vP42P;k9qm3^)m1hHZEHelPhrxs9<3H` z>m>{Une@;53CfBAg8iO>jLV6yq7Ahn3X0hL;7fbrgYo*j)C7rckCx-N4nh`l;C=GaGb-* zNh#J_R=j039dW1M=I%l}RFyPT;f(U$+&}R!OCXrE+%r(1gV&`TlhEZ4(=ufwb)Xt7 zMsgPSRF_Pf11_UEixmSVCkhTzlZCh$sX``l&z#dn$ehw6umJMpFseC`v zZuNU@9Tvae&arS=C!0PSvV|ltFu)e_tvP}h7M~8EvBf~B2lAF6Z>w49g3atUf(`PvLEiRDvIOU4?FF|L z9R>HLooqbkws&-2-o>HC#%_W=^0qS*X=$xOX21*>UYGxg9X(IH%)??SJ3kK9JakBGD*w>={9lE(>yBi-qq z6bXqHbW<@0{*+Y!EMlnD*RWryQzzjcRi?#)OWyTgc*Qmd;UHLxDS8}m*E5ZVXzPz%ikOxxs-NIE(4L;CTgq!j!gc+>-fe7rGoHFKsN zt)9c77MP&uY1>pe%4tPxY-9G*rn!+p(6S=CHbvW#OYjby6@U|VDfIMGd8lVX73L|xPj<8M_YFe=pz*j%pSb~I;$!xjwy_%bL>hQ`&h0Z}?6qJ-F$`^t?=pJ)xcWITPIC-v#@>z|Z_mlJkJ(F~ zo`_`a17883iY#I4aHzm1lS1)VuGA&NjFL(ErThC5zX=LIxPTt7R=-5kxPn?tep-|O z>-6DxePSwT{r4QtiJZF}xt6cu(se&1#RAWry7gc-9_@v1m%C^Ct4Z`B&+zi&x79K_ zGG}~pi?+#VN8XoN-LRvZUcU3f$-q6^$PP6Ra; zD}zx;wlval1;g3st)P|aKqVk_9HN{%2keX z1%;{Y8O7WTE;$UP7e`5_iPcJMmBJng19Q(&Gtzqm);JDHT65YCUO*aIZ}E&;if_R-PlaX$WCYZDIj5H;NIk zBh~ZGK=U{diX>I}A&|aJ%ZdYopzKZOtO-;}=n1bh?7+Y9jIE%xA8}f-F5}8_x?p=?fMiW)jn(RWjSan^Pjf|E(gEbr7Bk58ZBd9fD9Tn2(t&2ERjt5a zG~HAg7y<@Lx}*vqq#!f075yx zqdsZqAyZG_ES+zk*tLi;9K?!TzibBifrIp-J$k5QCXm~K5!{+f?gg^GM^XN0WE%bg z7n+O&!qZ=YK(60q_H?2L?<9LerWfr!L?uE9&ZsvRWckxTHU24#Hcd&Z!>HArr1sR> zkf15C#q`Br4CLk$&VhwG8+x)K*#+Vc>7$9Nkw8KmBQ%M(Wi4%g8+iovdlk)ZgT-a4v<65X(WtJ7^X?`j(p09hsrpEjV?z6wp{Y%1Bp@TuhOX6V^vLon zy6Ka&Y(Pe^V%m|c^4LGwiI`2A=&j_oHkxmzR%=q&X{I^~&^`b}VA<*4hHj7IfI)Ok zoQB2LGjzxPv<|>ZAf0IJ@9b>K_L%668k?3hpaz%EAE394IROD@k=o9U2QtZMM*V3-vYlfK=v!O^U ze@N&BzU+ulXinTTlg{^CN6&hk#Vkm4`c>1xiUh2{DW&n*8aa*2=c;#@Dj)8K4(F;? zCQCg2HQEDt2D1+58twF#W|S$z0`+Do-Pe%NT}pM6;}%NkAAd#rKrozjD6LH+r+rfG zALgv`3NSs4D^jytZ|!KMRqI~Rn;$n%N^4~?I0y9fV>z}lm-=NAhevWH-Q}jOv!Wo$ z-T`%@mF}&xrBuB-ZV}{LF?qL*czJe*TKn5;MPU|9EKy?Vq^xn`ICrhCwzJjXbP?K6u zl~UuAxEYXp*CI!DsdZ}l?Hp~j)xLnhRe+n<8UkU~@%ULg_f?L?+6GwCm5Z!`2(wa@ zM?4^FKQc?rpu5VLlv)|csBcAn%u7*PF16*AR3(>+2xK?$S<&LXTo8VZWrC0P#Gspl zV*qzt``n7^(gPQ9pfxAWh;i+>;0cQ$*%75}LBFilK7e#Kmv*A-e}G+B{&6{6`g@Bs z-F2J8=34~swB~J+CJu*SdHt_3mh9`fTtQ$FaNOzo28-NeF87yNj_eqsRniMmT@7+C z3S_47rt7T|$MIiM=d;|O%3@#QPy`A^c1&c_Zn}%CVg}CR&}-Zi83k{ex|&P3vPe_7 zhnb*+!@AQo8ZIcO8QYlPi@;dil4`P56c?-rWJZ@`y3F&3;65%GZ5Avd@Daj7hVBo* z9<@kka%m;aI>n@$+Qv3;*m<<7hYmGOchOR;UKZHPtb#Q4gdj!!N^}djnYAaN2M^VC zw4%ma92$lgX3@ACk7jB!EcPKZ9^zvM7D?G?hK_kxmuW@A>H?X+pfSm!@gyD%)nQUB zF70~Nu*W=-qgPk5Z!R3^;JLc@t@h<>do&J$7#)^#3O>-i7dcBf7@=dX!`L3EQp8uv*78H+!wNmQ4Dz*lPnfwB9 z>NeP;j?USl>ug24Dm8t1o@HATM{%_bEu>8&VAa;xOHc`JR@tLVw_ZYwLqq}@s!V%l*hF`t#ev=Go`ctSs@-Qj9u-&A|1 z+h|tHwqh&hjx=X-0>8i>cXyd+CDSmeei+~5iz?ELGIy3kKG3k`8CSASkEp-fR*kiw zn_uev$j6)29<<3iNeKcPT$a@g;>JPDMTuLX83u=Zk15IE4Vt|`av~2-;GwRaUJME6 z=`ak!=|y_iBPkY0LAXPz8A;8N_#&|_jV#gpEupnLG?<1Ku(#9K>(v;k;)t?4y{=7S z#t*@DNhak4YK+p4LRoNhnl0UhR%kE=xP4HAIkibS-lA+G_e*S2C=gJ zRD&_d^>dme-d(P1uTC-LOS-;`C8b~5B^jWKE%I-mT0KgG%zJQE^B#clqUIqUpk?bB zKV8=(V6OI&uM;ipqmH%E&q)da0yg`9G-Vz`bwl*yK%c#Nt*PV6cJz8J7|_)t)om<# z!;^xbmri>8ZqkduvVpz;dU$xej_L97!{ry6bm&b{x8nwPrPn8Oui-Mfe@uEorX^nW z94M2po{>)b0ZsHjax(#gJpVHNWNYfC)IOKcb4Kl3&@49>(use! zM6YkNWE^bPq@I=f8BmJQHXzUa-dH9})OLU-W!}MgHq!`^UfY-CW6CoLn)pyvN!^a? zi=defO?tYMwi}ern3d3|M*`~dDX!ED9}u(bwuM2dnk!{cfbg%SmqFJ=)XnTW@9O zu55;I!CQ==$>X)!97vDk(!(K59{t)H`?(#cbYjp75UhhJv&Xp?+P)B+!UZQMqn6(L ztMy(kI0u6J+;ptwIp~~Xi_k8g>tU2jVlD26)MdN>q9bKE}H?I{x`dZiQkMXqy(>zv{`ZJACcZMqb+%0%o&LQAU8 z*8R?PuJ_k}p^%^0^Eh7Vuy6OvLI8)PCV=c5L$JMnm#-^%8n>3`Pss3ZY-z zhYq=LD%pnC+)cj80Li1FiEsiGADa{@I!-5ycc-Jj!=);;;#pvngjPS{Cj(r`qj$~X z5(A@$I07?ZM7uZ^W=(iKGT&z z(Vu>$*My^>+LVh>)DY>`#7U$oj44KOMQ_t|JfcFkMoJeP(ruLS*FEXUcug3(n%IoA&G@(rX{Dz)^R_L^V`z1I#~L|nEjlkLG}aZdRnlU@EJFUVXH z+gEdn*5;&~w7|l~5p?1ZgA&CLGLcEYr7Omu|94%W`Nn0O$sJ90jMDTaO_NjX=|96$ z_L$Vi`)}Q?L>tbk(|uv{=K0&!6tb95^_XqAXw6U2?(3-k{MF~ok@%WPe+zqBwtidL zk3sCvud}Heec-JB2^qMO#0fYcdu*X*vWyn4G(5K=F2pd85zcVc@4oK0#GTrE*=Eu{yO^=zJQMJp-S$fgsI8S<^@#M1^g2*zpd zbUg*HPWnddKX%q*S-bKKUq$LmCtfljFpRlkU^_Nolg(lK>oFYJHBhgCDYLdJtuw&(B=?rte`Z(eBDI`m&b{<{7b30-r;1a2CS9q6NV zHsvswE8*L-5k}?>DBa>pwOr{TF9Tjl?u+Tq!I4^4t&r0@M&?3HhzgC&-%zUKN-wz5 zOU}%PDZwXGEIG|KvQX_rCoV9u>V)qUf)3-mLWiJR5?bsO#Ed1Ul?%1_t|@o9d>YyW zSMa7Y*BISRxwvu-U#=k!;_L6GG2;QE#n)emSw*z4)YuF8V3T3Hk*&*uoRX^vb8g8r<}HEq;riDqWP3-2GPWVp#8A)bgnrgh(!Y&3w)+!FZZA#OM*?S zano&rnZY1m#O0T8`K3WIT>iAJjs+sfx8(8{NtRb|XD+@Xh*it=L9Ci>G>f0};^JtF zs$jN+_BF}U2X`hnXZs+IlmxLjvV$vp9+bfF%P;74_!IJx!Q;4mr}*Fwq<2Se$X9Ur zgIxY_P%@XVj%V@+5p6&R8(YD0+_$^N7t%+$^tm9`q`oyvUun;z5q-LI>E2Abx4|2q zgJKDw9a<_6Nj!CZC(leNJnBh9+SWoxN&1DxrcBOyvzOIIH2s#*8EORmp zl<|o(eYB9XK-69tJPhSq!=#n?0L9g?1>(L27A)n4zA|#*qbOHePju<5W8kvexol^e zr!)}A8VxK8hZw;3X}K;LV!OFm6&K5&#k7;v{T#)jzLF?`qjJu&*v>4yL9KQr+Krv=Xr z-g>UX5ulyZ6;8zRS&cuR%#myJ!|)x_Ls~5h`2k!{^1WzMUu4K9JEkjIP}LH{N^4qd ztDg&h*sb=L_oJSx!_qNEE5JPXW491%3>Us8wJQu`8NNLYSdU>BE%t%}*%#oSPd&DU zwLuBhAuS-8W4bb7eu?2CDz)KbNa~s7lO0TQAD4{ck{$VXHDp?a;Tm;2XefbXJeNGk zBu{b4j1VVart>a{j6Q03K;6!9$@X0G9Fx4vC3|qm2!2?N^uK6$PTj6^$v#~2I+MK1 zC5LcH^Kwh4TLxIqt(J?9z0+qU0h*E>iwVB$kU*a*+rwlE_8qE0K0wMk;z=7o{JQ4k?CCI8AR+*W>E<5^fTGCUY<>A*WY;|lHnOW`tC=)n~(a)s+$q0fIQ+~o>GLRm$*#a&#> z6-NG-!V|7A5elp~HrDZq_=4+9fsVOySx4~t%B8T&^O4qRUsNyxl$%2^ud=TsJ-B3X zs4K%Wt*XSi1}k7p-(Y4;@=8?8Ma#ITJ55vu`$5XcrOIDP#d4`ii&O-cO5{@Xl~lV3 zG?4YjIYD5hL&_X?It8=1bLN$3PDB^WE2f7dOR` zUUCcj0fdf`dnwhvD)@LYKFBW#X(aMmjI;r%6se3Q{C#ucf0v2>&l1YO zrOc}nQfHwIT*`d1k-8)G6iUHm1Gp>(myz-TLK1b`20rw(I*ff)c9h&Jd5wxcP2CYZ z2~_lE({w{Nj0Q#e4(SR~&HpBtq{cG~se@1h8a1F%P9@4hrQ%I02RW5^GnIbGc0JMsqz6d#NDZ$i&}i^%kJJIFlhEMZ z8L2B$w$K0?4ZgjE2EVShPeXdDpMgd#Xng0NCv5P~7y47TQxP+;ev%P(gIlHcXfW?$ zo!H9?u*x}3rM;O7s~{yvSKtsv;~%6(p4tkHpwS3xG@^1ef<_~((FhuipwS2#jc`h1 z{6J&Vvd=ydwOyi`%O&E=T-|AysQSzGqlE*nCZ%UJN#WXA3qe znsGh206ywtt}cuXt0K%V%pi=32xg*tJN%g?h%kr8 z&yHpmU66A(B*vmAQdcW+>6R7EmqPhuxQKqeg+|z;!G8#t3>C^0!-YJOYU{U!Emzo+ zBTpiJq}L{fT?QZhD?VD9^&)s2EHedsSfk~ZfhD+QJm4Eo#-+WP%Uj^UEMnopEg}&Y zl`L((sY{)u715AH_^1&UX@Es)6eEN(<)}5d+jrlE$V{A-#VG;OdS1%F<{{s<=H-Z1&%Z6D6YWFNZ7?b^WJ}1L#fBBlY{9z5y{*vT(GF~1XUeQ*_MI=7`gD_ub2lz( zzIM&R6g5c%(?&3D0Mi=fD6kz3w!ZY7Yh(u*iCUF1l;*4q`x3)#A5MZ8Fv6U;&QLPQ zVloh@LB(OMiB)6K3#LLfHkk_M;BL#7h>J^?H{ZP%m=(kc!c>fa2m*~D(4ZJ4)TqV? zWvX%b#NlUO57YMjd1Yh@OsCh|k*KYVP$?&5;DpLKp-(M@+6txcTa5>rHg8jmkeLkg z4FWFekVKrhZeH_s^6A5KMfX&xh@dB;4vC6kNF#(sSffEX2870e(0CIedO9L9UB+l( zm2_{)NSd>ob7{@FP|oE5xS(CPkV#3g#CVQZE6m3}Y#?uqVPLbSh@;oz-kpkl(!a0rVaY6%l)C3j? zWq}hdT(TpvL67}be69Th<8p~}>BqTTHDpT2@s26(WXUzdqCAfdAk;}Hg;8qI1F@Lf z*fPeJ-?JMtsJ%FR(eyW7B?-jqy3i3>bw%SAm1Z)^u^{v|j5A(n0GS$)Dbq|cRp0zb ztfz4|1>8xQLUVrMbVhSJ_ZgkS2ZoJ#Fi9>p|^YEW@h%{j4~xi zY?Y4YZDyfhEJlNYiG`@10MitJ$-7`O2}}x2ObQ}{%uG^GrP>lzL&_wY^O)0_#_2rc zp8DHR!iERA@J=Zxu)eSXePN?-4kA#B=Nor*Yubf~?rj7S9h2zKYU}G%#t9<4BL=>M z8uu>fOcH7|Q-m_@R2GHkg`!9er(;WetWsyt97*_58J)a11bgzuwnju4_K^x%VsBiO z2dm`5H>I#j4JvE{s5E-D3EbF5<0@6F6 z^RCdSnJhGbN{x0Z=u8J4HLYF|iKDNF7W{!P|1Z=O3^jf zAm%rCr7QTi$St*c(Iv!Mbd8aUj^6fSc$e;C?2t^+KTpCP#Hxvf3arAYh@jF4Dh;4g zqkB&%)6D=K9lcT#DaUaXP3l~lqXH9ac7>ln9v%1bqANcQQNc!fBMX2AV@V#kJ0~WcyeS{K>nXZgn zzq`pVF1pDr$*Kwcc%yHB#P^{>BU*B!H>$U9UxZo~QP6NuT^r5yggJ*iUrGIO;CPoH%(E*b=j^g}dV zFYhm0@XT;{+$vS}40Zb{>gyA5VSPh_DUtP6I5`fQr(fVRaT2Ma#TnvIyf+ ztDhx&r=Kls2%3Yhwr_<*(%Tm!aiq+lSLz2er#t6zjdSV49n{ZQG6?4A=7-@UdKn5j zmr(p4LE%R>P(aqKyQ@J9W&yqiF{B0*SPZGruqHDZ^_11sX-FogTrpFips?65UtsqN zhq7h;+qW2#yf`Di&>6-|GnmtP!0C+SbVj4TfJzdA#|Vs?7V)9vAdH$Yasri7P$`8a zNoWQS zAHZ-Di;X2@=H!Hp^pR^6)}kF&F|n0g%!i8+F18M0zMcvBY`L&r8HF`yhpkMqluH`8 zWI31o)VPJ*ty7iKrx8&&Nae7XiS6dCrFAF^Ym|!}0HFH3kDPQpD9>a&NiWiwxXVe_ zxQ=o0j$Hf<7e5Q}D5;M(>2yxsf$jD-Wk<2o({{w|2NoVKagBal<0{v<294^zG43Sm zy1X;V+v|fY@}ugY<3v2~q|QPo#C1kAH0$D@K19mU5)-eWRQb@ zG*?>@^&3j9*W-$j|JT-e$7Nl9|Np@d5K%$dGH#GP?g{r~XgM3MG*|8!xkt_vbKwRP z4{qFON=9z2YAZ5ZGGGVMt7|#jc z@eksJN)hkT|A5nEhRhA{UsC)tDQ=SD7KleT^bcimH|k*xwMqla^_QHf>ebB6@G&yY z8JVVSB0JvpiJPf)kAP6>@>*yMSuN-E-$MK?7Vj*@FH7<6QbkXwXx)P?>ctkJ7OzY3 zK`cH%ivJ?The`2wAzpSZ1v&5K$ayc$IX3$r>d!&XcuqK0Cj46_oFo%YLBiCNfj-n` zYAEXd4MSJq=4AK^31)MGSu#O=HMhq3iCmKl64y}b!q7h4PC7~7A?o`W&LF`@oFGpo z2$Bg%CRl|8Q@ny2(krV&arU{BaE>srL7Q28qn3SfyqdqV?NWRP#MkM9V9?G`>~Fvv z9g9EuG;;&pxS{nEStZ&cq_M~}LYD1kiJSR0(`yGp(cqDyrA+Y!SKd*npuH46B^8`W zT$86N5pJEO(EnKIyfnI}H2R_xy39gl!gGKDRVq&aHu{+x>kTRSu9UnZb^nsMxkObT z$M*ip3?RRSiMae|-*uK-&yz&zpIU6OO`IarJeFzxW_#xzyYESyLbNp+&WByee$?9)jXvf;nv!$UbF>aCC#pOj2AF<6n=_@B{THmjq zD9JTMV4UEs+f05NqOd=YtD-V+XI^-?6IJ``%1TsNP9E2R!(izP)UX_fpkA$;eKrtp ztWzVD6{Z@A;EH1S)m~mDpaiElPH|QtgqbX952_HlU zL$>I$L*2aIi!5)kH8$yMuo9WIN3x{3N20c}6O+ek-Yp3SqS~n2U82H@_Hv=dU<`&H z7yAyWk2uj8&oH^Bp`$KG)Z@iglO)=hSkA<8uE~M$*1ARH_YGrR1$MA;Kd-utZihIW z=;!RjQ3dsgo21@cPoYJ8quz+y*fN{1Gw58MY1g8*(8!^29yH*5cnMJ#U16#;*79o$yIiJyf^R9;-2z{BNk!5O9e} zet)QU<6M!1yvL9Sb>`GCX`zG4%2Hk|o5s-q zIjIzD+*JV0)2*`y*UOQ>R z^HG&iaexZ3x>hPAlW6a)sgJWZff~+LxCZBd8j4a%DhFZ>BUBPm$jwQ^hzLf+GGd#8 zFo@PFO+z5!BtoM>v-T0C+a=;-Mrb8s4iYA+R=7_rZR&`N|^A~H2a)No@{ z?CuK*ImnO}b%j&T4W}cMS~96ElTIq6M3LSCA$CP&J4x!O*+Ty%`3K>sh9rH-q)yVD zb8Jq(=pyRVSye*C-5GL0fgl`ZCruC_JtU-`rjS=yLUD>iLcV86e+jwHkkQe&g*^b5 zNs5OtinzLh)j(tfAquhDJL`cO>aoCXJD#2TYpDq_L`9v~vuhbk+T>%pOJ3*T4Z(|GN%r? zOhE>TVt0;-S=t~B$Xscmw;mR5h~7;D^HfE&lNjgkz~$EA3K%CHRQfmS29&fxvw+JF z%mB%3#>_&=R59}tW^Pn%p>5j{c&$3d!7Qv}7CD$$ob;r`Pc#ed%vi}xWab{p)atiW z(2;2At%jDU3Tc~QtkHqpQ-|IEf3QasY@pa}Ndzj2g`(J8crvxZ5i$Nky-xlwh{LfFc{m?4fZ^5o@W~Jp#me3bA+oNbM~IoYOv6 zdSR5=So^*mIG=%4OSzSMr?O+qW%I&gP6Q^3dO-;anWqQkKf@V(m<>Hr$A(q6Mu^KT~dpgs+H6|OwF`Ybxbueb)P~VL=&~zAMI50^HhH_Wol>GsX|f@GqnX% zl`<{oGVK_%itnhs-!fts9cvpg9xhQYyRJbrrG@sg9o_DEv>zEeYG<>9Y$&#!lIRLX zcajF5V}tu~;fB!E&Jp{mvU|iJ_(+91gr;@UUbIttFtxVR2eqGeK0EOGV%tSYy~@=7 zl6sw~qwUlI5r^o)u!w$entIt`522a;wf|#kptv_&yXXb#Xze1g@lNu2)Yg3lj*-9z z44i2Pj*U1+_a;TW4&SNYK^RGVMfb*Nhchrl+@GwSZwL1IP8&qlnc5t&>9K57&ls3p zTcr6329)SB2^CXkMPNs=+Rac4%x0iVvPx9tXlK`1h(@(cJ6~*dS7Z28)rdc$Txp@V z4i;`;m`cpZiwFSB->^GRb(Vh1)eg0z3Z6$r&?_6Xv&Gf`i3(#>p+u<|^$DZmlnvUY z8zZpkSRG@K14pWCo*XBh7HOx|nUz4Vf1(}D_b9x?wpcZ{bu|O`)Y*1~fp`d^M6!&A z&q`EL=x&-PYlZV?+VOS1jK_0YL{P%nd9lqTSsBbKuPrzp)UBnMZy1;)mL8SBHin}m z2-QNBhU66Cc1An;{|q_d#@Zs_E>(44);VccuCAQ)*J5%d=DftbZ8%e+@_k`&%wx{} zqRS83=Ktp?4EmbxhyzSjeHnQjNKraOosFUDjR+T%*HFXx5|tNv_(AGyoMZh}i+C9? z45?M3Y?vCusH#z6gQ#q-f3mpwAoT%mTTR3q0a|~il@B9oUQB~|;@@K23?90#e~d{7 z%e^Q1{HqQ8|E-%Ot($?%6-~yN&(Yzz{vl$$lhNeNTY>GVZ?>VUi%X**T!}KSqbr{V zHKR9k3^>*!sJ;g-#H{)!xFy}riC^aEW^|`=)y&98d zZ@N_wzl53u$EHwBNbG2SXQ4BB_SAWa<$*e^$;f*;sUf-#TzK-*3aZvSRH;~1gj7}d zf~q3JIlC$kTA#@J0_a4sx|8w%?X{x#kElsPY!Zbf#ZF?4Zz@-27sTl}yp0#mETtx~ z#^u|k#$wi(YurjgYuq3n>7>RzFKFCv_=+>b)>6JrhgU!X=;&c}SMG#w?2pf*Cf3+E z3Qmii#`;<-@xwkeW3f&or0H^?N=Q|Q9hqyvnQIAEUN!yu_m_VL4<1Y#j~Qk)9XfPq z&7eVpY6cD*Sc6638b`J2Pa94d=j5aO{T{BlH2syWvs`3NqORAT|*a|u^FuMS8+vbjU zEkx-uBQE|w%9FY9PFY7+4;tH(ZLP68=>t;^apf#+hHah&YjjI!Wte8B8X~D<3#gwns zWOHn%syHaB`Z#toXGDin#d;4hs)!p}@Ge~e6vawK39M+3R8%4rY3mee_#GK{N<3s7 zMtZZN2$8Cx=%8*cEzQs%>;M#*6EHwKsN_f|hVDm>g#RJkT8!p4=&*8X#uTZ_%6iJB zo}*Gvi#k0qwCu349;v=Ejw5}$6ij&o>BBE|b7)=%%`&N?9p~jsdtSuQ(^AD(tYZ0N zO%t)DtwxPPdyRFRlRC~z9i8fQgv-Z3sM!z3Nu=*#*YQ2;=&M0!=usFEJ?xP%i>kg? zv?Pmxmsm@aA9RH%tnRX~da;7*Qo#+Wpua8{~G6$ezKxU zsgi%VN@h6pO=f-nu)bSrKYDf-_vt%7(V^39^sjCUifz6IPi0KfBtq5Hu>NIDOx)C* zOx$f`qbXN4Frnsh6a`A-YM`IRv8(fzYUWUVU0@L1&q+WG@&<965jt1rE82VLBV2^1 zmmX`0z;i2J$eHk#Xdj8rWppz}7bs|sbwvxB=|A8&*ZJ!;+4T3ZAfO8v-7IdiNDb8M z?1j`YM86eilIYcpR!MY(L>DqTkb#MDHl#xYfT#D+P6XrsY z`DT5x3!!IeEPT@R8*8gp$f`ZS{1%em()5E9{Co;Nkk^@iI%OC2eVwDipj0X}i+K(9 z-syxK{LIvL`gj*Ctr6-F5dz>#g65^1Ud5R~Xn|0td)KxXy*}9s}>DY+)dbY(R7GYtXyH z$h(Ytk8#7%4A@BN{+&kXOXNq|RBXMY!R6nodkh{U!DA)(0fVP8_z8oj*}=~k>`T8q zNmziN89dnzmeuAo9blZ{lg2(}X0~L`0yEz)705-5^hgDA5l6^rOmiD)fkaQ@k(i60 z8JUBui>Hh9`|$$DKkP`{wd_bd!@R2vX4Y~LTJStL*0DJdN&Ef!hB#+`P=82j@fSrVZ347dSxdRpa#U(*QKv;m zF<+TRz?Y{MQLiucm^q;IJ7{z115*G-ob3{qz?;KwK#Pwu1nO{FkD=J3FQG*&Z>weJ z@fs^QCl#ER3Ody(SO*`@?C+V~jPm+w@u`E{12tRyy<&e5UG0lYPu(u*ok0Gc?Qe2K zU&s?|Z2a}m!WHyl71yPT8&XC87gP*q6~A&Jh1050T72tJF`QNWs;CH68hOvV`g$(n z*{}F~b1po$S$ggl_&KTjDXW2@kQOf0E|RwA0F8?o zKIG!1D;BC%A4i_X<9eo%;g2AoaIA)o5C>UYjGy z1xyZ(#~?5yUJe4s@-(k9&`{_snuHh%B|Hit=lF#lV{jPYDhZE}@WL11MX3)Mo>y$I z)gp!`#A7gfB`i;f`4)3zTd9&Fe}BUus;zC`__02*3;tUU|msaHtcd1VQB^o1)GGU zY%wX?VprTkDsCw=RQ^JSPN)9G8OpEFW-A^&5zDx*#Yd3;8}T#iGStqn7a?cfFf2xC z4Nf+Tv#0n?9VJ(tB)qePpL+p*DfLO7iZJxoVzvWMe2L+`;^Qgoop?FBQVj25IE3gj z?-=IPPUIABf5{ynx!0fL3jN(w7hL(coA?1W$%@D9a76qFmz0zgI$s`yu$#jT$DM_7 zgkd^14hQpiTfvPnV}EP;I5YOQFzZdGS01E}am+!5{z>XbPCV1ir{KR6d&tWxEQguy z^mt{aE90kLnPMn+64vR4$u2zaR_KR#`@b~XoK}zTy`pPW$*+&j*SGZ~>k@MT0u&ev z>3{Cn5D#8p*z1O+NZlOQoHgreC?hzm6Lkm<^Pr`{VJe}{H5Vadkxx<~J#7>|43m7i z;K#@mye4WJOxAU^v_JitnT6*nL%EwAL1Q&im;G{Np+rUix%z0JSBa{V6CwPRJ6(>B zoQrRPFH(EqsZOTvevXdym>q`WZnP~{xA^7YJrb+~_`vc|1zedLiO)_;2Q0SX+)HG9 zZeF3}-bIJ&WzY6AQ656sVbU#l2{sCslFb+fK57Z<)Q-*i<*ELo%GQx+`Y8wm&Qx!D zOQ> z2-jj9Hw+Kj_pWUOuXJ|!-8_etXlT}Z#<7GViV~0Ra+R(erd#_GB}u~iz>K-Yqp?up zzazadov4n-27xd6S4FL$vlAn8r~)_hsCbHP0=GkG$Yu@6G;^A9JZn&iswZ3tD<{2F zLtL5B!UZ)83ij1Y*u}-uZv&dvoJFAK!c&IPu~)VGx`nmYb&p2qYfnz6_@!A{5A z)eWOoUExdYM?H8;d>-Td5{lULCQTTh&*g&%969C&RJO`Ck}?iL7wiwGDWR60tR|es zt})JHHCSH_OhG1=(@WK$m{b-nrj4v7n$;j|Tx9fGI=hwCged0+ckVz&8r_Odrhdtm z@vI?~Mt^LaZPySdHEe&W2Cc}@S_+_{gf*nvHRxGGS)?2uUTtS_qb;A=X3*7^F*+_P z4|*@%GK|%P(5QpPId(N>sRjXMUQ%8u;*}N_IP^zHSxsxZnparO308w>N&JrTrZcu| zs&IoZ9QvjOVL!fvw?QdkS-V}zX_V5bm%`H!?Z*O-{^&fzyK!B6QKK#l|1NR`|3`X; zZI^A+$$HS=Oj&&_!x0q50q-H<7hei*CA##t%mMrc!-pj7;r;wZ19|hw6>$M0SJ3ib zY`Iji#F9p%Mp_2j>-SfsetAJ&!tcBkK3F>3F_tLsAA)}%IMzoV>Ow?C zp)@Q4ywwi_ebK0KsLOLxG`x)~RYo_@p@s2j1)Od0b~CSm(T|2DnikoiMG_jT$Ifa= z)Dt@Pz#Jyd?XkEaw>m(d-o{sXwv3^rc4#U?Er33AVk19yKy41_ehD?%q1efknQjSQ zhnQHn+!G0F$@5tBb~@j>`2rllOhfjgsPESf)awcg-}Y(wNwfv(?8@L~l;1uuJr7%g z$h=Bap0l{Z&d%T#&y8ePj^k!-mDpRa=+-=!miA1;DvbyA{gJsm%~agQC5h|~#EdJF)o+S~`V+-qiO$0GHcLDjGM< zl+D(%hnB!e08X6}*u!pUY}sY&e>fdAi+L)#P%m)>c{;}w!Zm{@PeiX=kS4pFz6}u` zMDb^f6f3b)c{XmL|D&M z0{kMwF9RNv5?n}|`slUdW`FAwz;7hOQAg3eA&Kb8>>Yr5V9XpeTNH(C2Ah6K+si{y zcN#g;I)pW}Ci>OX+pghV*3i?K;6)qn=-1K*zXW!p*9J%B0w+qx$YObz3dvg^=Rv3{c4)|ci>yp zXis8oCbDHFoYZ@nUo|&z4p*EE9h~-I%s8s37qx{p)lZj7MlG?*jzN|?ie>@$e8!C5 zSfOq1hBY*+eo$vxit>k(wI*Tb$wz&fOXX31Vz%73Tplw9p~ItaBqb;vO(%rLt+V#$ z5~*dblFWv*DZsFq<^~15$zR)tJ{j8WHw&$ZDIcjm&V!VvTN9^qLwRLW%m}K8j@nD5 z@#*L!RrLOD>pKo$ClR?r0)1#_tYH%^jt^=hUBMn}3WE0Q)#Yr1^S(rk&I+g^6&%?j z4qMVu&`~t?b8C<1VV|WIAjjBCF&T(=%dKXdUw%b>yo7JCRkV&ePKON! zU%Jpf9nIitYgY%StB5%xIe|*a9d2t_L<`ynwdbs&-CD(O=d8|HfbF90k8654bfH@m zO0kIM{b+r|LFpk9E~hSqH8FI!yWu0s>uERSy0ryXqX(+zIN`NUCtCQs6`|Zvzyj_0 zD{N2ROZBUlr!vsVVTKVLt)TRQbr{}@9;f~qudpJdpj~vPbBXGq3%yd4in93^Q+yjD zhHi4kGn4Gk`ISui+|}5_u?d+@I7x}%%X88@<*EMSD31NvW)8eW>giE1N?MT z@>Fw_S1!)1HY0K6IuO|}%F~pk0Y)st9}BMqMlmo#0k)(IThia*V0-|&lWx0thZ1aH zKr~Yk)7RaGYb-Ik_c-7cUci_D`ff?bR!*#O7r+_`M))o~I6);T#=+E0=b-OZ=#9Et zKo@2(lN68DCsp@>j2KL_j5?HOePv1R!~ye2sQ6q_fxZ**ii=IgEzpx`*TZj0P)RG} zV6U38*F)u>1Dzt}?jqf6X>2MNXQ=XcI!YUJ?^9-cz&wY9b$wdvrqKN?xSbE$=qAf7 zoi$H)7FWJDbFeIAsjbXXN4u(>U5$7-sk4%sbgKN8nHZ^YS;b%E+(hvZ)R%g7(@myv zZ|i1D<`r|cv$*=BnL}uS*aa_)3{+_pp{>=Y@L0=yirK2$P9wK53lCi+FsmxrQVtfD)3zJ2_;u_Pn-(l@ zTE3TAB}#T9XkSVOoT-Yl>q#Ld%ZHqYm@>xgv*WCm70%*Oy5$gXadh|;+)1zf#wYl6 zk4UB$Ej^B%rfx?a%vQ_{QCg2*TMHsmyHex{T@huS#1T%st>A<3icEd_re!~GmUf7qS zK!@Hn{s!nD3|$|fYfMZ2GUiaXhYsijJ9Ls|1w~eKejkB{_3R)~F_n34Gc3EnGc&K5 zxb@gL5}B@HUZago@vsI0n^T^vX%2OB!U(6{rnF%CWKIUYHROCgL+fGel;ws4o_OXW zR8%fROGE<^o=Yu7;HHTRcN5m`jx|oJMK1KkP`;ZFXjn)0qn#@<&_+Nbrui|=A2gT< z+GiTR>~UR(gr60j3E+hC7gmZR$q3QKq?Yu52Yv?9$FH%nc;Z?cjz*V~&&+ z1McTj{G-K{ofeLx3~sUHwqh>&gjmVdIJgT_*i@Z@45H$_jPxZ>VZouSR5sNJBw7y+ zh@tc; zE`ruDbyOSueCF!J?Xxn5b)fLCu&k9xxsUX9Thm-1JKB*AXhB!g0_xHkNF4u+qJ7^o z64qQ~WH+2l8~3&zwPq3bugIv>cnapKrGSCrWOoyeRUGS=7KbNYzq!I}#jlZ0Arog-~jB8YC6 zRsIPh-`{K60GFxIO32N`j522IvooxHxI0?jrpO zwCJfP?SR*60Ua2y)C-}4&z_QiZzSMb2Ap>Qx?A^<@jLw%ntFi&5#mBG35XNwz6_Yr zy?G3^_&zE~oWCf)hHFfD$_?VfpG|oB^9E4L9!U#w8)n^48Mkv6;dz^q!} zCS<w;rN4^$gOkd2WW$d8$+d|Fp6*!RqBwW}RGOX~lM3 zaW_v!P_RLGJfgC3y06TuH_h`kqoMjd&m`+{>fmRvLJr26W6Jv_8hrU4lQha`fpq zkx^`&;6z>G1G|dbvE~tc*|908n)E>VnZgOAm=}4~Y%+V+Y)flY^J#m$0*#$0x~apf z8cIE(Jh0+iqC!l&Tu{%>=pN80Q9{8e(5TVKrmVu%oYuJ zo^wZ91kR>kB_~Y`y>ETPsU*nTg*IiGF#$&U(dki0Uw8B|LJa&fHO@(RKDL%Si=F>i zRn8*onYA4h`?}D!sb)AgB%2AfLO(ZszcU59+Sc-*9Lt}s#ud_$%2BNdYhc^r$}{)tRphCr*V&_BgC zhyUicImtN%;|+Oa;)d0B11T|_6=v*-S00gxPNWwgQ3(0B;zTHE9=kfV!t$zoF7oPY zHhvu*iB8Ex-^fJYrLRCD75R5n5*3GGBJ}JnEQ-tMo|k*s_yu}zvFV~2N1ZCK$waqg zB6OmIZRk%BH3~7z>F+_t1)?&`_CS%pBjx{)^3_t_m(-`y8<5`wE=LOjIv}Ekjqxi5kwaEs=?48*@d)LfcY->P&e`;H&jM#qv)R-qK4%C`tk|t$J@zxnR&UEh!Tag03_XV4B zwpOyOl&hci?1U71mBn5);q%9E@wK#{ z(LD_@bI)kG3(0RX;_wvAcNxcjBA#8fp_jR6xem!|8A+}p<5tFG zNDfNdPCpJZ?Pkf_S!qAG(!xnGt;B^pmLDMbM@EXPXj7dr0kt+B%q!zf@FF3iYHHd! zR|@WqJK9$sTP{JeCc}(38tP?^f#htKoXwI^;_1S))2{jJuQIfgxY^cv4#sq3aU5xn6TP}+z60_9rR_rVG!;tmD=hxB zYg`hWcC))o(N8L97#S~m56SF}6hEaEp${-^;Vj;}mv+gO9{mvv1;eEHXuEC||k*=M<`yZ#F?Gsdq*q7*+25tK?+c{CfMfjv@L;8>G!(vj*gSr29 zv!#E9R6WE~Vcm~ZN1jV{l2g_8Jzn(RtLc|HX+kSb8sd1`$yfNlo_+|BF`~(7Yat-t zJO{auiN!VvseUW{7gBdMcjCM0!M)S>D@iWNB-hYB<&EBPw=;1hf&Hg||D58)T_oZG z$o0Hk%5yLoBhpv6;E4j^f7iMe>i)>w1=L;~*E4jLx*7pD-=G2xRo) Jr8B}>{6B`FHJ$(f delta 55962 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 diff --git a/code/ryzom/client/data/gamedev/adds/interfaces/new_texture_interfaces_dxtc.txt b/code/ryzom/client/data/gamedev/adds/interfaces/new_texture_interfaces_dxtc.txt index ec1afb449..f35989e33 100644 --- a/code/ryzom/client/data/gamedev/adds/interfaces/new_texture_interfaces_dxtc.txt +++ b/code/ryzom/client/data/gamedev/adds/interfaces/new_texture_interfaces_dxtc.txt @@ -18,305 +18,305 @@ BK_goo.tga 0.156250000000 0.078125000000 0.195312500000 0.117187500000 bk_guild.tga 0.195312500000 0.078125000000 0.234375000000 0.117187500000 bk_horde.tga 0.000000000000 0.117187500000 0.039062500000 0.156250000000 bk_kami.tga 0.039062500000 0.117187500000 0.078125000000 0.156250000000 -bk_karavan.tga 0.078125000000 0.117187500000 0.117187500000 0.156250000000 -BK_matis.tga 0.117187500000 0.117187500000 0.156250000000 0.156250000000 -bk_mission.tga 0.156250000000 0.117187500000 0.195312500000 0.156250000000 -bk_mission2.tga 0.195312500000 0.117187500000 0.234375000000 0.156250000000 -BK_outpost.tga 0.000000000000 0.156250000000 0.039062500000 0.195312500000 -BK_primes.tga 0.039062500000 0.156250000000 0.078125000000 0.195312500000 -bk_service.tga 0.078125000000 0.156250000000 0.117187500000 0.195312500000 -bk_training.tga 0.117187500000 0.156250000000 0.156250000000 0.195312500000 -BK_tryker.tga 0.156250000000 0.156250000000 0.195312500000 0.195312500000 -BK_zorai.tga 0.195312500000 0.156250000000 0.234375000000 0.195312500000 -charge.tga 0.000000000000 0.195312500000 0.039062500000 0.234375000000 -clef.tga 0.039062500000 0.195312500000 0.078125000000 0.234375000000 -conso_branche.tga 0.078125000000 0.195312500000 0.117187500000 0.234375000000 -conso_branche_mask.tga 0.117187500000 0.195312500000 0.156250000000 0.234375000000 -conso_fleur.tga 0.156250000000 0.195312500000 0.195312500000 0.234375000000 -conso_fleur_mask.tga 0.195312500000 0.195312500000 0.234375000000 0.234375000000 -conso_grappe.tga 0.242187500000 0.000000000000 0.281250000000 0.039062500000 -conso_grappe_mask.tga 0.281250000000 0.000000000000 0.320312500000 0.039062500000 -conso_nectar.tga 0.320312500000 0.000000000000 0.359375000000 0.039062500000 -conso_nectar_mask.tga 0.359375000000 0.000000000000 0.398437500000 0.039062500000 -construction.tga 0.398437500000 0.000000000000 0.437500000000 0.039062500000 -cristal_ammo.tga 0.437500000000 0.000000000000 0.476562500000 0.039062500000 -cristal_spell.tga 0.238281250000 0.039062500000 0.277343750000 0.078125000000 -ge_mission_outpost_townhall.tga 0.277343750000 0.039062500000 0.316406250000 0.078125000000 -ico_amande.tga 0.316406250000 0.039062500000 0.355468750000 0.078125000000 -ico_cataliseur_xp.tga 0.355468750000 0.039062500000 0.394531250000 0.078125000000 -ico_consommable_over.tga 0.394531250000 0.039062500000 0.433593750000 0.078125000000 -ico_fleur_carac_1.tga 0.433593750000 0.039062500000 0.472656250000 0.078125000000 -ico_fleur_carac_1_mask.tga 0.234375000000 0.078125000000 0.273437500000 0.117187500000 -ico_fleur_carac_2.tga 0.273437500000 0.078125000000 0.312500000000 0.117187500000 -ico_fleur_carac_2_mask.tga 0.312500000000 0.078125000000 0.351562500000 0.117187500000 -ico_fleur_carac_3.tga 0.351562500000 0.078125000000 0.390625000000 0.117187500000 -ico_fleur_carac_3_mask.tga 0.390625000000 0.078125000000 0.429687500000 0.117187500000 -ico_foreuse.tga 0.429687500000 0.078125000000 0.468750000000 0.117187500000 -ico_haircolor.tga 0.234375000000 0.117187500000 0.273437500000 0.156250000000 -ico_haircut.tga 0.273437500000 0.117187500000 0.312500000000 0.156250000000 -ico_mission_art_fyros.tga 0.312500000000 0.117187500000 0.351562500000 0.156250000000 -ico_mission_art_matis.tga 0.351562500000 0.117187500000 0.390625000000 0.156250000000 -ico_mission_art_tryker.tga 0.390625000000 0.117187500000 0.429687500000 0.156250000000 -ico_mission_art_zorai.tga 0.429687500000 0.117187500000 0.468750000000 0.156250000000 -ico_mission_barrel.tga 0.234375000000 0.156250000000 0.273437500000 0.195312500000 -ico_mission_bottle.tga 0.273437500000 0.156250000000 0.312500000000 0.195312500000 -ico_mission_casket.tga 0.312500000000 0.156250000000 0.351562500000 0.195312500000 -ico_mission_medicine.tga 0.351562500000 0.156250000000 0.390625000000 0.195312500000 -ico_mission_message.tga 0.390625000000 0.156250000000 0.429687500000 0.195312500000 -ico_mission_package.tga 0.429687500000 0.156250000000 0.468750000000 0.195312500000 -ico_mission_pot.tga 0.234375000000 0.195312500000 0.273437500000 0.234375000000 -ico_mission_purse.tga 0.273437500000 0.195312500000 0.312500000000 0.234375000000 -ico_noix.tga 0.312500000000 0.195312500000 0.351562500000 0.234375000000 -ico_racine.tga 0.351562500000 0.195312500000 0.390625000000 0.234375000000 -ico_spores.tga 0.390625000000 0.195312500000 0.429687500000 0.234375000000 -ico_task_craft.tga 0.429687500000 0.195312500000 0.468750000000 0.234375000000 -ico_task_done.tga 0.000000000000 0.234375000000 0.039062500000 0.273437500000 -ico_task_failed.tga 0.039062500000 0.234375000000 0.078125000000 0.273437500000 -ico_task_fight.tga 0.078125000000 0.234375000000 0.117187500000 0.273437500000 -ico_task_forage.tga 0.117187500000 0.234375000000 0.156250000000 0.273437500000 -ico_task_generic.tga 0.156250000000 0.234375000000 0.195312500000 0.273437500000 -ico_task_generic_quart.tga 0.195312500000 0.234375000000 0.234375000000 0.273437500000 -ico_task_guild.tga 0.234375000000 0.234375000000 0.273437500000 0.273437500000 -ico_task_rite.tga 0.273437500000 0.234375000000 0.312500000000 0.273437500000 -ico_task_travel.tga 0.312500000000 0.234375000000 0.351562500000 0.273437500000 -ico_tatoo.tga 0.351562500000 0.234375000000 0.390625000000 0.273437500000 -ico_tourbe.tga 0.390625000000 0.234375000000 0.429687500000 0.273437500000 -improved_tool.tga 0.429687500000 0.234375000000 0.468750000000 0.273437500000 -item_default.tga 0.000000000000 0.273437500000 0.039062500000 0.312500000000 -item_plan_over.tga 0.039062500000 0.273437500000 0.078125000000 0.312500000000 -lucky_flower.tga 0.078125000000 0.273437500000 0.117187500000 0.312500000000 -mektoub_pack.tga 0.117187500000 0.273437500000 0.156250000000 0.312500000000 -mektoub_steed.tga 0.156250000000 0.273437500000 0.195312500000 0.312500000000 -mg_glove.tga 0.195312500000 0.273437500000 0.234375000000 0.312500000000 -mission_icon_0.tga 0.234375000000 0.273437500000 0.273437500000 0.312500000000 -mission_icon_1.tga 0.273437500000 0.273437500000 0.312500000000 0.312500000000 -mission_icon_2.tga 0.312500000000 0.273437500000 0.351562500000 0.312500000000 -mission_icon_3.tga 0.351562500000 0.273437500000 0.390625000000 0.312500000000 -mp_amber.tga 0.390625000000 0.273437500000 0.429687500000 0.312500000000 -mp_bark.tga 0.429687500000 0.273437500000 0.468750000000 0.312500000000 -mp_batiment_brique.tga 0.000000000000 0.312500000000 0.039062500000 0.351562500000 -mp_batiment_colonne.tga 0.039062500000 0.312500000000 0.078125000000 0.351562500000 -mp_batiment_colonne_justice.tga 0.078125000000 0.312500000000 0.117187500000 0.351562500000 -mp_batiment_comble.tga 0.117187500000 0.312500000000 0.156250000000 0.351562500000 -mp_batiment_noyau_maduk.tga 0.156250000000 0.312500000000 0.195312500000 0.351562500000 -mp_batiment_ornement.tga 0.195312500000 0.312500000000 0.234375000000 0.351562500000 -mp_batiment_revetement.tga 0.234375000000 0.312500000000 0.273437500000 0.351562500000 -mp_batiment_socle.tga 0.273437500000 0.312500000000 0.312500000000 0.351562500000 -mp_batiment_statue.tga 0.312500000000 0.312500000000 0.351562500000 0.351562500000 -mp_beak.tga 0.351562500000 0.312500000000 0.390625000000 0.351562500000 -mp_blood.tga 0.390625000000 0.312500000000 0.429687500000 0.351562500000 -mp_bone.tga 0.429687500000 0.312500000000 0.468750000000 0.351562500000 -mp_bud.tga 0.000000000000 0.351562500000 0.039062500000 0.390625000000 -mp_buterfly_blue.tga 0.039062500000 0.351562500000 0.078125000000 0.390625000000 -mp_buterfly_cocoon.tga 0.078125000000 0.351562500000 0.117187500000 0.390625000000 -mp_cereal.tga 0.117187500000 0.351562500000 0.156250000000 0.390625000000 -mp_claw.tga 0.156250000000 0.351562500000 0.195312500000 0.390625000000 -mp_dandelion.tga 0.195312500000 0.351562500000 0.234375000000 0.390625000000 -mp_dust.tga 0.234375000000 0.351562500000 0.273437500000 0.390625000000 -mp_egg.tga 0.273437500000 0.351562500000 0.312500000000 0.390625000000 -mp_eyes.tga 0.312500000000 0.351562500000 0.351562500000 0.390625000000 -mp_fang.tga 0.351562500000 0.351562500000 0.390625000000 0.390625000000 -mp_fiber.tga 0.390625000000 0.351562500000 0.429687500000 0.390625000000 -mp_filament.tga 0.429687500000 0.351562500000 0.468750000000 0.390625000000 -mp_firefly_abdomen.tga 0.000000000000 0.390625000000 0.039062500000 0.429687500000 -mp_fish_scale.tga 0.039062500000 0.390625000000 0.078125000000 0.429687500000 -mp_flowers.tga 0.078125000000 0.390625000000 0.117187500000 0.429687500000 -mp_fresh_loose_soil.tga 0.117187500000 0.390625000000 0.156250000000 0.429687500000 -mp_fruit.tga 0.156250000000 0.390625000000 0.195312500000 0.429687500000 -mp_generic.tga 0.195312500000 0.390625000000 0.234375000000 0.429687500000 -mp_generic_colorize.tga 0.234375000000 0.390625000000 0.273437500000 0.429687500000 -mp_gomme.tga 0.273437500000 0.390625000000 0.312500000000 0.429687500000 -mp_goo_residue.tga 0.312500000000 0.390625000000 0.351562500000 0.429687500000 -mp_hairs.tga 0.351562500000 0.390625000000 0.390625000000 0.429687500000 -mp_hoof.tga 0.390625000000 0.390625000000 0.429687500000 0.429687500000 -mp_horn.tga 0.429687500000 0.390625000000 0.468750000000 0.429687500000 -mp_horney.tga 0.000000000000 0.429687500000 0.039062500000 0.468750000000 -mp_insect_fossil.tga 0.039062500000 0.429687500000 0.078125000000 0.468750000000 -mp_kitinshell.tga 0.078125000000 0.429687500000 0.117187500000 0.468750000000 -mp_kitin_flesh.tga 0.117187500000 0.429687500000 0.156250000000 0.468750000000 -mp_kitin_secretion.tga 0.156250000000 0.429687500000 0.195312500000 0.468750000000 -mp_larva.tga 0.195312500000 0.429687500000 0.234375000000 0.468750000000 -mp_leaf.tga 0.234375000000 0.429687500000 0.273437500000 0.468750000000 -mp_leather.tga 0.273437500000 0.429687500000 0.312500000000 0.468750000000 -mp_liane.tga 0.312500000000 0.429687500000 0.351562500000 0.468750000000 -mp_lichen.tga 0.351562500000 0.429687500000 0.390625000000 0.468750000000 -mp_ligament.tga 0.390625000000 0.429687500000 0.429687500000 0.468750000000 -mp_mandible.tga 0.429687500000 0.429687500000 0.468750000000 0.468750000000 -mp_meat.tga 0.476562500000 0.000000000000 0.515625000000 0.039062500000 -mp_moss.tga 0.515625000000 0.000000000000 0.554687500000 0.039062500000 -mp_mushroom.tga 0.554687500000 0.000000000000 0.593750000000 0.039062500000 -mp_nail.tga 0.593750000000 0.000000000000 0.632812500000 0.039062500000 -mp_oil.tga 0.632812500000 0.000000000000 0.671875000000 0.039062500000 -mp_parasite.tga 0.671875000000 0.000000000000 0.710937500000 0.039062500000 -mp_pearl.tga 0.710937500000 0.000000000000 0.750000000000 0.039062500000 -mp_pelvis.tga 0.750000000000 0.000000000000 0.789062500000 0.039062500000 -mp_pigment.tga 0.789062500000 0.000000000000 0.828125000000 0.039062500000 -mp_pistil.tga 0.828125000000 0.000000000000 0.867187500000 0.039062500000 -mp_plant_fossil.tga 0.867187500000 0.000000000000 0.906250000000 0.039062500000 -mp_pollen.tga 0.906250000000 0.000000000000 0.945312500000 0.039062500000 -mp_resin.tga 0.945312500000 0.000000000000 0.984375000000 0.039062500000 -mp_ronce.tga 0.472656250000 0.039062500000 0.511718750000 0.078125000000 -mp_rostrum.tga 0.511718750000 0.039062500000 0.550781250000 0.078125000000 -mp_sap.tga 0.550781250000 0.039062500000 0.589843750000 0.078125000000 -mp_sawdust.tga 0.589843750000 0.039062500000 0.628906250000 0.078125000000 -mp_seed.tga 0.628906250000 0.039062500000 0.667968750000 0.078125000000 -mp_shell.tga 0.667968750000 0.039062500000 0.707031250000 0.078125000000 -mp_silk_worm.tga 0.707031250000 0.039062500000 0.746093750000 0.078125000000 -mp_skin.tga 0.746093750000 0.039062500000 0.785156250000 0.078125000000 -mp_skull.tga 0.785156250000 0.039062500000 0.824218750000 0.078125000000 -mp_spiders_web.tga 0.824218750000 0.039062500000 0.863281250000 0.078125000000 -mp_spine.tga 0.863281250000 0.039062500000 0.902343750000 0.078125000000 -mp_stem.tga 0.902343750000 0.039062500000 0.941406250000 0.078125000000 -mp_sting.tga 0.941406250000 0.039062500000 0.980468750000 0.078125000000 -mp_straw.tga 0.468750000000 0.078125000000 0.507812500000 0.117187500000 -mp_suc.tga 0.507812500000 0.078125000000 0.546875000000 0.117187500000 -mp_tail.tga 0.546875000000 0.078125000000 0.585937500000 0.117187500000 -mp_tooth.tga 0.585937500000 0.078125000000 0.625000000000 0.117187500000 -mp_trunk.tga 0.625000000000 0.078125000000 0.664062500000 0.117187500000 -mp_whiskers.tga 0.664062500000 0.078125000000 0.703125000000 0.117187500000 -mp_wing.tga 0.703125000000 0.078125000000 0.742187500000 0.117187500000 -mp_wood.tga 0.742187500000 0.078125000000 0.781250000000 0.117187500000 -mp_wood_node.tga 0.781250000000 0.078125000000 0.820312500000 0.117187500000 -MW_2h_axe.tga 0.820312500000 0.078125000000 0.859375000000 0.117187500000 -MW_2h_lance.tga 0.859375000000 0.078125000000 0.898437500000 0.117187500000 -MW_2h_mace.tga 0.898437500000 0.078125000000 0.937500000000 0.117187500000 -MW_2h_sword.tga 0.937500000000 0.078125000000 0.976562500000 0.117187500000 -MW_axe.tga 0.468750000000 0.117187500000 0.507812500000 0.156250000000 -MW_dagger.tga 0.507812500000 0.117187500000 0.546875000000 0.156250000000 -MW_lance.tga 0.546875000000 0.117187500000 0.585937500000 0.156250000000 -MW_mace.tga 0.585937500000 0.117187500000 0.625000000000 0.156250000000 -MW_staff.tga 0.625000000000 0.117187500000 0.664062500000 0.156250000000 -MW_sword.tga 0.664062500000 0.117187500000 0.703125000000 0.156250000000 -PA_anklet.tga 0.703125000000 0.117187500000 0.742187500000 0.156250000000 -PA_bracelet.tga 0.742187500000 0.117187500000 0.781250000000 0.156250000000 -PA_diadem.tga 0.781250000000 0.117187500000 0.820312500000 0.156250000000 -PA_earring.tga 0.820312500000 0.117187500000 0.859375000000 0.156250000000 -PA_pendant.tga 0.859375000000 0.117187500000 0.898437500000 0.156250000000 -PA_ring.tga 0.898437500000 0.117187500000 0.937500000000 0.156250000000 -protect_amber.tga 0.937500000000 0.117187500000 0.976562500000 0.156250000000 -pvp_aura.tga 0.468750000000 0.156250000000 0.507812500000 0.195312500000 -pvp_aura_mask.tga 0.507812500000 0.156250000000 0.546875000000 0.195312500000 -pvp_boost.tga 0.546875000000 0.156250000000 0.585937500000 0.195312500000 -pvp_boost_mask.tga 0.585937500000 0.156250000000 0.625000000000 0.195312500000 -pw_4.tga 0.625000000000 0.156250000000 0.664062500000 0.195312500000 -pw_5.tga 0.664062500000 0.156250000000 0.703125000000 0.195312500000 -pw_6.tga 0.703125000000 0.156250000000 0.742187500000 0.195312500000 -pw_7.tga 0.742187500000 0.156250000000 0.781250000000 0.195312500000 -PW_heavy.tga 0.781250000000 0.156250000000 0.820312500000 0.195312500000 -PW_light.tga 0.820312500000 0.156250000000 0.859375000000 0.195312500000 -PW_medium.tga 0.859375000000 0.156250000000 0.898437500000 0.195312500000 -quest_coeur.tga 0.898437500000 0.156250000000 0.937500000000 0.195312500000 -quest_foie.tga 0.937500000000 0.156250000000 0.976562500000 0.195312500000 -quest_jeton.tga 0.468750000000 0.195312500000 0.507812500000 0.234375000000 -quest_langue.tga 0.507812500000 0.195312500000 0.546875000000 0.234375000000 -quest_louche.tga 0.546875000000 0.195312500000 0.585937500000 0.234375000000 -quest_oreille.tga 0.585937500000 0.195312500000 0.625000000000 0.234375000000 -quest_patte.tga 0.625000000000 0.195312500000 0.664062500000 0.234375000000 -quest_poils.tga 0.664062500000 0.195312500000 0.703125000000 0.234375000000 -quest_queue.tga 0.703125000000 0.195312500000 0.742187500000 0.234375000000 -quest_ticket.tga 0.742187500000 0.195312500000 0.781250000000 0.234375000000 -AM_logo.tga 0.781250000000 0.195312500000 0.820312500000 0.234375000000 -AR_armpad.tga 0.820312500000 0.195312500000 0.859375000000 0.234375000000 -ar_armpad_mask.tga 0.859375000000 0.195312500000 0.898437500000 0.234375000000 -requirement.tga 0.898437500000 0.195312500000 0.937500000000 0.234375000000 -rm_f.tga 0.937500000000 0.195312500000 0.976562500000 0.234375000000 -rm_f_upgrade.tga 0.468750000000 0.234375000000 0.507812500000 0.273437500000 -rm_h.tga 0.507812500000 0.234375000000 0.546875000000 0.273437500000 -rm_h_upgrade.tga 0.546875000000 0.234375000000 0.585937500000 0.273437500000 -rm_m.tga 0.585937500000 0.234375000000 0.625000000000 0.273437500000 -rm_m_upgrade.tga 0.625000000000 0.234375000000 0.664062500000 0.273437500000 -rm_r.tga 0.664062500000 0.234375000000 0.703125000000 0.273437500000 -rm_r_upgrade.tga 0.703125000000 0.234375000000 0.742187500000 0.273437500000 -rpjobitem_200_a.tga 0.742187500000 0.234375000000 0.781250000000 0.273437500000 -rpjobitem_200_b.tga 0.781250000000 0.234375000000 0.820312500000 0.273437500000 -rpjobitem_200_c.tga 0.820312500000 0.234375000000 0.859375000000 0.273437500000 -rpjobitem_201_a.tga 0.859375000000 0.234375000000 0.898437500000 0.273437500000 -rpjobitem_201_b.tga 0.898437500000 0.234375000000 0.937500000000 0.273437500000 -rpjobitem_201_c.tga 0.937500000000 0.234375000000 0.976562500000 0.273437500000 -rpjobitem_202_a.tga 0.468750000000 0.273437500000 0.507812500000 0.312500000000 -rpjobitem_202_b.tga 0.507812500000 0.273437500000 0.546875000000 0.312500000000 -rpjobitem_202_c.tga 0.546875000000 0.273437500000 0.585937500000 0.312500000000 -rpjobitem_203_a.tga 0.585937500000 0.273437500000 0.625000000000 0.312500000000 -rpjobitem_203_b.tga 0.625000000000 0.273437500000 0.664062500000 0.312500000000 -rpjobitem_203_c.tga 0.664062500000 0.273437500000 0.703125000000 0.312500000000 -rpjobitem_204_a.tga 0.703125000000 0.273437500000 0.742187500000 0.312500000000 -rpjobitem_204_b.tga 0.742187500000 0.273437500000 0.781250000000 0.312500000000 -rpjobitem_204_c.tga 0.781250000000 0.273437500000 0.820312500000 0.312500000000 -rpjobitem_205_a.tga 0.820312500000 0.273437500000 0.859375000000 0.312500000000 -rpjobitem_205_b.tga 0.859375000000 0.273437500000 0.898437500000 0.312500000000 -rpjobitem_205_c.tga 0.898437500000 0.273437500000 0.937500000000 0.312500000000 -rpjobitem_206_a.tga 0.937500000000 0.273437500000 0.976562500000 0.312500000000 -rpjobitem_206_b.tga 0.468750000000 0.312500000000 0.507812500000 0.351562500000 -rpjobitem_206_c.tga 0.507812500000 0.312500000000 0.546875000000 0.351562500000 -rpjobitem_207_a.tga 0.546875000000 0.312500000000 0.585937500000 0.351562500000 -rpjobitem_207_b.tga 0.585937500000 0.312500000000 0.625000000000 0.351562500000 -rpjobitem_207_c.tga 0.625000000000 0.312500000000 0.664062500000 0.351562500000 -rpjobitem_certifications.tga 0.664062500000 0.312500000000 0.703125000000 0.351562500000 -rpjob_200.tga 0.703125000000 0.312500000000 0.742187500000 0.351562500000 -rpjob_201.tga 0.742187500000 0.312500000000 0.781250000000 0.351562500000 -rpjob_202.tga 0.781250000000 0.312500000000 0.820312500000 0.351562500000 -rpjob_203.tga 0.820312500000 0.312500000000 0.859375000000 0.351562500000 -rpjob_204.tga 0.859375000000 0.312500000000 0.898437500000 0.351562500000 -rpjob_205.tga 0.898437500000 0.312500000000 0.937500000000 0.351562500000 -rpjob_206.tga 0.937500000000 0.312500000000 0.976562500000 0.351562500000 -rpjob_207.tga 0.468750000000 0.351562500000 0.507812500000 0.390625000000 -rpjob_advanced.tga 0.507812500000 0.351562500000 0.546875000000 0.390625000000 -rpjob_elementary.tga 0.546875000000 0.351562500000 0.585937500000 0.390625000000 -rpjob_roleplay.tga 0.585937500000 0.351562500000 0.625000000000 0.390625000000 -rpjob_task.tga 0.625000000000 0.351562500000 0.664062500000 0.390625000000 -rpjob_task_certificats.tga 0.664062500000 0.351562500000 0.703125000000 0.390625000000 -rpjob_task_convert.tga 0.703125000000 0.351562500000 0.742187500000 0.390625000000 -rpjob_task_elementary.tga 0.742187500000 0.351562500000 0.781250000000 0.390625000000 -rpjob_task_generic.tga 0.781250000000 0.351562500000 0.820312500000 0.390625000000 -rpjob_task_upgrade.tga 0.820312500000 0.351562500000 0.859375000000 0.390625000000 -RW_autolaunch.tga 0.859375000000 0.351562500000 0.898437500000 0.390625000000 -RW_bowgun.tga 0.898437500000 0.351562500000 0.937500000000 0.390625000000 -RW_grenade.tga 0.937500000000 0.351562500000 0.976562500000 0.390625000000 -RW_harpoongun.tga 0.468750000000 0.390625000000 0.507812500000 0.429687500000 -RW_launcher.tga 0.507812500000 0.390625000000 0.546875000000 0.429687500000 -RW_pistol.tga 0.546875000000 0.390625000000 0.585937500000 0.429687500000 -RW_pistolarc.tga 0.585937500000 0.390625000000 0.625000000000 0.429687500000 -RW_rifle.tga 0.625000000000 0.390625000000 0.664062500000 0.429687500000 -SH_buckler.tga 0.664062500000 0.390625000000 0.703125000000 0.429687500000 -SH_large_shield.tga 0.703125000000 0.390625000000 0.742187500000 0.429687500000 -spe_beast.tga 0.742187500000 0.390625000000 0.781250000000 0.429687500000 -spe_com.tga 0.781250000000 0.390625000000 0.820312500000 0.429687500000 -spe_inventory.tga 0.820312500000 0.390625000000 0.859375000000 0.429687500000 -spe_labs.tga 0.859375000000 0.390625000000 0.898437500000 0.429687500000 -spe_memory.tga 0.898437500000 0.390625000000 0.937500000000 0.429687500000 -spe_options.tga 0.937500000000 0.390625000000 0.976562500000 0.429687500000 -spe_status.tga 0.468750000000 0.429687500000 0.507812500000 0.468750000000 -stimulating_water.tga 0.507812500000 0.429687500000 0.546875000000 0.468750000000 -tetekitin.tga 0.546875000000 0.429687500000 0.585937500000 0.468750000000 -to_ammo.tga 0.585937500000 0.429687500000 0.625000000000 0.468750000000 -to_armor.tga 0.625000000000 0.429687500000 0.664062500000 0.468750000000 -to_cooking_pot.tga 0.664062500000 0.429687500000 0.703125000000 0.468750000000 -to_fishing_rod.tga 0.703125000000 0.429687500000 0.742187500000 0.468750000000 -to_forage.tga 0.742187500000 0.429687500000 0.781250000000 0.468750000000 -to_hammer.tga 0.781250000000 0.429687500000 0.820312500000 0.468750000000 -to_jewelry_hammer.tga 0.820312500000 0.429687500000 0.859375000000 0.468750000000 -to_jewels.tga 0.859375000000 0.429687500000 0.898437500000 0.468750000000 -to_leathercutter.tga 0.898437500000 0.429687500000 0.937500000000 0.468750000000 -to_melee.tga 0.937500000000 0.429687500000 0.976562500000 0.468750000000 -to_needle.tga 0.000000000000 0.468750000000 0.039062500000 0.507812500000 -to_pestle.tga 0.039062500000 0.468750000000 0.078125000000 0.507812500000 -to_range.tga 0.078125000000 0.468750000000 0.117187500000 0.507812500000 -to_searake.tga 0.117187500000 0.468750000000 0.156250000000 0.507812500000 -to_spade.tga 0.156250000000 0.468750000000 0.195312500000 0.507812500000 -to_stick.tga 0.195312500000 0.468750000000 0.234375000000 0.507812500000 -to_tunneling_knife.tga 0.234375000000 0.468750000000 0.273437500000 0.507812500000 -to_whip.tga 0.273437500000 0.468750000000 0.312500000000 0.507812500000 -to_wrench.tga 0.312500000000 0.468750000000 0.351562500000 0.507812500000 -TP_caravane.tga 0.351562500000 0.468750000000 0.390625000000 0.507812500000 -TP_kami.tga 0.390625000000 0.468750000000 0.429687500000 0.507812500000 -W_AM_logo.tga 0.429687500000 0.468750000000 0.468750000000 0.507812500000 -w_pa_anklet.tga 0.468750000000 0.468750000000 0.507812500000 0.507812500000 -w_pa_bracelet.tga 0.507812500000 0.468750000000 0.546875000000 0.507812500000 -w_pa_diadem.tga 0.546875000000 0.468750000000 0.585937500000 0.507812500000 -w_pa_earring.tga 0.585937500000 0.468750000000 0.625000000000 0.507812500000 -w_pa_pendant.tga 0.625000000000 0.468750000000 0.664062500000 0.507812500000 -w_pa_ring.tga 0.664062500000 0.468750000000 0.703125000000 0.507812500000 -xp_cat_green.tga 0.703125000000 0.468750000000 0.742187500000 0.507812500000 +BK_matis.tga 0.078125000000 0.117187500000 0.117187500000 0.156250000000 +bk_mission.tga 0.117187500000 0.117187500000 0.156250000000 0.156250000000 +bk_mission2.tga 0.156250000000 0.117187500000 0.195312500000 0.156250000000 +BK_outpost.tga 0.195312500000 0.117187500000 0.234375000000 0.156250000000 +BK_primes.tga 0.000000000000 0.156250000000 0.039062500000 0.195312500000 +bk_service.tga 0.039062500000 0.156250000000 0.078125000000 0.195312500000 +bk_training.tga 0.078125000000 0.156250000000 0.117187500000 0.195312500000 +BK_tryker.tga 0.117187500000 0.156250000000 0.156250000000 0.195312500000 +BK_zorai.tga 0.156250000000 0.156250000000 0.195312500000 0.195312500000 +charge.tga 0.195312500000 0.156250000000 0.234375000000 0.195312500000 +clef.tga 0.000000000000 0.195312500000 0.039062500000 0.234375000000 +conso_branche.tga 0.039062500000 0.195312500000 0.078125000000 0.234375000000 +conso_branche_mask.tga 0.078125000000 0.195312500000 0.117187500000 0.234375000000 +conso_fleur.tga 0.117187500000 0.195312500000 0.156250000000 0.234375000000 +conso_fleur_mask.tga 0.156250000000 0.195312500000 0.195312500000 0.234375000000 +conso_grappe.tga 0.195312500000 0.195312500000 0.234375000000 0.234375000000 +conso_nectar.tga 0.242187500000 0.000000000000 0.281250000000 0.039062500000 +conso_nectar_mask.tga 0.281250000000 0.000000000000 0.320312500000 0.039062500000 +construction.tga 0.320312500000 0.000000000000 0.359375000000 0.039062500000 +cristal_ammo.tga 0.359375000000 0.000000000000 0.398437500000 0.039062500000 +cristal_spell.tga 0.398437500000 0.000000000000 0.437500000000 0.039062500000 +ico_haircolor.tga 0.437500000000 0.000000000000 0.476562500000 0.039062500000 +ico_haircut.tga 0.238281250000 0.039062500000 0.277343750000 0.078125000000 +bk_karavan.tga 0.277343750000 0.039062500000 0.316406250000 0.078125000000 +conso_grappe_mask.tga 0.316406250000 0.039062500000 0.355468750000 0.078125000000 +ico_foreuse.tga 0.355468750000 0.039062500000 0.394531250000 0.078125000000 +ico_noix.tga 0.394531250000 0.039062500000 0.433593750000 0.078125000000 +ico_spores.tga 0.433593750000 0.039062500000 0.472656250000 0.078125000000 +mektoub_pack.tga 0.234375000000 0.078125000000 0.273437500000 0.117187500000 +mp_beak.tga 0.273437500000 0.078125000000 0.312500000000 0.117187500000 +mp_fresh_loose_soil.tga 0.312500000000 0.078125000000 0.351562500000 0.117187500000 +mp_lichen.tga 0.351562500000 0.078125000000 0.390625000000 0.117187500000 +mp_sawdust.tga 0.390625000000 0.078125000000 0.429687500000 0.117187500000 +MW_2h_axe.tga 0.429687500000 0.078125000000 0.468750000000 0.117187500000 +PA_bracelet.tga 0.234375000000 0.117187500000 0.273437500000 0.156250000000 +pvp_aura_mask.tga 0.273437500000 0.117187500000 0.312500000000 0.156250000000 +quest_queue.tga 0.312500000000 0.117187500000 0.351562500000 0.156250000000 +rpjobitem_201_b.tga 0.351562500000 0.117187500000 0.390625000000 0.156250000000 +rpjobitem_207_a.tga 0.390625000000 0.117187500000 0.429687500000 0.156250000000 +rpjob_task_elementary.tga 0.429687500000 0.117187500000 0.468750000000 0.156250000000 +spe_options.tga 0.234375000000 0.156250000000 0.273437500000 0.195312500000 +to_range.tga 0.273437500000 0.156250000000 0.312500000000 0.195312500000 +w_pa_anklet.tga 0.312500000000 0.156250000000 0.351562500000 0.195312500000 +ico_task_craft.tga 0.351562500000 0.156250000000 0.390625000000 0.195312500000 +ico_task_done.tga 0.390625000000 0.156250000000 0.429687500000 0.195312500000 +ico_task_failed.tga 0.429687500000 0.156250000000 0.468750000000 0.195312500000 +ico_task_fight.tga 0.234375000000 0.195312500000 0.273437500000 0.234375000000 +ico_task_forage.tga 0.273437500000 0.195312500000 0.312500000000 0.234375000000 +ico_task_generic.tga 0.312500000000 0.195312500000 0.351562500000 0.234375000000 +ico_task_generic_quart.tga 0.351562500000 0.195312500000 0.390625000000 0.234375000000 +ico_task_guild.tga 0.390625000000 0.195312500000 0.429687500000 0.234375000000 +ico_task_rite.tga 0.429687500000 0.195312500000 0.468750000000 0.234375000000 +ico_task_travel.tga 0.000000000000 0.234375000000 0.039062500000 0.273437500000 +ico_tatoo.tga 0.039062500000 0.234375000000 0.078125000000 0.273437500000 +mektoub_steed.tga 0.078125000000 0.234375000000 0.117187500000 0.273437500000 +mg_glove.tga 0.117187500000 0.234375000000 0.156250000000 0.273437500000 +mission_icon_0.tga 0.156250000000 0.234375000000 0.195312500000 0.273437500000 +mission_icon_1.tga 0.195312500000 0.234375000000 0.234375000000 0.273437500000 +mission_icon_2.tga 0.234375000000 0.234375000000 0.273437500000 0.273437500000 +mission_icon_3.tga 0.273437500000 0.234375000000 0.312500000000 0.273437500000 +mp_amber.tga 0.312500000000 0.234375000000 0.351562500000 0.273437500000 +mp_bark.tga 0.351562500000 0.234375000000 0.390625000000 0.273437500000 +mp_batiment_brique.tga 0.390625000000 0.234375000000 0.429687500000 0.273437500000 +mp_batiment_colonne.tga 0.429687500000 0.234375000000 0.468750000000 0.273437500000 +mp_batiment_colonne_justice.tga 0.000000000000 0.273437500000 0.039062500000 0.312500000000 +mp_batiment_comble.tga 0.039062500000 0.273437500000 0.078125000000 0.312500000000 +mp_batiment_noyau_maduk.tga 0.078125000000 0.273437500000 0.117187500000 0.312500000000 +mp_batiment_ornement.tga 0.117187500000 0.273437500000 0.156250000000 0.312500000000 +mp_batiment_revetement.tga 0.156250000000 0.273437500000 0.195312500000 0.312500000000 +mp_batiment_socle.tga 0.195312500000 0.273437500000 0.234375000000 0.312500000000 +mp_batiment_statue.tga 0.234375000000 0.273437500000 0.273437500000 0.312500000000 +mp_blood.tga 0.273437500000 0.273437500000 0.312500000000 0.312500000000 +mp_bone.tga 0.312500000000 0.273437500000 0.351562500000 0.312500000000 +mp_bud.tga 0.351562500000 0.273437500000 0.390625000000 0.312500000000 +mp_buterfly_blue.tga 0.390625000000 0.273437500000 0.429687500000 0.312500000000 +mp_buterfly_cocoon.tga 0.429687500000 0.273437500000 0.468750000000 0.312500000000 +mp_cereal.tga 0.000000000000 0.312500000000 0.039062500000 0.351562500000 +mp_claw.tga 0.039062500000 0.312500000000 0.078125000000 0.351562500000 +mp_dandelion.tga 0.078125000000 0.312500000000 0.117187500000 0.351562500000 +mp_dust.tga 0.117187500000 0.312500000000 0.156250000000 0.351562500000 +mp_egg.tga 0.156250000000 0.312500000000 0.195312500000 0.351562500000 +mp_eyes.tga 0.195312500000 0.312500000000 0.234375000000 0.351562500000 +mp_fang.tga 0.234375000000 0.312500000000 0.273437500000 0.351562500000 +mp_fiber.tga 0.273437500000 0.312500000000 0.312500000000 0.351562500000 +mp_filament.tga 0.312500000000 0.312500000000 0.351562500000 0.351562500000 +mp_firefly_abdomen.tga 0.351562500000 0.312500000000 0.390625000000 0.351562500000 +mp_fish_scale.tga 0.390625000000 0.312500000000 0.429687500000 0.351562500000 +mp_flowers.tga 0.429687500000 0.312500000000 0.468750000000 0.351562500000 +mp_fruit.tga 0.000000000000 0.351562500000 0.039062500000 0.390625000000 +mp_generic.tga 0.039062500000 0.351562500000 0.078125000000 0.390625000000 +mp_generic_colorize.tga 0.078125000000 0.351562500000 0.117187500000 0.390625000000 +mp_gomme.tga 0.117187500000 0.351562500000 0.156250000000 0.390625000000 +mp_goo_residue.tga 0.156250000000 0.351562500000 0.195312500000 0.390625000000 +mp_hairs.tga 0.195312500000 0.351562500000 0.234375000000 0.390625000000 +mp_hoof.tga 0.234375000000 0.351562500000 0.273437500000 0.390625000000 +mp_horn.tga 0.273437500000 0.351562500000 0.312500000000 0.390625000000 +mp_horney.tga 0.312500000000 0.351562500000 0.351562500000 0.390625000000 +mp_insect_fossil.tga 0.351562500000 0.351562500000 0.390625000000 0.390625000000 +mp_kitinshell.tga 0.390625000000 0.351562500000 0.429687500000 0.390625000000 +mp_kitin_flesh.tga 0.429687500000 0.351562500000 0.468750000000 0.390625000000 +mp_kitin_secretion.tga 0.000000000000 0.390625000000 0.039062500000 0.429687500000 +mp_larva.tga 0.039062500000 0.390625000000 0.078125000000 0.429687500000 +mp_leaf.tga 0.078125000000 0.390625000000 0.117187500000 0.429687500000 +mp_leather.tga 0.117187500000 0.390625000000 0.156250000000 0.429687500000 +mp_liane.tga 0.156250000000 0.390625000000 0.195312500000 0.429687500000 +mp_ligament.tga 0.195312500000 0.390625000000 0.234375000000 0.429687500000 +mp_mandible.tga 0.234375000000 0.390625000000 0.273437500000 0.429687500000 +mp_meat.tga 0.273437500000 0.390625000000 0.312500000000 0.429687500000 +mp_moss.tga 0.312500000000 0.390625000000 0.351562500000 0.429687500000 +mp_mushroom.tga 0.351562500000 0.390625000000 0.390625000000 0.429687500000 +mp_nail.tga 0.390625000000 0.390625000000 0.429687500000 0.429687500000 +mp_oil.tga 0.429687500000 0.390625000000 0.468750000000 0.429687500000 +mp_parasite.tga 0.000000000000 0.429687500000 0.039062500000 0.468750000000 +mp_pearl.tga 0.039062500000 0.429687500000 0.078125000000 0.468750000000 +mp_pelvis.tga 0.078125000000 0.429687500000 0.117187500000 0.468750000000 +mp_pigment.tga 0.117187500000 0.429687500000 0.156250000000 0.468750000000 +mp_pistil.tga 0.156250000000 0.429687500000 0.195312500000 0.468750000000 +mp_plant_fossil.tga 0.195312500000 0.429687500000 0.234375000000 0.468750000000 +mp_pollen.tga 0.234375000000 0.429687500000 0.273437500000 0.468750000000 +mp_resin.tga 0.273437500000 0.429687500000 0.312500000000 0.468750000000 +mp_ronce.tga 0.312500000000 0.429687500000 0.351562500000 0.468750000000 +mp_rostrum.tga 0.351562500000 0.429687500000 0.390625000000 0.468750000000 +mp_sap.tga 0.390625000000 0.429687500000 0.429687500000 0.468750000000 +mp_seed.tga 0.429687500000 0.429687500000 0.468750000000 0.468750000000 +mp_shell.tga 0.476562500000 0.000000000000 0.515625000000 0.039062500000 +mp_silk_worm.tga 0.515625000000 0.000000000000 0.554687500000 0.039062500000 +mp_skin.tga 0.554687500000 0.000000000000 0.593750000000 0.039062500000 +mp_skull.tga 0.593750000000 0.000000000000 0.632812500000 0.039062500000 +mp_spiders_web.tga 0.632812500000 0.000000000000 0.671875000000 0.039062500000 +mp_spine.tga 0.671875000000 0.000000000000 0.710937500000 0.039062500000 +mp_stem.tga 0.710937500000 0.000000000000 0.750000000000 0.039062500000 +mp_sting.tga 0.750000000000 0.000000000000 0.789062500000 0.039062500000 +mp_straw.tga 0.789062500000 0.000000000000 0.828125000000 0.039062500000 +mp_suc.tga 0.828125000000 0.000000000000 0.867187500000 0.039062500000 +mp_tail.tga 0.867187500000 0.000000000000 0.906250000000 0.039062500000 +mp_tooth.tga 0.906250000000 0.000000000000 0.945312500000 0.039062500000 +mp_trunk.tga 0.945312500000 0.000000000000 0.984375000000 0.039062500000 +mp_whiskers.tga 0.472656250000 0.039062500000 0.511718750000 0.078125000000 +mp_wing.tga 0.511718750000 0.039062500000 0.550781250000 0.078125000000 +mp_wood.tga 0.550781250000 0.039062500000 0.589843750000 0.078125000000 +mp_wood_node.tga 0.589843750000 0.039062500000 0.628906250000 0.078125000000 +MW_2h_lance.tga 0.628906250000 0.039062500000 0.667968750000 0.078125000000 +MW_2h_mace.tga 0.667968750000 0.039062500000 0.707031250000 0.078125000000 +MW_2h_sword.tga 0.707031250000 0.039062500000 0.746093750000 0.078125000000 +MW_axe.tga 0.746093750000 0.039062500000 0.785156250000 0.078125000000 +MW_dagger.tga 0.785156250000 0.039062500000 0.824218750000 0.078125000000 +MW_lance.tga 0.824218750000 0.039062500000 0.863281250000 0.078125000000 +MW_mace.tga 0.863281250000 0.039062500000 0.902343750000 0.078125000000 +MW_staff.tga 0.902343750000 0.039062500000 0.941406250000 0.078125000000 +MW_sword.tga 0.941406250000 0.039062500000 0.980468750000 0.078125000000 +PA_anklet.tga 0.468750000000 0.078125000000 0.507812500000 0.117187500000 +pvp_boost.tga 0.507812500000 0.078125000000 0.546875000000 0.117187500000 +pvp_boost_mask.tga 0.546875000000 0.078125000000 0.585937500000 0.117187500000 +pw_4.tga 0.585937500000 0.078125000000 0.625000000000 0.117187500000 +pw_5.tga 0.625000000000 0.078125000000 0.664062500000 0.117187500000 +pw_6.tga 0.664062500000 0.078125000000 0.703125000000 0.117187500000 +pw_7.tga 0.703125000000 0.078125000000 0.742187500000 0.117187500000 +PW_heavy.tga 0.742187500000 0.078125000000 0.781250000000 0.117187500000 +PW_light.tga 0.781250000000 0.078125000000 0.820312500000 0.117187500000 +PW_medium.tga 0.820312500000 0.078125000000 0.859375000000 0.117187500000 +quest_coeur.tga 0.859375000000 0.078125000000 0.898437500000 0.117187500000 +quest_foie.tga 0.898437500000 0.078125000000 0.937500000000 0.117187500000 +quest_jeton.tga 0.937500000000 0.078125000000 0.976562500000 0.117187500000 +quest_langue.tga 0.468750000000 0.117187500000 0.507812500000 0.156250000000 +quest_louche.tga 0.507812500000 0.117187500000 0.546875000000 0.156250000000 +quest_oreille.tga 0.546875000000 0.117187500000 0.585937500000 0.156250000000 +quest_patte.tga 0.585937500000 0.117187500000 0.625000000000 0.156250000000 +quest_poils.tga 0.625000000000 0.117187500000 0.664062500000 0.156250000000 +quest_ticket.tga 0.664062500000 0.117187500000 0.703125000000 0.156250000000 +AM_logo.tga 0.703125000000 0.117187500000 0.742187500000 0.156250000000 +AR_armpad.tga 0.742187500000 0.117187500000 0.781250000000 0.156250000000 +ar_armpad_mask.tga 0.781250000000 0.117187500000 0.820312500000 0.156250000000 +requirement.tga 0.820312500000 0.117187500000 0.859375000000 0.156250000000 +rm_f.tga 0.859375000000 0.117187500000 0.898437500000 0.156250000000 +rm_f_upgrade.tga 0.898437500000 0.117187500000 0.937500000000 0.156250000000 +rm_h.tga 0.937500000000 0.117187500000 0.976562500000 0.156250000000 +rm_h_upgrade.tga 0.468750000000 0.156250000000 0.507812500000 0.195312500000 +rm_m.tga 0.507812500000 0.156250000000 0.546875000000 0.195312500000 +rm_m_upgrade.tga 0.546875000000 0.156250000000 0.585937500000 0.195312500000 +rm_r.tga 0.585937500000 0.156250000000 0.625000000000 0.195312500000 +rm_r_upgrade.tga 0.625000000000 0.156250000000 0.664062500000 0.195312500000 +rpjobitem_200_a.tga 0.664062500000 0.156250000000 0.703125000000 0.195312500000 +rpjobitem_200_b.tga 0.703125000000 0.156250000000 0.742187500000 0.195312500000 +rpjobitem_200_c.tga 0.742187500000 0.156250000000 0.781250000000 0.195312500000 +rpjobitem_201_a.tga 0.781250000000 0.156250000000 0.820312500000 0.195312500000 +rpjobitem_201_c.tga 0.820312500000 0.156250000000 0.859375000000 0.195312500000 +rpjobitem_202_a.tga 0.859375000000 0.156250000000 0.898437500000 0.195312500000 +rpjobitem_202_b.tga 0.898437500000 0.156250000000 0.937500000000 0.195312500000 +rpjobitem_202_c.tga 0.937500000000 0.156250000000 0.976562500000 0.195312500000 +rpjobitem_203_a.tga 0.468750000000 0.195312500000 0.507812500000 0.234375000000 +rpjobitem_203_b.tga 0.507812500000 0.195312500000 0.546875000000 0.234375000000 +rpjobitem_203_c.tga 0.546875000000 0.195312500000 0.585937500000 0.234375000000 +rpjobitem_204_a.tga 0.585937500000 0.195312500000 0.625000000000 0.234375000000 +rpjobitem_204_b.tga 0.625000000000 0.195312500000 0.664062500000 0.234375000000 +rpjobitem_204_c.tga 0.664062500000 0.195312500000 0.703125000000 0.234375000000 +rpjobitem_205_a.tga 0.703125000000 0.195312500000 0.742187500000 0.234375000000 +rpjobitem_205_b.tga 0.742187500000 0.195312500000 0.781250000000 0.234375000000 +rpjobitem_205_c.tga 0.781250000000 0.195312500000 0.820312500000 0.234375000000 +rpjobitem_206_a.tga 0.820312500000 0.195312500000 0.859375000000 0.234375000000 +rpjobitem_206_b.tga 0.859375000000 0.195312500000 0.898437500000 0.234375000000 +rpjobitem_206_c.tga 0.898437500000 0.195312500000 0.937500000000 0.234375000000 +rpjobitem_207_b.tga 0.937500000000 0.195312500000 0.976562500000 0.234375000000 +rpjobitem_207_c.tga 0.468750000000 0.234375000000 0.507812500000 0.273437500000 +rpjobitem_certifications.tga 0.507812500000 0.234375000000 0.546875000000 0.273437500000 +rpjob_200.tga 0.546875000000 0.234375000000 0.585937500000 0.273437500000 +rpjob_201.tga 0.585937500000 0.234375000000 0.625000000000 0.273437500000 +rpjob_202.tga 0.625000000000 0.234375000000 0.664062500000 0.273437500000 +rpjob_203.tga 0.664062500000 0.234375000000 0.703125000000 0.273437500000 +rpjob_204.tga 0.703125000000 0.234375000000 0.742187500000 0.273437500000 +rpjob_205.tga 0.742187500000 0.234375000000 0.781250000000 0.273437500000 +rpjob_206.tga 0.781250000000 0.234375000000 0.820312500000 0.273437500000 +rpjob_207.tga 0.820312500000 0.234375000000 0.859375000000 0.273437500000 +rpjob_advanced.tga 0.859375000000 0.234375000000 0.898437500000 0.273437500000 +rpjob_elementary.tga 0.898437500000 0.234375000000 0.937500000000 0.273437500000 +rpjob_roleplay.tga 0.937500000000 0.234375000000 0.976562500000 0.273437500000 +rpjob_task.tga 0.468750000000 0.273437500000 0.507812500000 0.312500000000 +rpjob_task_certificats.tga 0.507812500000 0.273437500000 0.546875000000 0.312500000000 +rpjob_task_convert.tga 0.546875000000 0.273437500000 0.585937500000 0.312500000000 +rpjob_task_generic.tga 0.585937500000 0.273437500000 0.625000000000 0.312500000000 +rpjob_task_upgrade.tga 0.625000000000 0.273437500000 0.664062500000 0.312500000000 +RW_autolaunch.tga 0.664062500000 0.273437500000 0.703125000000 0.312500000000 +RW_bowgun.tga 0.703125000000 0.273437500000 0.742187500000 0.312500000000 +RW_grenade.tga 0.742187500000 0.273437500000 0.781250000000 0.312500000000 +RW_harpoongun.tga 0.781250000000 0.273437500000 0.820312500000 0.312500000000 +RW_launcher.tga 0.820312500000 0.273437500000 0.859375000000 0.312500000000 +RW_pistol.tga 0.859375000000 0.273437500000 0.898437500000 0.312500000000 +RW_pistolarc.tga 0.898437500000 0.273437500000 0.937500000000 0.312500000000 +RW_rifle.tga 0.937500000000 0.273437500000 0.976562500000 0.312500000000 +SH_buckler.tga 0.468750000000 0.312500000000 0.507812500000 0.351562500000 +SH_large_shield.tga 0.507812500000 0.312500000000 0.546875000000 0.351562500000 +spe_beast.tga 0.546875000000 0.312500000000 0.585937500000 0.351562500000 +spe_com.tga 0.585937500000 0.312500000000 0.625000000000 0.351562500000 +spe_inventory.tga 0.625000000000 0.312500000000 0.664062500000 0.351562500000 +spe_labs.tga 0.664062500000 0.312500000000 0.703125000000 0.351562500000 +spe_memory.tga 0.703125000000 0.312500000000 0.742187500000 0.351562500000 +spe_status.tga 0.742187500000 0.312500000000 0.781250000000 0.351562500000 +stimulating_water.tga 0.781250000000 0.312500000000 0.820312500000 0.351562500000 +ico_cataliseur_xp.tga 0.820312500000 0.312500000000 0.859375000000 0.351562500000 +ico_consommable_over.tga 0.859375000000 0.312500000000 0.898437500000 0.351562500000 +ico_fleur_carac_1.tga 0.898437500000 0.312500000000 0.937500000000 0.351562500000 +ico_fleur_carac_1_mask.tga 0.937500000000 0.312500000000 0.976562500000 0.351562500000 +ico_fleur_carac_2.tga 0.468750000000 0.351562500000 0.507812500000 0.390625000000 +ico_fleur_carac_2_mask.tga 0.507812500000 0.351562500000 0.546875000000 0.390625000000 +ico_fleur_carac_3.tga 0.546875000000 0.351562500000 0.585937500000 0.390625000000 +ico_fleur_carac_3_mask.tga 0.585937500000 0.351562500000 0.625000000000 0.390625000000 +ico_mission_art_fyros.tga 0.625000000000 0.351562500000 0.664062500000 0.390625000000 +ico_mission_art_matis.tga 0.664062500000 0.351562500000 0.703125000000 0.390625000000 +ico_mission_art_tryker.tga 0.703125000000 0.351562500000 0.742187500000 0.390625000000 +ico_mission_art_zorai.tga 0.742187500000 0.351562500000 0.781250000000 0.390625000000 +ico_mission_barrel.tga 0.781250000000 0.351562500000 0.820312500000 0.390625000000 +ico_mission_bottle.tga 0.820312500000 0.351562500000 0.859375000000 0.390625000000 +ico_mission_casket.tga 0.859375000000 0.351562500000 0.898437500000 0.390625000000 +ico_mission_medicine.tga 0.898437500000 0.351562500000 0.937500000000 0.390625000000 +ico_mission_message.tga 0.937500000000 0.351562500000 0.976562500000 0.390625000000 +ico_mission_package.tga 0.468750000000 0.390625000000 0.507812500000 0.429687500000 +ico_mission_pot.tga 0.507812500000 0.390625000000 0.546875000000 0.429687500000 +ico_mission_purse.tga 0.546875000000 0.390625000000 0.585937500000 0.429687500000 +ico_racine.tga 0.585937500000 0.390625000000 0.625000000000 0.429687500000 +ge_mission_outpost_townhall.tga 0.625000000000 0.390625000000 0.664062500000 0.429687500000 +ico_amande.tga 0.664062500000 0.390625000000 0.703125000000 0.429687500000 +to_searake.tga 0.703125000000 0.390625000000 0.742187500000 0.429687500000 +to_spade.tga 0.742187500000 0.390625000000 0.781250000000 0.429687500000 +to_stick.tga 0.781250000000 0.390625000000 0.820312500000 0.429687500000 +to_tunneling_knife.tga 0.820312500000 0.390625000000 0.859375000000 0.429687500000 +to_whip.tga 0.859375000000 0.390625000000 0.898437500000 0.429687500000 +to_wrench.tga 0.898437500000 0.390625000000 0.937500000000 0.429687500000 +TP_caravane.tga 0.937500000000 0.390625000000 0.976562500000 0.429687500000 +TP_kami.tga 0.468750000000 0.429687500000 0.507812500000 0.468750000000 +tetekitin.tga 0.507812500000 0.429687500000 0.546875000000 0.468750000000 +to_ammo.tga 0.546875000000 0.429687500000 0.585937500000 0.468750000000 +to_armor.tga 0.585937500000 0.429687500000 0.625000000000 0.468750000000 +to_cooking_pot.tga 0.625000000000 0.429687500000 0.664062500000 0.468750000000 +to_fishing_rod.tga 0.664062500000 0.429687500000 0.703125000000 0.468750000000 +to_forage.tga 0.703125000000 0.429687500000 0.742187500000 0.468750000000 +to_hammer.tga 0.742187500000 0.429687500000 0.781250000000 0.468750000000 +to_jewelry_hammer.tga 0.781250000000 0.429687500000 0.820312500000 0.468750000000 +to_jewels.tga 0.820312500000 0.429687500000 0.859375000000 0.468750000000 +to_leathercutter.tga 0.859375000000 0.429687500000 0.898437500000 0.468750000000 +to_melee.tga 0.898437500000 0.429687500000 0.937500000000 0.468750000000 +to_needle.tga 0.937500000000 0.429687500000 0.976562500000 0.468750000000 +to_pestle.tga 0.000000000000 0.468750000000 0.039062500000 0.507812500000 +ico_tourbe.tga 0.039062500000 0.468750000000 0.078125000000 0.507812500000 +improved_tool.tga 0.078125000000 0.468750000000 0.117187500000 0.507812500000 +item_default.tga 0.117187500000 0.468750000000 0.156250000000 0.507812500000 +item_plan_over.tga 0.156250000000 0.468750000000 0.195312500000 0.507812500000 +lucky_flower.tga 0.195312500000 0.468750000000 0.234375000000 0.507812500000 +W_AM_logo.tga 0.234375000000 0.468750000000 0.273437500000 0.507812500000 +w_pa_bracelet.tga 0.273437500000 0.468750000000 0.312500000000 0.507812500000 +w_pa_diadem.tga 0.312500000000 0.468750000000 0.351562500000 0.507812500000 +w_pa_earring.tga 0.351562500000 0.468750000000 0.390625000000 0.507812500000 +w_pa_pendant.tga 0.390625000000 0.468750000000 0.429687500000 0.507812500000 +w_pa_ring.tga 0.429687500000 0.468750000000 0.468750000000 0.507812500000 +xp_cat_green.tga 0.468750000000 0.468750000000 0.507812500000 0.507812500000 +PA_diadem.tga 0.507812500000 0.468750000000 0.546875000000 0.507812500000 +PA_earring.tga 0.546875000000 0.468750000000 0.585937500000 0.507812500000 +PA_pendant.tga 0.585937500000 0.468750000000 0.625000000000 0.507812500000 +PA_ring.tga 0.625000000000 0.468750000000 0.664062500000 0.507812500000 +protect_amber.tga 0.664062500000 0.468750000000 0.703125000000 0.507812500000 +pvp_aura.tga 0.703125000000 0.468750000000 0.742187500000 0.507812500000 asc_exit.tga 0.742187500000 0.468750000000 0.773437500000 0.500000000000 asc_rolemastercraft.tga 0.773437500000 0.468750000000 0.804687500000 0.500000000000 asc_rolemasterfight.tga 0.804687500000 0.468750000000 0.835937500000 0.500000000000 @@ -324,340 +324,350 @@ asc_rolemasterharvest.tga 0.835937500000 0.468750000000 0.867187500000 0.5000000 asc_rolemastermagic.tga 0.867187500000 0.468750000000 0.898437500000 0.500000000000 asc_unknown.tga 0.898437500000 0.468750000000 0.929687500000 0.500000000000 mail.tga 0.929687500000 0.468750000000 0.960937500000 0.492187500000 -mp_back_curative.tga 0.976562500000 0.078125000000 1.000000000000 0.101562500000 -mp_back_offensive.tga 0.976562500000 0.101562500000 1.000000000000 0.125000000000 -mp_back_selfonly.tga 0.976562500000 0.125000000000 1.000000000000 0.148437500000 -building_state_24x24.tga 0.976562500000 0.148437500000 1.000000000000 0.171875000000 -ico_ammo_bullet.tga 0.976562500000 0.171875000000 1.000000000000 0.195312500000 -ico_ammo_jacket.tga 0.976562500000 0.195312500000 1.000000000000 0.218750000000 -ico_angle.tga 0.976562500000 0.218750000000 1.000000000000 0.242187500000 -ico_anti_magic_shield.tga 0.976562500000 0.242187500000 1.000000000000 0.265625000000 -ico_armor.tga 0.976562500000 0.265625000000 1.000000000000 0.289062500000 -ico_armor_clip.tga 0.976562500000 0.289062500000 1.000000000000 0.312500000000 -ico_armor_heavy.tga 0.976562500000 0.312500000000 1.000000000000 0.335937500000 -ico_armor_kitin.tga 0.976562500000 0.335937500000 1.000000000000 0.359375000000 -ico_armor_light.tga 0.976562500000 0.359375000000 1.000000000000 0.382812500000 -ico_armor_medium.tga 0.976562500000 0.382812500000 1.000000000000 0.406250000000 -ico_armor_penalty.tga 0.976562500000 0.406250000000 1.000000000000 0.429687500000 -ico_armor_shell.tga 0.976562500000 0.429687500000 1.000000000000 0.453125000000 -ico_atys.tga 0.976562500000 0.453125000000 1.000000000000 0.476562500000 -ico_atysian.tga 0.960937500000 0.476562500000 0.984375000000 0.500000000000 -ico_balance_hp.tga 0.929687500000 0.492187500000 0.953125000000 0.515625000000 -ico_barrel.tga 0.742187500000 0.500000000000 0.765625000000 0.523437500000 -ico_bash.tga 0.765625000000 0.500000000000 0.789062500000 0.523437500000 -ico_berserk.tga 0.789062500000 0.500000000000 0.812500000000 0.523437500000 -ico_blade.tga 0.812500000000 0.500000000000 0.835937500000 0.523437500000 -ico_bleeding.tga 0.835937500000 0.500000000000 0.859375000000 0.523437500000 -ico_blind.tga 0.859375000000 0.500000000000 0.882812500000 0.523437500000 -ico_blunt.tga 0.882812500000 0.500000000000 0.906250000000 0.523437500000 -ico_bomb.tga 0.906250000000 0.500000000000 0.929687500000 0.523437500000 -cb_main_nue.tga 0.953125000000 0.500000000000 0.976562500000 0.523437500000 -ico_celestial.tga 0.976562500000 0.500000000000 1.000000000000 0.523437500000 -ico_circular_attack.tga 0.000000000000 0.507812500000 0.023437500000 0.531250000000 -ico_clothes.tga 0.023437500000 0.507812500000 0.046875000000 0.531250000000 -ico_cold.tga 0.046875000000 0.507812500000 0.070312500000 0.531250000000 -ico_concentration.tga 0.070312500000 0.507812500000 0.093750000000 0.531250000000 -BK_matis_brick.tga 0.093750000000 0.507812500000 0.117187500000 0.531250000000 -ico_constitution.tga 0.117187500000 0.507812500000 0.140625000000 0.531250000000 -ico_counterweight.tga 0.140625000000 0.507812500000 0.164062500000 0.531250000000 -ico_craft_buff.tga 0.164062500000 0.507812500000 0.187500000000 0.531250000000 -ico_create_sapload.tga 0.187500000000 0.507812500000 0.210937500000 0.531250000000 -ico_curse.tga 0.210937500000 0.507812500000 0.234375000000 0.531250000000 -ico_debuff.tga 0.234375000000 0.507812500000 0.257812500000 0.531250000000 -ico_debuff_resist.tga 0.257812500000 0.507812500000 0.281250000000 0.531250000000 -ico_debuff_skill.tga 0.281250000000 0.507812500000 0.304687500000 0.531250000000 -ico_desert.tga 0.304687500000 0.507812500000 0.328125000000 0.531250000000 -ico_dexterity.tga 0.328125000000 0.507812500000 0.351562500000 0.531250000000 -ico_disarm.tga 0.351562500000 0.507812500000 0.375000000000 0.531250000000 -ico_dodge.tga 0.375000000000 0.507812500000 0.398437500000 0.531250000000 -ico_dot.tga 0.398437500000 0.507812500000 0.421875000000 0.531250000000 -ico_durability.tga 0.421875000000 0.507812500000 0.445312500000 0.531250000000 -ico_electric.tga 0.445312500000 0.507812500000 0.468750000000 0.531250000000 -ico_explosif.tga 0.468750000000 0.507812500000 0.492187500000 0.531250000000 -ico_extracting.tga 0.492187500000 0.507812500000 0.515625000000 0.531250000000 -ico_fear.tga 0.515625000000 0.507812500000 0.539062500000 0.531250000000 -ico_feint.tga 0.539062500000 0.507812500000 0.562500000000 0.531250000000 -ico_fire.tga 0.562500000000 0.507812500000 0.585937500000 0.531250000000 -ico_firing_pin.tga 0.585937500000 0.507812500000 0.609375000000 0.531250000000 -ch_back.tga 0.609375000000 0.507812500000 0.632812500000 0.531250000000 -BK_generic_brick.tga 0.632812500000 0.507812500000 0.656250000000 0.531250000000 -mp_over_link.tga 0.656250000000 0.507812500000 0.679687500000 0.531250000000 -bk_aura.tga 0.679687500000 0.507812500000 0.703125000000 0.531250000000 -bk_conso.tga 0.703125000000 0.507812500000 0.726562500000 0.531250000000 -bk_outpost_brick.tga 0.929687500000 0.515625000000 0.953125000000 0.539062500000 -bk_power.tga 0.726562500000 0.523437500000 0.750000000000 0.546875000000 -ico_focus.tga 0.750000000000 0.523437500000 0.773437500000 0.546875000000 -ico_forage_buff.tga 0.773437500000 0.523437500000 0.796875000000 0.546875000000 -ico_forbid_item.tga 0.796875000000 0.523437500000 0.820312500000 0.546875000000 -ico_forest.tga 0.820312500000 0.523437500000 0.843750000000 0.546875000000 -2h_over.tga 0.843750000000 0.523437500000 0.867187500000 0.546875000000 -ico_gardening.tga 0.867187500000 0.523437500000 0.890625000000 0.546875000000 -ico_gentle.tga 0.890625000000 0.523437500000 0.914062500000 0.546875000000 -ico_goo.tga 0.953125000000 0.523437500000 0.976562500000 0.546875000000 -ico_gripp.tga 0.976562500000 0.523437500000 1.000000000000 0.546875000000 -1h_over.tga 0.000000000000 0.531250000000 0.023437500000 0.554687500000 -BK_fyros_brick.tga 0.023437500000 0.531250000000 0.046875000000 0.554687500000 -ico_hammer.tga 0.046875000000 0.531250000000 0.070312500000 0.554687500000 -ico_harmful.tga 0.070312500000 0.531250000000 0.093750000000 0.554687500000 -ico_hatred.tga 0.093750000000 0.531250000000 0.117187500000 0.554687500000 -ico_heal.tga 0.117187500000 0.531250000000 0.140625000000 0.554687500000 -ico_hit_rate.tga 0.140625000000 0.531250000000 0.164062500000 0.554687500000 -ico_incapacity.tga 0.164062500000 0.531250000000 0.187500000000 0.554687500000 -ico_intelligence.tga 0.187500000000 0.531250000000 0.210937500000 0.554687500000 -ico_interrupt.tga 0.210937500000 0.531250000000 0.234375000000 0.554687500000 -ico_invulnerability.tga 0.234375000000 0.531250000000 0.257812500000 0.554687500000 -ico_jewel_stone.tga 0.257812500000 0.531250000000 0.281250000000 0.554687500000 -ico_jewel_stone_support.tga 0.281250000000 0.531250000000 0.304687500000 0.554687500000 -ico_jungle.tga 0.304687500000 0.531250000000 0.328125000000 0.554687500000 -ico_lacustre.tga 0.328125000000 0.531250000000 0.351562500000 0.554687500000 -ico_landmark_bonus.tga 0.351562500000 0.531250000000 0.375000000000 0.554687500000 -ico_level.tga 0.375000000000 0.531250000000 0.398437500000 0.554687500000 -ico_lining.tga 0.398437500000 0.531250000000 0.421875000000 0.554687500000 -ico_location.tga 0.421875000000 0.531250000000 0.445312500000 0.554687500000 -ico_madness.tga 0.445312500000 0.531250000000 0.468750000000 0.554687500000 -ico_magic.tga 0.468750000000 0.531250000000 0.492187500000 0.554687500000 -ico_magic_action_buff.tga 0.492187500000 0.531250000000 0.515625000000 0.554687500000 -ico_magic_focus.tga 0.515625000000 0.531250000000 0.539062500000 0.554687500000 -ico_magic_target_buff.tga 0.539062500000 0.531250000000 0.562500000000 0.554687500000 -ico_melee_action_buff.tga 0.562500000000 0.531250000000 0.585937500000 0.554687500000 -ico_melee_target_buff.tga 0.585937500000 0.531250000000 0.609375000000 0.554687500000 -ico_mental.tga 0.609375000000 0.531250000000 0.632812500000 0.554687500000 -no_action.tga 0.632812500000 0.531250000000 0.656250000000 0.554687500000 -op_back.tga 0.656250000000 0.531250000000 0.679687500000 0.554687500000 -op_over_break.tga 0.679687500000 0.531250000000 0.703125000000 0.554687500000 -op_over_less.tga 0.703125000000 0.531250000000 0.726562500000 0.554687500000 -op_over_more.tga 0.914062500000 0.539062500000 0.937500000000 0.562500000000 -ico_metabolism.tga 0.726562500000 0.546875000000 0.750000000000 0.570312500000 -pa_back.tga 0.750000000000 0.546875000000 0.773437500000 0.570312500000 -ico_mezz.tga 0.773437500000 0.546875000000 0.796875000000 0.570312500000 -ico_misfortune.tga 0.796875000000 0.546875000000 0.820312500000 0.570312500000 -BK_magie_noire_brick.tga 0.820312500000 0.546875000000 0.843750000000 0.570312500000 -pa_over_break.tga 0.843750000000 0.546875000000 0.867187500000 0.570312500000 -pa_over_less.tga 0.867187500000 0.546875000000 0.890625000000 0.570312500000 -pa_over_more.tga 0.890625000000 0.546875000000 0.914062500000 0.570312500000 -BK_tryker_brick.tga 0.937500000000 0.546875000000 0.960937500000 0.570312500000 -cp_back.tga 0.960937500000 0.546875000000 0.984375000000 0.570312500000 -cp_over_break.tga 0.000000000000 0.554687500000 0.023437500000 0.578125000000 -pvp_ally_0.tga 0.023437500000 0.554687500000 0.046875000000 0.578125000000 -pvp_ally_1.tga 0.046875000000 0.554687500000 0.070312500000 0.578125000000 -pvp_ally_2.tga 0.070312500000 0.554687500000 0.093750000000 0.578125000000 -pvp_ally_3.tga 0.093750000000 0.554687500000 0.117187500000 0.578125000000 -pvp_ally_4.tga 0.117187500000 0.554687500000 0.140625000000 0.578125000000 -pvp_ally_6.tga 0.140625000000 0.554687500000 0.164062500000 0.578125000000 -pvp_ally_primas.tga 0.164062500000 0.554687500000 0.187500000000 0.578125000000 -pvp_ally_ranger.tga 0.187500000000 0.554687500000 0.210937500000 0.578125000000 -cp_over_less.tga 0.210937500000 0.554687500000 0.234375000000 0.578125000000 -cp_over_more.tga 0.234375000000 0.554687500000 0.257812500000 0.578125000000 -cp_over_opening.tga 0.257812500000 0.554687500000 0.281250000000 0.578125000000 -cp_over_opening_2.tga 0.281250000000 0.554687500000 0.304687500000 0.578125000000 -pvp_enemy_0.tga 0.304687500000 0.554687500000 0.328125000000 0.578125000000 -pvp_enemy_1.tga 0.328125000000 0.554687500000 0.351562500000 0.578125000000 -pvp_enemy_2.tga 0.351562500000 0.554687500000 0.375000000000 0.578125000000 -pvp_enemy_3.tga 0.375000000000 0.554687500000 0.398437500000 0.578125000000 -pvp_enemy_4.tga 0.398437500000 0.554687500000 0.421875000000 0.578125000000 -pvp_enemy_6.tga 0.421875000000 0.554687500000 0.445312500000 0.578125000000 -pvp_enemy_marauder.tga 0.445312500000 0.554687500000 0.468750000000 0.578125000000 -pvp_enemy_trytonist.tga 0.468750000000 0.554687500000 0.492187500000 0.578125000000 -bg_downloader.tga 0.492187500000 0.554687500000 0.515625000000 0.578125000000 -BK_zorai_brick.tga 0.515625000000 0.554687500000 0.539062500000 0.578125000000 -ef_back.tga 0.539062500000 0.554687500000 0.562500000000 0.578125000000 -ef_over_break.tga 0.562500000000 0.554687500000 0.585937500000 0.578125000000 -ico_move.tga 0.585937500000 0.554687500000 0.609375000000 0.578125000000 -ico_multiple_spots.tga 0.609375000000 0.554687500000 0.632812500000 0.578125000000 -ico_multi_fight.tga 0.632812500000 0.554687500000 0.656250000000 0.578125000000 -ef_over_less.tga 0.656250000000 0.554687500000 0.679687500000 0.578125000000 -ico_opening_hit.tga 0.679687500000 0.554687500000 0.703125000000 0.578125000000 -ico_over_autumn.tga 0.703125000000 0.554687500000 0.726562500000 0.578125000000 -ico_over_degenerated.tga 0.914062500000 0.562500000000 0.937500000000 0.585937500000 -ico_over_fauna.tga 0.726562500000 0.570312500000 0.750000000000 0.593750000000 -ico_over_flora.tga 0.750000000000 0.570312500000 0.773437500000 0.593750000000 -ico_over_hit_arms.tga 0.773437500000 0.570312500000 0.796875000000 0.593750000000 -ico_over_hit_chest.tga 0.796875000000 0.570312500000 0.820312500000 0.593750000000 -ico_over_hit_feet.tga 0.820312500000 0.570312500000 0.843750000000 0.593750000000 -ico_over_hit_feet_hands.tga 0.843750000000 0.570312500000 0.867187500000 0.593750000000 -ico_over_hit_feet_head.tga 0.867187500000 0.570312500000 0.890625000000 0.593750000000 -ico_over_hit_feet_x2.tga 0.890625000000 0.570312500000 0.914062500000 0.593750000000 -ico_over_hit_feint_x3.tga 0.937500000000 0.570312500000 0.960937500000 0.593750000000 -ico_over_hit_hands.tga 0.960937500000 0.570312500000 0.984375000000 0.593750000000 -ico_over_hit_hands_chest.tga 0.000000000000 0.578125000000 0.023437500000 0.601562500000 -ico_over_hit_hands_head.tga 0.023437500000 0.578125000000 0.046875000000 0.601562500000 -ico_over_hit_head.tga 0.046875000000 0.578125000000 0.070312500000 0.601562500000 -ico_over_hit_head_x3.tga 0.070312500000 0.578125000000 0.093750000000 0.601562500000 -ico_over_hit_legs.tga 0.093750000000 0.578125000000 0.117187500000 0.601562500000 -ico_over_homin.tga 0.117187500000 0.578125000000 0.140625000000 0.601562500000 -ico_over_kitin.tga 0.140625000000 0.578125000000 0.164062500000 0.601562500000 -ico_over_magic.tga 0.164062500000 0.578125000000 0.187500000000 0.601562500000 -ico_over_melee.tga 0.187500000000 0.578125000000 0.210937500000 0.601562500000 -ico_over_racial.tga 0.210937500000 0.578125000000 0.234375000000 0.601562500000 -ico_over_range.tga 0.234375000000 0.578125000000 0.257812500000 0.601562500000 -ico_over_special.tga 0.257812500000 0.578125000000 0.281250000000 0.601562500000 -ico_over_spring.tga 0.281250000000 0.578125000000 0.304687500000 0.601562500000 -ico_over_summer.tga 0.304687500000 0.578125000000 0.328125000000 0.601562500000 -ico_over_winter.tga 0.328125000000 0.578125000000 0.351562500000 0.601562500000 -ico_parry.tga 0.351562500000 0.578125000000 0.375000000000 0.601562500000 -ico_piercing.tga 0.375000000000 0.578125000000 0.398437500000 0.601562500000 -ico_pointe.tga 0.398437500000 0.578125000000 0.421875000000 0.601562500000 -ico_poison.tga 0.421875000000 0.578125000000 0.445312500000 0.601562500000 -ico_power.tga 0.445312500000 0.578125000000 0.468750000000 0.601562500000 -ico_preservation.tga 0.468750000000 0.578125000000 0.492187500000 0.601562500000 -ico_primal.tga 0.492187500000 0.578125000000 0.515625000000 0.601562500000 -ico_prime_roots.tga 0.515625000000 0.578125000000 0.539062500000 0.601562500000 -ico_private.tga 0.539062500000 0.578125000000 0.562500000000 0.601562500000 -ico_prospecting.tga 0.562500000000 0.578125000000 0.585937500000 0.601562500000 -ico_quality.tga 0.585937500000 0.578125000000 0.609375000000 0.601562500000 -ef_over_more.tga 0.609375000000 0.578125000000 0.632812500000 0.601562500000 -ico_range.tga 0.632812500000 0.578125000000 0.656250000000 0.601562500000 -ico_range_action_buff.tga 0.656250000000 0.578125000000 0.679687500000 0.601562500000 -ico_range_target_buff.tga 0.679687500000 0.578125000000 0.703125000000 0.601562500000 -ico_ricochet.tga 0.703125000000 0.578125000000 0.726562500000 0.601562500000 -ico_root.tga 0.914062500000 0.585937500000 0.937500000000 0.609375000000 -ico_rot.tga 0.726562500000 0.593750000000 0.750000000000 0.617187500000 -ico_safe.tga 0.750000000000 0.593750000000 0.773437500000 0.617187500000 -ico_sap.tga 0.773437500000 0.593750000000 0.796875000000 0.617187500000 -ico_self_damage.tga 0.796875000000 0.593750000000 0.820312500000 0.617187500000 -ico_shaft.tga 0.820312500000 0.593750000000 0.843750000000 0.617187500000 -ico_shielding.tga 0.843750000000 0.593750000000 0.867187500000 0.617187500000 -ico_shield_buff.tga 0.867187500000 0.593750000000 0.890625000000 0.617187500000 -ico_shield_up.tga 0.890625000000 0.593750000000 0.914062500000 0.617187500000 -ico_shockwave.tga 0.937500000000 0.593750000000 0.960937500000 0.617187500000 -ico_sickness.tga 0.960937500000 0.593750000000 0.984375000000 0.617187500000 -ico_slashing.tga 0.000000000000 0.601562500000 0.023437500000 0.625000000000 -ico_slow.tga 0.023437500000 0.601562500000 0.046875000000 0.625000000000 -ico_soft_spot.tga 0.046875000000 0.601562500000 0.070312500000 0.625000000000 -ico_source_time.tga 0.070312500000 0.601562500000 0.093750000000 0.625000000000 -ico_speed.tga 0.093750000000 0.601562500000 0.117187500000 0.625000000000 -ico_speeding_up.tga 0.117187500000 0.601562500000 0.140625000000 0.625000000000 -ico_spell_break.tga 0.140625000000 0.601562500000 0.164062500000 0.625000000000 -fo_back.tga 0.164062500000 0.601562500000 0.187500000000 0.625000000000 -ico_spray.tga 0.187500000000 0.601562500000 0.210937500000 0.625000000000 -ico_spying.tga 0.210937500000 0.601562500000 0.234375000000 0.625000000000 -ico_stamina.tga 0.234375000000 0.601562500000 0.257812500000 0.625000000000 -ico_strength.tga 0.257812500000 0.601562500000 0.281250000000 0.625000000000 -ico_stuffing.tga 0.281250000000 0.601562500000 0.304687500000 0.625000000000 -ico_stunn.tga 0.304687500000 0.601562500000 0.328125000000 0.625000000000 -fo_over.tga 0.328125000000 0.601562500000 0.351562500000 0.625000000000 -fp_ammo.tga 0.351562500000 0.601562500000 0.375000000000 0.625000000000 -fp_armor.tga 0.375000000000 0.601562500000 0.398437500000 0.625000000000 -fp_building.tga 0.398437500000 0.601562500000 0.421875000000 0.625000000000 -fp_jewel.tga 0.421875000000 0.601562500000 0.445312500000 0.625000000000 -fp_melee.tga 0.445312500000 0.601562500000 0.468750000000 0.625000000000 -fp_over.tga 0.468750000000 0.601562500000 0.492187500000 0.625000000000 -fp_range.tga 0.492187500000 0.601562500000 0.515625000000 0.625000000000 -fp_shield.tga 0.515625000000 0.601562500000 0.539062500000 0.625000000000 -fp_tools.tga 0.539062500000 0.601562500000 0.562500000000 0.625000000000 -brick_default.tga 0.562500000000 0.601562500000 0.585937500000 0.625000000000 -ico_taunt.tga 0.585937500000 0.601562500000 0.609375000000 0.625000000000 -tb_action_attack.tga 0.609375000000 0.601562500000 0.632812500000 0.625000000000 -tb_action_config.tga 0.632812500000 0.601562500000 0.656250000000 0.625000000000 -tb_action_disband.tga 0.656250000000 0.601562500000 0.679687500000 0.625000000000 -tb_action_disengage.tga 0.679687500000 0.601562500000 0.703125000000 0.625000000000 -tb_action_extract.tga 0.703125000000 0.601562500000 0.726562500000 0.625000000000 -tb_action_invite.tga 0.914062500000 0.609375000000 0.937500000000 0.632812500000 -tb_action_kick.tga 0.726562500000 0.617187500000 0.750000000000 0.640625000000 -tb_action_move.tga 0.750000000000 0.617187500000 0.773437500000 0.640625000000 -tb_action_run.tga 0.773437500000 0.617187500000 0.796875000000 0.640625000000 -tb_action_sit.tga 0.796875000000 0.617187500000 0.820312500000 0.640625000000 -tb_action_stand.tga 0.820312500000 0.617187500000 0.843750000000 0.640625000000 -tb_action_stop.tga 0.843750000000 0.617187500000 0.867187500000 0.640625000000 -tb_action_talk.tga 0.867187500000 0.617187500000 0.890625000000 0.640625000000 -tb_action_walk.tga 0.890625000000 0.617187500000 0.914062500000 0.640625000000 -tb_animals.tga 0.937500000000 0.617187500000 0.960937500000 0.640625000000 -tb_config.tga 0.960937500000 0.617187500000 0.984375000000 0.640625000000 -tb_connection.tga 0.000000000000 0.625000000000 0.023437500000 0.648437500000 -tb_contacts.tga 0.023437500000 0.625000000000 0.046875000000 0.648437500000 -tb_desk_1.tga 0.046875000000 0.625000000000 0.070312500000 0.648437500000 -tb_desk_2.tga 0.070312500000 0.625000000000 0.093750000000 0.648437500000 -tb_desk_3.tga 0.093750000000 0.625000000000 0.117187500000 0.648437500000 -tb_desk_4.tga 0.117187500000 0.625000000000 0.140625000000 0.648437500000 -tb_faction.tga 0.140625000000 0.625000000000 0.164062500000 0.648437500000 -tb_forum.tga 0.164062500000 0.625000000000 0.187500000000 0.648437500000 -tb_guild.tga 0.187500000000 0.625000000000 0.210937500000 0.648437500000 -TB_help2.tga 0.210937500000 0.625000000000 0.234375000000 0.648437500000 -tb_keys.tga 0.234375000000 0.625000000000 0.257812500000 0.648437500000 -tb_macros.tga 0.257812500000 0.625000000000 0.281250000000 0.648437500000 -tb_mail.tga 0.281250000000 0.625000000000 0.304687500000 0.648437500000 -tb_mode_dodge.tga 0.304687500000 0.625000000000 0.328125000000 0.648437500000 -tb_mode_parry.tga 0.328125000000 0.625000000000 0.351562500000 0.648437500000 -tb_over.tga 0.351562500000 0.625000000000 0.375000000000 0.648437500000 -tb_support.tga 0.375000000000 0.625000000000 0.398437500000 0.648437500000 -tb_team.tga 0.398437500000 0.625000000000 0.421875000000 0.648437500000 -tb_windows.tga 0.421875000000 0.625000000000 0.445312500000 0.648437500000 -ico_time.tga 0.445312500000 0.625000000000 0.468750000000 0.648437500000 -ico_time_bonus.tga 0.468750000000 0.625000000000 0.492187500000 0.648437500000 -ico_absorb_damage.tga 0.492187500000 0.625000000000 0.515625000000 0.648437500000 -ico_trigger.tga 0.515625000000 0.625000000000 0.539062500000 0.648437500000 -ico_umbrella.tga 0.539062500000 0.625000000000 0.562500000000 0.648437500000 -ico_use_enchantement.tga 0.562500000000 0.625000000000 0.585937500000 0.648437500000 -ico_vampire.tga 0.585937500000 0.625000000000 0.609375000000 0.648437500000 -ico_visibility.tga 0.609375000000 0.625000000000 0.632812500000 0.648437500000 -ico_war_cry.tga 0.632812500000 0.625000000000 0.656250000000 0.648437500000 -ico_weight.tga 0.656250000000 0.625000000000 0.679687500000 0.648437500000 -ico_wellbalanced.tga 0.679687500000 0.625000000000 0.703125000000 0.648437500000 -ico_will.tga 0.703125000000 0.625000000000 0.726562500000 0.648437500000 -ico_windding.tga 0.914062500000 0.632812500000 0.937500000000 0.656250000000 -ico_wisdom.tga 0.726562500000 0.640625000000 0.750000000000 0.664062500000 -ico_accurate.tga 0.750000000000 0.640625000000 0.773437500000 0.664062500000 -ico_acid.tga 0.773437500000 0.640625000000 0.796875000000 0.664062500000 -ico_aim.tga 0.796875000000 0.640625000000 0.820312500000 0.664062500000 -ico_aim_bird_wings.tga 0.820312500000 0.640625000000 0.843750000000 0.664062500000 -ico_aim_flying_kitin_abdomen.tga 0.843750000000 0.640625000000 0.867187500000 0.664062500000 -ico_aim_homin_arms.tga 0.867187500000 0.640625000000 0.890625000000 0.664062500000 -ico_aim_homin_chest.tga 0.890625000000 0.640625000000 0.914062500000 0.664062500000 -mf_back.tga 0.937500000000 0.640625000000 0.960937500000 0.664062500000 -us_back_0.tga 0.960937500000 0.640625000000 0.984375000000 0.664062500000 -us_back_1.tga 0.000000000000 0.648437500000 0.023437500000 0.671875000000 -us_back_2.tga 0.023437500000 0.648437500000 0.046875000000 0.671875000000 -us_back_3.tga 0.046875000000 0.648437500000 0.070312500000 0.671875000000 -us_back_4.tga 0.070312500000 0.648437500000 0.093750000000 0.671875000000 -us_back_5.tga 0.093750000000 0.648437500000 0.117187500000 0.671875000000 -us_back_6.tga 0.117187500000 0.648437500000 0.140625000000 0.671875000000 -us_back_7.tga 0.140625000000 0.648437500000 0.164062500000 0.671875000000 -us_back_8.tga 0.164062500000 0.648437500000 0.187500000000 0.671875000000 -us_back_9.tga 0.187500000000 0.648437500000 0.210937500000 0.671875000000 -us_ico_0.tga 0.210937500000 0.648437500000 0.234375000000 0.671875000000 -us_ico_1.tga 0.234375000000 0.648437500000 0.257812500000 0.671875000000 -us_ico_2.tga 0.257812500000 0.648437500000 0.281250000000 0.671875000000 -us_ico_3.tga 0.281250000000 0.648437500000 0.304687500000 0.671875000000 -us_ico_4.tga 0.304687500000 0.648437500000 0.328125000000 0.671875000000 -us_ico_5.tga 0.328125000000 0.648437500000 0.351562500000 0.671875000000 -us_ico_6.tga 0.351562500000 0.648437500000 0.375000000000 0.671875000000 -us_ico_7.tga 0.375000000000 0.648437500000 0.398437500000 0.671875000000 -us_ico_8.tga 0.398437500000 0.648437500000 0.421875000000 0.671875000000 -us_ico_9.tga 0.421875000000 0.648437500000 0.445312500000 0.671875000000 -us_over_0.tga 0.445312500000 0.648437500000 0.468750000000 0.671875000000 -us_over_1.tga 0.468750000000 0.648437500000 0.492187500000 0.671875000000 -us_over_2.tga 0.492187500000 0.648437500000 0.515625000000 0.671875000000 -us_over_3.tga 0.515625000000 0.648437500000 0.539062500000 0.671875000000 -us_over_4.tga 0.539062500000 0.648437500000 0.562500000000 0.671875000000 -mf_over.tga 0.562500000000 0.648437500000 0.585937500000 0.671875000000 -ico_aim_homin_feet.tga 0.585937500000 0.648437500000 0.609375000000 0.671875000000 -ico_aim_homin_feint.tga 0.609375000000 0.648437500000 0.632812500000 0.671875000000 -ico_aim_homin_hands.tga 0.632812500000 0.648437500000 0.656250000000 0.671875000000 -ico_aim_homin_head.tga 0.656250000000 0.648437500000 0.679687500000 0.671875000000 -ico_aim_homin_legs.tga 0.679687500000 0.648437500000 0.703125000000 0.671875000000 -mp3.tga 0.703125000000 0.648437500000 0.726562500000 0.671875000000 -W_slot_shortcut_id0.tga 0.914062500000 0.656250000000 0.937500000000 0.679687500000 -W_slot_shortcut_id1.tga 0.726562500000 0.664062500000 0.750000000000 0.687500000000 -W_slot_shortcut_id2.tga 0.750000000000 0.664062500000 0.773437500000 0.687500000000 -W_slot_shortcut_id3.tga 0.773437500000 0.664062500000 0.796875000000 0.687500000000 -W_slot_shortcut_id4.tga 0.796875000000 0.664062500000 0.820312500000 0.687500000000 -W_slot_shortcut_id5.tga 0.820312500000 0.664062500000 0.843750000000 0.687500000000 -W_slot_shortcut_id6.tga 0.843750000000 0.664062500000 0.867187500000 0.687500000000 -W_slot_shortcut_id7.tga 0.867187500000 0.664062500000 0.890625000000 0.687500000000 -W_slot_shortcut_id8.tga 0.890625000000 0.664062500000 0.914062500000 0.687500000000 -W_slot_shortcut_id9.tga 0.937500000000 0.664062500000 0.960937500000 0.687500000000 -w_slot_shortcut_shift_id0.tga 0.960937500000 0.664062500000 0.984375000000 0.687500000000 -w_slot_shortcut_shift_id1.tga 0.000000000000 0.671875000000 0.023437500000 0.695312500000 -w_slot_shortcut_shift_id2.tga 0.023437500000 0.671875000000 0.046875000000 0.695312500000 -w_slot_shortcut_shift_id3.tga 0.046875000000 0.671875000000 0.070312500000 0.695312500000 -w_slot_shortcut_shift_id4.tga 0.070312500000 0.671875000000 0.093750000000 0.695312500000 -w_slot_shortcut_shift_id5.tga 0.093750000000 0.671875000000 0.117187500000 0.695312500000 -w_slot_shortcut_shift_id6.tga 0.117187500000 0.671875000000 0.140625000000 0.695312500000 -w_slot_shortcut_shift_id7.tga 0.140625000000 0.671875000000 0.164062500000 0.695312500000 -w_slot_shortcut_shift_id8.tga 0.164062500000 0.671875000000 0.187500000000 0.695312500000 -w_slot_shortcut_shift_id9.tga 0.187500000000 0.671875000000 0.210937500000 0.695312500000 -ico_aim_kitin_head.tga 0.210937500000 0.671875000000 0.234375000000 0.695312500000 -ico_source_knowledge.tga 0.234375000000 0.671875000000 0.255859375000 0.695312500000 +ico_taunt.tga 0.976562500000 0.078125000000 1.000000000000 0.101562500000 +BK_generic_brick.tga 0.976562500000 0.101562500000 1.000000000000 0.125000000000 +bk_aura.tga 0.976562500000 0.125000000000 1.000000000000 0.148437500000 +bk_outpost_brick.tga 0.976562500000 0.148437500000 1.000000000000 0.171875000000 +bk_power.tga 0.976562500000 0.171875000000 1.000000000000 0.195312500000 +no_action.tga 0.976562500000 0.195312500000 1.000000000000 0.218750000000 +no_pvp.tga 0.976562500000 0.218750000000 1.000000000000 0.242187500000 +op_back.tga 0.976562500000 0.242187500000 1.000000000000 0.265625000000 +op_over_break.tga 0.976562500000 0.265625000000 1.000000000000 0.289062500000 +op_over_less.tga 0.976562500000 0.289062500000 1.000000000000 0.312500000000 +op_over_more.tga 0.976562500000 0.312500000000 1.000000000000 0.335937500000 +bk_conso.tga 0.976562500000 0.335937500000 1.000000000000 0.359375000000 +pa_back.tga 0.976562500000 0.359375000000 1.000000000000 0.382812500000 +2h_over.tga 0.976562500000 0.382812500000 1.000000000000 0.406250000000 +1h_over.tga 0.976562500000 0.406250000000 1.000000000000 0.429687500000 +pvp_duel.tga 0.976562500000 0.429687500000 1.000000000000 0.453125000000 +pvp_enemy_0.tga 0.976562500000 0.453125000000 1.000000000000 0.476562500000 +pvp_enemy_1.tga 0.960937500000 0.476562500000 0.984375000000 0.500000000000 +pvp_enemy_2.tga 0.929687500000 0.492187500000 0.953125000000 0.515625000000 +pvp_enemy_3.tga 0.742187500000 0.500000000000 0.765625000000 0.523437500000 +pvp_enemy_4.tga 0.765625000000 0.500000000000 0.789062500000 0.523437500000 +pvp_enemy_6.tga 0.789062500000 0.500000000000 0.812500000000 0.523437500000 +pvp_enemy_flag.tga 0.812500000000 0.500000000000 0.835937500000 0.523437500000 +pvp_enemy_marauder.tga 0.835937500000 0.500000000000 0.859375000000 0.523437500000 +pvp_enemy_tag.tga 0.859375000000 0.500000000000 0.882812500000 0.523437500000 +tb_action_attack.tga 0.882812500000 0.500000000000 0.906250000000 0.523437500000 +tb_action_config.tga 0.906250000000 0.500000000000 0.929687500000 0.523437500000 +tb_action_disband.tga 0.953125000000 0.500000000000 0.976562500000 0.523437500000 +tb_action_disengage.tga 0.976562500000 0.500000000000 1.000000000000 0.523437500000 +tb_action_extract.tga 0.000000000000 0.507812500000 0.023437500000 0.531250000000 +tb_action_invite.tga 0.023437500000 0.507812500000 0.046875000000 0.531250000000 +tb_action_kick.tga 0.046875000000 0.507812500000 0.070312500000 0.531250000000 +tb_action_move.tga 0.070312500000 0.507812500000 0.093750000000 0.531250000000 +tb_action_run.tga 0.093750000000 0.507812500000 0.117187500000 0.531250000000 +tb_action_sit.tga 0.117187500000 0.507812500000 0.140625000000 0.531250000000 +tb_action_stand.tga 0.140625000000 0.507812500000 0.164062500000 0.531250000000 +tb_action_stop.tga 0.164062500000 0.507812500000 0.187500000000 0.531250000000 +tb_action_talk.tga 0.187500000000 0.507812500000 0.210937500000 0.531250000000 +tb_action_walk.tga 0.210937500000 0.507812500000 0.234375000000 0.531250000000 +ico_armor_penalty.tga 0.234375000000 0.507812500000 0.257812500000 0.531250000000 +ico_armor_shell.tga 0.257812500000 0.507812500000 0.281250000000 0.531250000000 +ico_atys.tga 0.281250000000 0.507812500000 0.304687500000 0.531250000000 +ico_atysian.tga 0.304687500000 0.507812500000 0.328125000000 0.531250000000 +ico_balance_hp.tga 0.328125000000 0.507812500000 0.351562500000 0.531250000000 +ico_barrel.tga 0.351562500000 0.507812500000 0.375000000000 0.531250000000 +ico_bash.tga 0.375000000000 0.507812500000 0.398437500000 0.531250000000 +ico_berserk.tga 0.398437500000 0.507812500000 0.421875000000 0.531250000000 +ico_blade.tga 0.421875000000 0.507812500000 0.445312500000 0.531250000000 +ico_bleeding.tga 0.445312500000 0.507812500000 0.468750000000 0.531250000000 +ico_blind.tga 0.468750000000 0.507812500000 0.492187500000 0.531250000000 +ico_blunt.tga 0.492187500000 0.507812500000 0.515625000000 0.531250000000 +ico_bomb.tga 0.515625000000 0.507812500000 0.539062500000 0.531250000000 +pvp_enemy_trytonist.tga 0.539062500000 0.507812500000 0.562500000000 0.531250000000 +ico_celestial.tga 0.562500000000 0.507812500000 0.585937500000 0.531250000000 +ico_circular_attack.tga 0.585937500000 0.507812500000 0.609375000000 0.531250000000 +ico_cold.tga 0.609375000000 0.507812500000 0.632812500000 0.531250000000 +ico_concentration.tga 0.632812500000 0.507812500000 0.656250000000 0.531250000000 +pvp_flag.tga 0.656250000000 0.507812500000 0.679687500000 0.531250000000 +ico_constitution.tga 0.679687500000 0.507812500000 0.703125000000 0.531250000000 +ico_counterweight.tga 0.703125000000 0.507812500000 0.726562500000 0.531250000000 +ico_craft_buff.tga 0.929687500000 0.515625000000 0.953125000000 0.539062500000 +ico_create_sapload.tga 0.726562500000 0.523437500000 0.750000000000 0.546875000000 +ico_curse.tga 0.750000000000 0.523437500000 0.773437500000 0.546875000000 +ico_debuff.tga 0.773437500000 0.523437500000 0.796875000000 0.546875000000 +ico_debuff_resist.tga 0.796875000000 0.523437500000 0.820312500000 0.546875000000 +ico_debuff_skill.tga 0.820312500000 0.523437500000 0.843750000000 0.546875000000 +ico_desert.tga 0.843750000000 0.523437500000 0.867187500000 0.546875000000 +ico_dexterity.tga 0.867187500000 0.523437500000 0.890625000000 0.546875000000 +ico_disarm.tga 0.890625000000 0.523437500000 0.914062500000 0.546875000000 +ico_dodge.tga 0.953125000000 0.523437500000 0.976562500000 0.546875000000 +ico_dot.tga 0.976562500000 0.523437500000 1.000000000000 0.546875000000 +ico_electric.tga 0.000000000000 0.531250000000 0.023437500000 0.554687500000 +ico_explosif.tga 0.023437500000 0.531250000000 0.046875000000 0.554687500000 +ico_extracting.tga 0.046875000000 0.531250000000 0.070312500000 0.554687500000 +ico_fear.tga 0.070312500000 0.531250000000 0.093750000000 0.554687500000 +ico_feint.tga 0.093750000000 0.531250000000 0.117187500000 0.554687500000 +ico_fire.tga 0.117187500000 0.531250000000 0.140625000000 0.554687500000 +ico_firing_pin.tga 0.140625000000 0.531250000000 0.164062500000 0.554687500000 +pvp_neutral.tga 0.164062500000 0.531250000000 0.187500000000 0.554687500000 +pvp_tag.tga 0.187500000000 0.531250000000 0.210937500000 0.554687500000 +BK_magie_noire_brick.tga 0.210937500000 0.531250000000 0.234375000000 0.554687500000 +cp_back.tga 0.234375000000 0.531250000000 0.257812500000 0.554687500000 +cp_over_break.tga 0.257812500000 0.531250000000 0.281250000000 0.554687500000 +cp_over_less.tga 0.281250000000 0.531250000000 0.304687500000 0.554687500000 +ico_focus.tga 0.304687500000 0.531250000000 0.328125000000 0.554687500000 +ico_forage_buff.tga 0.328125000000 0.531250000000 0.351562500000 0.554687500000 +ico_forbid_item.tga 0.351562500000 0.531250000000 0.375000000000 0.554687500000 +ico_forest.tga 0.375000000000 0.531250000000 0.398437500000 0.554687500000 +ico_jungle.tga 0.398437500000 0.531250000000 0.421875000000 0.554687500000 +ico_lacustre.tga 0.421875000000 0.531250000000 0.445312500000 0.554687500000 +ico_landmark_bonus.tga 0.445312500000 0.531250000000 0.468750000000 0.554687500000 +ico_level.tga 0.468750000000 0.531250000000 0.492187500000 0.554687500000 +ico_lining.tga 0.492187500000 0.531250000000 0.515625000000 0.554687500000 +ico_location.tga 0.515625000000 0.531250000000 0.539062500000 0.554687500000 +ico_madness.tga 0.539062500000 0.531250000000 0.562500000000 0.554687500000 +ico_magic.tga 0.562500000000 0.531250000000 0.585937500000 0.554687500000 +ico_magic_action_buff.tga 0.585937500000 0.531250000000 0.609375000000 0.554687500000 +ico_magic_focus.tga 0.609375000000 0.531250000000 0.632812500000 0.554687500000 +ico_magic_target_buff.tga 0.632812500000 0.531250000000 0.656250000000 0.554687500000 +ico_melee_action_buff.tga 0.656250000000 0.531250000000 0.679687500000 0.554687500000 +ico_melee_target_buff.tga 0.679687500000 0.531250000000 0.703125000000 0.554687500000 +ico_mental.tga 0.703125000000 0.531250000000 0.726562500000 0.554687500000 +ico_metabolism.tga 0.914062500000 0.539062500000 0.937500000000 0.562500000000 +ico_mezz.tga 0.726562500000 0.546875000000 0.750000000000 0.570312500000 +cp_over_more.tga 0.750000000000 0.546875000000 0.773437500000 0.570312500000 +cp_over_opening.tga 0.773437500000 0.546875000000 0.796875000000 0.570312500000 +tb_animals.tga 0.796875000000 0.546875000000 0.820312500000 0.570312500000 +cp_over_opening_2.tga 0.820312500000 0.546875000000 0.843750000000 0.570312500000 +us_back_9.tga 0.843750000000 0.546875000000 0.867187500000 0.570312500000 +BK_tryker_brick.tga 0.867187500000 0.546875000000 0.890625000000 0.570312500000 +ico_spray.tga 0.890625000000 0.546875000000 0.914062500000 0.570312500000 +ico_spying.tga 0.937500000000 0.546875000000 0.960937500000 0.570312500000 +ico_stamina.tga 0.960937500000 0.546875000000 0.984375000000 0.570312500000 +ico_strength.tga 0.000000000000 0.554687500000 0.023437500000 0.578125000000 +ico_stuffing.tga 0.023437500000 0.554687500000 0.046875000000 0.578125000000 +ico_stunn.tga 0.046875000000 0.554687500000 0.070312500000 0.578125000000 +ico_move.tga 0.070312500000 0.554687500000 0.093750000000 0.578125000000 +ico_multiple_spots.tga 0.093750000000 0.554687500000 0.117187500000 0.578125000000 +ico_multi_fight.tga 0.117187500000 0.554687500000 0.140625000000 0.578125000000 +ico_opening_hit.tga 0.140625000000 0.554687500000 0.164062500000 0.578125000000 +ico_over_autumn.tga 0.164062500000 0.554687500000 0.187500000000 0.578125000000 +ico_over_degenerated.tga 0.187500000000 0.554687500000 0.210937500000 0.578125000000 +ico_over_fauna.tga 0.210937500000 0.554687500000 0.234375000000 0.578125000000 +ico_over_flora.tga 0.234375000000 0.554687500000 0.257812500000 0.578125000000 +ico_over_hit_arms.tga 0.257812500000 0.554687500000 0.281250000000 0.578125000000 +ico_over_hit_chest.tga 0.281250000000 0.554687500000 0.304687500000 0.578125000000 +ico_over_hit_feet.tga 0.304687500000 0.554687500000 0.328125000000 0.578125000000 +ico_over_hit_feet_hands.tga 0.328125000000 0.554687500000 0.351562500000 0.578125000000 +ico_over_hit_feet_head.tga 0.351562500000 0.554687500000 0.375000000000 0.578125000000 +ico_over_hit_feet_x2.tga 0.375000000000 0.554687500000 0.398437500000 0.578125000000 +ico_over_hit_feint_x3.tga 0.398437500000 0.554687500000 0.421875000000 0.578125000000 +ico_over_hit_hands.tga 0.421875000000 0.554687500000 0.445312500000 0.578125000000 +ico_over_hit_hands_chest.tga 0.445312500000 0.554687500000 0.468750000000 0.578125000000 +ico_over_hit_hands_head.tga 0.468750000000 0.554687500000 0.492187500000 0.578125000000 +ico_over_hit_head.tga 0.492187500000 0.554687500000 0.515625000000 0.578125000000 +ico_over_hit_legs.tga 0.515625000000 0.554687500000 0.539062500000 0.578125000000 +ico_over_homin.tga 0.539062500000 0.554687500000 0.562500000000 0.578125000000 +ico_over_kitin.tga 0.562500000000 0.554687500000 0.585937500000 0.578125000000 +ico_over_magic.tga 0.585937500000 0.554687500000 0.609375000000 0.578125000000 +ico_over_melee.tga 0.609375000000 0.554687500000 0.632812500000 0.578125000000 +ico_over_racial.tga 0.632812500000 0.554687500000 0.656250000000 0.578125000000 +ico_over_range.tga 0.656250000000 0.554687500000 0.679687500000 0.578125000000 +ico_over_special.tga 0.679687500000 0.554687500000 0.703125000000 0.578125000000 +ico_over_spring.tga 0.703125000000 0.554687500000 0.726562500000 0.578125000000 +ico_over_summer.tga 0.914062500000 0.562500000000 0.937500000000 0.585937500000 +ico_over_winter.tga 0.726562500000 0.570312500000 0.750000000000 0.593750000000 +ico_parry.tga 0.750000000000 0.570312500000 0.773437500000 0.593750000000 +ico_piercing.tga 0.773437500000 0.570312500000 0.796875000000 0.593750000000 +ico_pointe.tga 0.796875000000 0.570312500000 0.820312500000 0.593750000000 +ico_poison.tga 0.820312500000 0.570312500000 0.843750000000 0.593750000000 +ico_power.tga 0.843750000000 0.570312500000 0.867187500000 0.593750000000 +ico_preservation.tga 0.867187500000 0.570312500000 0.890625000000 0.593750000000 +ico_prime_roots.tga 0.890625000000 0.570312500000 0.914062500000 0.593750000000 +ico_private.tga 0.937500000000 0.570312500000 0.960937500000 0.593750000000 +ico_prospecting.tga 0.960937500000 0.570312500000 0.984375000000 0.593750000000 +ico_quality.tga 0.000000000000 0.578125000000 0.023437500000 0.601562500000 +BK_fyros_brick.tga 0.023437500000 0.578125000000 0.046875000000 0.601562500000 +ico_range.tga 0.046875000000 0.578125000000 0.070312500000 0.601562500000 +ico_range_action_buff.tga 0.070312500000 0.578125000000 0.093750000000 0.601562500000 +ico_range_target_buff.tga 0.093750000000 0.578125000000 0.117187500000 0.601562500000 +ico_ricochet.tga 0.117187500000 0.578125000000 0.140625000000 0.601562500000 +ico_root.tga 0.140625000000 0.578125000000 0.164062500000 0.601562500000 +ico_rot.tga 0.164062500000 0.578125000000 0.187500000000 0.601562500000 +ico_safe.tga 0.187500000000 0.578125000000 0.210937500000 0.601562500000 +ico_sap.tga 0.210937500000 0.578125000000 0.234375000000 0.601562500000 +ico_self_damage.tga 0.234375000000 0.578125000000 0.257812500000 0.601562500000 +ico_shaft.tga 0.257812500000 0.578125000000 0.281250000000 0.601562500000 +ico_shielding.tga 0.281250000000 0.578125000000 0.304687500000 0.601562500000 +ico_shield_buff.tga 0.304687500000 0.578125000000 0.328125000000 0.601562500000 +ico_shield_up.tga 0.328125000000 0.578125000000 0.351562500000 0.601562500000 +ico_shockwave.tga 0.351562500000 0.578125000000 0.375000000000 0.601562500000 +ico_sickness.tga 0.375000000000 0.578125000000 0.398437500000 0.601562500000 +ico_slashing.tga 0.398437500000 0.578125000000 0.421875000000 0.601562500000 +ico_slow.tga 0.421875000000 0.578125000000 0.445312500000 0.601562500000 +ico_soft_spot.tga 0.445312500000 0.578125000000 0.468750000000 0.601562500000 +ico_source_time.tga 0.468750000000 0.578125000000 0.492187500000 0.601562500000 +ico_speed.tga 0.492187500000 0.578125000000 0.515625000000 0.601562500000 +ico_speeding_up.tga 0.515625000000 0.578125000000 0.539062500000 0.601562500000 +ico_spell_break.tga 0.539062500000 0.578125000000 0.562500000000 0.601562500000 +fp_armor.tga 0.562500000000 0.578125000000 0.585937500000 0.601562500000 +fp_building.tga 0.585937500000 0.578125000000 0.609375000000 0.601562500000 +fp_jewel.tga 0.609375000000 0.578125000000 0.632812500000 0.601562500000 +fp_melee.tga 0.632812500000 0.578125000000 0.656250000000 0.601562500000 +fp_over.tga 0.656250000000 0.578125000000 0.679687500000 0.601562500000 +fp_range.tga 0.679687500000 0.578125000000 0.703125000000 0.601562500000 +fp_shield.tga 0.703125000000 0.578125000000 0.726562500000 0.601562500000 +fp_tools.tga 0.914062500000 0.585937500000 0.937500000000 0.609375000000 +ef_back.tga 0.726562500000 0.593750000000 0.750000000000 0.617187500000 +ico_absorb_damage.tga 0.750000000000 0.593750000000 0.773437500000 0.617187500000 +ico_accurate.tga 0.773437500000 0.593750000000 0.796875000000 0.617187500000 +ico_acid.tga 0.796875000000 0.593750000000 0.820312500000 0.617187500000 +ico_aim.tga 0.820312500000 0.593750000000 0.843750000000 0.617187500000 +ico_aim_bird_wings.tga 0.843750000000 0.593750000000 0.867187500000 0.617187500000 +ico_aim_flying_kitin_abdomen.tga 0.867187500000 0.593750000000 0.890625000000 0.617187500000 +ico_aim_homin_arms.tga 0.890625000000 0.593750000000 0.914062500000 0.617187500000 +ico_aim_homin_chest.tga 0.937500000000 0.593750000000 0.960937500000 0.617187500000 +ico_aim_homin_feet.tga 0.960937500000 0.593750000000 0.984375000000 0.617187500000 +ico_aim_homin_feint.tga 0.000000000000 0.601562500000 0.023437500000 0.625000000000 +ico_aim_homin_hands.tga 0.023437500000 0.601562500000 0.046875000000 0.625000000000 +ico_aim_homin_head.tga 0.046875000000 0.601562500000 0.070312500000 0.625000000000 +ico_aim_homin_legs.tga 0.070312500000 0.601562500000 0.093750000000 0.625000000000 +ico_aim_kitin_head.tga 0.093750000000 0.601562500000 0.117187500000 0.625000000000 +ef_over_break.tga 0.117187500000 0.601562500000 0.140625000000 0.625000000000 +ico_ammo_bullet.tga 0.140625000000 0.601562500000 0.164062500000 0.625000000000 +ico_ammo_jacket.tga 0.164062500000 0.601562500000 0.187500000000 0.625000000000 +ico_angle.tga 0.187500000000 0.601562500000 0.210937500000 0.625000000000 +ico_anti_magic_shield.tga 0.210937500000 0.601562500000 0.234375000000 0.625000000000 +ico_armor.tga 0.234375000000 0.601562500000 0.257812500000 0.625000000000 +ico_armor_clip.tga 0.257812500000 0.601562500000 0.281250000000 0.625000000000 +ico_armor_heavy.tga 0.281250000000 0.601562500000 0.304687500000 0.625000000000 +ico_armor_kitin.tga 0.304687500000 0.601562500000 0.328125000000 0.625000000000 +ico_armor_light.tga 0.328125000000 0.601562500000 0.351562500000 0.625000000000 +ef_over_less.tga 0.351562500000 0.601562500000 0.375000000000 0.625000000000 +ef_over_more.tga 0.375000000000 0.601562500000 0.398437500000 0.625000000000 +fo_back.tga 0.398437500000 0.601562500000 0.421875000000 0.625000000000 +fo_over.tga 0.421875000000 0.601562500000 0.445312500000 0.625000000000 +ico_gardening.tga 0.445312500000 0.601562500000 0.468750000000 0.625000000000 +ico_gentle.tga 0.468750000000 0.601562500000 0.492187500000 0.625000000000 +mp_over_link.tga 0.492187500000 0.601562500000 0.515625000000 0.625000000000 +ico_goo.tga 0.515625000000 0.601562500000 0.539062500000 0.625000000000 +us_back_0.tga 0.539062500000 0.601562500000 0.562500000000 0.625000000000 +us_back_1.tga 0.562500000000 0.601562500000 0.585937500000 0.625000000000 +us_back_2.tga 0.585937500000 0.601562500000 0.609375000000 0.625000000000 +us_back_3.tga 0.609375000000 0.601562500000 0.632812500000 0.625000000000 +us_back_4.tga 0.632812500000 0.601562500000 0.656250000000 0.625000000000 +us_back_5.tga 0.656250000000 0.601562500000 0.679687500000 0.625000000000 +us_back_6.tga 0.679687500000 0.601562500000 0.703125000000 0.625000000000 +us_back_7.tga 0.703125000000 0.601562500000 0.726562500000 0.625000000000 +us_back_8.tga 0.914062500000 0.609375000000 0.937500000000 0.632812500000 +tb_config.tga 0.726562500000 0.617187500000 0.750000000000 0.640625000000 +tb_connection.tga 0.750000000000 0.617187500000 0.773437500000 0.640625000000 +tb_contacts.tga 0.773437500000 0.617187500000 0.796875000000 0.640625000000 +tb_desk_1.tga 0.796875000000 0.617187500000 0.820312500000 0.640625000000 +tb_desk_2.tga 0.820312500000 0.617187500000 0.843750000000 0.640625000000 +tb_desk_3.tga 0.843750000000 0.617187500000 0.867187500000 0.640625000000 +tb_desk_4.tga 0.867187500000 0.617187500000 0.890625000000 0.640625000000 +tb_faction.tga 0.890625000000 0.617187500000 0.914062500000 0.640625000000 +tb_forum.tga 0.937500000000 0.617187500000 0.960937500000 0.640625000000 +tb_guild.tga 0.960937500000 0.617187500000 0.984375000000 0.640625000000 +TB_help2.tga 0.000000000000 0.625000000000 0.023437500000 0.648437500000 +tb_keys.tga 0.023437500000 0.625000000000 0.046875000000 0.648437500000 +tb_macros.tga 0.046875000000 0.625000000000 0.070312500000 0.648437500000 +tb_mail.tga 0.070312500000 0.625000000000 0.093750000000 0.648437500000 +tb_mode_dodge.tga 0.093750000000 0.625000000000 0.117187500000 0.648437500000 +tb_mode_parry.tga 0.117187500000 0.625000000000 0.140625000000 0.648437500000 +tb_over.tga 0.140625000000 0.625000000000 0.164062500000 0.648437500000 +tb_support.tga 0.164062500000 0.625000000000 0.187500000000 0.648437500000 +tb_team.tga 0.187500000000 0.625000000000 0.210937500000 0.648437500000 +tb_windows.tga 0.210937500000 0.625000000000 0.234375000000 0.648437500000 +ico_gripp.tga 0.234375000000 0.625000000000 0.257812500000 0.648437500000 +BK_zorai_brick.tga 0.257812500000 0.625000000000 0.281250000000 0.648437500000 +mf_back.tga 0.281250000000 0.625000000000 0.304687500000 0.648437500000 +mf_over.tga 0.304687500000 0.625000000000 0.328125000000 0.648437500000 +brick_default.tga 0.328125000000 0.625000000000 0.351562500000 0.648437500000 +ico_hammer.tga 0.351562500000 0.625000000000 0.375000000000 0.648437500000 +ico_harmful.tga 0.375000000000 0.625000000000 0.398437500000 0.648437500000 +ico_hatred.tga 0.398437500000 0.625000000000 0.421875000000 0.648437500000 +ico_heal.tga 0.421875000000 0.625000000000 0.445312500000 0.648437500000 +mp3.tga 0.445312500000 0.625000000000 0.468750000000 0.648437500000 +ico_hit_rate.tga 0.468750000000 0.625000000000 0.492187500000 0.648437500000 +mp_back_curative.tga 0.492187500000 0.625000000000 0.515625000000 0.648437500000 +mp_back_offensive.tga 0.515625000000 0.625000000000 0.539062500000 0.648437500000 +ico_time.tga 0.539062500000 0.625000000000 0.562500000000 0.648437500000 +ico_time_bonus.tga 0.562500000000 0.625000000000 0.585937500000 0.648437500000 +mp_back_selfonly.tga 0.585937500000 0.625000000000 0.609375000000 0.648437500000 +ico_trigger.tga 0.609375000000 0.625000000000 0.632812500000 0.648437500000 +ico_umbrella.tga 0.632812500000 0.625000000000 0.656250000000 0.648437500000 +ico_use_enchantement.tga 0.656250000000 0.625000000000 0.679687500000 0.648437500000 +ico_vampire.tga 0.679687500000 0.625000000000 0.703125000000 0.648437500000 +ico_visibility.tga 0.703125000000 0.625000000000 0.726562500000 0.648437500000 +ico_war_cry.tga 0.914062500000 0.632812500000 0.937500000000 0.656250000000 +ico_weight.tga 0.726562500000 0.640625000000 0.750000000000 0.664062500000 +ico_wellbalanced.tga 0.750000000000 0.640625000000 0.773437500000 0.664062500000 +ico_will.tga 0.773437500000 0.640625000000 0.796875000000 0.664062500000 +ico_windding.tga 0.796875000000 0.640625000000 0.820312500000 0.664062500000 +ico_wisdom.tga 0.820312500000 0.640625000000 0.843750000000 0.664062500000 +ico_incapacity.tga 0.843750000000 0.640625000000 0.867187500000 0.664062500000 +ico_intelligence.tga 0.867187500000 0.640625000000 0.890625000000 0.664062500000 +ico_interrupt.tga 0.890625000000 0.640625000000 0.914062500000 0.664062500000 +ico_invulnerability.tga 0.937500000000 0.640625000000 0.960937500000 0.664062500000 +ico_jewel_stone.tga 0.960937500000 0.640625000000 0.984375000000 0.664062500000 +us_ico_0.tga 0.000000000000 0.648437500000 0.023437500000 0.671875000000 +us_ico_1.tga 0.023437500000 0.648437500000 0.046875000000 0.671875000000 +us_ico_2.tga 0.046875000000 0.648437500000 0.070312500000 0.671875000000 +us_ico_3.tga 0.070312500000 0.648437500000 0.093750000000 0.671875000000 +us_ico_4.tga 0.093750000000 0.648437500000 0.117187500000 0.671875000000 +us_ico_5.tga 0.117187500000 0.648437500000 0.140625000000 0.671875000000 +us_ico_6.tga 0.140625000000 0.648437500000 0.164062500000 0.671875000000 +us_ico_7.tga 0.164062500000 0.648437500000 0.187500000000 0.671875000000 +us_ico_8.tga 0.187500000000 0.648437500000 0.210937500000 0.671875000000 +us_ico_9.tga 0.210937500000 0.648437500000 0.234375000000 0.671875000000 +us_over_0.tga 0.234375000000 0.648437500000 0.257812500000 0.671875000000 +us_over_1.tga 0.257812500000 0.648437500000 0.281250000000 0.671875000000 +us_over_2.tga 0.281250000000 0.648437500000 0.304687500000 0.671875000000 +us_over_3.tga 0.304687500000 0.648437500000 0.328125000000 0.671875000000 +us_over_4.tga 0.328125000000 0.648437500000 0.351562500000 0.671875000000 +building_state_24x24.tga 0.351562500000 0.648437500000 0.375000000000 0.671875000000 +cb_main_nue.tga 0.375000000000 0.648437500000 0.398437500000 0.671875000000 +fp_ammo.tga 0.398437500000 0.648437500000 0.421875000000 0.671875000000 +ico_armor_medium.tga 0.421875000000 0.648437500000 0.445312500000 0.671875000000 +ico_clothes.tga 0.445312500000 0.648437500000 0.468750000000 0.671875000000 +ico_durability.tga 0.468750000000 0.648437500000 0.492187500000 0.671875000000 +W_slot_shortcut_id0.tga 0.492187500000 0.648437500000 0.515625000000 0.671875000000 +W_slot_shortcut_id1.tga 0.515625000000 0.648437500000 0.539062500000 0.671875000000 +W_slot_shortcut_id2.tga 0.539062500000 0.648437500000 0.562500000000 0.671875000000 +W_slot_shortcut_id3.tga 0.562500000000 0.648437500000 0.585937500000 0.671875000000 +W_slot_shortcut_id4.tga 0.585937500000 0.648437500000 0.609375000000 0.671875000000 +W_slot_shortcut_id5.tga 0.609375000000 0.648437500000 0.632812500000 0.671875000000 +W_slot_shortcut_id6.tga 0.632812500000 0.648437500000 0.656250000000 0.671875000000 +W_slot_shortcut_id7.tga 0.656250000000 0.648437500000 0.679687500000 0.671875000000 +W_slot_shortcut_id8.tga 0.679687500000 0.648437500000 0.703125000000 0.671875000000 +W_slot_shortcut_id9.tga 0.703125000000 0.648437500000 0.726562500000 0.671875000000 +w_slot_shortcut_shift_id0.tga 0.914062500000 0.656250000000 0.937500000000 0.679687500000 +w_slot_shortcut_shift_id1.tga 0.726562500000 0.664062500000 0.750000000000 0.687500000000 +w_slot_shortcut_shift_id2.tga 0.750000000000 0.664062500000 0.773437500000 0.687500000000 +w_slot_shortcut_shift_id3.tga 0.773437500000 0.664062500000 0.796875000000 0.687500000000 +w_slot_shortcut_shift_id4.tga 0.796875000000 0.664062500000 0.820312500000 0.687500000000 +w_slot_shortcut_shift_id5.tga 0.820312500000 0.664062500000 0.843750000000 0.687500000000 +w_slot_shortcut_shift_id6.tga 0.843750000000 0.664062500000 0.867187500000 0.687500000000 +w_slot_shortcut_shift_id7.tga 0.867187500000 0.664062500000 0.890625000000 0.687500000000 +w_slot_shortcut_shift_id8.tga 0.890625000000 0.664062500000 0.914062500000 0.687500000000 +w_slot_shortcut_shift_id9.tga 0.937500000000 0.664062500000 0.960937500000 0.687500000000 +BK_matis_brick.tga 0.960937500000 0.664062500000 0.984375000000 0.687500000000 +ico_jewel_stone_support.tga 0.000000000000 0.671875000000 0.023437500000 0.695312500000 +ico_misfortune.tga 0.023437500000 0.671875000000 0.046875000000 0.695312500000 +pa_over_break.tga 0.046875000000 0.671875000000 0.070312500000 0.695312500000 +pa_over_less.tga 0.070312500000 0.671875000000 0.093750000000 0.695312500000 +pa_over_more.tga 0.093750000000 0.671875000000 0.117187500000 0.695312500000 +ch_back.tga 0.117187500000 0.671875000000 0.140625000000 0.695312500000 +ico_over_hit_head_x3.tga 0.140625000000 0.671875000000 0.164062500000 0.695312500000 +ico_primal.tga 0.164062500000 0.671875000000 0.187500000000 0.695312500000 +pvp_ally_0.tga 0.187500000000 0.671875000000 0.210937500000 0.695312500000 +pvp_ally_1.tga 0.210937500000 0.671875000000 0.234375000000 0.695312500000 +pvp_ally_2.tga 0.234375000000 0.671875000000 0.257812500000 0.695312500000 +pvp_ally_3.tga 0.257812500000 0.671875000000 0.281250000000 0.695312500000 +pvp_ally_4.tga 0.281250000000 0.671875000000 0.304687500000 0.695312500000 +pvp_ally_6.tga 0.304687500000 0.671875000000 0.328125000000 0.695312500000 +pvp_ally_flag.tga 0.328125000000 0.671875000000 0.351562500000 0.695312500000 +pvp_ally_primas.tga 0.351562500000 0.671875000000 0.375000000000 0.695312500000 +pvp_ally_ranger.tga 0.375000000000 0.671875000000 0.398437500000 0.695312500000 +pvp_ally_tag.tga 0.398437500000 0.671875000000 0.421875000000 0.695312500000 +bg_downloader.tga 0.421875000000 0.671875000000 0.445312500000 0.695312500000 +ico_source_knowledge.tga 0.445312500000 0.671875000000 0.466796875000 0.695312500000 +filter_tp.tga 0.468750000000 0.671875000000 0.492187500000 0.687500000000 small_task_done.tga 0.984375000000 0.000000000000 1.000000000000 0.015625000000 small_task_failed.tga 0.984375000000 0.015625000000 1.000000000000 0.031250000000 small_task_fight.tga 0.984375000000 0.031250000000 1.000000000000 0.046875000000 @@ -669,6 +679,6 @@ small_task_travel.tga 0.914062500000 0.523437500000 0.929687500000 0.53906250000 small_task_craft.tga 0.984375000000 0.546875000000 1.000000000000 0.562500000000 num_slash.tga 0.984375000000 0.562500000000 0.996093750000 0.576171875000 W_leader.tga 0.984375000000 0.578125000000 0.997070312500 0.589843750000 -tb_mode.tga 0.984375000000 0.589843750000 0.996093750000 0.601562500000 -profile.tga 0.984375000000 0.601562500000 0.996093750000 0.613281250000 -w_major.tga 0.984375000000 0.613281250000 0.996093750000 0.625000000000 +w_major.tga 0.984375000000 0.589843750000 0.996093750000 0.601562500000 +tb_mode.tga 0.984375000000 0.601562500000 0.996093750000 0.613281250000 +profile.tga 0.984375000000 0.613281250000 0.996093750000 0.625000000000 diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml b/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml index ca013f242..f0455028a 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/commands.xml @@ -78,9 +78,18 @@ - + + + + + + + + + + diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/config.xml b/code/ryzom/client/data/gamedev/interfaces_v3/config.xml index 1d593ef06..9fb0dd958 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/config.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/config.xml @@ -258,6 +258,9 @@ + @@ -291,6 +294,9 @@ + @@ -327,6 +333,9 @@ + @@ -2797,6 +2806,9 @@ This MUST follow the Enum MISSION_DESC::TIconId + - + + + + + + + + @@ -3045,6 +3081,9 @@ This MUST follow the Enum MISSION_DESC::TIconId + @@ -3066,6 +3105,9 @@ This MUST follow the Enum MISSION_DESC::TIconId + @@ -3087,6 +3129,9 @@ This MUST follow the Enum MISSION_DESC::TIconId + @@ -3108,6 +3153,9 @@ This MUST follow the Enum MISSION_DESC::TIconId + @@ -3129,6 +3177,9 @@ This MUST follow the Enum MISSION_DESC::TIconId + @@ -3151,6 +3202,9 @@ This MUST follow the Enum MISSION_DESC::TIconId + @@ -3173,6 +3227,9 @@ This MUST follow the Enum MISSION_DESC::TIconId + + + diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/encyclopedia.xml b/code/ryzom/client/data/gamedev/interfaces_v3/encyclopedia.xml index b2db7ab26..30f2c34a0 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/encyclopedia.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/encyclopedia.xml @@ -11,7 +11,7 @@ -