Merge remote-tracking branch 'hg/develop/hg/develop' into ryzomcore
This commit is contained in:
commit
46af0c090e
107 changed files with 8410 additions and 1199 deletions
34
azure-pipelines.yml
Normal file
34
azure-pipelines.yml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
jobs:
|
||||||
|
- job: ubuntu16
|
||||||
|
pool:
|
||||||
|
vmImage: 'Ubuntu-16.04'
|
||||||
|
steps:
|
||||||
|
- script: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y software-properties-common
|
||||||
|
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install cmake build-essential -y
|
||||||
|
sudo apt-get install gcc-8 g++-8 -y
|
||||||
|
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 60
|
||||||
|
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 60
|
||||||
|
sudo apt-get install libmysqlclient-dev -y
|
||||||
|
sudo apt-get install bison autoconf automake -y
|
||||||
|
sudo apt-get install libpng12-dev libjpeg62-dev -y
|
||||||
|
sudo apt-get install liblua5.1-dev libluabind-dev libcpptest-dev -y
|
||||||
|
sudo apt-get install libogg-dev libvorbis-dev libopenal-dev -y
|
||||||
|
sudo apt-get install libgif-dev libfreetype6-dev -y
|
||||||
|
sudo apt-get install libxml2-dev -y
|
||||||
|
sudo apt-get install libcurl4-openssl-dev -y
|
||||||
|
displayName: 'Dependencies'
|
||||||
|
- script: |
|
||||||
|
mkdir build
|
||||||
|
cmake --version
|
||||||
|
cd build
|
||||||
|
cmake -DWITH_NEL_TESTS=OFF -DWITH_NEL_SAMPLES=ON -DWITH_LUA51=ON -DWITH_RYZOM_SERVER=ON -DWITH_RYZOM_TOOLS=OFF -DWITH_NEL_TOOLS=OFF ../code
|
||||||
|
cat CMakeCache.txt
|
||||||
|
displayName: 'CMake'
|
||||||
|
- script: |
|
||||||
|
cd build
|
||||||
|
make -j`nproc`
|
||||||
|
displayName: 'Make'
|
173
code/CMakeModules/FindFFmpeg.cmake
Normal file
173
code/CMakeModules/FindFFmpeg.cmake
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# vim: ts=2 sw=2
|
||||||
|
# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC)
|
||||||
|
#
|
||||||
|
# Once done this will define
|
||||||
|
# FFMPEG_FOUND - System has the all required components.
|
||||||
|
# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers.
|
||||||
|
# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components.
|
||||||
|
# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components.
|
||||||
|
#
|
||||||
|
# For each of the components it will additionaly set.
|
||||||
|
# - AVCODEC
|
||||||
|
# - AVDEVICE
|
||||||
|
# - AVFORMAT
|
||||||
|
# - AVUTIL
|
||||||
|
# - POSTPROC
|
||||||
|
# - SWSCALE
|
||||||
|
# - SWRESAMPLE
|
||||||
|
# the following variables will be defined
|
||||||
|
# <component>_FOUND - System has <component>
|
||||||
|
# <component>_INCLUDE_DIRS - Include directory necessary for using the <component> headers
|
||||||
|
# <component>_LIBRARIES - Link these to use <component>
|
||||||
|
# <component>_DEFINITIONS - Compiler switches required for using <component>
|
||||||
|
# <component>_VERSION - The components version
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006, Matthias Kretz, <kretz@kde.org>
|
||||||
|
# Copyright (c) 2008, Alexander Neundorf, <neundorf@kde.org>
|
||||||
|
# Copyright (c) 2011, Michael Jansen, <kde@michael-jansen.biz>
|
||||||
|
#
|
||||||
|
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
if(NOT FFmpeg_FIND_COMPONENTS)
|
||||||
|
set(FFmpeg_FIND_COMPONENTS AVFORMAT AVCODEC AVUTIL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
### Macro: set_component_found
|
||||||
|
#
|
||||||
|
# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present.
|
||||||
|
#
|
||||||
|
macro(set_component_found _component)
|
||||||
|
if(${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS)
|
||||||
|
# message(STATUS " - ${_component} found.")
|
||||||
|
set(${_component}_FOUND TRUE)
|
||||||
|
else()
|
||||||
|
# message(STATUS " - ${_component} not found.")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
#
|
||||||
|
### Macro: find_component
|
||||||
|
#
|
||||||
|
# Checks for the given component by invoking pkgconfig and then looking up the libraries and
|
||||||
|
# include directories.
|
||||||
|
#
|
||||||
|
macro(find_component _component _pkgconfig _library _header)
|
||||||
|
if(NOT WIN32)
|
||||||
|
# use pkg-config to get the directories and then use these values
|
||||||
|
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||||
|
find_package(PkgConfig)
|
||||||
|
if(PKG_CONFIG_FOUND)
|
||||||
|
pkg_check_modules(PC_${_component} ${_pkgconfig})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_path(${_component}_INCLUDE_DIRS ${_header}
|
||||||
|
HINTS
|
||||||
|
${FFMPEGSDK_INC}
|
||||||
|
${PC_LIB${_component}_INCLUDEDIR}
|
||||||
|
${PC_LIB${_component}_INCLUDE_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
ffmpeg
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(${_component}_LIBRARIES NAMES ${_library}
|
||||||
|
HINTS
|
||||||
|
${FFMPEGSDK_LIB}
|
||||||
|
${PC_LIB${_component}_LIBDIR}
|
||||||
|
${PC_LIB${_component}_LIBRARY_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
STRING(REGEX REPLACE "/.*" "/version.h" _ver_header ${_header})
|
||||||
|
if(EXISTS "${${_component}_INCLUDE_DIRS}/${_ver_header}")
|
||||||
|
file(STRINGS "${${_component}_INCLUDE_DIRS}/${_ver_header}" version_str REGEX "^#define[\t ]+LIB${_component}_VERSION_M.*")
|
||||||
|
|
||||||
|
foreach(_str "${version_str}")
|
||||||
|
if(NOT version_maj)
|
||||||
|
string(REGEX REPLACE "^.*LIB${_component}_VERSION_MAJOR[\t ]+([0-9]*).*$" "\\1" version_maj "${_str}")
|
||||||
|
endif()
|
||||||
|
if(NOT version_min)
|
||||||
|
string(REGEX REPLACE "^.*LIB${_component}_VERSION_MINOR[\t ]+([0-9]*).*$" "\\1" version_min "${_str}")
|
||||||
|
endif()
|
||||||
|
if(NOT version_mic)
|
||||||
|
string(REGEX REPLACE "^.*LIB${_component}_VERSION_MICRO[\t ]+([0-9]*).*$" "\\1" version_mic "${_str}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
unset(version_str)
|
||||||
|
|
||||||
|
set(${_component}_VERSION "${version_maj}.${version_min}.${version_mic}" CACHE STRING "The ${_component} version number.")
|
||||||
|
unset(version_maj)
|
||||||
|
unset(version_min)
|
||||||
|
unset(version_mic)
|
||||||
|
endif(EXISTS "${${_component}_INCLUDE_DIRS}/${_ver_header}")
|
||||||
|
set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.")
|
||||||
|
set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.")
|
||||||
|
|
||||||
|
set_component_found(${_component})
|
||||||
|
|
||||||
|
mark_as_advanced(
|
||||||
|
${_component}_INCLUDE_DIRS
|
||||||
|
${_component}_LIBRARIES
|
||||||
|
${_component}_DEFINITIONS
|
||||||
|
${_component}_VERSION)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
|
||||||
|
set(FFMPEGSDK $ENV{FFMPEG_HOME})
|
||||||
|
if(FFMPEGSDK)
|
||||||
|
set(FFMPEGSDK_INC "${FFMPEGSDK}/include")
|
||||||
|
set(FFMPEGSDK_LIB "${FFMPEGSDK}/lib")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check for all possible components.
|
||||||
|
find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h)
|
||||||
|
find_component(AVFORMAT libavformat avformat libavformat/avformat.h)
|
||||||
|
find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h)
|
||||||
|
find_component(AVUTIL libavutil avutil libavutil/avutil.h)
|
||||||
|
find_component(SWSCALE libswscale swscale libswscale/swscale.h)
|
||||||
|
find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h)
|
||||||
|
find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h)
|
||||||
|
|
||||||
|
# Check if the required components were found and add their stuff to the FFMPEG_* vars.
|
||||||
|
foreach(_component ${FFmpeg_FIND_COMPONENTS})
|
||||||
|
if(${_component}_FOUND)
|
||||||
|
# message(STATUS "Required component ${_component} present.")
|
||||||
|
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES})
|
||||||
|
set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS})
|
||||||
|
list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS})
|
||||||
|
else()
|
||||||
|
# message(STATUS "Required component ${_component} missing.")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Build the include path and library list with duplicates removed.
|
||||||
|
if(FFMPEG_INCLUDE_DIRS)
|
||||||
|
list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(FFMPEG_LIBRARIES)
|
||||||
|
list(REMOVE_DUPLICATES FFMPEG_LIBRARIES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# cache the vars.
|
||||||
|
set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE)
|
||||||
|
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE)
|
||||||
|
set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE)
|
||||||
|
|
||||||
|
mark_as_advanced(FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARIES FFMPEG_DEFINITIONS)
|
||||||
|
|
||||||
|
# Now set the noncached _FOUND vars for the components.
|
||||||
|
foreach(_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWRESAMPLE SWSCALE)
|
||||||
|
set_component_found(${_component})
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
# Compile the list of required vars
|
||||||
|
set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS)
|
||||||
|
foreach(_component ${FFmpeg_FIND_COMPONENTS})
|
||||||
|
list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Give a nice error message if some of the required vars are missing.
|
||||||
|
find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS})
|
|
@ -41,31 +41,49 @@ ENDMACRO()
|
||||||
MACRO(PCH_SET_COMPILE_FLAGS _target)
|
MACRO(PCH_SET_COMPILE_FLAGS _target)
|
||||||
SET(PCH_FLAGS)
|
SET(PCH_FLAGS)
|
||||||
SET(PCH_ARCHS)
|
SET(PCH_ARCHS)
|
||||||
|
SET(PCH_INCLUDES)
|
||||||
|
|
||||||
SET(_FLAGS)
|
# Append target for clang if defined
|
||||||
|
IF(CMAKE_CXX_COMPILER_TARGET)
|
||||||
|
LIST(APPEND PCH_FLAGS "--target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN)
|
||||||
|
LIST(APPEND PCH_FLAGS "--gcc-toolchain=${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_SYSROOT)
|
||||||
|
LIST(APPEND PCH_FLAGS "--sysroot=${CMAKE_SYSROOT}")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
IF(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES)
|
||||||
|
FOREACH(item ${CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES})
|
||||||
|
LIST(APPEND PCH_FLAGS "-isystem ${item}")
|
||||||
|
ENDFOREACH()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
# C++ flags
|
# C++ flags
|
||||||
SET(_FLAG ${CMAKE_CXX_FLAGS})
|
SET(_FLAGS ${CMAKE_CXX_FLAGS})
|
||||||
SEPARATE_ARGUMENTS(_FLAG)
|
SEPARATE_ARGUMENTS(_FLAGS)
|
||||||
|
|
||||||
LIST(APPEND _FLAGS ${_FLAG})
|
LIST(APPEND PCH_FLAGS ${_FLAGS})
|
||||||
|
|
||||||
# C++ config flags
|
# C++ config flags
|
||||||
STRING(TOUPPER "${CMAKE_BUILD_TYPE}" _UPPER_BUILD)
|
STRING(TOUPPER "${CMAKE_BUILD_TYPE}" _UPPER_BUILD)
|
||||||
|
|
||||||
SET(_FLAG ${CMAKE_CXX_FLAGS_${_UPPER_BUILD}})
|
SET(_FLAGS ${CMAKE_CXX_FLAGS_${_UPPER_BUILD}})
|
||||||
SEPARATE_ARGUMENTS(_FLAG)
|
SEPARATE_ARGUMENTS(_FLAGS)
|
||||||
|
|
||||||
LIST(APPEND _FLAGS ${_FLAG})
|
LIST(APPEND PCH_FLAGS ${_FLAGS})
|
||||||
|
|
||||||
GET_TARGET_PROPERTY(_targetType ${_target} TYPE)
|
GET_TARGET_PROPERTY(_targetType ${_target} TYPE)
|
||||||
|
|
||||||
SET(_USE_PIC OFF)
|
SET(_USE_PIC OFF)
|
||||||
|
|
||||||
IF(${_targetType} STREQUAL "SHARED_LIBRARY" OR ${_targetType} STREQUAL "MODULE_LIBRARY")
|
IF(${_targetType} STREQUAL "SHARED_LIBRARY" OR ${_targetType} STREQUAL "MODULE_LIBRARY")
|
||||||
SET(_FLAG ${CMAKE_SHARED_LIBRARY_CXX_FLAGS})
|
SET(_FLAGS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS})
|
||||||
SEPARATE_ARGUMENTS(_FLAG)
|
SEPARATE_ARGUMENTS(_FLAGS)
|
||||||
LIST(APPEND _FLAGS ${_FLAG})
|
LIST(APPEND PCH_FLAGS ${_FLAGS})
|
||||||
ELSE()
|
ELSE()
|
||||||
GET_TARGET_PROPERTY(_pic ${_target} POSITION_INDEPENDENT_CODE)
|
GET_TARGET_PROPERTY(_pic ${_target} POSITION_INDEPENDENT_CODE)
|
||||||
IF(_pic)
|
IF(_pic)
|
||||||
|
@ -75,7 +93,7 @@ MACRO(PCH_SET_COMPILE_FLAGS _target)
|
||||||
|
|
||||||
GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES)
|
GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES)
|
||||||
FOREACH(item ${DIRINC})
|
FOREACH(item ${DIRINC})
|
||||||
LIST(APPEND _FLAGS -I"${item}")
|
LIST(APPEND PCH_INCLUDES "${item}")
|
||||||
ENDFOREACH()
|
ENDFOREACH()
|
||||||
|
|
||||||
# NOTE: As cmake files (eg FindQT4) may now use generator expressions around their defines that evaluate
|
# NOTE: As cmake files (eg FindQT4) may now use generator expressions around their defines that evaluate
|
||||||
|
@ -98,14 +116,14 @@ MACRO(PCH_SET_COMPILE_FLAGS _target)
|
||||||
ENDFOREACH()
|
ENDFOREACH()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
GET_DIRECTORY_PROPERTY(DEFINITIONS DIRECTORY ${CMAKE_SOURCE_DIR} COMPILE_DEFINITIONS)
|
GET_DIRECTORY_PROPERTY(DEFINITIONS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS)
|
||||||
IF(DEFINITIONS)
|
IF(DEFINITIONS)
|
||||||
FOREACH(item ${DEFINITIONS})
|
FOREACH(item ${DEFINITIONS})
|
||||||
APPEND_DEFINITION(GLOBAL_DEFINITIONS ${item})
|
APPEND_DEFINITION(GLOBAL_DEFINITIONS ${item})
|
||||||
ENDFOREACH()
|
ENDFOREACH()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
GET_DIRECTORY_PROPERTY(DEFINITIONS DIRECTORY ${CMAKE_SOURCE_DIR} COMPILE_DEFINITIONS_${_UPPER_BUILD})
|
GET_DIRECTORY_PROPERTY(DEFINITIONS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS_${_UPPER_BUILD})
|
||||||
IF(DEFINITIONS)
|
IF(DEFINITIONS)
|
||||||
FOREACH(item ${DEFINITIONS})
|
FOREACH(item ${DEFINITIONS})
|
||||||
APPEND_DEFINITION(GLOBAL_DEFINITIONS ${item})
|
APPEND_DEFINITION(GLOBAL_DEFINITIONS ${item})
|
||||||
|
@ -114,22 +132,22 @@ MACRO(PCH_SET_COMPILE_FLAGS _target)
|
||||||
|
|
||||||
GET_TARGET_PROPERTY(oldProps ${_target} COMPILE_FLAGS)
|
GET_TARGET_PROPERTY(oldProps ${_target} COMPILE_FLAGS)
|
||||||
IF(oldProps)
|
IF(oldProps)
|
||||||
SET(_FLAG ${oldProps})
|
SET(_FLAGS ${oldProps})
|
||||||
SEPARATE_ARGUMENTS(_FLAG)
|
SEPARATE_ARGUMENTS(_FLAGS)
|
||||||
LIST(APPEND _FLAGS ${_FLAG})
|
LIST(APPEND PCH_FLAGS ${_FLAGS})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
GET_TARGET_PROPERTY(oldPropsBuild ${_target} COMPILE_FLAGS_${_UPPER_BUILD})
|
GET_TARGET_PROPERTY(oldPropsBuild ${_target} COMPILE_FLAGS_${_UPPER_BUILD})
|
||||||
IF(oldPropsBuild)
|
IF(oldPropsBuild)
|
||||||
SET(_FLAG ${oldPropsBuild})
|
SET(_FLAGS ${oldPropsBuild})
|
||||||
SEPARATE_ARGUMENTS(_FLAG)
|
SEPARATE_ARGUMENTS(_FLAGS)
|
||||||
LIST(APPEND _FLAGS ${_FLAG})
|
LIST(APPEND PCH_FLAGS ${_FLAGS})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
GET_TARGET_PROPERTY(DIRINC ${_target} INCLUDE_DIRECTORIES)
|
GET_TARGET_PROPERTY(DIRINC ${_target} INCLUDE_DIRECTORIES)
|
||||||
IF(DIRINC)
|
IF(DIRINC)
|
||||||
FOREACH(item ${DIRINC})
|
FOREACH(item ${DIRINC})
|
||||||
LIST(APPEND _FLAGS -I"${item}")
|
LIST(APPEND PCH_INCLUDES "${item}")
|
||||||
ENDFOREACH()
|
ENDFOREACH()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
@ -147,6 +165,18 @@ MACRO(PCH_SET_COMPILE_FLAGS _target)
|
||||||
ENDFOREACH()
|
ENDFOREACH()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
GET_TARGET_PROPERTY(OPTIONS ${_target} COMPILE_OPTIONS)
|
||||||
|
IF(OPTIONS)
|
||||||
|
SEPARATE_ARGUMENTS(OPTIONS)
|
||||||
|
LIST(APPEND PCH_FLAGS ${OPTIONS})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
GET_TARGET_PROPERTY(OPTIONS ${_target} COMPILE_OPTIONS_${_UPPER_BUILD})
|
||||||
|
IF(OPTIONS)
|
||||||
|
SEPARATE_ARGUMENTS(OPTIONS)
|
||||||
|
LIST(APPEND PCH_FLAGS ${OPTIONS})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
GET_TARGET_PROPERTY(_LIBS ${_target} INTERFACE_LINK_LIBRARIES)
|
GET_TARGET_PROPERTY(_LIBS ${_target} INTERFACE_LINK_LIBRARIES)
|
||||||
IF(_LIBS)
|
IF(_LIBS)
|
||||||
FOREACH(_LIB ${_LIBS})
|
FOREACH(_LIB ${_LIBS})
|
||||||
|
@ -156,7 +186,7 @@ MACRO(PCH_SET_COMPILE_FLAGS _target)
|
||||||
|
|
||||||
IF(_DIRS)
|
IF(_DIRS)
|
||||||
FOREACH(item ${_DIRS})
|
FOREACH(item ${_DIRS})
|
||||||
LIST(APPEND GLOBAL_DEFINITIONS -I"${item}")
|
LIST(APPEND PCH_INCLUDES "${item}")
|
||||||
ENDFOREACH()
|
ENDFOREACH()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
@ -185,7 +215,7 @@ MACRO(PCH_SET_COMPILE_FLAGS _target)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(_USE_PIC)
|
IF(_USE_PIC)
|
||||||
LIST(APPEND _FLAGS ${CMAKE_CXX_COMPILE_OPTIONS_PIC})
|
LIST(APPEND PCH_FLAGS ${CMAKE_CXX_COMPILE_OPTIONS_PIC})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
@ -195,116 +225,81 @@ MACRO(PCH_SET_COMPILE_FLAGS _target)
|
||||||
IF(_DIRECTORY_FLAGS)
|
IF(_DIRECTORY_FLAGS)
|
||||||
SEPARATE_ARGUMENTS(_DIRECTORY_FLAGS)
|
SEPARATE_ARGUMENTS(_DIRECTORY_FLAGS)
|
||||||
FOREACH(item ${_DIRECTORY_FLAGS})
|
FOREACH(item ${_DIRECTORY_FLAGS})
|
||||||
LIST(APPEND _FLAGS "${item}")
|
LIST(APPEND PCH_FLAGS "${item}")
|
||||||
ENDFOREACH()
|
ENDFOREACH()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
GET_DIRECTORY_PROPERTY(_DIRECTORY_DEFINITIONS DIRECTORY ${CMAKE_SOURCE_DIR} DEFINITIONS)
|
GET_DIRECTORY_PROPERTY(_DIRECTORY_DEFINITIONS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEFINITIONS)
|
||||||
|
|
||||||
IF(_DIRECTORY_DEFINITIONS)
|
IF(_DIRECTORY_DEFINITIONS)
|
||||||
SEPARATE_ARGUMENTS(_DIRECTORY_DEFINITIONS)
|
SEPARATE_ARGUMENTS(_DIRECTORY_DEFINITIONS)
|
||||||
FOREACH(item ${_DIRECTORY_DEFINITIONS})
|
FOREACH(item ${_DIRECTORY_DEFINITIONS})
|
||||||
LIST(APPEND _FLAGS "${item}")
|
LIST(APPEND PCH_FLAGS "${item}")
|
||||||
ENDFOREACH()
|
ENDFOREACH()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(CMAKE_CXX11_EXTENSION_COMPILE_OPTION)
|
IF(CMAKE_CXX11_EXTENSION_COMPILE_OPTION)
|
||||||
LIST(APPEND _FLAGS ${CMAKE_CXX11_EXTENSION_COMPILE_OPTION})
|
LIST(APPEND PCH_FLAGS "${CMAKE_CXX11_EXTENSION_COMPILE_OPTION}")
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# Format definitions
|
|
||||||
IF(MSVC)
|
|
||||||
# Fix path with space
|
|
||||||
SEPARATE_ARGUMENTS(_FLAGS UNIX_COMMAND "${_FLAGS}")
|
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# Already in list form and items may contain non-leading spaces that should not be split on
|
# Already in list form and items may contain non-leading spaces that should not be split on
|
||||||
LIST(INSERT _FLAGS 0 "${GLOBAL_DEFINITIONS}")
|
LIST(APPEND PCH_FLAGS "${GLOBAL_DEFINITIONS}")
|
||||||
|
|
||||||
IF(CLANG)
|
IF(WIN32)
|
||||||
# Determining all architectures and get common flags
|
SET(SYSTEM_FLAG "[-/$]")
|
||||||
SET(_ARCH_NEXT)
|
|
||||||
SET(_XARCH_NEXT)
|
|
||||||
FOREACH(item ${_FLAGS})
|
|
||||||
IF(_ARCH_NEXT)
|
|
||||||
LIST(FIND PCH_ARCHS ${item} ITEM_FOUND)
|
|
||||||
IF(ITEM_FOUND EQUAL -1)
|
|
||||||
LIST(APPEND PCH_ARCHS ${item})
|
|
||||||
STRING(TOUPPER "${item}" _UPPER_ARCH)
|
|
||||||
SET(PCH_ARCH_${_UPPER_ARCH}_FLAGS "-arch" ${item})
|
|
||||||
ENDIF()
|
|
||||||
SET(_ARCH_NEXT OFF)
|
|
||||||
ELSEIF(_XARCH_NEXT)
|
|
||||||
SET(_XARCH_NEXT OFF)
|
|
||||||
ELSE()
|
|
||||||
IF(item MATCHES "^-arch")
|
|
||||||
SET(_ARCH_NEXT ON)
|
|
||||||
ELSEIF(item MATCHES "^-Xarch_")
|
|
||||||
STRING(REGEX REPLACE "-Xarch_([a-z0-9_]+)" "\\1" item ${item})
|
|
||||||
LIST(FIND PCH_ARCHS ${item} ITEM_FOUND)
|
|
||||||
IF(ITEM_FOUND EQUAL -1)
|
|
||||||
LIST(APPEND PCH_ARCHS ${item})
|
|
||||||
STRING(TOUPPER "${item}" _UPPER_ARCH)
|
|
||||||
SET(PCH_ARCH_${_UPPER_ARCH}_FLAGS "-arch" ${item})
|
|
||||||
ENDIF()
|
|
||||||
SET(_XARCH_NEXT ON)
|
|
||||||
ELSE()
|
|
||||||
LIST(APPEND PCH_FLAGS ${item})
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
ENDFOREACH()
|
|
||||||
|
|
||||||
# Get architcture specific flags
|
|
||||||
SET(_XARCH_NEXT)
|
|
||||||
FOREACH(item ${_FLAGS})
|
|
||||||
IF(_XARCH_NEXT)
|
|
||||||
STRING(TOUPPER "${_XARCH_NEXT}" _UPPER_XARCH)
|
|
||||||
LIST(APPEND PCH_ARCH_${_UPPER_XARCH}_FLAGS ${item})
|
|
||||||
SET(_XARCH_NEXT OFF)
|
|
||||||
ELSE()
|
|
||||||
IF(item MATCHES "^-Xarch_")
|
|
||||||
STRING(SUBSTRING "${item}" 7 -1 _XARCH_NEXT)
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
ENDFOREACH()
|
|
||||||
|
|
||||||
# Remove duplicated architectures
|
|
||||||
IF(_ARCHS AND PCH_ARCHS)
|
|
||||||
LIST(REMOVE_DUPLICATES PCH_ARCHS)
|
|
||||||
ENDIF()
|
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(PCH_FLAGS ${_FLAGS})
|
SET(SYSTEM_FLAG "[-$]")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(PCH_FLAGS)
|
SET(_FINAL_FLAGS)
|
||||||
LIST(REMOVE_ITEM PCH_FLAGS "")
|
SET(_PREVIOUS_FLAG)
|
||||||
LIST(REMOVE_DUPLICATES PCH_FLAGS)
|
|
||||||
|
FOREACH(_FLAG ${PCH_FLAGS})
|
||||||
|
# If parameter is really a flag (starts with -)
|
||||||
|
IF(_FLAG MATCHES "^${SYSTEM_FLAG}")
|
||||||
|
IF(_PREVIOUS_FLAG)
|
||||||
|
# Append previous flag
|
||||||
|
LIST(APPEND _FINAL_FLAGS ${_PREVIOUS_FLAG})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
SET(_PREVIOUS_FLAG ${_FLAG})
|
||||||
|
ELSE()
|
||||||
|
IF(_PREVIOUS_FLAG)
|
||||||
|
# Append previous flag and its parameter
|
||||||
|
# TODO: escape them only if there is an space
|
||||||
|
LIST(APPEND _FINAL_FLAGS "${_PREVIOUS_FLAG} \"${_FLAG}\"")
|
||||||
|
SET(_PREVIOUS_FLAG)
|
||||||
|
ELSE()
|
||||||
|
# Shouldn't happen
|
||||||
|
MESSAGE(FATAL_ERROR "No previous flag before ${_FLAG}")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
ENDFOREACH()
|
||||||
|
|
||||||
|
IF(_PREVIOUS_FLAG)
|
||||||
|
LIST(APPEND _FINAL_FLAGS ${_PREVIOUS_FLAG})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
SET(PCH_FLAGS ${_FINAL_FLAGS})
|
||||||
|
|
||||||
|
# Remove flags that don't work with PCH
|
||||||
|
LIST(REMOVE_ITEM PCH_FLAGS "-Wa,--noexecstack")
|
||||||
|
|
||||||
|
# Remove all empty parameters
|
||||||
|
LIST(REMOVE_ITEM PCH_FLAGS "")
|
||||||
|
|
||||||
|
# Remove duplicate parameters
|
||||||
|
LIST(REMOVE_DUPLICATES PCH_FLAGS)
|
||||||
|
|
||||||
|
# create a command-line string
|
||||||
|
STRING(REGEX REPLACE ";" " " PCH_FLAGS "${PCH_FLAGS}")
|
||||||
|
|
||||||
|
# and separate arguments
|
||||||
|
SEPARATE_ARGUMENTS(PCH_FLAGS)
|
||||||
ENDMACRO()
|
ENDMACRO()
|
||||||
|
|
||||||
MACRO(GET_PDB_FILENAME _out_filename _target)
|
MACRO(PCH_SET_COMPILE_COMMAND _inputcpp _compile_FLAGS _includes)
|
||||||
# determine output directory based on target type
|
|
||||||
GET_TARGET_PROPERTY(_targetType ${_target} TYPE)
|
|
||||||
IF(${_targetType} STREQUAL EXECUTABLE)
|
|
||||||
SET(_targetOutput ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
|
||||||
ELSEIF(${_targetType} STREQUAL STATIC_LIBRARY)
|
|
||||||
SET(_targetOutput ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY})
|
|
||||||
ELSE()
|
|
||||||
SET(_targetOutput ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# determine target postfix
|
|
||||||
STRING(TOUPPER "${CMAKE_BUILD_TYPE}_POSTFIX" _postfix_var_name)
|
|
||||||
GET_TARGET_PROPERTY(_targetPostfix ${_target} ${_postfix_var_name})
|
|
||||||
IF(${_targetPostfix} MATCHES NOTFOUND)
|
|
||||||
SET(_targetPostfix "")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
SET(${_out_filename} "${_targetOutput}/${_target}${_targetPostfix}.pdb")
|
|
||||||
ENDMACRO(GET_PDB_FILENAME)
|
|
||||||
|
|
||||||
MACRO(PCH_SET_COMPILE_COMMAND _inputcpp _compile_FLAGS)
|
|
||||||
IF(CMAKE_CXX_COMPILER_ARG1)
|
IF(CMAKE_CXX_COMPILER_ARG1)
|
||||||
# remove leading space in compiler argument
|
# remove leading space in compiler argument
|
||||||
STRING(REGEX REPLACE "^ +" "" pchsupport_compiler_cxx_arg1 ${CMAKE_CXX_COMPILER_ARG1})
|
STRING(REGEX REPLACE "^ +" "" pchsupport_compiler_cxx_arg1 ${CMAKE_CXX_COMPILER_ARG1})
|
||||||
|
@ -313,19 +308,34 @@ MACRO(PCH_SET_COMPILE_COMMAND _inputcpp _compile_FLAGS)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
GET_PDB_FILENAME(_PDB_FILE ${_PCH_current_target})
|
GET_INTERMEDIATE_PDB_FULLPATH(${_PCH_current_target} _PDB_FILE)
|
||||||
SET(PCH_COMMAND ${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} /Yc /Fp"${PCH_OUTPUT}" ${_inputcpp} /Fd"${_PDB_FILE}" /c /Fo"${PCH_OUTPUT}.obj")
|
|
||||||
|
SET(PCH_TEMP_CONTENT)
|
||||||
|
|
||||||
|
FOREACH(_include ${_includes})
|
||||||
|
SET(PCH_TEMP_CONTENT "${PCH_TEMP_CONTENT} -I \"${_include}\"")
|
||||||
|
ENDFOREACH()
|
||||||
|
|
||||||
|
SET(PCH_TEMP_FILE ${CMAKE_CURRENT_BINARY_DIR}/pch_command.txt)
|
||||||
|
FILE(WRITE ${PCH_TEMP_FILE} "${PCH_TEMP_CONTENT}")
|
||||||
|
|
||||||
|
SET(PCH_COMMAND ${CMAKE_CXX_COMPILER} /nologo @${PCH_TEMP_FILE} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} /Yc /Fp"${PCH_OUTPUT}" ${_inputcpp} /Fd"${_PDB_FILE}" /c /Fo"${PCH_OUTPUT}.obj")
|
||||||
|
|
||||||
# Ninja PCH Support
|
# Ninja PCH Support
|
||||||
# http://public.kitware.com/pipermail/cmake-developers/2012-March/003653.html
|
# http://public.kitware.com/pipermail/cmake-developers/2012-March/003653.html
|
||||||
SET_SOURCE_FILES_PROPERTIES(${_inputcpp} PROPERTIES OBJECT_OUTPUTS "${PCH_OUTPUT}.obj")
|
SET_SOURCE_FILES_PROPERTIES(${_inputcpp} PROPERTIES OBJECT_OUTPUTS "${PCH_OUTPUT}.obj")
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(HEADER_FORMAT "c++-header")
|
SET(HEADER_FORMAT "c++-header")
|
||||||
SET(_FLAGS "")
|
SET(_FLAGS)
|
||||||
IF(APPLE)
|
IF(APPLE)
|
||||||
SET(HEADER_FORMAT "objective-${HEADER_FORMAT}")
|
SET(HEADER_FORMAT "objective-${HEADER_FORMAT}")
|
||||||
SET(_FLAGS ${OBJC_FLAGS})
|
LIST(APPEND _FLAGS ${OBJC_FLAGS})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
FOREACH(_include ${_includes})
|
||||||
|
LIST(APPEND _FLAGS -I "${_include}")
|
||||||
|
ENDFOREACH()
|
||||||
|
|
||||||
SET(PCH_COMMAND ${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} ${_FLAGS} -x ${HEADER_FORMAT} -o ${PCH_OUTPUT} -c ${PCH_INPUT})
|
SET(PCH_COMMAND ${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} ${_FLAGS} -x ${HEADER_FORMAT} -o ${PCH_OUTPUT} -c ${PCH_INPUT})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDMACRO()
|
ENDMACRO()
|
||||||
|
@ -467,7 +477,7 @@ MACRO(ADD_PRECOMPILED_HEADER _targetName _inputh _inputcpp)
|
||||||
PCH_SET_PRECOMPILED_HEADER_OUTPUT(${_targetName} ${_inputh} ${_ARCH} "")
|
PCH_SET_PRECOMPILED_HEADER_OUTPUT(${_targetName} ${_inputh} ${_ARCH} "")
|
||||||
LIST(APPEND PCH_OUTPUTS ${PCH_OUTPUT})
|
LIST(APPEND PCH_OUTPUTS ${PCH_OUTPUT})
|
||||||
|
|
||||||
PCH_SET_COMPILE_COMMAND(${_inputcpp} "${PCH_ARCH_${_UPPER_ARCH}_FLAGS};${PCH_FLAGS}")
|
PCH_SET_COMPILE_COMMAND(${_inputcpp} "${PCH_ARCH_${_UPPER_ARCH}_FLAGS};${PCH_FLAGS}" "${PCH_INCLUDES}")
|
||||||
PCH_CREATE_TARGET(${_targetName} ${_targetName}_pch_${_ARCH})
|
PCH_CREATE_TARGET(${_targetName} ${_targetName}_pch_${_ARCH})
|
||||||
|
|
||||||
ADD_PRECOMPILED_HEADER_TO_TARGET_ARCH(${_targetName} ${_ARCH})
|
ADD_PRECOMPILED_HEADER_TO_TARGET_ARCH(${_targetName} ${_ARCH})
|
||||||
|
@ -476,7 +486,7 @@ MACRO(ADD_PRECOMPILED_HEADER _targetName _inputh _inputcpp)
|
||||||
PCH_SET_PRECOMPILED_HEADER_OUTPUT(${_targetName} ${_inputh} "" "")
|
PCH_SET_PRECOMPILED_HEADER_OUTPUT(${_targetName} ${_inputh} "" "")
|
||||||
LIST(APPEND PCH_OUTPUTS ${PCH_OUTPUT})
|
LIST(APPEND PCH_OUTPUTS ${PCH_OUTPUT})
|
||||||
|
|
||||||
PCH_SET_COMPILE_COMMAND(${_inputcpp} "${PCH_FLAGS}")
|
PCH_SET_COMPILE_COMMAND(${_inputcpp} "${PCH_FLAGS}" "${PCH_INCLUDES}")
|
||||||
PCH_CREATE_TARGET(${_targetName} ${_targetName}_pch)
|
PCH_CREATE_TARGET(${_targetName} ${_targetName}_pch)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
@ -525,7 +535,13 @@ MACRO(ADD_NATIVE_PRECOMPILED_HEADER _targetName _inputh _inputcpp)
|
||||||
SET_TARGET_PROPERTIES(${_targetName} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES")
|
SET_TARGET_PROPERTIES(${_targetName} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES")
|
||||||
ELSE()
|
ELSE()
|
||||||
#Fallback to the "old" precompiled suppport
|
#Fallback to the "old" precompiled suppport
|
||||||
ADD_PRECOMPILED_HEADER(${_targetName} ${_inputh} ${_inputcpp})
|
IF(CMAKE_OSX_ARCHITECTURES AND TARGETS_COUNT GREATER 1)
|
||||||
|
FOREACH(_ARCH ${CMAKE_OSX_ARCHITECTURES})
|
||||||
|
ADD_PRECOMPILED_HEADER(${_targetName}_${_ARCH} ${_inputh} ${_inputcpp})
|
||||||
|
ENDFOREACH()
|
||||||
|
ELSE()
|
||||||
|
ADD_PRECOMPILED_HEADER(${_targetName} ${_inputh} ${_inputcpp})
|
||||||
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(TARGET ${_targetName}_static)
|
IF(TARGET ${_targetName}_static)
|
||||||
|
|
|
@ -20,6 +20,7 @@ ENDIF()
|
||||||
IF(WITH_SOUND)
|
IF(WITH_SOUND)
|
||||||
FIND_PACKAGE(Ogg)
|
FIND_PACKAGE(Ogg)
|
||||||
FIND_PACKAGE(Vorbis)
|
FIND_PACKAGE(Vorbis)
|
||||||
|
FIND_PACKAGE(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL SWRESAMPLE)
|
||||||
|
|
||||||
IF(WITH_DRIVER_OPENAL)
|
IF(WITH_DRIVER_OPENAL)
|
||||||
FIND_PACKAGE(OpenAL)
|
FIND_PACKAGE(OpenAL)
|
||||||
|
|
|
@ -178,6 +178,10 @@ public:
|
||||||
CVertexBuffer Vertices;
|
CVertexBuffer Vertices;
|
||||||
CMaterial *Material;
|
CMaterial *Material;
|
||||||
CRGBA Color;
|
CRGBA Color;
|
||||||
|
ucstring Text;
|
||||||
|
|
||||||
|
uint32 CacheVersion;
|
||||||
|
|
||||||
/// The width of the string, in pixels (eg: 30)
|
/// The width of the string, in pixels (eg: 30)
|
||||||
float StringWidth;
|
float StringWidth;
|
||||||
/// The height of the string, in pixels (eg: 10)
|
/// The height of the string, in pixels (eg: 10)
|
||||||
|
@ -223,6 +227,7 @@ public:
|
||||||
*/
|
*/
|
||||||
CComputedString (bool bSetupVB=true)
|
CComputedString (bool bSetupVB=true)
|
||||||
{
|
{
|
||||||
|
CacheVersion = 0;
|
||||||
StringWidth = 0;
|
StringWidth = 0;
|
||||||
StringHeight = 0;
|
StringHeight = 0;
|
||||||
if (bSetupVB)
|
if (bSetupVB)
|
||||||
|
|
|
@ -74,6 +74,8 @@ public:
|
||||||
|
|
||||||
uint32 getUID() { return _UID; }
|
uint32 getUID() { return _UID; }
|
||||||
|
|
||||||
|
std::string getFontFileName() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static uint32 _FontGeneratorCounterUID;
|
static uint32 _FontGeneratorCounterUID;
|
||||||
|
|
|
@ -59,6 +59,9 @@ class CFontManager
|
||||||
CSmartPtr<CMaterial> _MatFont;
|
CSmartPtr<CMaterial> _MatFont;
|
||||||
CSmartPtr<CTextureFont> _TexFont;
|
CSmartPtr<CTextureFont> _TexFont;
|
||||||
|
|
||||||
|
// Keep track number of textures created to properly report cache version
|
||||||
|
uint32 _TexCacheNr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,6 +74,7 @@ public:
|
||||||
_NbChar = 0;
|
_NbChar = 0;
|
||||||
_MatFont = NULL;
|
_MatFont = NULL;
|
||||||
_TexFont = NULL;
|
_TexFont = NULL;
|
||||||
|
_TexCacheNr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,7 +98,6 @@ public:
|
||||||
*/
|
*/
|
||||||
CMaterial* getFontMaterial();
|
CMaterial* getFontMaterial();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute primitive blocks and materials of each character of
|
* Compute primitive blocks and materials of each character of
|
||||||
* the string.
|
* the string.
|
||||||
|
@ -152,7 +155,8 @@ public:
|
||||||
|
|
||||||
void dumpCache (const char *filename)
|
void dumpCache (const char *filename)
|
||||||
{
|
{
|
||||||
_TexFont->dumpTextureFont (filename);
|
if (_TexFont)
|
||||||
|
_TexFont->dumpTextureFont (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,6 +164,15 @@ public:
|
||||||
*/
|
*/
|
||||||
void invalidate();
|
void invalidate();
|
||||||
|
|
||||||
|
// get font atlas rebuild count
|
||||||
|
uint32 getCacheVersion() const
|
||||||
|
{
|
||||||
|
if (_TexFont)
|
||||||
|
return (_TexFont->getCacheVersion() << 16) + _TexCacheNr;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,10 @@ public:
|
||||||
{
|
{
|
||||||
nlassert (index < _CacheStrings.size());
|
nlassert (index < _CacheStrings.size());
|
||||||
CComputedString &rCS = _CacheStrings[index];
|
CComputedString &rCS = _CacheStrings[index];
|
||||||
|
if (rCS.CacheVersion != _FontManager->getCacheVersion())
|
||||||
|
{
|
||||||
|
computeString(rCS.Text, rCS);
|
||||||
|
}
|
||||||
if (_Shaded)
|
if (_Shaded)
|
||||||
{
|
{
|
||||||
CRGBA bkup = rCS.Color;
|
CRGBA bkup = rCS.Color;
|
||||||
|
@ -184,6 +188,10 @@ public:
|
||||||
{
|
{
|
||||||
nlassert (index < _CacheStrings.size());
|
nlassert (index < _CacheStrings.size());
|
||||||
CComputedString &rCS = _CacheStrings[index];
|
CComputedString &rCS = _CacheStrings[index];
|
||||||
|
if (rCS.CacheVersion != _FontManager->getCacheVersion())
|
||||||
|
{
|
||||||
|
computeString(rCS.Text, rCS);
|
||||||
|
}
|
||||||
if(_Shaded)
|
if(_Shaded)
|
||||||
{
|
{
|
||||||
CRGBA bkup = rCS.Color;
|
CRGBA bkup = rCS.Color;
|
||||||
|
@ -218,6 +226,11 @@ public:
|
||||||
{
|
{
|
||||||
nlassert (index < _CacheStrings.size());
|
nlassert (index < _CacheStrings.size());
|
||||||
CComputedString &rCS = _CacheStrings[index];
|
CComputedString &rCS = _CacheStrings[index];
|
||||||
|
if (rCS.CacheVersion != _FontManager->getCacheVersion())
|
||||||
|
{
|
||||||
|
computeString(rCS.Text, rCS);
|
||||||
|
}
|
||||||
|
|
||||||
if (_Shaded)
|
if (_Shaded)
|
||||||
{
|
{
|
||||||
CRGBA bkup = rCS.Color;
|
CRGBA bkup = rCS.Color;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#define NL_TEXTURE_FONT_H
|
#define NL_TEXTURE_FONT_H
|
||||||
|
|
||||||
#include "nel/misc/types_nl.h"
|
#include "nel/misc/types_nl.h"
|
||||||
|
#include "nel/misc/rect.h"
|
||||||
#include "nel/3d/texture.h"
|
#include "nel/3d/texture.h"
|
||||||
|
|
||||||
namespace NL3D
|
namespace NL3D
|
||||||
|
@ -25,9 +26,6 @@ namespace NL3D
|
||||||
|
|
||||||
class CFontGenerator;
|
class CFontGenerator;
|
||||||
|
|
||||||
#define TEXTUREFONT_NBCATEGORY 5 // Config 1
|
|
||||||
//#define TEXTUREFONT_NBCATEGORY 4
|
|
||||||
|
|
||||||
// ****************************************************************************
|
// ****************************************************************************
|
||||||
/**
|
/**
|
||||||
* CTextureFont
|
* CTextureFont
|
||||||
|
@ -37,32 +35,59 @@ class CTextureFont : public ITexture
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct SLetterInfo
|
// Holds info for glyphs rendered on atlas
|
||||||
|
struct SGlyphInfo
|
||||||
{
|
{
|
||||||
// To generate the letter
|
// font atlas info
|
||||||
ucchar Char;
|
uint32 CacheVersion;
|
||||||
CFontGenerator *FontGenerator;
|
|
||||||
|
// atlas region with padding
|
||||||
|
uint32 X, Y, W, H;
|
||||||
|
|
||||||
|
// rendered glyph size without padding
|
||||||
|
uint32 CharWidth;
|
||||||
|
uint32 CharHeight;
|
||||||
|
|
||||||
|
// UV coords for rendered glyph without padding
|
||||||
|
float U0, V0, U1, V1;
|
||||||
|
|
||||||
|
uint32 GlyphIndex;
|
||||||
sint Size;
|
sint Size;
|
||||||
bool Embolden;
|
bool Embolden;
|
||||||
bool Oblique;
|
bool Oblique;
|
||||||
|
CFontGenerator *FontGenerator;
|
||||||
|
|
||||||
|
SGlyphInfo()
|
||||||
|
: CacheVersion(0),
|
||||||
|
U0(0.f), V0(0.f), U1(0.f), V1(0.f),
|
||||||
|
X(0), Y(0), W(0), H(0), CharWidth(0), CharHeight(0),
|
||||||
|
GlyphIndex(0), Size(0), Embolden(false), Oblique(false), FontGenerator(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// The less recently used infos
|
// Holds info for glyphs displayed on screen
|
||||||
SLetterInfo *Next, *Prev;
|
struct SLetterInfo
|
||||||
|
{
|
||||||
|
ucchar Char;
|
||||||
|
sint Size;
|
||||||
|
bool Embolden;
|
||||||
|
bool Oblique;
|
||||||
|
CFontGenerator *FontGenerator;
|
||||||
|
|
||||||
uint Cat; // 8x8, 16x16, 24x24, 32x32
|
uint32 GlyphIndex;
|
||||||
|
uint32 CharWidth; // Displayed glyph height
|
||||||
//////////////////////////////////////////////////////////////////////
|
uint32 CharHeight; // Displayed glyph height
|
||||||
|
|
||||||
float U ,V;
|
|
||||||
uint32 CharWidth;
|
|
||||||
uint32 CharHeight;
|
|
||||||
uint32 GlyphIndex; // number of the character in the this font
|
|
||||||
sint32 Top; // Distance between origin and top of the texture
|
sint32 Top; // Distance between origin and top of the texture
|
||||||
sint32 Left; // Distance between origin and left of the texture
|
sint32 Left; // Distance between origin and left of the texture
|
||||||
sint32 AdvX; // Advance to the next caracter
|
sint32 AdvX; // Advance to the next caracter
|
||||||
|
|
||||||
SLetterInfo():Char(0), FontGenerator(NULL), Size(0), Embolden(false), Oblique(false), Next(NULL), Prev(NULL), Cat(0), CharWidth(0), CharHeight(0), GlyphIndex(0), Top(0), Left(0), AdvX(0)
|
SGlyphInfo* glyph;
|
||||||
|
|
||||||
|
SLetterInfo()
|
||||||
|
: Char(0), Size(0), Embolden(false), Oblique(false), FontGenerator(NULL),
|
||||||
|
GlyphIndex(0), CharWidth(0), CharHeight(0), Top(0), Left(0), AdvX(0),
|
||||||
|
glyph(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -70,14 +95,13 @@ public:
|
||||||
struct SLetterKey
|
struct SLetterKey
|
||||||
{
|
{
|
||||||
ucchar Char;
|
ucchar Char;
|
||||||
CFontGenerator *FontGenerator;
|
|
||||||
sint Size;
|
sint Size;
|
||||||
bool Embolden;
|
bool Embolden;
|
||||||
bool Oblique;
|
bool Oblique;
|
||||||
|
CFontGenerator *FontGenerator;
|
||||||
|
|
||||||
|
// Does not use FontGenerator in return value
|
||||||
uint32 getVal();
|
uint32 getVal();
|
||||||
//bool operator < (const SLetterKey&k) const;
|
|
||||||
//bool operator == (const SLetterKey&k) const;
|
|
||||||
|
|
||||||
SLetterKey():Char(0), FontGenerator(NULL), Size(0), Embolden(false), Oblique(false)
|
SLetterKey():Char(0), FontGenerator(NULL), Size(0), Embolden(false), Oblique(false)
|
||||||
{
|
{
|
||||||
|
@ -96,19 +120,76 @@ public:
|
||||||
void doGenerate (bool async = false);
|
void doGenerate (bool async = false);
|
||||||
|
|
||||||
// This function manage the cache if the letter wanted does not exist
|
// This function manage the cache if the letter wanted does not exist
|
||||||
SLetterInfo* getLetterInfo (SLetterKey& k);
|
// \param render Set to true if letter is currently visible on screen
|
||||||
|
SLetterInfo* getLetterInfo (SLetterKey& k, bool render);
|
||||||
|
|
||||||
void dumpTextureFont (const char *filename);
|
void dumpTextureFont (const char *filename);
|
||||||
|
|
||||||
|
// Version is increased with each rebuild of font atlas
|
||||||
|
uint32 getCacheVersion() const { return _CacheVersion; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint32 _CacheVersion;
|
||||||
|
|
||||||
|
// current texture size
|
||||||
|
uint32 _TextureSizeX;
|
||||||
|
uint32 _TextureSizeY;
|
||||||
|
|
||||||
|
// maximum texture size allowed
|
||||||
|
uint32 _TextureMaxW;
|
||||||
|
uint32 _TextureMaxH;
|
||||||
|
|
||||||
|
// padding around glyphs
|
||||||
|
uint8 _PaddingL, _PaddingT;
|
||||||
|
uint8 _PaddingR, _PaddingB;
|
||||||
|
|
||||||
// To find a letter in the texture
|
// To find a letter in the texture
|
||||||
std::map<uint32, SLetterInfo*> Accel;
|
|
||||||
|
|
||||||
std::vector<SLetterInfo> Letters[TEXTUREFONT_NBCATEGORY];
|
// Keep track of available space in main texture
|
||||||
SLetterInfo *Front[TEXTUREFONT_NBCATEGORY], *Back[TEXTUREFONT_NBCATEGORY];
|
std::vector<NLMISC::CRect> _AtlasNodes;
|
||||||
|
|
||||||
void rebuildLetter (sint cat, sint x, sint y);
|
std::vector <SLetterInfo> _Letters;
|
||||||
|
|
||||||
|
// lookup letter from letter cache or create new
|
||||||
|
SLetterInfo* findLetter(SLetterKey& k, bool insert);
|
||||||
|
|
||||||
|
// lower/upper bound of glyphs to render, sizes outside are scaled bitmaps
|
||||||
|
uint _MinGlyphSize;
|
||||||
|
uint _MaxGlyphSize;
|
||||||
|
// start using size stem from this font size
|
||||||
|
uint _GlyphSizeStepMin;
|
||||||
|
// every n'th font size is rendered, intermediates are using bitmap scaling
|
||||||
|
uint _GlyphSizeStep;
|
||||||
|
|
||||||
|
// rendered glyph cache
|
||||||
|
std::list<SGlyphInfo> _GlyphCache;
|
||||||
|
SGlyphInfo* findLetterGlyph(SLetterInfo *letter, bool insert);
|
||||||
|
|
||||||
|
// render letter glyph into glyph cache
|
||||||
|
SGlyphInfo* renderLetterGlyph(SLetterInfo *letter, uint32 bitmapFontSize);
|
||||||
|
|
||||||
|
// copy glyph bitmap into texture and invalidate that region
|
||||||
|
void copyGlyphBitmap(uint8* bitmap, uint32 bitmapW, uint32 bitmapH, uint32 atlasX, uint32 atlasY);
|
||||||
|
|
||||||
|
// Find best fit for WxH rect in atlas
|
||||||
|
uint fitRegion(uint index, uint width, uint height);
|
||||||
|
|
||||||
|
// Return top/left from font texture or false if there is no more room
|
||||||
|
bool reserveAtlas(const uint32 width, const uint32 height, uint32 &x, uint32 &y);
|
||||||
|
|
||||||
|
// repack glyphs, resize texture, and invalidate unused glyphs.
|
||||||
|
void repackAtlas();
|
||||||
|
void repackAtlas(uint32 width, uint32 height);
|
||||||
|
|
||||||
|
// resize texture,
|
||||||
|
bool resizeAtlas();
|
||||||
|
|
||||||
|
// remove all glyphs from atlas, clear glyph cache, letter info is kept
|
||||||
|
void clearAtlas();
|
||||||
|
|
||||||
|
// if return true: newW, newH contains next size font atlas should be resized
|
||||||
|
// if return false: _TextureMaxW and _TextureMaxH is reached
|
||||||
|
bool getNextTextureSize(uint32 &newW, uint32 &newH) const;
|
||||||
|
|
||||||
/// Todo: serialize a font texture.
|
/// Todo: serialize a font texture.
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -175,6 +175,7 @@ namespace NLGUI
|
||||||
bool _CallingAH : 1;
|
bool _CallingAH : 1;
|
||||||
bool _Cancelable : 1; // true if the slider may be cancelled when pressed on the mouse right button
|
bool _Cancelable : 1; // true if the slider may be cancelled when pressed on the mouse right button
|
||||||
bool _Frozen : 1;
|
bool _Frozen : 1;
|
||||||
|
bool _Scale : 1;
|
||||||
|
|
||||||
// For Target Scroller only: the target offset step in pixel.
|
// For Target Scroller only: the target offset step in pixel.
|
||||||
sint32 _TargetStepX;
|
sint32 _TargetStepX;
|
||||||
|
|
|
@ -111,9 +111,19 @@ namespace NLGUI
|
||||||
sint32 getWMin() const { return _WMin; }
|
sint32 getWMin() const { return _WMin; }
|
||||||
void setWMin( sint32 wmin ) { _WMin = wmin; }
|
void setWMin( sint32 wmin ) { _WMin = wmin; }
|
||||||
|
|
||||||
|
sint32 getHMin() const { return _HMin; }
|
||||||
|
void setHMin( sint32 hmin ) { _HMin = hmin; }
|
||||||
|
|
||||||
// Compute Size according to bitmap and Text (Ensure as big as possible button)
|
// Compute Size according to bitmap and Text (Ensure as big as possible button)
|
||||||
sint32 getWMax() const;
|
sint32 getWMax() const;
|
||||||
|
|
||||||
|
// Set texture directly without _l.tga, _m.tga, _r.tga convention
|
||||||
|
// Texture size is only read from normal textures
|
||||||
|
// If updateHeight == false, then _BmpH will keep its value
|
||||||
|
void setTexture(const std::string &l, const std::string &m, const std::string &r, bool updateHeight = true);
|
||||||
|
void setTexturePushed(const std::string &l, const std::string &m, const std::string &r);
|
||||||
|
void setTextureOver(const std::string &l, const std::string &m, const std::string &r);
|
||||||
|
|
||||||
int luaGetViewText(CLuaState &ls);
|
int luaGetViewText(CLuaState &ls);
|
||||||
|
|
||||||
REFLECT_EXPORT_START(CCtrlTextButton, CCtrlBaseButton)
|
REFLECT_EXPORT_START(CCtrlTextButton, CCtrlBaseButton)
|
||||||
|
@ -122,6 +132,7 @@ namespace NLGUI
|
||||||
REFLECT_SINT32("text_x", getTextX, setTextX)
|
REFLECT_SINT32("text_x", getTextX, setTextX)
|
||||||
REFLECT_SINT32("wmargin", getWMargin, setWMargin)
|
REFLECT_SINT32("wmargin", getWMargin, setWMargin)
|
||||||
REFLECT_SINT32("wmin", getWMin, setWMin)
|
REFLECT_SINT32("wmin", getWMin, setWMin)
|
||||||
|
REFLECT_SINT32("hmin", getHMin, setHMin)
|
||||||
REFLECT_LUA_METHOD("getViewText", luaGetViewText)
|
REFLECT_LUA_METHOD("getViewText", luaGetViewText)
|
||||||
REFLECT_EXPORT_END
|
REFLECT_EXPORT_END
|
||||||
|
|
||||||
|
@ -151,8 +162,8 @@ namespace NLGUI
|
||||||
sint32 _BmpLeftW, _BmpMiddleW, _BmpRightW, _BmpH;
|
sint32 _BmpLeftW, _BmpMiddleW, _BmpRightW, _BmpH;
|
||||||
// Value to add to TextW to get button W.
|
// Value to add to TextW to get button W.
|
||||||
sint32 _WMargin;
|
sint32 _WMargin;
|
||||||
// Min W Value
|
// Min W, H Value
|
||||||
sint32 _WMin;
|
sint32 _WMin, _HMin;
|
||||||
sint32 _TextY;
|
sint32 _TextY;
|
||||||
sint32 _TextX;
|
sint32 _TextX;
|
||||||
THotSpot _TextPosRef;
|
THotSpot _TextPosRef;
|
||||||
|
|
|
@ -85,6 +85,7 @@ namespace NLGUI
|
||||||
// view text
|
// view text
|
||||||
void setViewText(const ucstring & text);
|
void setViewText(const ucstring & text);
|
||||||
ucstring getViewText() const;
|
ucstring getViewText() const;
|
||||||
|
CViewText *getViewText();
|
||||||
|
|
||||||
void setTexture(uint i, const ucstring &texture);
|
void setTexture(uint i, const ucstring &texture);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ typedef std::map<std::string, std::string> TStyle;
|
||||||
namespace NLGUI
|
namespace NLGUI
|
||||||
{
|
{
|
||||||
class CCtrlButton;
|
class CCtrlButton;
|
||||||
|
class CCtrlTextButton;
|
||||||
class CCtrlScroll;
|
class CCtrlScroll;
|
||||||
class CGroupList;
|
class CGroupList;
|
||||||
class CGroupMenu;
|
class CGroupMenu;
|
||||||
|
@ -105,6 +106,9 @@ namespace NLGUI
|
||||||
Height=-1;
|
Height=-1;
|
||||||
MaxWidth=-1;
|
MaxWidth=-1;
|
||||||
MaxHeight=-1;
|
MaxHeight=-1;
|
||||||
|
BorderWidth=1;
|
||||||
|
BackgroundColor=NLMISC::CRGBA::Black;
|
||||||
|
BackgroundColorOver=NLMISC::CRGBA::Black;
|
||||||
}
|
}
|
||||||
uint FontSize;
|
uint FontSize;
|
||||||
uint FontWeight;
|
uint FontWeight;
|
||||||
|
@ -119,6 +123,9 @@ namespace NLGUI
|
||||||
sint32 Height;
|
sint32 Height;
|
||||||
sint32 MaxWidth;
|
sint32 MaxWidth;
|
||||||
sint32 MaxHeight;
|
sint32 MaxHeight;
|
||||||
|
sint32 BorderWidth;
|
||||||
|
NLMISC::CRGBA BackgroundColor;
|
||||||
|
NLMISC::CRGBA BackgroundColorOver;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ImageDownload system
|
// ImageDownload system
|
||||||
|
@ -262,6 +269,8 @@ namespace NLGUI
|
||||||
void browseUndo ();
|
void browseUndo ();
|
||||||
// Redo browse: Browse the precedent url undoed. no op if none
|
// Redo browse: Browse the precedent url undoed. no op if none
|
||||||
void browseRedo ();
|
void browseRedo ();
|
||||||
|
// disable refresh button
|
||||||
|
void clearRefresh();
|
||||||
// clear undo/redo
|
// clear undo/redo
|
||||||
void clearUndoRedo();
|
void clearUndoRedo();
|
||||||
|
|
||||||
|
@ -270,6 +279,8 @@ namespace NLGUI
|
||||||
void setURL(const std::string &url);
|
void setURL(const std::string &url);
|
||||||
|
|
||||||
|
|
||||||
|
int luaClearRefresh(CLuaState &ls);
|
||||||
|
int luaClearUndoRedo(CLuaState &ls);
|
||||||
int luaBrowse(CLuaState &ls);
|
int luaBrowse(CLuaState &ls);
|
||||||
int luaRefresh(CLuaState &ls);
|
int luaRefresh(CLuaState &ls);
|
||||||
int luaRemoveContent(CLuaState &ls);
|
int luaRemoveContent(CLuaState &ls);
|
||||||
|
@ -285,6 +296,8 @@ namespace NLGUI
|
||||||
REFLECT_EXPORT_START(CGroupHTML, CGroupScrollText)
|
REFLECT_EXPORT_START(CGroupHTML, CGroupScrollText)
|
||||||
REFLECT_LUA_METHOD("browse", luaBrowse)
|
REFLECT_LUA_METHOD("browse", luaBrowse)
|
||||||
REFLECT_LUA_METHOD("refresh", luaRefresh)
|
REFLECT_LUA_METHOD("refresh", luaRefresh)
|
||||||
|
REFLECT_LUA_METHOD("clearUndoRedo", luaClearUndoRedo)
|
||||||
|
REFLECT_LUA_METHOD("clearRefresh", luaClearRefresh)
|
||||||
REFLECT_LUA_METHOD("removeContent", luaRemoveContent)
|
REFLECT_LUA_METHOD("removeContent", luaRemoveContent)
|
||||||
REFLECT_LUA_METHOD("insertText", luaInsertText)
|
REFLECT_LUA_METHOD("insertText", luaInsertText)
|
||||||
REFLECT_LUA_METHOD("addString", luaAddString)
|
REFLECT_LUA_METHOD("addString", luaAddString)
|
||||||
|
@ -296,6 +309,7 @@ namespace NLGUI
|
||||||
REFLECT_LUA_METHOD("renderHtml", luaRenderHtml)
|
REFLECT_LUA_METHOD("renderHtml", luaRenderHtml)
|
||||||
REFLECT_STRING("url", getURL, setURL)
|
REFLECT_STRING("url", getURL, setURL)
|
||||||
REFLECT_FLOAT("timeout", getTimeout, setTimeout)
|
REFLECT_FLOAT("timeout", getTimeout, setTimeout)
|
||||||
|
REFLECT_STRING("title", getTitle, setTitle)
|
||||||
REFLECT_EXPORT_END
|
REFLECT_EXPORT_END
|
||||||
|
|
||||||
protected :
|
protected :
|
||||||
|
@ -339,6 +353,9 @@ namespace NLGUI
|
||||||
// Get Home URL
|
// Get Home URL
|
||||||
virtual std::string home();
|
virtual std::string home();
|
||||||
|
|
||||||
|
// Clear style stack and restore default style
|
||||||
|
void resetCssStyle();
|
||||||
|
|
||||||
// Parse style html tag
|
// Parse style html tag
|
||||||
TStyle parseStyle(const std::string &str_styles);
|
TStyle parseStyle(const std::string &str_styles);
|
||||||
|
|
||||||
|
@ -366,7 +383,7 @@ namespace NLGUI
|
||||||
void addString(const ucstring &str);
|
void addString(const ucstring &str);
|
||||||
|
|
||||||
// Add an image in the current paragraph
|
// Add an image in the current paragraph
|
||||||
void addImage(const char *image, bool reloadImg=false, const CStyleParams &style = CStyleParams());
|
void addImage(const std::string &id, const char *image, bool reloadImg=false, const CStyleParams &style = CStyleParams());
|
||||||
|
|
||||||
// Add a text area in the current paragraph
|
// Add a text area in the current paragraph
|
||||||
CInterfaceGroup *addTextArea (const std::string &templateName, const char *name, uint rows, uint cols, bool multiLine, const ucstring &content, uint maxlength);
|
CInterfaceGroup *addTextArea (const std::string &templateName, const char *name, uint rows, uint cols, bool multiLine, const ucstring &content, uint maxlength);
|
||||||
|
@ -391,6 +408,8 @@ namespace NLGUI
|
||||||
|
|
||||||
// Set the title
|
// Set the title
|
||||||
void setTitle (const ucstring &title);
|
void setTitle (const ucstring &title);
|
||||||
|
void setTitle (const std::string &title);
|
||||||
|
std::string getTitle() const;
|
||||||
|
|
||||||
// Lookup a url in local file system
|
// Lookup a url in local file system
|
||||||
bool lookupLocalFile (std::string &result, const char *url, bool isUrl);
|
bool lookupLocalFile (std::string &result, const char *url, bool isUrl);
|
||||||
|
@ -780,7 +799,7 @@ namespace NLGUI
|
||||||
static TGroupHtmlByUIDMap _GroupHtmlByUID;
|
static TGroupHtmlByUIDMap _GroupHtmlByUID;
|
||||||
|
|
||||||
// read style attribute
|
// read style attribute
|
||||||
void getStyleParams(const std::string &styleString, CStyleParams &style, bool inherit = true);
|
void getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams ¤t);
|
||||||
void applyCssMinMax(sint32 &width, sint32 &height, sint32 minw=0, sint32 minh=0, sint32 maxw=0, sint32 maxh=0);
|
void applyCssMinMax(sint32 &width, sint32 &height, sint32 minw=0, sint32 minh=0, sint32 maxw=0, sint32 maxh=0);
|
||||||
|
|
||||||
// load and render local html file (from bnp for example)
|
// load and render local html file (from bnp for example)
|
||||||
|
@ -846,6 +865,9 @@ namespace NLGUI
|
||||||
void setImage(CViewBase *view, const std::string &file, const TImageType type);
|
void setImage(CViewBase *view, const std::string &file, const TImageType type);
|
||||||
void setImageSize(CViewBase *view, const CStyleParams &style = CStyleParams());
|
void setImageSize(CViewBase *view, const CStyleParams &style = CStyleParams());
|
||||||
|
|
||||||
|
void setTextButtonStyle(CCtrlTextButton *ctrlButton, const CStyleParams &style);
|
||||||
|
void setTextStyle(CViewText *pVT, const CStyleParams &style);
|
||||||
|
|
||||||
// BnpDownload system
|
// BnpDownload system
|
||||||
void initBnpDownload();
|
void initBnpDownload();
|
||||||
void checkBnpDownload();
|
void checkBnpDownload();
|
||||||
|
|
|
@ -351,6 +351,9 @@ namespace NLGUI
|
||||||
void setMinW(sint32 minW);
|
void setMinW(sint32 minW);
|
||||||
void setMinH(sint32 minH);
|
void setMinH(sint32 minH);
|
||||||
|
|
||||||
|
// change fontsize for new menu items
|
||||||
|
void setFontSize(uint32 fontSize);
|
||||||
|
|
||||||
// Gray a line on the RootMenu
|
// Gray a line on the RootMenu
|
||||||
void setGrayedLine(uint line, bool g);
|
void setGrayedLine(uint line, bool g);
|
||||||
|
|
||||||
|
|
|
@ -206,6 +206,11 @@ namespace NLGUI
|
||||||
invalidateContent();
|
invalidateContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// temporarily enable mouse over effect
|
||||||
|
// will be automatically disabled when mouse leaves element
|
||||||
|
void enableTempOver() { _TempOver = true; }
|
||||||
|
void disableTempOver() { _TempOver = false; }
|
||||||
|
|
||||||
/// \from CInterfaceElement
|
/// \from CInterfaceElement
|
||||||
void onInvalidateContent();
|
void onInvalidateContent();
|
||||||
sint32 getMaxUsedW() const;
|
sint32 getMaxUsedW() const;
|
||||||
|
@ -233,6 +238,8 @@ namespace NLGUI
|
||||||
|
|
||||||
// Do we have a color under the element pointed by the mouse
|
// Do we have a color under the element pointed by the mouse
|
||||||
bool _Over;
|
bool _Over;
|
||||||
|
// Temporarily force mouse over effect. Deactivated when mouse moves away
|
||||||
|
bool _TempOver;
|
||||||
|
|
||||||
// If over is true so we have a color
|
// If over is true so we have a color
|
||||||
NLMISC::CRGBA _OverColor;
|
NLMISC::CRGBA _OverColor;
|
||||||
|
|
|
@ -38,6 +38,16 @@ namespace NLGUI
|
||||||
class IActionHandler;
|
class IActionHandler;
|
||||||
class CGroupParagraph;
|
class CGroupParagraph;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for UI scale change event
|
||||||
|
*/
|
||||||
|
class IInterfaceScaleWatcher
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IInterfaceScaleWatcher(){}
|
||||||
|
virtual void onInterfaceScaleChanged()=0;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A visitor to walk a tree of interface elements and apply a teartment on them.
|
* A visitor to walk a tree of interface elements and apply a teartment on them.
|
||||||
*
|
*
|
||||||
|
@ -66,7 +76,7 @@ namespace NLGUI
|
||||||
* \author Nevrax France
|
* \author Nevrax France
|
||||||
* \date 2002
|
* \date 2002
|
||||||
*/
|
*/
|
||||||
class CInterfaceElement : public CReflectableRefPtrTarget, public NLMISC::IStreamable
|
class CInterfaceElement : public IInterfaceScaleWatcher, public CReflectableRefPtrTarget, public NLMISC::IStreamable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -409,6 +419,10 @@ namespace NLGUI
|
||||||
*/
|
*/
|
||||||
virtual void onInvalidateContent() {}
|
virtual void onInvalidateContent() {}
|
||||||
|
|
||||||
|
/* Element UI scale change event callback
|
||||||
|
*/
|
||||||
|
virtual void onInterfaceScaleChanged() {}
|
||||||
|
|
||||||
// called by interfaceManager for master window only
|
// called by interfaceManager for master window only
|
||||||
void resetInvalidCoords();
|
void resetInvalidCoords();
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,14 @@ namespace NLGUI
|
||||||
#undef HTML_ATTR
|
#undef HTML_ATTR
|
||||||
#define HTML_ATTR(t,a) MY_HTML_##t##_##a
|
#define HTML_ATTR(t,a) MY_HTML_##t##_##a
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
HTML_ATTR(HTML,DIR) = 0,
|
||||||
|
HTML_ATTR(HTML,LANG),
|
||||||
|
HTML_ATTR(HTML,VERSION),
|
||||||
|
HTML_ATTR(HTML,STYLE),
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
HTML_ATTR(A,ACCESSKEY) = 0,
|
HTML_ATTR(A,ACCESSKEY) = 0,
|
||||||
|
@ -208,6 +216,7 @@ namespace NLGUI
|
||||||
HTML_ATTR(P,QUICK_HELP_EVENTS),
|
HTML_ATTR(P,QUICK_HELP_EVENTS),
|
||||||
HTML_ATTR(P,QUICK_HELP_LINK),
|
HTML_ATTR(P,QUICK_HELP_LINK),
|
||||||
HTML_ATTR(P,NAME),
|
HTML_ATTR(P,NAME),
|
||||||
|
HTML_ATTR(P,STYLE),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -271,6 +280,9 @@ namespace NLGUI
|
||||||
#undef HTML_ATTR
|
#undef HTML_ATTR
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
// Read a CSS length value, return true if one of supported units '%, rem, em, px, pt'
|
||||||
|
// On failure: 'value' and 'unit' values are undefined
|
||||||
|
bool getCssLength (float &value, std::string &unit, const std::string &str);
|
||||||
|
|
||||||
// Read a width HTML parameter. "100" or "100%". Returns true if percent (0 ~ 1) else false
|
// Read a width HTML parameter. "100" or "100%". Returns true if percent (0 ~ 1) else false
|
||||||
bool getPercentage (sint32 &width, float &percent, const char *str);
|
bool getPercentage (sint32 &width, float &percent, const char *str);
|
||||||
|
|
|
@ -176,6 +176,13 @@ namespace NLGUI
|
||||||
*/
|
*/
|
||||||
void getScreenOOSize (float &oow, float &ooh);
|
void getScreenOOSize (float &oow, float &ooh);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UI scaling
|
||||||
|
*/
|
||||||
|
void setInterfaceScale(float scale, sint32 width = 0, sint32 height = 0);
|
||||||
|
float getInterfaceScale() const { return _InterfaceScale; }
|
||||||
|
void setBilinearFiltering(bool b) { _Bilinear = b; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* is the Screen minimized?
|
* is the Screen minimized?
|
||||||
*/
|
*/
|
||||||
|
@ -185,7 +192,7 @@ namespace NLGUI
|
||||||
* drawBitmap : this is the interface with all the views
|
* drawBitmap : this is the interface with all the views
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void drawRotFlipBitmap (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, uint8 rot, bool flipv,
|
void drawRotFlipBitmap (sint layerId, float x, float y, float width, float height, uint8 rot, bool flipv,
|
||||||
sint32 nTxId, const NLMISC::CRGBA &col = NLMISC::CRGBA(255,255,255,255));
|
sint32 nTxId, const NLMISC::CRGBA &col = NLMISC::CRGBA(255,255,255,255));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -526,6 +533,14 @@ namespace NLGUI
|
||||||
float _OneOverScreenW, _OneOverScreenH;
|
float _OneOverScreenW, _OneOverScreenH;
|
||||||
bool _IsMinimized;
|
bool _IsMinimized;
|
||||||
|
|
||||||
|
// UI scaling
|
||||||
|
float _InterfaceScale;
|
||||||
|
float _InterfaceUserScale;
|
||||||
|
sint32 _InterfaceBaseW, _InterfaceBaseH;
|
||||||
|
sint32 _EffectiveScreenW, _EffectiveScreenH;
|
||||||
|
bool _Bilinear;
|
||||||
|
|
||||||
|
void updateInterfaceScale();
|
||||||
|
|
||||||
//map linking a uint to a bitmap. Used to display figurs
|
//map linking a uint to a bitmap. Used to display figurs
|
||||||
std::vector<sint32> _IndexesToTextureIds;
|
std::vector<sint32> _IndexesToTextureIds;
|
||||||
|
@ -596,7 +611,6 @@ namespace NLGUI
|
||||||
/// Set of hw cursor images
|
/// Set of hw cursor images
|
||||||
static std::set< std::string > *hwCursors;
|
static std::set< std::string > *hwCursors;
|
||||||
static float hwCursorScale;
|
static float hwCursorScale;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace NLGUI
|
||||||
class CViewText : public CViewBase
|
class CViewText : public CViewBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum TTextMode { ClipWord, DontClipWord, Justified };
|
enum TTextMode { ClipWord, DontClipWord, Justified, Centered };
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DECLARE_UI_CLASS(CViewText)
|
DECLARE_UI_CLASS(CViewText)
|
||||||
|
@ -70,6 +70,7 @@ namespace NLGUI
|
||||||
virtual void checkCoords();
|
virtual void checkCoords();
|
||||||
virtual void updateCoords();
|
virtual void updateCoords();
|
||||||
virtual void onAddToGroup();
|
virtual void onAddToGroup();
|
||||||
|
virtual void onInterfaceScaleChanged();
|
||||||
|
|
||||||
/// From CInterfaceElement
|
/// From CInterfaceElement
|
||||||
sint32 getMaxUsedW() const;
|
sint32 getMaxUsedW() const;
|
||||||
|
@ -81,7 +82,7 @@ namespace NLGUI
|
||||||
|
|
||||||
void setText (const ucstring &text);
|
void setText (const ucstring &text);
|
||||||
void setFontName (const std::string &name);
|
void setFontName (const std::string &name);
|
||||||
void setFontSize (sint nFontSize);
|
void setFontSize (sint nFontSize, bool coef = true);
|
||||||
void setEmbolden (bool nEmbolden);
|
void setEmbolden (bool nEmbolden);
|
||||||
void setOblique (bool nOblique);
|
void setOblique (bool nOblique);
|
||||||
void setColor (const NLMISC::CRGBA &color);
|
void setColor (const NLMISC::CRGBA &color);
|
||||||
|
@ -90,6 +91,7 @@ namespace NLGUI
|
||||||
void setShadowColor (const NLMISC::CRGBA &color);
|
void setShadowColor (const NLMISC::CRGBA &color);
|
||||||
void setShadowOffset (sint x, sint y);
|
void setShadowOffset (sint x, sint y);
|
||||||
void setLineMaxW (sint nMaxW, bool invalidate=true);
|
void setLineMaxW (sint nMaxW, bool invalidate=true);
|
||||||
|
void setOverflowText(const ucstring &text) { _OverflowText = text; }
|
||||||
void setMultiLine (bool bMultiLine);
|
void setMultiLine (bool bMultiLine);
|
||||||
void setMultiLineSpace (sint nMultiLineSpace);
|
void setMultiLineSpace (sint nMultiLineSpace);
|
||||||
void setMultiLineMaxWOnly (bool state);
|
void setMultiLineMaxWOnly (bool state);
|
||||||
|
@ -98,6 +100,9 @@ namespace NLGUI
|
||||||
void setMultiMaxLine(uint l) { _MultiMaxLine = l; }
|
void setMultiMaxLine(uint l) { _MultiMaxLine = l; }
|
||||||
void setMultiMinLine(uint l) { _MultiMinLine = l; }
|
void setMultiMinLine(uint l) { _MultiMinLine = l; }
|
||||||
|
|
||||||
|
// Override chars used to compute font size
|
||||||
|
void setFontSizing(const std::string &chars, const std::string &fallback);
|
||||||
|
|
||||||
// Force only a subset of letter to be displayed. Default is 0/0xFFFFFFFF
|
// Force only a subset of letter to be displayed. Default is 0/0xFFFFFFFF
|
||||||
void enableStringSelection(uint start, uint end);
|
void enableStringSelection(uint start, uint end);
|
||||||
void disableStringSelection();
|
void disableStringSelection();
|
||||||
|
@ -115,6 +120,7 @@ namespace NLGUI
|
||||||
NLMISC::CRGBA getShadowColor() { return _ShadowColor; }
|
NLMISC::CRGBA getShadowColor() { return _ShadowColor; }
|
||||||
void getShadowOffset(sint &x, sint &y) { x = _ShadowX; y = _ShadowY; }
|
void getShadowOffset(sint &x, sint &y) { x = _ShadowX; y = _ShadowY; }
|
||||||
sint getLineMaxW() const { return _LineMaxW; }
|
sint getLineMaxW() const { return _LineMaxW; }
|
||||||
|
ucstring getOverflowText() const { return _OverflowText; }
|
||||||
bool getMultiLine() const { return _MultiLine; }
|
bool getMultiLine() const { return _MultiLine; }
|
||||||
sint getMultiLineSpace() const { return _MultiLineSpace; }
|
sint getMultiLineSpace() const { return _MultiLineSpace; }
|
||||||
bool getMultiLineMaxWOnly() const { return _MultiLineMaxWOnly; }
|
bool getMultiLineMaxWOnly() const { return _MultiLineMaxWOnly; }
|
||||||
|
@ -128,6 +134,8 @@ namespace NLGUI
|
||||||
uint getFontHeight() const;
|
uint getFontHeight() const;
|
||||||
// get current font leg height, in pixels
|
// get current font leg height, in pixels
|
||||||
uint getFontLegHeight() const;
|
uint getFontLegHeight() const;
|
||||||
|
// get current line height, in pixels
|
||||||
|
float getLineHeight() const;
|
||||||
// Set the display mode (supported with multiline only for now)
|
// Set the display mode (supported with multiline only for now)
|
||||||
void setTextMode(TTextMode mode);
|
void setTextMode(TTextMode mode);
|
||||||
TTextMode getTextMode() const { return _TextMode; }
|
TTextMode getTextMode() const { return _TextMode; }
|
||||||
|
@ -148,11 +156,11 @@ namespace NLGUI
|
||||||
* When looking at standard edit box, we see that if a line is split accross to line with no
|
* When looking at standard edit box, we see that if a line is split accross to line with no
|
||||||
* This also returns the height of the line
|
* This also returns the height of the line
|
||||||
*/
|
*/
|
||||||
void getCharacterPositionFromIndex(sint index, bool lineEnd, sint &x, sint &y, sint &height) const;
|
void getCharacterPositionFromIndex(sint index, bool lineEnd, float &x, float &y, float &height) const;
|
||||||
/** From a coordinate relative to the BR BR corner of the text, return the index of a character.
|
/** From a coordinate relative to the BR BR corner of the text, return the index of a character.
|
||||||
* If no character is found at the given position, the closest character is returned (first or last character, for the line or the whole text)
|
* If no character is found at the given position, the closest character is returned (first or last character, for the line or the whole text)
|
||||||
*/
|
*/
|
||||||
void getCharacterIndexFromPosition(sint x, sint y, uint &index, bool &lineEnd) const;
|
void getCharacterIndexFromPosition(float x, float y, uint &index, bool &lineEnd) const;
|
||||||
/** From a character index, get the index of the line it belongs to, or -1 if the index is invalid
|
/** From a character index, get the index of the line it belongs to, or -1 if the index is invalid
|
||||||
* \param cursorDisplayedAtEndOfPreviousLine true if the cursor is displayed at the end of the previous line that match its index
|
* \param cursorDisplayedAtEndOfPreviousLine true if the cursor is displayed at the end of the previous line that match its index
|
||||||
*/
|
*/
|
||||||
|
@ -235,15 +243,21 @@ namespace NLGUI
|
||||||
std::string _FontName;
|
std::string _FontName;
|
||||||
/// the font size
|
/// the font size
|
||||||
sint _FontSize;
|
sint _FontSize;
|
||||||
|
bool _FontSizeCoef;
|
||||||
bool _Embolden;
|
bool _Embolden;
|
||||||
bool _Oblique;
|
bool _Oblique;
|
||||||
// width of the font in pixel. Just a Hint for tabing format (computed with '_')
|
// width of the font in pixel. Just a Hint for tabing format (computed with '_')
|
||||||
uint _FontWidth;
|
float _FontWidth;
|
||||||
|
// strings to use when computing font size
|
||||||
|
ucstring _FontSizingChars;
|
||||||
|
ucstring _FontSizingFallback;
|
||||||
// height of the font in pixel.
|
// height of the font in pixel.
|
||||||
// use getFontHeight
|
// use getFontHeight
|
||||||
uint _FontHeight;
|
float _FontHeight;
|
||||||
uint _FontLegHeight;
|
float _FontLegHeight;
|
||||||
float _SpaceWidth;
|
float _SpaceWidth;
|
||||||
|
/// last UI scale used to calculate font size
|
||||||
|
float _Scale;
|
||||||
/// the text color
|
/// the text color
|
||||||
NLMISC::CRGBA _Color;
|
NLMISC::CRGBA _Color;
|
||||||
/// the shadow mode
|
/// the shadow mode
|
||||||
|
@ -260,6 +274,7 @@ namespace NLGUI
|
||||||
sint32 _LineMaxW;
|
sint32 _LineMaxW;
|
||||||
/// For single line, true if the text is clamped (ie displayed with "...")
|
/// For single line, true if the text is clamped (ie displayed with "...")
|
||||||
bool _SingleLineTextClamped;
|
bool _SingleLineTextClamped;
|
||||||
|
ucstring _OverflowText;
|
||||||
|
|
||||||
/// Multiple lines handling
|
/// Multiple lines handling
|
||||||
bool _MultiLine;
|
bool _MultiLine;
|
||||||
|
@ -341,8 +356,8 @@ namespace NLGUI
|
||||||
// Clear the line & remove text contexts
|
// Clear the line & remove text contexts
|
||||||
void clear(NL3D::UTextContext &textContext);
|
void clear(NL3D::UTextContext &textContext);
|
||||||
// Add a new word (and its context) in the line + a number of spaces to append at the end of the line
|
// Add a new word (and its context) in the line + a number of spaces to append at the end of the line
|
||||||
void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, uint fontWidth, NL3D::UTextContext &textContext);
|
void addWord(const ucstring &word, uint numSpaces, const CFormatInfo &wordFormat, float fontWidth, NL3D::UTextContext &textContext);
|
||||||
void addWord(const CWord &word, uint fontWidth);
|
void addWord(const CWord &word, float fontWidth);
|
||||||
uint getNumWords() const { return (uint)_Words.size(); }
|
uint getNumWords() const { return (uint)_Words.size(); }
|
||||||
CWord &getWord(uint index) { return _Words[index]; }
|
CWord &getWord(uint index) { return _Words[index]; }
|
||||||
float getSpaceWidth() const { return _SpaceWidth; }
|
float getSpaceWidth() const { return _SpaceWidth; }
|
||||||
|
@ -402,7 +417,7 @@ namespace NLGUI
|
||||||
uint _TextSelectionEnd;
|
uint _TextSelectionEnd;
|
||||||
|
|
||||||
// First line X coordinate
|
// First line X coordinate
|
||||||
sint _FirstLineX;
|
float _FirstLineX;
|
||||||
|
|
||||||
/// Dynamic tooltips
|
/// Dynamic tooltips
|
||||||
std::vector<CCtrlToolTip*> _Tooltips;
|
std::vector<CCtrlToolTip*> _Tooltips;
|
||||||
|
@ -427,9 +442,9 @@ namespace NLGUI
|
||||||
// Clear all the lines and free their datas
|
// Clear all the lines and free their datas
|
||||||
void clearLines();
|
void clearLines();
|
||||||
// Update in the case of a multiline text
|
// Update in the case of a multiline text
|
||||||
void updateTextContextMultiLine(uint nMaxWidth);
|
void updateTextContextMultiLine(float nMaxWidth);
|
||||||
// Update in the case of a multiline text with justification
|
// Update in the case of a multiline text with justification
|
||||||
void updateTextContextMultiLineJustified(uint nMaxWidth, bool expandSpaces);
|
void updateTextContextMultiLineJustified(float nMaxWidth, bool expandSpaces);
|
||||||
// Recompute font size info
|
// Recompute font size info
|
||||||
void computeFontSize ();
|
void computeFontSize ();
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ namespace NLGUI
|
||||||
class CProcedure;
|
class CProcedure;
|
||||||
class IEditorSelectionWatcher;
|
class IEditorSelectionWatcher;
|
||||||
class IWidgetAdditionWatcher;
|
class IWidgetAdditionWatcher;
|
||||||
|
class IInterfaceScaleWatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
GUI Widget Manager
|
GUI Widget Manager
|
||||||
|
@ -530,6 +531,11 @@ namespace NLGUI
|
||||||
bool unGroupSelection();
|
bool unGroupSelection();
|
||||||
void setMultiSelection( bool b ){ multiSelection = b; }
|
void setMultiSelection( bool b ){ multiSelection = b; }
|
||||||
|
|
||||||
|
float getInterfaceScale() const { return _InterfaceScale; }
|
||||||
|
void notifyInterfaceScaleWatchers();
|
||||||
|
void registerInterfaceScaleWatcher(IInterfaceScaleWatcher *watcher);
|
||||||
|
void unregisterInterfaceScaleWatcher(IInterfaceScaleWatcher *watcher);
|
||||||
|
|
||||||
bool createNewGUI( const std::string &project, const std::string &window );
|
bool createNewGUI( const std::string &project, const std::string &window );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -615,6 +621,7 @@ namespace NLGUI
|
||||||
|
|
||||||
uint32 _ScreenH;
|
uint32 _ScreenH;
|
||||||
uint32 _ScreenW;
|
uint32 _ScreenW;
|
||||||
|
float _InterfaceScale;
|
||||||
|
|
||||||
std::vector< CInterfaceAnim* > activeAnims;
|
std::vector< CInterfaceAnim* > activeAnims;
|
||||||
|
|
||||||
|
@ -622,6 +629,7 @@ namespace NLGUI
|
||||||
std::vector< IOnWidgetsDrawnHandler* > onWidgetsDrawnHandlers;
|
std::vector< IOnWidgetsDrawnHandler* > onWidgetsDrawnHandlers;
|
||||||
std::vector< IEditorSelectionWatcher* > selectionWatchers;
|
std::vector< IEditorSelectionWatcher* > selectionWatchers;
|
||||||
std::vector< IWidgetWatcher* > widgetWatchers;
|
std::vector< IWidgetWatcher* > widgetWatchers;
|
||||||
|
std::vector< IInterfaceScaleWatcher* > scaleWatchers;
|
||||||
|
|
||||||
std::vector< std::string > editorSelection;
|
std::vector< std::string > editorSelection;
|
||||||
bool _GroupSelection;
|
bool _GroupSelection;
|
||||||
|
|
|
@ -222,6 +222,7 @@ inline double isValidDouble (double v)
|
||||||
* \param str a string to transform to lower case
|
* \param str a string to transform to lower case
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
std::string toLower ( const char *str );
|
||||||
std::string toLower ( const std::string &str );
|
std::string toLower ( const std::string &str );
|
||||||
void toLower ( char *str );
|
void toLower ( char *str );
|
||||||
char toLower ( const char ch ); // convert only one character
|
char toLower ( const char ch ); // convert only one character
|
||||||
|
|
108
code/nel/include/nel/sound/audio_decoder_ffmpeg.h
Normal file
108
code/nel/include/nel/sound/audio_decoder_ffmpeg.h
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||||
|
// Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef NLSOUND_AUDIO_DECODER_FFMPEG_H
|
||||||
|
#define NLSOUND_AUDIO_DECODER_FFMPEG_H
|
||||||
|
#include <nel/misc/types_nl.h>
|
||||||
|
|
||||||
|
#include <nel/sound/audio_decoder.h>
|
||||||
|
|
||||||
|
struct AVCodecContext;
|
||||||
|
struct AVFormatContext;
|
||||||
|
struct AVIOContext;
|
||||||
|
struct AVPacket;
|
||||||
|
struct SwrContext;
|
||||||
|
|
||||||
|
namespace NLSOUND {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief CAudioDecoderFfmpeg
|
||||||
|
* \date 2018-10-21 08:08GMT
|
||||||
|
* \author Meelis Mägi (Nimetu)
|
||||||
|
* CAudioDecoderFfmpeg
|
||||||
|
* Create trough IAudioDecoder
|
||||||
|
*/
|
||||||
|
class CAudioDecoderFfmpeg : public IAudioDecoder
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
NLMISC::IStream *_Stream;
|
||||||
|
|
||||||
|
bool _IsSupported;
|
||||||
|
bool _Loop;
|
||||||
|
bool _IsMusicEnded;
|
||||||
|
sint32 _StreamOffset;
|
||||||
|
sint32 _StreamSize;
|
||||||
|
|
||||||
|
AVIOContext *_AvioContext;
|
||||||
|
AVFormatContext *_FormatContext;
|
||||||
|
AVCodecContext *_AudioContext;
|
||||||
|
SwrContext *_SwrContext;
|
||||||
|
|
||||||
|
// selected stream
|
||||||
|
sint32 _AudioStreamIndex;
|
||||||
|
|
||||||
|
// output buffer for decoded frame
|
||||||
|
SwrContext *_ConvertContext;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// called from constructor if ffmpeg fails to initialize
|
||||||
|
// or from destructor to cleanup ffmpeg pointers
|
||||||
|
void release();
|
||||||
|
|
||||||
|
public:
|
||||||
|
CAudioDecoderFfmpeg(NLMISC::IStream *stream, bool loop);
|
||||||
|
virtual ~CAudioDecoderFfmpeg();
|
||||||
|
|
||||||
|
inline NLMISC::IStream *getStream() { return _Stream; }
|
||||||
|
inline sint32 getStreamSize() { return _StreamSize; }
|
||||||
|
inline sint32 getStreamOffset() { return _StreamOffset; }
|
||||||
|
|
||||||
|
// Return true if ffmpeg is able to decode the stream
|
||||||
|
bool isFormatSupported() const;
|
||||||
|
|
||||||
|
/// Get information on a music file (only artist and title at the moment).
|
||||||
|
static bool getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length);
|
||||||
|
|
||||||
|
/// Get how many bytes the music buffer requires for output minimum.
|
||||||
|
virtual uint32 getRequiredBytes();
|
||||||
|
|
||||||
|
/// Get an amount of bytes between minimum and maximum (can be lower than minimum if at end).
|
||||||
|
virtual uint32 getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum);
|
||||||
|
|
||||||
|
/// Get the amount of channels (2 is stereo) in output.
|
||||||
|
virtual uint8 getChannels();
|
||||||
|
|
||||||
|
/// Get the samples per second (often 44100) in output.
|
||||||
|
virtual uint getSamplesPerSec();
|
||||||
|
|
||||||
|
/// Get the bits per sample (often 16) in output.
|
||||||
|
virtual uint8 getBitsPerSample();
|
||||||
|
|
||||||
|
/// Get if the music has ended playing (never true if loop).
|
||||||
|
virtual bool isMusicEnded();
|
||||||
|
|
||||||
|
/// Get the total time in seconds.
|
||||||
|
virtual float getLength();
|
||||||
|
|
||||||
|
/// Set looping
|
||||||
|
virtual void setLooping(bool loop);
|
||||||
|
}; /* class CAudioDecoderFfmpeg */
|
||||||
|
|
||||||
|
} /* namespace NLSOUND */
|
||||||
|
|
||||||
|
#endif // NLSOUND_AUDIO_DECODER_FFMPEG_H
|
||||||
|
|
||||||
|
/* end of file */
|
96
code/nel/include/nel/sound/audio_decoder_mp3.h
Normal file
96
code/nel/include/nel/sound/audio_decoder_mp3.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||||
|
// Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef NLSOUND_AUDIO_DECODER_MP3_H
|
||||||
|
#define NLSOUND_AUDIO_DECODER_MP3_H
|
||||||
|
#include <nel/misc/types_nl.h>
|
||||||
|
|
||||||
|
#include <nel/sound/audio_decoder.h>
|
||||||
|
|
||||||
|
// disable drmp3_init_file()
|
||||||
|
#define DR_MP3_NO_STDIO
|
||||||
|
#include <nel/sound/decoder/dr_mp3.h>
|
||||||
|
|
||||||
|
namespace NLSOUND {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief CAudioDecoderMP3
|
||||||
|
* \date 2019-01-13 12:39GMT
|
||||||
|
* \author Meelis Mägi (Nimetu)
|
||||||
|
* CAudioDecoderMP3
|
||||||
|
* Create trough IAudioDecoder, type "mp3"
|
||||||
|
*/
|
||||||
|
class CAudioDecoderMP3 : public IAudioDecoder
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
NLMISC::IStream *_Stream;
|
||||||
|
|
||||||
|
bool _IsSupported;
|
||||||
|
bool _Loop;
|
||||||
|
bool _IsMusicEnded;
|
||||||
|
sint32 _StreamOffset;
|
||||||
|
sint32 _StreamSize;
|
||||||
|
|
||||||
|
drmp3 _Decoder;
|
||||||
|
|
||||||
|
// set to total pcm frames after getLength() is called
|
||||||
|
uint64 _PCMFrameCount;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CAudioDecoderMP3(NLMISC::IStream *stream, bool loop);
|
||||||
|
virtual ~CAudioDecoderMP3();
|
||||||
|
|
||||||
|
inline NLMISC::IStream *getStream() { return _Stream; }
|
||||||
|
inline sint32 getStreamSize() { return _StreamSize; }
|
||||||
|
inline sint32 getStreamOffset() { return _StreamOffset; }
|
||||||
|
|
||||||
|
// Return true if mp3 is valid
|
||||||
|
bool isFormatSupported() const;
|
||||||
|
|
||||||
|
/// Get information on a music file (only ID3v1 tag is read.
|
||||||
|
static bool getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length);
|
||||||
|
|
||||||
|
/// Get how many bytes the music buffer requires for output minimum.
|
||||||
|
virtual uint32 getRequiredBytes();
|
||||||
|
|
||||||
|
/// Get an amount of bytes between minimum and maximum (can be lower than minimum if at end).
|
||||||
|
virtual uint32 getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum);
|
||||||
|
|
||||||
|
/// Get the amount of channels (2 is stereo) in output.
|
||||||
|
virtual uint8 getChannels();
|
||||||
|
|
||||||
|
/// Get the samples per second (often 44100) in output.
|
||||||
|
virtual uint getSamplesPerSec();
|
||||||
|
|
||||||
|
/// Get the bits per sample (often 16) in output.
|
||||||
|
virtual uint8 getBitsPerSample();
|
||||||
|
|
||||||
|
/// Get if the music has ended playing (never true if loop).
|
||||||
|
virtual bool isMusicEnded();
|
||||||
|
|
||||||
|
/// Get the total time in seconds.
|
||||||
|
virtual float getLength();
|
||||||
|
|
||||||
|
/// Set looping
|
||||||
|
virtual void setLooping(bool loop);
|
||||||
|
|
||||||
|
}; /* class CAudioDecoderMP3 */
|
||||||
|
|
||||||
|
} /* namespace NLSOUND */
|
||||||
|
|
||||||
|
#endif // NLSOUND_AUDIO_DECODER_MP3_H
|
||||||
|
|
||||||
|
/* end of file */
|
3566
code/nel/include/nel/sound/decoder/dr_mp3.h
Normal file
3566
code/nel/include/nel/sound/decoder/dr_mp3.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -98,8 +98,9 @@ private:
|
||||||
NLMISC::IThread *m_Thread;
|
NLMISC::IThread *m_Thread;
|
||||||
|
|
||||||
IAudioDecoder *m_AudioDecoder;
|
IAudioDecoder *m_AudioDecoder;
|
||||||
|
|
||||||
bool m_Paused;
|
bool m_Paused;
|
||||||
|
bool m_DecodingEnded;
|
||||||
|
|
||||||
}; /* class CStreamFileSource */
|
}; /* class CStreamFileSource */
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,11 @@ const char *CFontGenerator::getFT2Error(FT_Error fte)
|
||||||
return ukn;
|
return ukn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CFontGenerator::getFontFileName() const
|
||||||
|
{
|
||||||
|
return _FontFileName;
|
||||||
|
}
|
||||||
|
|
||||||
CFontGenerator *newCFontGenerator(const std::string &fontFileName)
|
CFontGenerator *newCFontGenerator(const std::string &fontFileName)
|
||||||
{
|
{
|
||||||
return new CFontGenerator(fontFileName);
|
return new CFontGenerator(fontFileName);
|
||||||
|
|
|
@ -46,6 +46,7 @@ CMaterial* CFontManager::getFontMaterial()
|
||||||
if (_TexFont == NULL)
|
if (_TexFont == NULL)
|
||||||
{
|
{
|
||||||
_TexFont = new CTextureFont;
|
_TexFont = new CTextureFont;
|
||||||
|
_TexCacheNr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_MatFont == NULL)
|
if (_MatFont == NULL)
|
||||||
|
@ -142,11 +143,17 @@ void CFontManager::computeString (const ucstring &s,
|
||||||
sint32 nMaxZ = -1000000, nMinZ = 1000000;
|
sint32 nMaxZ = -1000000, nMinZ = 1000000;
|
||||||
output.StringHeight = 0;
|
output.StringHeight = 0;
|
||||||
|
|
||||||
|
// save string info for later rebuild as needed
|
||||||
|
output.Text = s;
|
||||||
|
output.CacheVersion = getCacheVersion();
|
||||||
|
|
||||||
uint j = 0;
|
uint j = 0;
|
||||||
{
|
{
|
||||||
CVertexBufferReadWrite vba;
|
CVertexBufferReadWrite vba;
|
||||||
output.Vertices.lock (vba);
|
output.Vertices.lock (vba);
|
||||||
|
|
||||||
|
hlfPixScrW = 0.f;
|
||||||
|
hlfPixScrH = 0.f;
|
||||||
|
|
||||||
// For all chars
|
// For all chars
|
||||||
for (uint i = 0; i < s.size(); i++)
|
for (uint i = 0; i < s.size(); i++)
|
||||||
|
@ -157,38 +164,43 @@ void CFontManager::computeString (const ucstring &s,
|
||||||
k.Size = fontSize;
|
k.Size = fontSize;
|
||||||
k.Embolden = embolden;
|
k.Embolden = embolden;
|
||||||
k.Oblique = oblique;
|
k.Oblique = oblique;
|
||||||
CTextureFont::SLetterInfo *pLI = pTexFont->getLetterInfo (k);
|
// render letter
|
||||||
|
CTextureFont::SLetterInfo *pLI = pTexFont->getLetterInfo (k, true);
|
||||||
if(pLI != NULL)
|
if(pLI != NULL)
|
||||||
{
|
{
|
||||||
if ((pLI->CharWidth > 0) && (pLI->CharHeight > 0))
|
if (pLI->glyph)
|
||||||
{
|
{
|
||||||
|
// If letter is heavily upscaled, then there is noticeable clipping on edges
|
||||||
|
// fixing UV will make it bit better
|
||||||
|
if ((pLI->Size >> 1) > pLI->glyph->Size)
|
||||||
|
{
|
||||||
|
hlfPixTexW = 0.5f * TexRatioW;
|
||||||
|
hlfPixTexH = 0.5f * TexRatioH;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating vertices
|
// Creating vertices
|
||||||
dx = pLI->Left;
|
dx = pLI->Left;
|
||||||
dz = -((sint32)pLI->CharHeight-(sint32)(pLI->Top));
|
dz = -((sint32)pLI->CharHeight - (sint32)(pLI->Top));
|
||||||
u1 = pLI->U - hlfPixTexW;
|
|
||||||
v1 = pLI->V - hlfPixTexH;
|
|
||||||
u2 = pLI->U + ((float)pLI->CharWidth) * TexRatioW + hlfPixTexW;
|
|
||||||
v2 = pLI->V + ((float)pLI->CharHeight) * TexRatioH + hlfPixTexH;
|
|
||||||
|
|
||||||
x1 = (penx + dx) - hlfPixScrW;
|
x1 = (penx + dx) - hlfPixScrW;
|
||||||
z1 = (penz + dz) - hlfPixScrH;
|
z1 = (penz + dz) - hlfPixScrH;
|
||||||
x2 = (penx + dx + (sint32)pLI->CharWidth) + hlfPixScrW;
|
x2 = (penx + dx + (sint32)pLI->CharWidth) + hlfPixScrW;
|
||||||
z2 = (penz + dz + (sint32)pLI->CharHeight) + hlfPixScrH;
|
z2 = (penz + dz + (sint32)pLI->CharHeight) + hlfPixScrH;
|
||||||
|
|
||||||
vba.setVertexCoord (j, x1, 0, z1);
|
vba.setVertexCoord (j, x1, 0, z1);
|
||||||
vba.setTexCoord (j, 0, u1, v2);
|
vba.setTexCoord (j, 0, pLI->glyph->U0-hlfPixTexW, pLI->glyph->V1+hlfPixTexH);
|
||||||
++j;
|
++j;
|
||||||
|
|
||||||
vba.setVertexCoord (j, x2, 0, z1);
|
vba.setVertexCoord (j, x2, 0, z1);
|
||||||
vba.setTexCoord (j, 0, u2, v2);
|
vba.setTexCoord (j, 0, pLI->glyph->U1+hlfPixTexW, pLI->glyph->V1+hlfPixTexH);
|
||||||
++j;
|
++j;
|
||||||
|
|
||||||
vba.setVertexCoord (j, x2, 0, z2);
|
vba.setVertexCoord (j, x2, 0, z2);
|
||||||
vba.setTexCoord (j, 0, u2, v1);
|
vba.setTexCoord (j, 0, pLI->glyph->U1+hlfPixTexW, pLI->glyph->V0-hlfPixTexH);
|
||||||
++j;
|
++j;
|
||||||
|
|
||||||
vba.setVertexCoord (j, x1, 0, z2);
|
vba.setVertexCoord (j, x1, 0, z2);
|
||||||
vba.setTexCoord (j, 0, u1, v1);
|
vba.setTexCoord (j, 0, pLI->glyph->U0-hlfPixTexW, pLI->glyph->V0-hlfPixTexH);
|
||||||
++j;
|
++j;
|
||||||
|
|
||||||
// String Bound
|
// String Bound
|
||||||
|
@ -245,6 +257,19 @@ void CFontManager::computeStringInfo ( const ucstring &s,
|
||||||
{
|
{
|
||||||
output.Color = color;
|
output.Color = color;
|
||||||
|
|
||||||
|
// save string info for later rebuild as needed
|
||||||
|
output.Text = s;
|
||||||
|
output.CacheVersion = 0;
|
||||||
|
|
||||||
|
if (s.empty())
|
||||||
|
{
|
||||||
|
output.StringWidth = 0.f;
|
||||||
|
output.StringHeight = 0;
|
||||||
|
output.StringLine = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// resize fontSize if window not of 800x600.
|
// resize fontSize if window not of 800x600.
|
||||||
if (keep800x600Ratio)
|
if (keep800x600Ratio)
|
||||||
{
|
{
|
||||||
|
@ -273,7 +298,7 @@ void CFontManager::computeStringInfo ( const ucstring &s,
|
||||||
k.Size = fontSize;
|
k.Size = fontSize;
|
||||||
k.Embolden = embolden;
|
k.Embolden = embolden;
|
||||||
k.Oblique = oblique;
|
k.Oblique = oblique;
|
||||||
pLI = pTexFont->getLetterInfo (k);
|
pLI = pTexFont->getLetterInfo (k, false);
|
||||||
if(pLI != NULL)
|
if(pLI != NULL)
|
||||||
{
|
{
|
||||||
if ((pLI->CharWidth > 0) && (pLI->CharHeight > 0))
|
if ((pLI->CharWidth > 0) && (pLI->CharHeight > 0))
|
||||||
|
@ -318,7 +343,11 @@ void CFontManager::invalidate()
|
||||||
{
|
{
|
||||||
if (_TexFont)
|
if (_TexFont)
|
||||||
_TexFont = NULL;
|
_TexFont = NULL;
|
||||||
|
|
||||||
_TexFont = new CTextureFont;
|
_TexFont = new CTextureFont;
|
||||||
|
_TexCacheNr++;
|
||||||
|
|
||||||
|
getFontMaterial()->setTexture(0, _TexFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -74,25 +74,9 @@ uint32 CTextContext::textPush (const char *format, ...)
|
||||||
char *str;
|
char *str;
|
||||||
NLMISC_CONVERT_VARGS (str, format, NLMISC::MaxCStringSize);
|
NLMISC_CONVERT_VARGS (str, format, NLMISC::MaxCStringSize);
|
||||||
|
|
||||||
if (_CacheNbFreePlaces == 0)
|
ucstring uc;
|
||||||
{
|
uc.fromUtf8((const char *)str);
|
||||||
CComputedString csTmp;
|
return textPush(uc);
|
||||||
|
|
||||||
_CacheStrings.push_back (csTmp);
|
|
||||||
if (_CacheFreePlaces.empty())
|
|
||||||
_CacheFreePlaces.resize (1);
|
|
||||||
_CacheFreePlaces[0] = (uint32)_CacheStrings.size()-1;
|
|
||||||
_CacheNbFreePlaces = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute the string.
|
|
||||||
uint32 index = _CacheFreePlaces[_CacheNbFreePlaces-1];
|
|
||||||
CComputedString &strToFill = _CacheStrings[index];
|
|
||||||
_FontManager->computeString (str, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio);
|
|
||||||
|
|
||||||
_CacheNbFreePlaces--;
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -115,8 +99,10 @@ uint32 CTextContext::textPush (const ucstring &str)
|
||||||
uint32 index = _CacheFreePlaces[_CacheNbFreePlaces-1];
|
uint32 index = _CacheFreePlaces[_CacheNbFreePlaces-1];
|
||||||
nlassert (index < _CacheStrings.size());
|
nlassert (index < _CacheStrings.size());
|
||||||
CComputedString &strToFill = _CacheStrings[index];
|
CComputedString &strToFill = _CacheStrings[index];
|
||||||
_FontManager->computeString (str, _FontGen, _Color
|
|
||||||
, _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio);
|
_FontManager->computeString (str, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio);
|
||||||
|
// just compute letters, glyphs are rendered on demand before first draw
|
||||||
|
//_FontManager->computeStringInfo(str, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio);
|
||||||
|
|
||||||
_CacheNbFreePlaces--;
|
_CacheNbFreePlaces--;
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "nel/misc/common.h"
|
#include "nel/misc/common.h"
|
||||||
#include "nel/misc/rect.h"
|
#include "nel/misc/rect.h"
|
||||||
#include "nel/misc/file.h"
|
#include "nel/misc/file.h"
|
||||||
|
#include "nel/misc/path.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace NLMISC;
|
using namespace NLMISC;
|
||||||
|
@ -35,37 +35,14 @@ using namespace NLMISC;
|
||||||
namespace NL3D
|
namespace NL3D
|
||||||
{
|
{
|
||||||
|
|
||||||
// Config 1
|
|
||||||
const int TextureSizeX = 1024;
|
|
||||||
const int TextureSizeY = 1024; // If change this value -> change NbLine too
|
|
||||||
const int Categories[TEXTUREFONT_NBCATEGORY] = { 8, 16, 24, 32, 64 };
|
|
||||||
const int NbLine[TEXTUREFONT_NBCATEGORY] = { 8, 24, 16, 4, 1 }; // Based on textsize
|
|
||||||
|
|
||||||
/*
|
|
||||||
const int TextureSizeX = 256;
|
|
||||||
const int TextureSizeY = 256;
|
|
||||||
const int Categories[TEXTUREFONT_NBCATEGORY] = { 8, 16, 24, 32 };
|
|
||||||
const int NbLine[TEXTUREFONT_NBCATEGORY] = { 4, 6, 4, 1 }; // Based on textsize
|
|
||||||
*/
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
inline uint32 CTextureFont::SLetterKey::getVal()
|
|
||||||
{
|
|
||||||
// this limits Size to 6bits
|
|
||||||
// Large sizes already render wrong when many
|
|
||||||
// different glyphs are used due to limited texture atlas
|
|
||||||
uint8 eb = ((uint)Embolden) + ((uint)Oblique << 1);
|
|
||||||
if (FontGenerator == NULL)
|
|
||||||
return Char + ((Size&255)<<16) + (eb << 22);
|
|
||||||
else
|
|
||||||
return Char + ((Size&255)<<16) + (eb << 22) + ((FontGenerator->getUID()&0xFF)<<24);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
CTextureFont::CTextureFont()
|
CTextureFont::CTextureFont()
|
||||||
|
: _CacheVersion(1),
|
||||||
|
_TextureSizeX(512), _TextureSizeY(512), _TextureMaxW(4096), _TextureMaxH(4096),
|
||||||
|
_PaddingL(0), _PaddingT(0), _PaddingR(1), _PaddingB(1),
|
||||||
|
_MinGlyphSize(5), _MaxGlyphSize(200),
|
||||||
|
_GlyphSizeStepMin(50), _GlyphSizeStep(5)
|
||||||
{
|
{
|
||||||
uint i;
|
|
||||||
|
|
||||||
setFilterMode (ITexture::Linear, ITexture::LinearMipMapOff);
|
setFilterMode (ITexture::Linear, ITexture::LinearMipMapOff);
|
||||||
|
|
||||||
setWrapS (ITexture::Repeat);
|
setWrapS (ITexture::Repeat);
|
||||||
|
@ -75,53 +52,9 @@ CTextureFont::CTextureFont()
|
||||||
|
|
||||||
setReleasable (false);
|
setReleasable (false);
|
||||||
|
|
||||||
resize (TextureSizeX, TextureSizeY, CBitmap::Alpha);
|
resize (_TextureSizeX, _TextureSizeY, CBitmap::Alpha, true);
|
||||||
for(i = 0; i < TextureSizeX*TextureSizeY; ++i)
|
|
||||||
getPixels()[i] = 0;
|
|
||||||
// convertToType (CBitmap::Alpha);
|
|
||||||
|
|
||||||
sint posY = 0;
|
_AtlasNodes.push_back(CRect(0, 0, _TextureSizeX, _TextureSizeY));
|
||||||
|
|
||||||
for(i = 0; i < TEXTUREFONT_NBCATEGORY; ++i)
|
|
||||||
{
|
|
||||||
// Number of chars per cache
|
|
||||||
Letters[i].resize ((TextureSizeX/Categories[i])*NbLine[i]);
|
|
||||||
|
|
||||||
for(uint32 j = 0; j < Letters[i].size(); ++j)
|
|
||||||
{
|
|
||||||
SLetterInfo &rLetter = Letters[i][j];
|
|
||||||
rLetter.Char = 0xffff;
|
|
||||||
rLetter.FontGenerator = NULL;
|
|
||||||
rLetter.Size= 0;
|
|
||||||
rLetter.Embolden = false;
|
|
||||||
rLetter.Oblique = false;
|
|
||||||
|
|
||||||
// The less recently used infos
|
|
||||||
if (j < Letters[i].size()-1)
|
|
||||||
rLetter.Next = &Letters[i][j+1];
|
|
||||||
else
|
|
||||||
rLetter.Next = NULL;
|
|
||||||
|
|
||||||
if (j > 0)
|
|
||||||
rLetter.Prev = &Letters[i][j-1];
|
|
||||||
else
|
|
||||||
rLetter.Prev = NULL;
|
|
||||||
|
|
||||||
rLetter.Cat = i;
|
|
||||||
|
|
||||||
sint sizeX = TextureSizeX/Categories[i];
|
|
||||||
rLetter.U = (Categories[i]*(j%sizeX)) / ((float)TextureSizeX);
|
|
||||||
rLetter.V = (posY + Categories[i]*((sint)(j/sizeX))) / ((float)TextureSizeY);
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////
|
|
||||||
|
|
||||||
rLetter.CharWidth = rLetter.CharHeight = 0;
|
|
||||||
rLetter.GlyphIndex = rLetter.Top = rLetter.Left = rLetter.AdvX = 0;
|
|
||||||
}
|
|
||||||
Front[i] = &Letters[i][0];
|
|
||||||
Back[i] = &Letters[i][Letters[i].size()-1];
|
|
||||||
posY += NbLine[i] * Categories[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,17 +62,16 @@ CTextureFont::~CTextureFont()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
void CTextureFont::dumpTextureFont(const char *filename)
|
void CTextureFont::dumpTextureFont(const char *filename)
|
||||||
{
|
{
|
||||||
CBitmap b;
|
CBitmap b;
|
||||||
COFile f( filename );
|
COFile f( filename );
|
||||||
b.resize (TextureSizeX, TextureSizeY, CBitmap::RGBA);
|
b.resize (_TextureSizeX, _TextureSizeY, CBitmap::RGBA);
|
||||||
CObjectVector<uint8>&bits = b.getPixels();
|
CObjectVector<uint8>&bits = b.getPixels();
|
||||||
CObjectVector<uint8>&src = getPixels();
|
CObjectVector<uint8>&src = getPixels();
|
||||||
|
|
||||||
for (uint i = 0; i < (TextureSizeX*TextureSizeY); ++i)
|
for (uint i = 0; i < (_TextureSizeX*_TextureSizeY); ++i)
|
||||||
{
|
{
|
||||||
bits[i*4+0] = bits[i*4+1] = bits[i*4+2] = bits[i*4+3] = src[i];
|
bits[i*4+0] = bits[i*4+1] = bits[i*4+2] = bits[i*4+3] = src[i];
|
||||||
}
|
}
|
||||||
|
@ -147,242 +79,471 @@ void CTextureFont::dumpTextureFont(const char *filename)
|
||||||
b.writeTGA (f, 32);
|
b.writeTGA (f, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
bool CTextureFont::getNextTextureSize(uint32 &newW, uint32 &newH) const
|
||||||
|
{
|
||||||
|
// width will be resized first (256x256 -> 512x256)
|
||||||
|
if (_TextureSizeX <= _TextureSizeY)
|
||||||
|
{
|
||||||
|
newW = _TextureSizeX * 2;
|
||||||
|
newH = _TextureSizeY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newW = _TextureSizeX;
|
||||||
|
newH = _TextureSizeY * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no more room
|
||||||
|
return newW <= _TextureMaxW && newH <= _TextureMaxH;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// cat : categories where the letter is
|
// out of room, clear everything and rebuild glyphs on demand
|
||||||
// x : pos x of the letter
|
// note: text will display wrong until glyphs get rendered again
|
||||||
// y : pos y of the letter
|
void CTextureFont::clearAtlas()
|
||||||
void CTextureFont::rebuildLetter (sint cat, sint x, sint y)
|
|
||||||
{
|
{
|
||||||
sint sizex = TextureSizeX / Categories[cat];
|
nlwarning("Glyph cache will be cleared.");
|
||||||
sint index = x + y*sizex;
|
|
||||||
SLetterInfo &rLetter = Letters[cat][index];
|
|
||||||
|
|
||||||
if (rLetter.FontGenerator == NULL)
|
_AtlasNodes.clear();
|
||||||
return;
|
_AtlasNodes.push_back(CRect(0, 0, _TextureSizeX, _TextureSizeY));
|
||||||
|
|
||||||
sint catTopY = 0;
|
// clear texture
|
||||||
sint c = 0;
|
_Data[0].fill(0);
|
||||||
while (c < cat)
|
|
||||||
|
// clear glyph cache
|
||||||
|
for(uint i = 0; i< _Letters.size(); ++i)
|
||||||
{
|
{
|
||||||
catTopY += NbLine[c] * Categories[c];
|
_Letters[i].glyph = NULL;
|
||||||
++c;
|
|
||||||
}
|
}
|
||||||
// Destination position in pixel of the letter
|
_GlyphCache.clear();
|
||||||
sint posx = x * Categories[cat];
|
|
||||||
sint posy = catTopY + y * Categories[cat];
|
|
||||||
|
|
||||||
uint32 pitch = 0;
|
_CacheVersion++;
|
||||||
uint8 *bitmap = rLetter.FontGenerator->getBitmap ( rLetter.Char, rLetter.Size, rLetter.Embolden, rLetter.Oblique,
|
|
||||||
rLetter.CharWidth, rLetter.CharHeight,
|
|
||||||
pitch, rLetter.Left, rLetter.Top,
|
|
||||||
rLetter.AdvX, rLetter.GlyphIndex );
|
|
||||||
|
|
||||||
// Copy FreeType buffer
|
touch();
|
||||||
uint i;
|
}
|
||||||
for (i = 0; i < rLetter.CharHeight; ++i)
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
void CTextureFont::repackAtlas()
|
||||||
|
{
|
||||||
|
repackAtlas(_TextureSizeX, _TextureSizeY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// backup old glyphs and move them to newly resized texture
|
||||||
|
// new atlas will be sorted if _GlyphCache is
|
||||||
|
void CTextureFont::repackAtlas(uint32 newW, uint32 newH)
|
||||||
|
{
|
||||||
|
uint32 newCacheVersion = _CacheVersion+1;
|
||||||
|
|
||||||
|
CBitmap btm;
|
||||||
|
uint32 oldW, oldH;
|
||||||
|
|
||||||
|
oldW = _TextureSizeX;
|
||||||
|
oldH = _TextureSizeY;
|
||||||
|
btm.resize(oldW, oldH, CBitmap::Alpha, true);
|
||||||
|
btm.blit(this, 0, 0);
|
||||||
|
|
||||||
|
// resize texture
|
||||||
|
if (_TextureSizeX != newW || _TextureSizeY != newH)
|
||||||
{
|
{
|
||||||
uint8 *pDst = &_Data[0][posx + (posy+i)*TextureSizeY];
|
_TextureSizeX = newW;
|
||||||
uint8 *pSrc = &bitmap[i*pitch];
|
_TextureSizeY = newH;
|
||||||
for (uint j = 0; j < rLetter.CharWidth; ++j)
|
resize (_TextureSizeX, _TextureSizeY, CBitmap::Alpha, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_Data[0].fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// release atlas and rebuild
|
||||||
|
_AtlasNodes.clear();
|
||||||
|
_AtlasNodes.push_back(CRect(0, 0, _TextureSizeX, _TextureSizeY));
|
||||||
|
|
||||||
|
CObjectVector<uint8>&src = btm.getPixels();
|
||||||
|
for(std::list<SGlyphInfo>::iterator it = _GlyphCache.begin(); it != _GlyphCache.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->CacheVersion != _CacheVersion)
|
||||||
{
|
{
|
||||||
*pDst = *pSrc;
|
// TODO: must remove glyph from all letters before removing glyph from cache
|
||||||
++pDst;
|
//continue;
|
||||||
++pSrc;
|
}
|
||||||
|
|
||||||
|
SGlyphInfo &glyph = *it;
|
||||||
|
|
||||||
|
glyph.CacheVersion = newCacheVersion;
|
||||||
|
|
||||||
|
uint32 atlasX, atlasY;
|
||||||
|
if (reserveAtlas(glyph.W, glyph.H, atlasX, atlasY))
|
||||||
|
{
|
||||||
|
for (uint y = 0; y < glyph.H; ++y)
|
||||||
|
{
|
||||||
|
uint8 *pDst = &_Data[0][(atlasY + y) * _TextureSizeX + atlasX];
|
||||||
|
for (uint x = 0; x < glyph.W; ++x)
|
||||||
|
{
|
||||||
|
*pDst = src[(glyph.Y + y) * oldW + glyph.X + x];
|
||||||
|
++pDst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: dup code with renderGlyph
|
||||||
|
glyph.U0 = (atlasX+_PaddingL) / (float)_TextureSizeX;
|
||||||
|
glyph.V0 = (atlasY+_PaddingT) / (float)_TextureSizeY;
|
||||||
|
glyph.U1 = (atlasX+_PaddingL+glyph.CharWidth) / (float)_TextureSizeX;
|
||||||
|
glyph.V1 = (atlasY+_PaddingT+glyph.CharHeight) / (float)_TextureSizeY;
|
||||||
|
|
||||||
|
glyph.X = atlasX;
|
||||||
|
glyph.Y = atlasY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Black border bottom and right
|
_CacheVersion = newCacheVersion;
|
||||||
for (i = 0; i < rLetter.CharHeight+1; ++i)
|
|
||||||
|
// invalidate full texture
|
||||||
|
touch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
bool CTextureFont::resizeAtlas()
|
||||||
|
{
|
||||||
|
uint32 newW, newH;
|
||||||
|
if (!getNextTextureSize(newW, newH))
|
||||||
{
|
{
|
||||||
_Data[0][posx + rLetter.CharWidth + (posy+i)*TextureSizeY] = 0;
|
nlwarning("Font texture at maximum (%d,%d). Resize failed.", _TextureSizeX, _TextureSizeY);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < rLetter.CharWidth+1; ++i)
|
// resize and redraw
|
||||||
{
|
repackAtlas(newW, newH);
|
||||||
_Data[0][posx + i + (posy+rLetter.CharHeight)*TextureSizeY] = 0;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
dumpTextureFont (this);
|
|
||||||
int a = 5;
|
|
||||||
a++;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
void CTextureFont::doGenerate(bool async)
|
void CTextureFont::doGenerate(bool async)
|
||||||
{
|
{
|
||||||
// Rectangle invalidate ?
|
/*
|
||||||
if (_ListInvalidRect.begin()!=_ListInvalidRect.end())
|
nlinfo("doGenerate: Letters(%d/%d), Glyphs(%d/%d)\n", _Letters.size(), _Letters.size() * sizeof(SLetterInfo),
|
||||||
{
|
_GlyphCache.size(), _GlyphCache.size() * sizeof(SGlyphInfo));
|
||||||
// Yes, rebuild only those rectangles.
|
//std::string fname = CFile::findNewFile("/tmp/font-texture.tga");
|
||||||
|
std::string fname = toString("/tmp/font-texture-%p-%03d.tga", this, _CacheVersion);
|
||||||
// For each rectangle to compute
|
dumpTextureFont (fname.c_str());
|
||||||
std::list<NLMISC::CRect>::iterator ite=_ListInvalidRect.begin();
|
*/
|
||||||
while (ite!=_ListInvalidRect.end())
|
|
||||||
{
|
|
||||||
// Compute rectangle coordinates
|
|
||||||
sint x = ite->left();
|
|
||||||
sint y = ite->bottom();
|
|
||||||
|
|
||||||
// Look in which category is the rectangle
|
|
||||||
sint cat = 0;
|
|
||||||
sint catTopY = 0;
|
|
||||||
sint catBotY = NbLine[cat] * Categories[cat];
|
|
||||||
while (y > catBotY)
|
|
||||||
{
|
|
||||||
if (y < catBotY)
|
|
||||||
break;
|
|
||||||
++cat;
|
|
||||||
nlassert (cat < TEXTUREFONT_NBCATEGORY);
|
|
||||||
catTopY = catBotY;
|
|
||||||
catBotY += NbLine[cat] * Categories[cat];
|
|
||||||
}
|
|
||||||
|
|
||||||
x = x / Categories[cat];
|
|
||||||
y = ite->top();
|
|
||||||
y = y - catTopY;
|
|
||||||
y = y / Categories[cat];
|
|
||||||
|
|
||||||
rebuildLetter (cat, x, y);
|
|
||||||
|
|
||||||
// Next rectangle
|
|
||||||
ite++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(int cat = 0; cat < TEXTUREFONT_NBCATEGORY; ++cat)
|
|
||||||
{
|
|
||||||
sint sizex = TextureSizeX / Categories[cat];
|
|
||||||
sint sizey = NbLine[cat];
|
|
||||||
for (sint y = 0; y < sizey; y++)
|
|
||||||
for (sint x = 0; x < sizex; x++)
|
|
||||||
{
|
|
||||||
rebuildLetter (cat, x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
dumpTextureFont (this);
|
|
||||||
int a = 5;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
CTextureFont::SLetterInfo* CTextureFont::getLetterInfo (SLetterKey& k)
|
uint CTextureFont::fitRegion(uint index, uint width, uint height)
|
||||||
{
|
{
|
||||||
sint cat;
|
if (_AtlasNodes[index].X + width > _TextureSizeX - 1)
|
||||||
uint32 nTmp = k.getVal();
|
|
||||||
map<uint32, SLetterInfo*>::iterator itAccel = Accel.find (nTmp);
|
|
||||||
if (itAccel != Accel.end())
|
|
||||||
{
|
{
|
||||||
// Put it in the first place
|
return -1;
|
||||||
SLetterInfo *pLetterToMove = itAccel->second;
|
}
|
||||||
cat = pLetterToMove->Cat;
|
|
||||||
if (pLetterToMove != Front[cat])
|
uint x = _AtlasNodes[index].X;
|
||||||
|
uint y = _AtlasNodes[index].Y;
|
||||||
|
sint widthLeft = width;
|
||||||
|
|
||||||
|
while(widthLeft > 0)
|
||||||
|
{
|
||||||
|
if (_AtlasNodes[index].Y > y)
|
||||||
{
|
{
|
||||||
// unlink
|
y = _AtlasNodes[index].Y;
|
||||||
nlassert(pLetterToMove->Prev);
|
|
||||||
pLetterToMove->Prev->Next = pLetterToMove->Next;
|
|
||||||
if (pLetterToMove == Back[cat])
|
|
||||||
{
|
|
||||||
Back[cat] = pLetterToMove->Prev;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pLetterToMove->Next->Prev = pLetterToMove->Prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
// link to front
|
|
||||||
pLetterToMove->Prev = NULL;
|
|
||||||
pLetterToMove->Next = Front[cat];
|
|
||||||
Front[cat]->Prev = pLetterToMove;
|
|
||||||
Front[cat] = pLetterToMove;
|
|
||||||
}
|
}
|
||||||
return pLetterToMove;
|
|
||||||
|
// _AtlasNodes[0] for margin is not used here
|
||||||
|
if (_AtlasNodes[index].Y + height > _TextureSizeY - 1)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
widthLeft -= _AtlasNodes[index].Width;
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The letter is not already present
|
return y;
|
||||||
// Found the category of the new letter
|
}
|
||||||
uint32 width, height;
|
|
||||||
|
|
||||||
//k.FontGenerator->getSizes (k.Char, k.Size, width, height);
|
bool CTextureFont::reserveAtlas(const uint32 width, const uint32 height, uint32 &x, uint32 &y)
|
||||||
// \todo mat : Temp !!! Try to use freetype cache
|
{
|
||||||
uint32 nPitch, nGlyphIndex;
|
if (_AtlasNodes.empty())
|
||||||
sint32 nLeft, nTop, nAdvX;
|
{
|
||||||
k.FontGenerator->getBitmap (k.Char, k.Size, k.Embolden, k.Oblique, width, height, nPitch, nLeft, nTop,
|
nlwarning("No available space in texture atlas (_AtlasNodes.empty() == true)");
|
||||||
nAdvX, nGlyphIndex );
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Add 1 pixel space for black border to get correct category
|
x = 0;
|
||||||
cat = 0;
|
y = 0;
|
||||||
if (((sint)width+1 > Categories[TEXTUREFONT_NBCATEGORY-1]) ||
|
|
||||||
((sint)height+1 > Categories[TEXTUREFONT_NBCATEGORY-1]))
|
sint bestIndex = -1;
|
||||||
|
sint bestWidth = _TextureSizeX;
|
||||||
|
sint bestHeight = _TextureSizeY;
|
||||||
|
|
||||||
|
sint selY=0;
|
||||||
|
|
||||||
|
for (uint i = 0; i < _AtlasNodes.size(); ++i)
|
||||||
|
{
|
||||||
|
selY = fitRegion(i, width, height);
|
||||||
|
if (selY >=0)
|
||||||
|
{
|
||||||
|
if (((selY + height) < bestHeight) || ((selY + height) == bestHeight && _AtlasNodes[i].Width > 0 && _AtlasNodes[i].Width < bestWidth))
|
||||||
|
{
|
||||||
|
bestHeight = selY + height;
|
||||||
|
bestIndex = i;
|
||||||
|
bestWidth = _AtlasNodes[i].Width;
|
||||||
|
x = _AtlasNodes[i].X;
|
||||||
|
y = selY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestIndex == -1)
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CRect r(x, y + height, width, 0);
|
||||||
|
_AtlasNodes.insert(_AtlasNodes.begin() + bestIndex, r);
|
||||||
|
|
||||||
|
// shrink or remove nodes overlaping with newly inserted node
|
||||||
|
for(uint i = bestIndex+1; i< _AtlasNodes.size(); i++)
|
||||||
|
{
|
||||||
|
if (_AtlasNodes[i].X < (_AtlasNodes[i-1].X + _AtlasNodes[i-1].Width))
|
||||||
|
{
|
||||||
|
sint shrink = _AtlasNodes[i-1].X + _AtlasNodes[i-1].Width - _AtlasNodes[i].X;
|
||||||
|
_AtlasNodes[i].X += shrink;
|
||||||
|
if (_AtlasNodes[i].Width > shrink)
|
||||||
|
{
|
||||||
|
_AtlasNodes[i].Width -= shrink;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_AtlasNodes.erase(_AtlasNodes.begin() + i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge nearby nodes from same row
|
||||||
|
for(uint i = 0; i < _AtlasNodes.size() - 1; i++)
|
||||||
|
{
|
||||||
|
if (_AtlasNodes[i].Y == _AtlasNodes[i+1].Y)
|
||||||
|
{
|
||||||
|
_AtlasNodes[i].Width += _AtlasNodes[i+1].Width;
|
||||||
|
_AtlasNodes.erase(_AtlasNodes.begin() + i + 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// bitmap : texture data
|
||||||
|
// bitmapW : bitmap width
|
||||||
|
// bitmapH : bitmap height
|
||||||
|
// atlasX : pos x in font texture
|
||||||
|
// atlasY : pos y in font texture
|
||||||
|
void CTextureFont::copyGlyphBitmap(uint8* bitmap, uint32 bitmapW, uint32 bitmapH, uint32 atlasX, uint32 atlasY)
|
||||||
|
{
|
||||||
|
for (uint bY = 0; bY < bitmapH; ++bY)
|
||||||
|
{
|
||||||
|
uint8 *pDst = &_Data[0][(atlasY+_PaddingT+bY) * _TextureSizeX+atlasX+_PaddingL];
|
||||||
|
for (uint bX = 0; bX < bitmapW; ++bX)
|
||||||
|
{
|
||||||
|
*pDst = bitmap[bY * bitmapW+bX];
|
||||||
|
++pDst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PaddingR > 0 || _PaddingB > 0 || _PaddingL > 0 || _PaddingT > 0)
|
||||||
|
{
|
||||||
|
for(uint i = 0; i<(bitmapH+_PaddingT+_PaddingB); ++i)
|
||||||
|
{
|
||||||
|
if (_PaddingT > 0) _Data[0][(atlasY + i) * _TextureSizeX + atlasX ] = 0;
|
||||||
|
if (_PaddingB > 0) _Data[0][(atlasY + i) * _TextureSizeX + atlasX + _PaddingL + bitmapW] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0; i<(bitmapW+_PaddingL+_PaddingR); ++i)
|
||||||
|
{
|
||||||
|
if (_PaddingL > 0) _Data[0][atlasY * _TextureSizeX + atlasX + i] = 0;
|
||||||
|
if (_PaddingB > 0) _Data[0][(atlasY + _PaddingT + bitmapH) * _TextureSizeX + atlasX + i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CRect r(atlasX, atlasY, bitmapW + _PaddingL + _PaddingR, bitmapH + _PaddingT + _PaddingB);
|
||||||
|
touchRect(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
CTextureFont::SGlyphInfo* CTextureFont::renderLetterGlyph(SLetterInfo *letter, uint bitmapFontSize)
|
||||||
|
{
|
||||||
|
uint32 nPitch;
|
||||||
|
sint32 left;
|
||||||
|
sint32 top;
|
||||||
|
sint32 advx;
|
||||||
|
uint32 charWidth;
|
||||||
|
uint32 charHeight;
|
||||||
|
uint32 glyphIndex;
|
||||||
|
|
||||||
|
uint8 *bitmap = letter->FontGenerator->getBitmap (letter->Char, bitmapFontSize, letter->Embolden, letter->Oblique,
|
||||||
|
charWidth, charHeight,
|
||||||
|
nPitch, left, top,
|
||||||
|
advx, glyphIndex );
|
||||||
|
|
||||||
|
uint32 atlasX, atlasY;
|
||||||
|
uint32 rectW, rectH;
|
||||||
|
rectW = charWidth + _PaddingL + _PaddingR;
|
||||||
|
rectH = charHeight + _PaddingT + _PaddingB;
|
||||||
|
|
||||||
|
if (!reserveAtlas(rectW, rectH, atlasX, atlasY))
|
||||||
|
{
|
||||||
|
// no room
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
copyGlyphBitmap(bitmap, charWidth, charHeight, atlasX, atlasY);
|
||||||
|
|
||||||
while (((sint)width+1 > Categories[cat]) || ((sint)height+1 > Categories[cat]))
|
SGlyphInfo* glyphInfo = NULL;
|
||||||
{
|
{
|
||||||
++cat;
|
// keep cache sorted by height (smaller first)
|
||||||
nlassert (cat != TEXTUREFONT_NBCATEGORY);
|
std::list<SGlyphInfo>::iterator it = _GlyphCache.begin();
|
||||||
|
while(it != _GlyphCache.end() && it->CharHeight < charHeight)
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = _GlyphCache.insert(it, SGlyphInfo());
|
||||||
|
glyphInfo = &(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And replace the less recently used letter
|
glyphInfo->GlyphIndex = glyphIndex;
|
||||||
SLetterKey k2;
|
glyphInfo->Size = bitmapFontSize;
|
||||||
k2.Char = Back[cat]->Char;
|
glyphInfo->Embolden = letter->Embolden;
|
||||||
k2.FontGenerator = Back[cat]->FontGenerator;
|
glyphInfo->Oblique = letter->Oblique;
|
||||||
k2.Size = Back[cat]->Size;
|
glyphInfo->FontGenerator = letter->FontGenerator;
|
||||||
k2.Embolden = Back[cat]->Embolden;
|
glyphInfo->CacheVersion = _CacheVersion;
|
||||||
k2.Oblique = Back[cat]->Oblique;
|
|
||||||
|
|
||||||
itAccel = Accel.find (k2.getVal());
|
glyphInfo->U0 = (atlasX+_PaddingL) / (float)_TextureSizeX;
|
||||||
if (itAccel != Accel.end())
|
glyphInfo->V0 = (atlasY+_PaddingT) / (float)_TextureSizeY;
|
||||||
|
glyphInfo->U1 = (atlasX+_PaddingL+charWidth) / (float)_TextureSizeX;
|
||||||
|
glyphInfo->V1 = (atlasY+_PaddingT+charHeight) / (float)_TextureSizeY;
|
||||||
|
|
||||||
|
glyphInfo->CharWidth = charWidth;
|
||||||
|
glyphInfo->CharHeight = charHeight;
|
||||||
|
|
||||||
|
glyphInfo->X = atlasX;
|
||||||
|
glyphInfo->Y = atlasY;
|
||||||
|
glyphInfo->W = rectW;
|
||||||
|
glyphInfo->H = rectH;
|
||||||
|
|
||||||
|
return glyphInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
CTextureFont::SGlyphInfo* CTextureFont::findLetterGlyph(SLetterInfo *letter, bool insert)
|
||||||
|
{
|
||||||
|
uint bitmapFontSize = max((sint)_MinGlyphSize, min((sint)_MaxGlyphSize, letter->Size));
|
||||||
|
if (_GlyphSizeStep > 1 && bitmapFontSize > _GlyphSizeStepMin)
|
||||||
{
|
{
|
||||||
Accel.erase (itAccel);
|
bitmapFontSize = (bitmapFontSize / _GlyphSizeStep) * _GlyphSizeStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLetterInfo *NewBack = Back[cat]->Prev;
|
// CacheVersion not checked, all glyphs in cache must be rendered on texture
|
||||||
NewBack->Next = NULL;
|
for(std::list<SGlyphInfo>::iterator it = _GlyphCache.begin(); it != _GlyphCache.end(); ++it)
|
||||||
Back[cat]->Cat = cat;
|
|
||||||
Back[cat]->Char = k.Char;
|
|
||||||
Back[cat]->FontGenerator = k.FontGenerator;
|
|
||||||
Back[cat]->Size = k.Size;
|
|
||||||
Back[cat]->Embolden = k.Embolden;
|
|
||||||
Back[cat]->Oblique = k.Oblique;
|
|
||||||
Back[cat]->CharWidth = width;
|
|
||||||
Back[cat]->CharHeight = height;
|
|
||||||
Back[cat]->Top = nTop;
|
|
||||||
Back[cat]->Left = nLeft;
|
|
||||||
Back[cat]->AdvX = nAdvX;
|
|
||||||
Back[cat]->Prev = NULL;
|
|
||||||
Back[cat]->Next = Front[cat];
|
|
||||||
Front[cat]->Prev = Back[cat];
|
|
||||||
Front[cat] = Back[cat];
|
|
||||||
Back[cat] = NewBack;
|
|
||||||
|
|
||||||
Accel.insert (map<uint32, SLetterInfo*>::value_type(k.getVal(),Front[cat]));
|
|
||||||
|
|
||||||
// Invalidate the zone
|
|
||||||
sint index = (sint)(Front[cat] - &Letters[cat][0]);// / sizeof (SLetterInfo);
|
|
||||||
sint sizex = TextureSizeX / Categories[cat];
|
|
||||||
sint x = index % sizex;
|
|
||||||
sint y = index / sizex;
|
|
||||||
x = x * Categories[cat];
|
|
||||||
y = y * Categories[cat];
|
|
||||||
|
|
||||||
sint c = 0;
|
|
||||||
while (c < cat)
|
|
||||||
{
|
{
|
||||||
y = y + NbLine[c] * Categories[c];
|
if (it->GlyphIndex == letter->GlyphIndex &&
|
||||||
++c;
|
it->Size == bitmapFontSize &&
|
||||||
|
it->Embolden == letter->Embolden &&
|
||||||
|
it->Oblique == letter->Oblique &&
|
||||||
|
it->FontGenerator == letter->FontGenerator)
|
||||||
|
{
|
||||||
|
return &(*it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// must update the char, WITH the black borders
|
if (insert)
|
||||||
CRect r (x, y, width+1, height+1);
|
{
|
||||||
|
return renderLetterGlyph(letter, bitmapFontSize);
|
||||||
|
}
|
||||||
|
|
||||||
touchRect (r);
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return Front[cat];
|
// ---------------------------------------------------------------------------
|
||||||
|
CTextureFont::SLetterInfo* CTextureFont::findLetter(SLetterKey &k, bool insert)
|
||||||
|
{
|
||||||
|
// TODO: use std::map<uint64>
|
||||||
|
for(uint i = 0; i < _Letters.size(); ++i)
|
||||||
|
{
|
||||||
|
if (_Letters[i].Char == k.Char && _Letters[i].Size == k.Size &&
|
||||||
|
_Letters[i].Embolden == k.Embolden && _Letters[i].Oblique == k.Oblique &&
|
||||||
|
_Letters[i].FontGenerator == k.FontGenerator)
|
||||||
|
{
|
||||||
|
return &_Letters[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insert)
|
||||||
|
{
|
||||||
|
_Letters.push_back(SLetterInfo());
|
||||||
|
SLetterInfo* letter = &_Letters.back();
|
||||||
|
|
||||||
|
// get metrics for requested size
|
||||||
|
letter->Char = k.Char;
|
||||||
|
letter->Size = k.Size;
|
||||||
|
letter->Embolden = k.Embolden;
|
||||||
|
letter->Oblique = k.Oblique;
|
||||||
|
letter->FontGenerator = k.FontGenerator;
|
||||||
|
|
||||||
|
uint32 nPitch;
|
||||||
|
letter->FontGenerator->getBitmap(letter->Char, letter->Size, letter->Embolden, letter->Oblique,
|
||||||
|
letter->CharWidth, letter->CharHeight,
|
||||||
|
nPitch, letter->Left, letter->Top,
|
||||||
|
letter->AdvX, letter->GlyphIndex );
|
||||||
|
|
||||||
|
return letter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
CTextureFont::SLetterInfo* CTextureFont::getLetterInfo (SLetterKey& k, bool render)
|
||||||
|
{
|
||||||
|
// find already cached letter or create new one
|
||||||
|
SLetterInfo* letter = findLetter(k, true);
|
||||||
|
// letter not found (=NULL) or render not requested
|
||||||
|
if (!letter || !render) return letter;
|
||||||
|
|
||||||
|
// nothing to render, ie space char
|
||||||
|
if (letter->CharWidth == 0 || letter->CharHeight == 0) return letter;
|
||||||
|
|
||||||
|
if (!letter->glyph || letter->glyph->CacheVersion != _CacheVersion)
|
||||||
|
{
|
||||||
|
// render glyph
|
||||||
|
letter->glyph = findLetterGlyph(letter, true);
|
||||||
|
if (letter->glyph == NULL)
|
||||||
|
{
|
||||||
|
// resize/repack and try again
|
||||||
|
if (!resizeAtlas()) repackAtlas();
|
||||||
|
|
||||||
|
letter->glyph = findLetterGlyph(letter, true);
|
||||||
|
if (letter->glyph == NULL)
|
||||||
|
{
|
||||||
|
// make room by clearing all glyphs and reduce max size for glyphs
|
||||||
|
clearAtlas();
|
||||||
|
if (_MaxGlyphSize > _MinGlyphSize)
|
||||||
|
{
|
||||||
|
_MaxGlyphSize = max(_MinGlyphSize, _MaxGlyphSize - 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
letter->glyph = findLetterGlyph(letter, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return letter;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // NL3D
|
} // NL3D
|
||||||
|
|
|
@ -748,8 +748,12 @@ namespace NLGUI
|
||||||
{
|
{
|
||||||
virtual void execute (CCtrlBase *pCaller, const std::string ¶ms)
|
virtual void execute (CCtrlBase *pCaller, const std::string ¶ms)
|
||||||
{
|
{
|
||||||
if (!CViewRenderer::getInstance()->getDriver()->copyTextToClipboard(params))
|
ucstring s;
|
||||||
|
s.fromUtf8(params);
|
||||||
|
if (!CViewRenderer::getInstance()->getDriver()->copyTextToClipboard(s))
|
||||||
|
{
|
||||||
nlwarning("Copy to clipboard failed: '%s'", params.c_str());
|
nlwarning("Copy to clipboard failed: '%s'", params.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_ACTION_HANDLER(CAHCopyToClipboard, "copy_to_clipboard");
|
REGISTER_ACTION_HANDLER(CAHCopyToClipboard, "copy_to_clipboard");
|
||||||
|
|
|
@ -68,6 +68,7 @@ namespace NLGUI
|
||||||
_StepValue = 0;
|
_StepValue = 0;
|
||||||
_TileM = false;
|
_TileM = false;
|
||||||
_Frozen = false;
|
_Frozen = false;
|
||||||
|
_Scale = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -108,6 +109,11 @@ namespace NLGUI
|
||||||
return getTextureTopOrRight();
|
return getTextureTopOrRight();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if( name == "scale" )
|
||||||
|
{
|
||||||
|
return toString( _Scale );
|
||||||
|
}
|
||||||
|
else
|
||||||
if( name == "vertical" )
|
if( name == "vertical" )
|
||||||
{
|
{
|
||||||
return toString( _Vertical );
|
return toString( _Vertical );
|
||||||
|
@ -244,6 +250,14 @@ namespace NLGUI
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if( name =="scale" )
|
||||||
|
{
|
||||||
|
bool b;
|
||||||
|
if (fromString( value, b ) )
|
||||||
|
_Scale = b;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
if( name == "vertical" )
|
if( name == "vertical" )
|
||||||
{
|
{
|
||||||
bool b;
|
bool b;
|
||||||
|
@ -408,6 +422,7 @@ namespace NLGUI
|
||||||
xmlSetProp( node, BAD_CAST "tx_bottomleft", BAD_CAST getTextureBottomOrLeft().c_str() );
|
xmlSetProp( node, BAD_CAST "tx_bottomleft", BAD_CAST getTextureBottomOrLeft().c_str() );
|
||||||
xmlSetProp( node, BAD_CAST "tx_middle", BAD_CAST getTextureMiddle().c_str() );
|
xmlSetProp( node, BAD_CAST "tx_middle", BAD_CAST getTextureMiddle().c_str() );
|
||||||
xmlSetProp( node, BAD_CAST "tx_topright", BAD_CAST getTextureTopOrRight().c_str() );
|
xmlSetProp( node, BAD_CAST "tx_topright", BAD_CAST getTextureTopOrRight().c_str() );
|
||||||
|
xmlSetProp( node, BAD_CAST "scale", BAD_CAST toString( _Scale ).c_str() );
|
||||||
xmlSetProp( node, BAD_CAST "vertical", BAD_CAST toString( _Vertical ).c_str() );
|
xmlSetProp( node, BAD_CAST "vertical", BAD_CAST toString( _Vertical ).c_str() );
|
||||||
|
|
||||||
std::string align;
|
std::string align;
|
||||||
|
@ -480,6 +495,10 @@ namespace NLGUI
|
||||||
if(prop) setTextureTopOrRight(string((const char*)prop));
|
if(prop) setTextureTopOrRight(string((const char*)prop));
|
||||||
else setTextureTopOrRight ("w_scroll_l0_t.tga");
|
else setTextureTopOrRight ("w_scroll_l0_t.tga");
|
||||||
|
|
||||||
|
// Override texture size (w for vertical, h for horizontal)
|
||||||
|
prop = (char*) xmlGetProp( node, (xmlChar*)"scale" );
|
||||||
|
if (prop) _Scale = convertBool((const char*)prop);
|
||||||
|
|
||||||
// Read properties
|
// Read properties
|
||||||
prop = (char*) xmlGetProp( node, (xmlChar*)"vertical" );
|
prop = (char*) xmlGetProp( node, (xmlChar*)"vertical" );
|
||||||
if (prop) _Vertical = convertBool((const char*)prop);
|
if (prop) _Vertical = convertBool((const char*)prop);
|
||||||
|
@ -606,13 +625,13 @@ namespace NLGUI
|
||||||
|
|
||||||
if (_Vertical)
|
if (_Vertical)
|
||||||
{
|
{
|
||||||
_W = w;
|
if (!_Scale) _W = w;
|
||||||
_H = _Target->getMaxHReal();
|
_H = _Target->getMaxHReal();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_W = _Target->getMaxWReal();
|
_W = _Target->getMaxWReal();
|
||||||
_H = h;
|
if (!_Scale) _H = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
CCtrlBase::updateCoords ();
|
CCtrlBase::updateCoords ();
|
||||||
|
|
|
@ -46,6 +46,7 @@ namespace NLGUI
|
||||||
_BmpLeftW= _BmpMiddleW= _BmpRightW= _BmpH= 0;
|
_BmpLeftW= _BmpMiddleW= _BmpRightW= _BmpH= 0;
|
||||||
_WMargin= 0;
|
_WMargin= 0;
|
||||||
_WMin= 0;
|
_WMin= 0;
|
||||||
|
_HMin= 0;
|
||||||
_TextX= 0;
|
_TextX= 0;
|
||||||
_TextY= 0;
|
_TextY= 0;
|
||||||
_Setuped= false;
|
_Setuped= false;
|
||||||
|
@ -124,6 +125,11 @@ namespace NLGUI
|
||||||
return toString( _WMin );
|
return toString( _WMin );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if( name == "hmin" )
|
||||||
|
{
|
||||||
|
return toString( _HMin );
|
||||||
|
}
|
||||||
|
else
|
||||||
if( name == "hardtext" )
|
if( name == "hardtext" )
|
||||||
{
|
{
|
||||||
if( _ViewText != NULL )
|
if( _ViewText != NULL )
|
||||||
|
@ -296,6 +302,14 @@ namespace NLGUI
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if( name == "hmin" )
|
||||||
|
{
|
||||||
|
sint32 i;
|
||||||
|
if( fromString( value, i ) )
|
||||||
|
_HMin = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
if( name == "hardtext" )
|
if( name == "hardtext" )
|
||||||
{
|
{
|
||||||
if( _ViewText != NULL )
|
if( _ViewText != NULL )
|
||||||
|
@ -469,6 +483,7 @@ namespace NLGUI
|
||||||
|
|
||||||
xmlNewProp( node, BAD_CAST "wmargin", BAD_CAST toString( _WMargin ).c_str() );
|
xmlNewProp( node, BAD_CAST "wmargin", BAD_CAST toString( _WMargin ).c_str() );
|
||||||
xmlNewProp( node, BAD_CAST "wmin", BAD_CAST toString( _WMin ).c_str() );
|
xmlNewProp( node, BAD_CAST "wmin", BAD_CAST toString( _WMin ).c_str() );
|
||||||
|
xmlNewProp( node, BAD_CAST "hmin", BAD_CAST toString( _HMin ).c_str() );
|
||||||
xmlNewProp( node, BAD_CAST "hardtext", BAD_CAST _ViewText->getText().toString().c_str() );
|
xmlNewProp( node, BAD_CAST "hardtext", BAD_CAST _ViewText->getText().toString().c_str() );
|
||||||
xmlNewProp( node, BAD_CAST "text_y", BAD_CAST toString( _TextY ).c_str() );
|
xmlNewProp( node, BAD_CAST "text_y", BAD_CAST toString( _TextY ).c_str() );
|
||||||
xmlNewProp( node, BAD_CAST "text_x", BAD_CAST toString( _TextX ).c_str() );
|
xmlNewProp( node, BAD_CAST "text_x", BAD_CAST toString( _TextX ).c_str() );
|
||||||
|
@ -519,7 +534,6 @@ namespace NLGUI
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// *** Read Textures.
|
// *** Read Textures.
|
||||||
prop = (char*) xmlGetProp( cur, (xmlChar*)"tx_normal" );
|
prop = (char*) xmlGetProp( cur, (xmlChar*)"tx_normal" );
|
||||||
if (prop)
|
if (prop)
|
||||||
|
@ -604,6 +618,15 @@ namespace NLGUI
|
||||||
// _WMin is at least the size of All W Bitmaps
|
// _WMin is at least the size of All W Bitmaps
|
||||||
_WMin= max(_WMin, _BmpLeftW + _BmpMiddleW + _BmpRightW);
|
_WMin= max(_WMin, _BmpLeftW + _BmpMiddleW + _BmpRightW);
|
||||||
|
|
||||||
|
// hmin
|
||||||
|
_HMin= 0;
|
||||||
|
prop = (char*) xmlGetProp( cur, (xmlChar*)"hmin" );
|
||||||
|
if (prop)
|
||||||
|
{
|
||||||
|
fromString((const char *) prop, _HMin);
|
||||||
|
}
|
||||||
|
_HMin= max(_HMin, _BmpH);
|
||||||
|
|
||||||
// TextY
|
// TextY
|
||||||
_TextY= 0;
|
_TextY= 0;
|
||||||
prop = (char*) xmlGetProp( cur, (xmlChar*)"text_y" );
|
prop = (char*) xmlGetProp( cur, (xmlChar*)"text_y" );
|
||||||
|
@ -705,6 +728,43 @@ namespace NLGUI
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
void CCtrlTextButton::setTexture(const std::string &l, const std::string &m, const std::string &r, bool updateHeight)
|
||||||
|
{
|
||||||
|
nlctassert(NumTexture==3);
|
||||||
|
_TextureIdNormal[0].setTexture(l.c_str());
|
||||||
|
_TextureIdNormal[1].setTexture(m.c_str());
|
||||||
|
_TextureIdNormal[2].setTexture(r.c_str());
|
||||||
|
|
||||||
|
sint32 newH;
|
||||||
|
|
||||||
|
// Compute Bmp Sizes
|
||||||
|
CViewRenderer &rVR = *CViewRenderer::getInstance();
|
||||||
|
rVR.getTextureSizeFromId(_TextureIdNormal[0], _BmpLeftW, newH);
|
||||||
|
rVR.getTextureSizeFromId(_TextureIdNormal[1], _BmpMiddleW, newH);
|
||||||
|
rVR.getTextureSizeFromId(_TextureIdNormal[2], _BmpRightW, newH);
|
||||||
|
|
||||||
|
if (updateHeight) _BmpH = newH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
void CCtrlTextButton::setTexturePushed(const std::string &l, const std::string &m, const std::string &r)
|
||||||
|
{
|
||||||
|
nlctassert(NumTexture==3);
|
||||||
|
_TextureIdPushed[0].setTexture(l.c_str());
|
||||||
|
_TextureIdPushed[1].setTexture(m.c_str());
|
||||||
|
_TextureIdPushed[2].setTexture(r.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
void CCtrlTextButton::setTextureOver(const std::string &l, const std::string &m, const std::string &r)
|
||||||
|
{
|
||||||
|
nlctassert(NumTexture==3);
|
||||||
|
_TextureIdOver[0].setTexture(l.c_str());
|
||||||
|
_TextureIdOver[1].setTexture(m.c_str());
|
||||||
|
_TextureIdOver[2].setTexture(r.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
void CCtrlTextButton::draw ()
|
void CCtrlTextButton::draw ()
|
||||||
{
|
{
|
||||||
|
@ -899,7 +959,8 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
if (!(_SizeRef & 2))
|
if (!(_SizeRef & 2))
|
||||||
{
|
{
|
||||||
_H= _BmpH;
|
_H= max(_BmpH, _ViewText->getH());
|
||||||
|
_H= max(_H, _HMin);
|
||||||
}
|
}
|
||||||
|
|
||||||
CViewBase::updateCoords();
|
CViewBase::updateCoords();
|
||||||
|
|
|
@ -473,6 +473,12 @@ namespace NLGUI
|
||||||
return _ViewText->getText();
|
return _ViewText->getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
CViewText *CDBGroupComboBox::getViewText()
|
||||||
|
{
|
||||||
|
return _ViewText;
|
||||||
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
std::string CDBGroupComboBox::getSelectionText() const
|
std::string CDBGroupComboBox::getSelectionText() const
|
||||||
{
|
{
|
||||||
|
@ -633,6 +639,9 @@ namespace NLGUI
|
||||||
{
|
{
|
||||||
nlassert(groupMenu);
|
nlassert(groupMenu);
|
||||||
|
|
||||||
|
if (_ViewText)
|
||||||
|
groupMenu->setFontSize(_ViewText->getFontSize());
|
||||||
|
|
||||||
// Setup the menu with combo action.
|
// Setup the menu with combo action.
|
||||||
groupMenu->reset();
|
groupMenu->reset();
|
||||||
for(uint i=0; i<getNumTexts(); i++)
|
for(uint i=0; i<getNumTexts(); i++)
|
||||||
|
|
|
@ -702,9 +702,9 @@ namespace NLGUI
|
||||||
sint32 maxPos= max(_CursorPos, _SelectCursorPos) + (sint32)_Prompt.length();
|
sint32 maxPos= max(_CursorPos, _SelectCursorPos) + (sint32)_Prompt.length();
|
||||||
|
|
||||||
// get its position on screen
|
// get its position on screen
|
||||||
sint cxMinPos, cyMinPos;
|
float cxMinPos, cyMinPos;
|
||||||
sint cxMaxPos, cyMaxPos;
|
float cxMaxPos, cyMaxPos;
|
||||||
sint height;
|
float height;
|
||||||
_ViewText->getCharacterPositionFromIndex(minPos, false, cxMinPos, cyMinPos, height);
|
_ViewText->getCharacterPositionFromIndex(minPos, false, cxMinPos, cyMinPos, height);
|
||||||
_ViewText->getCharacterPositionFromIndex(maxPos, false, cxMaxPos, cyMaxPos, height);
|
_ViewText->getCharacterPositionFromIndex(maxPos, false, cxMaxPos, cyMaxPos, height);
|
||||||
|
|
||||||
|
@ -755,8 +755,8 @@ namespace NLGUI
|
||||||
if (_BlinkState) // is the cursor shown ?
|
if (_BlinkState) // is the cursor shown ?
|
||||||
{
|
{
|
||||||
// get its position on screen
|
// get its position on screen
|
||||||
sint cx, cy;
|
float cx, cy;
|
||||||
sint height;
|
float height;
|
||||||
_ViewText->getCharacterPositionFromIndex(_CursorPos + (sint)_Prompt.length(), _CursorAtPreviousLineEnd, cx, cy, height);
|
_ViewText->getCharacterPositionFromIndex(_CursorPos + (sint)_Prompt.length(), _CursorAtPreviousLineEnd, cx, cy, height);
|
||||||
// display the cursor
|
// display the cursor
|
||||||
// get the texture for the cursor
|
// get the texture for the cursor
|
||||||
|
@ -1482,7 +1482,7 @@ namespace NLGUI
|
||||||
if (_ViewText->getWReal() > _WReal)
|
if (_ViewText->getWReal() > _WReal)
|
||||||
{
|
{
|
||||||
// Check if cursor visible
|
// Check if cursor visible
|
||||||
sint xCursVT, xCurs, yTmp, hTmp;
|
float xCursVT, xCurs, yTmp, hTmp;
|
||||||
// Get the cursor pos from the BL of the viewtext
|
// Get the cursor pos from the BL of the viewtext
|
||||||
_ViewText->getCharacterPositionFromIndex(_CursorPos+(sint)_Prompt.size(), false, xCursVT, yTmp, hTmp);
|
_ViewText->getCharacterPositionFromIndex(_CursorPos+(sint)_Prompt.size(), false, xCursVT, yTmp, hTmp);
|
||||||
// Get the cursor pos from the BL of the edit box
|
// Get the cursor pos from the BL of the edit box
|
||||||
|
|
|
@ -381,7 +381,61 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGroupHTML::setTextButtonStyle(CCtrlTextButton *ctrlButton, const CStyleParams &style)
|
||||||
|
{
|
||||||
|
// this will also set size for <a class="ryzom-ui-button"> treating it like "display: inline-block;"
|
||||||
|
if (style.Width > 0) ctrlButton->setWMin(_Style.Width);
|
||||||
|
if (style.Height > 0) ctrlButton->setHMin(_Style.Height);
|
||||||
|
|
||||||
|
CViewText *pVT = ctrlButton->getViewText();
|
||||||
|
if (pVT)
|
||||||
|
{
|
||||||
|
setTextStyle(pVT, _Style);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_Style.BackgroundColor.A > 0)
|
||||||
|
{
|
||||||
|
if (_Style.BackgroundColorOver.A == 0)
|
||||||
|
_Style.BackgroundColorOver = _Style.BackgroundColor;
|
||||||
|
|
||||||
|
ctrlButton->setColor(_Style.BackgroundColor);
|
||||||
|
ctrlButton->setColorOver(_Style.BackgroundColorOver);
|
||||||
|
ctrlButton->setTexture("", "blank.tga", "", false);
|
||||||
|
ctrlButton->setTextureOver("", "blank.tga", "");
|
||||||
|
ctrlButton->setProperty("force_text_over", "true");
|
||||||
|
}
|
||||||
|
else if (_Style.BackgroundColorOver.A > 0)
|
||||||
|
{
|
||||||
|
ctrlButton->setColorOver(_Style.BackgroundColorOver);
|
||||||
|
ctrlButton->setProperty("force_text_over", "true");
|
||||||
|
ctrlButton->setTextureOver("blank.tga", "blank.tga", "blank.tga");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGroupHTML::setTextStyle(CViewText *pVT, const CStyleParams &style)
|
||||||
|
{
|
||||||
|
if (pVT)
|
||||||
|
{
|
||||||
|
pVT->setFontSize(style.FontSize);
|
||||||
|
pVT->setColor(style.TextColor);
|
||||||
|
pVT->setColor(style.TextColor);
|
||||||
|
pVT->setFontName(style.FontFamily);
|
||||||
|
pVT->setFontSize(style.FontSize);
|
||||||
|
pVT->setEmbolden(style.FontWeight >= FONT_WEIGHT_BOLD);
|
||||||
|
pVT->setOblique(style.FontOblique);
|
||||||
|
pVT->setUnderlined(style.Underlined);
|
||||||
|
pVT->setStrikeThrough(style.StrikeThrough);
|
||||||
|
if (style.TextShadow.Enabled)
|
||||||
|
{
|
||||||
|
pVT->setShadow(true);
|
||||||
|
pVT->setShadowColor(style.TextShadow.Color);
|
||||||
|
pVT->setShadowOutline(style.TextShadow.Outline);
|
||||||
|
pVT->setShadowOffset(style.TextShadow.X, style.TextShadow.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get an url and return the local filename with the path where the url image should be
|
// Get an url and return the local filename with the path where the url image should be
|
||||||
string CGroupHTML::localImageName(const string &url)
|
string CGroupHTML::localImageName(const string &url)
|
||||||
{
|
{
|
||||||
|
@ -1489,6 +1543,13 @@ namespace NLGUI
|
||||||
// Paragraph ?
|
// Paragraph ?
|
||||||
switch(element_number)
|
switch(element_number)
|
||||||
{
|
{
|
||||||
|
case HTML_HTML:
|
||||||
|
if (present[MY_HTML_HTML_STYLE] && value[MY_HTML_HTML_STYLE])
|
||||||
|
getStyleParams(value[MY_HTML_HTML_STYLE], _StyleDefault, _StyleDefault);
|
||||||
|
|
||||||
|
_Style = _StyleDefault;
|
||||||
|
setBackgroundColor(_Style.BackgroundColor);
|
||||||
|
break;
|
||||||
case HTML_HEAD:
|
case HTML_HEAD:
|
||||||
_ReadingHeadTag = !_IgnoreHeadTag;
|
_ReadingHeadTag = !_IgnoreHeadTag;
|
||||||
_IgnoreHeadTag = true;
|
_IgnoreHeadTag = true;
|
||||||
|
@ -1549,9 +1610,13 @@ namespace NLGUI
|
||||||
_Style.TextColor = LinkColor;
|
_Style.TextColor = LinkColor;
|
||||||
_Style.Underlined = true;
|
_Style.Underlined = true;
|
||||||
_Style.GlobalColor = LinkColorGlobalColor;
|
_Style.GlobalColor = LinkColorGlobalColor;
|
||||||
|
_Style.BackgroundColor.A = 0;
|
||||||
|
_Style.BackgroundColorOver.A = 0;
|
||||||
|
_Style.Width = -1;
|
||||||
|
_Style.Height = -1;
|
||||||
|
|
||||||
if (present[HTML_A_STYLE] && value[HTML_A_STYLE])
|
if (present[HTML_A_STYLE] && value[HTML_A_STYLE])
|
||||||
getStyleParams(value[HTML_A_STYLE], _Style);
|
getStyleParams(value[HTML_A_STYLE], _Style, _StyleParams.back());
|
||||||
|
|
||||||
_A.push_back(true);
|
_A.push_back(true);
|
||||||
_Link.push_back ("");
|
_Link.push_back ("");
|
||||||
|
@ -1604,7 +1669,7 @@ namespace NLGUI
|
||||||
style = value[MY_HTML_DIV_STYLE];
|
style = value[MY_HTML_DIV_STYLE];
|
||||||
|
|
||||||
if (!style.empty())
|
if (!style.empty())
|
||||||
getStyleParams(style, _Style);
|
getStyleParams(style, _Style, _StyleParams.back());
|
||||||
|
|
||||||
// use generic template system
|
// use generic template system
|
||||||
if (_TrustedDomain && !instClass.empty() && instClass == "ryzom-ui-grouptemplate")
|
if (_TrustedDomain && !instClass.empty() && instClass == "ryzom-ui-grouptemplate")
|
||||||
|
@ -1708,18 +1773,22 @@ namespace NLGUI
|
||||||
break;
|
break;
|
||||||
case HTML_BODY:
|
case HTML_BODY:
|
||||||
{
|
{
|
||||||
if (present[HTML_BODY_BGCOLOR] && value[HTML_BODY_BGCOLOR])
|
pushStyle();
|
||||||
{
|
|
||||||
CRGBA bgColor;
|
|
||||||
if (scanHTMLColor(value[HTML_BODY_BGCOLOR], bgColor))
|
|
||||||
setBackgroundColor (bgColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
string style;
|
string style;
|
||||||
if (present[HTML_BODY_STYLE] && value[HTML_BODY_STYLE])
|
if (present[HTML_BODY_STYLE] && value[HTML_BODY_STYLE])
|
||||||
style = value[HTML_BODY_STYLE];
|
style = value[HTML_BODY_STYLE];
|
||||||
|
|
||||||
|
if (!style.empty())
|
||||||
|
getStyleParams(style, _Style, _StyleParams.back());
|
||||||
|
|
||||||
|
CRGBA bgColor = _Style.BackgroundColor;
|
||||||
|
if (present[HTML_BODY_BGCOLOR] && value[HTML_BODY_BGCOLOR])
|
||||||
|
scanHTMLColor(value[HTML_BODY_BGCOLOR], bgColor);
|
||||||
|
|
||||||
|
if (bgColor != _Style.BackgroundColor)
|
||||||
|
setBackgroundColor(bgColor);
|
||||||
|
|
||||||
if (!style.empty())
|
if (!style.empty())
|
||||||
{
|
{
|
||||||
TStyle styles = parseStyle(style);
|
TStyle styles = parseStyle(style);
|
||||||
|
@ -1743,10 +1812,6 @@ namespace NLGUI
|
||||||
image = image.substr(4, image.size()-5);
|
image = image.substr(4, image.size()-5);
|
||||||
setBackground (image, scale, repeat);
|
setBackground (image, scale, repeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set default text style from <body>
|
|
||||||
getStyleParams(style, _StyleDefault);
|
|
||||||
_Style = _StyleDefault;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1776,7 +1841,7 @@ namespace NLGUI
|
||||||
_Style.TextColor = H1Color;
|
_Style.TextColor = H1Color;
|
||||||
_Style.GlobalColor = H1ColorGlobalColor;
|
_Style.GlobalColor = H1ColorGlobalColor;
|
||||||
if (present[MY_HTML_H1_STYLE] && value[MY_HTML_H1_STYLE])
|
if (present[MY_HTML_H1_STYLE] && value[MY_HTML_H1_STYLE])
|
||||||
getStyleParams(value[MY_HTML_H1_STYLE], _Style);
|
getStyleParams(value[MY_HTML_H1_STYLE], _Style, _StyleParams.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTML_H2:
|
case HTML_H2:
|
||||||
|
@ -1788,7 +1853,7 @@ namespace NLGUI
|
||||||
_Style.TextColor = H2Color;
|
_Style.TextColor = H2Color;
|
||||||
_Style.GlobalColor = H2ColorGlobalColor;
|
_Style.GlobalColor = H2ColorGlobalColor;
|
||||||
if (present[MY_HTML_H2_STYLE] && value[MY_HTML_H2_STYLE])
|
if (present[MY_HTML_H2_STYLE] && value[MY_HTML_H2_STYLE])
|
||||||
getStyleParams(value[MY_HTML_H2_STYLE], _Style);
|
getStyleParams(value[MY_HTML_H2_STYLE], _Style, _StyleParams.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTML_H3:
|
case HTML_H3:
|
||||||
|
@ -1800,7 +1865,7 @@ namespace NLGUI
|
||||||
_Style.TextColor = H3Color;
|
_Style.TextColor = H3Color;
|
||||||
_Style.GlobalColor = H3ColorGlobalColor;
|
_Style.GlobalColor = H3ColorGlobalColor;
|
||||||
if (present[MY_HTML_H3_STYLE] && value[MY_HTML_H3_STYLE])
|
if (present[MY_HTML_H3_STYLE] && value[MY_HTML_H3_STYLE])
|
||||||
getStyleParams(value[MY_HTML_H3_STYLE], _Style);
|
getStyleParams(value[MY_HTML_H3_STYLE], _Style, _StyleParams.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTML_H4:
|
case HTML_H4:
|
||||||
|
@ -1812,7 +1877,7 @@ namespace NLGUI
|
||||||
_Style.TextColor = H4Color;
|
_Style.TextColor = H4Color;
|
||||||
_Style.GlobalColor = H4ColorGlobalColor;
|
_Style.GlobalColor = H4ColorGlobalColor;
|
||||||
if (present[MY_HTML_H4_STYLE] && value[MY_HTML_H4_STYLE])
|
if (present[MY_HTML_H4_STYLE] && value[MY_HTML_H4_STYLE])
|
||||||
getStyleParams(value[MY_HTML_H4_STYLE], _Style);
|
getStyleParams(value[MY_HTML_H4_STYLE], _Style, _StyleParams.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTML_H5:
|
case HTML_H5:
|
||||||
|
@ -1824,7 +1889,7 @@ namespace NLGUI
|
||||||
_Style.TextColor = H5Color;
|
_Style.TextColor = H5Color;
|
||||||
_Style.GlobalColor = H5ColorGlobalColor;
|
_Style.GlobalColor = H5ColorGlobalColor;
|
||||||
if (present[MY_HTML_H5_STYLE] && value[MY_HTML_H5_STYLE])
|
if (present[MY_HTML_H5_STYLE] && value[MY_HTML_H5_STYLE])
|
||||||
getStyleParams(value[MY_HTML_H5_STYLE], _Style);
|
getStyleParams(value[MY_HTML_H5_STYLE], _Style, _StyleParams.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTML_H6:
|
case HTML_H6:
|
||||||
|
@ -1836,7 +1901,7 @@ namespace NLGUI
|
||||||
_Style.TextColor = H6Color;
|
_Style.TextColor = H6Color;
|
||||||
_Style.GlobalColor = H6ColorGlobalColor;
|
_Style.GlobalColor = H6ColorGlobalColor;
|
||||||
if (present[MY_HTML_H6_STYLE] && value[MY_HTML_H6_STYLE])
|
if (present[MY_HTML_H6_STYLE] && value[MY_HTML_H6_STYLE])
|
||||||
getStyleParams(value[MY_HTML_H6_STYLE], _Style);
|
getStyleParams(value[MY_HTML_H6_STYLE], _Style, _StyleParams.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTML_IMG:
|
case HTML_IMG:
|
||||||
|
@ -1844,9 +1909,14 @@ namespace NLGUI
|
||||||
// Get the string name
|
// Get the string name
|
||||||
if (present[MY_HTML_IMG_SRC] && value[MY_HTML_IMG_SRC])
|
if (present[MY_HTML_IMG_SRC] && value[MY_HTML_IMG_SRC])
|
||||||
{
|
{
|
||||||
CStyleParams style;
|
|
||||||
float tmpf;
|
float tmpf;
|
||||||
|
std::string id;
|
||||||
|
CStyleParams style;
|
||||||
|
style.FontSize = _Style.FontSize;
|
||||||
|
|
||||||
|
if (present[MY_HTML_IMG_ID] && value[MY_HTML_IMG_ID])
|
||||||
|
id = value[MY_HTML_IMG_ID];
|
||||||
|
|
||||||
if (present[MY_HTML_IMG_WIDTH] && value[MY_HTML_IMG_WIDTH])
|
if (present[MY_HTML_IMG_WIDTH] && value[MY_HTML_IMG_WIDTH])
|
||||||
getPercentage(style.Width, tmpf, value[MY_HTML_IMG_WIDTH]);
|
getPercentage(style.Width, tmpf, value[MY_HTML_IMG_WIDTH]);
|
||||||
if (present[MY_HTML_IMG_HEIGHT] && value[MY_HTML_IMG_HEIGHT])
|
if (present[MY_HTML_IMG_HEIGHT] && value[MY_HTML_IMG_HEIGHT])
|
||||||
|
@ -1858,7 +1928,7 @@ namespace NLGUI
|
||||||
|
|
||||||
// width, height from inline css
|
// width, height from inline css
|
||||||
if (present[MY_HTML_IMG_STYLE] && value[MY_HTML_IMG_STYLE])
|
if (present[MY_HTML_IMG_STYLE] && value[MY_HTML_IMG_STYLE])
|
||||||
getStyleParams(value[MY_HTML_IMG_STYLE], style);
|
getStyleParams(value[MY_HTML_IMG_STYLE], style, _Style);
|
||||||
|
|
||||||
// Tooltip
|
// Tooltip
|
||||||
const char *tooltip = NULL;
|
const char *tooltip = NULL;
|
||||||
|
@ -1880,13 +1950,13 @@ namespace NLGUI
|
||||||
if (getA() && getParent () && getParent ()->getParent())
|
if (getA() && getParent () && getParent ()->getParent())
|
||||||
{
|
{
|
||||||
string params = "name=" + getId() + "|url=" + getLink ();
|
string params = "name=" + getId() + "|url=" + getLink ();
|
||||||
addButton(CCtrlButton::PushButton, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC],
|
addButton(CCtrlButton::PushButton, id, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC],
|
||||||
overSrc, "browse", params.c_str(), tooltip, style);
|
overSrc, "browse", params.c_str(), tooltip, style);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (tooltip || !overSrc.empty())
|
if (tooltip || !overSrc.empty())
|
||||||
{
|
{
|
||||||
addButton(CCtrlButton::PushButton, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC],
|
addButton(CCtrlButton::PushButton, id, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC],
|
||||||
overSrc, "", "", tooltip, style);
|
overSrc, "", "", tooltip, style);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1908,7 +1978,7 @@ namespace NLGUI
|
||||||
reloadImg = true;
|
reloadImg = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
addImage (value[MY_HTML_IMG_SRC], reloadImg, style);
|
addImage(id, value[MY_HTML_IMG_SRC], reloadImg, style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1920,6 +1990,10 @@ namespace NLGUI
|
||||||
// read general property
|
// read general property
|
||||||
string templateName;
|
string templateName;
|
||||||
string minWidth;
|
string minWidth;
|
||||||
|
string id;
|
||||||
|
|
||||||
|
if (present[MY_HTML_INPUT_ID] && value[MY_HTML_INPUT_ID])
|
||||||
|
id = value[MY_HTML_INPUT_ID];
|
||||||
|
|
||||||
// Widget template name
|
// Widget template name
|
||||||
if (present[MY_HTML_INPUT_Z_BTN_TMPL] && value[MY_HTML_INPUT_Z_BTN_TMPL])
|
if (present[MY_HTML_INPUT_Z_BTN_TMPL] && value[MY_HTML_INPUT_Z_BTN_TMPL])
|
||||||
|
@ -1940,6 +2014,13 @@ namespace NLGUI
|
||||||
_Style.FontSize = TextFontSize;
|
_Style.FontSize = TextFontSize;
|
||||||
_Style.FontWeight = FONT_WEIGHT_NORMAL;
|
_Style.FontWeight = FONT_WEIGHT_NORMAL;
|
||||||
_Style.FontOblique = false;
|
_Style.FontOblique = false;
|
||||||
|
_Style.TextShadow = STextShadow(true);
|
||||||
|
_Style.Width = -1;
|
||||||
|
_Style.Height = -1;
|
||||||
|
// by default background texture is transparent,
|
||||||
|
// using alpha value to decide if to change it to 'blank.tga' for coloring
|
||||||
|
_Style.BackgroundColor.A = 0;
|
||||||
|
_Style.BackgroundColorOver.A = 0;
|
||||||
|
|
||||||
// Global color flag
|
// Global color flag
|
||||||
if (present[MY_HTML_INPUT_GLOBAL_COLOR])
|
if (present[MY_HTML_INPUT_GLOBAL_COLOR])
|
||||||
|
@ -1951,7 +2032,7 @@ namespace NLGUI
|
||||||
tooltip = value[MY_HTML_INPUT_ALT];
|
tooltip = value[MY_HTML_INPUT_ALT];
|
||||||
|
|
||||||
if (present[MY_HTML_INPUT_STYLE] && value[MY_HTML_INPUT_STYLE])
|
if (present[MY_HTML_INPUT_STYLE] && value[MY_HTML_INPUT_STYLE])
|
||||||
getStyleParams(value[MY_HTML_INPUT_STYLE], _Style);
|
getStyleParams(value[MY_HTML_INPUT_STYLE], _Style, _StyleParams.back());
|
||||||
|
|
||||||
string type = toLower(value[MY_HTML_INPUT_TYPE]);
|
string type = toLower(value[MY_HTML_INPUT_TYPE]);
|
||||||
if (type == "image")
|
if (type == "image")
|
||||||
|
@ -2042,6 +2123,8 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrlButton->setText(ucstring::makeFromUtf8(text));
|
ctrlButton->setText(ucstring::makeFromUtf8(text));
|
||||||
|
|
||||||
|
setTextButtonStyle(ctrlButton, _Style);
|
||||||
}
|
}
|
||||||
getParagraph()->addChild (buttonGroup);
|
getParagraph()->addChild (buttonGroup);
|
||||||
paragraphChange ();
|
paragraphChange ();
|
||||||
|
@ -2114,6 +2197,10 @@ namespace NLGUI
|
||||||
{
|
{
|
||||||
if (btnType == CCtrlButton::RadioButton)
|
if (btnType == CCtrlButton::RadioButton)
|
||||||
{
|
{
|
||||||
|
// override with 'id' because radio buttons share same name
|
||||||
|
if (!id.empty())
|
||||||
|
checkbox->setId(id);
|
||||||
|
|
||||||
// group together buttons with same name
|
// group together buttons with same name
|
||||||
CForm &form = _Forms.back();
|
CForm &form = _Forms.back();
|
||||||
bool notfound = true;
|
bool notfound = true;
|
||||||
|
@ -2184,7 +2271,7 @@ namespace NLGUI
|
||||||
if (present[HTML_SELECT_MULTIPLE] && value[HTML_SELECT_MULTIPLE])
|
if (present[HTML_SELECT_MULTIPLE] && value[HTML_SELECT_MULTIPLE])
|
||||||
multiple = true;
|
multiple = true;
|
||||||
if (present[HTML_SELECT_STYLE] && value[HTML_SELECT_STYLE])
|
if (present[HTML_SELECT_STYLE] && value[HTML_SELECT_STYLE])
|
||||||
getStyleParams(value[HTML_SELECT_STYLE], style);
|
getStyleParams(value[HTML_SELECT_STYLE], style, _Style);
|
||||||
|
|
||||||
CGroupHTML::CForm::CEntry entry;
|
CGroupHTML::CForm::CEntry entry;
|
||||||
entry.Name = name;
|
entry.Name = name;
|
||||||
|
@ -2205,6 +2292,7 @@ namespace NLGUI
|
||||||
sb->setMinH(style.Height);
|
sb->setMinH(style.Height);
|
||||||
|
|
||||||
sb->setMaxVisibleLine(size);
|
sb->setMaxVisibleLine(size);
|
||||||
|
sb->setFontSize(style.FontSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.SelectBox = sb;
|
entry.SelectBox = sb;
|
||||||
|
@ -2213,6 +2301,14 @@ namespace NLGUI
|
||||||
{
|
{
|
||||||
CDBGroupComboBox *cb = addComboBox(DefaultFormSelectGroup, name.c_str());
|
CDBGroupComboBox *cb = addComboBox(DefaultFormSelectGroup, name.c_str());
|
||||||
entry.ComboBox = cb;
|
entry.ComboBox = cb;
|
||||||
|
|
||||||
|
if (cb)
|
||||||
|
{
|
||||||
|
// create view text
|
||||||
|
cb->updateCoords();
|
||||||
|
if (cb->getViewText())
|
||||||
|
setTextStyle(cb->getViewText(), style);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_Forms.back().Entries.push_back (entry);
|
_Forms.back().Entries.push_back (entry);
|
||||||
}
|
}
|
||||||
|
@ -2259,7 +2355,7 @@ namespace NLGUI
|
||||||
|
|
||||||
pushStyle();
|
pushStyle();
|
||||||
if (present[HTML_LI_STYLE] && value[HTML_LI_STYLE])
|
if (present[HTML_LI_STYLE] && value[HTML_LI_STYLE])
|
||||||
getStyleParams(value[HTML_LI_STYLE], _Style);
|
getStyleParams(value[HTML_LI_STYLE], _Style, _StyleParams.back());
|
||||||
|
|
||||||
ucstring str;
|
ucstring str;
|
||||||
str.fromUtf8(_UL.back().getListMarkerText());
|
str.fromUtf8(_UL.back().getListMarkerText());
|
||||||
|
@ -2281,8 +2377,8 @@ namespace NLGUI
|
||||||
{
|
{
|
||||||
newParagraph(PBeginSpace);
|
newParagraph(PBeginSpace);
|
||||||
pushStyle();
|
pushStyle();
|
||||||
if (present[HTML_BLOCK_STYLE] && value[HTML_BLOCK_STYLE])
|
if (present[MY_HTML_P_STYLE] && value[MY_HTML_P_STYLE])
|
||||||
getStyleParams(value[HTML_BLOCK_STYLE], _Style);
|
getStyleParams(value[MY_HTML_P_STYLE], _Style, _StyleParams.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTML_PRE:
|
case HTML_PRE:
|
||||||
|
@ -2291,7 +2387,7 @@ namespace NLGUI
|
||||||
_Style.FontFamily = "monospace";
|
_Style.FontFamily = "monospace";
|
||||||
|
|
||||||
if (present[HTML_PRE_STYLE] && value[HTML_PRE_STYLE])
|
if (present[HTML_PRE_STYLE] && value[HTML_PRE_STYLE])
|
||||||
getStyleParams(value[HTML_PRE_STYLE], _Style);
|
getStyleParams(value[HTML_PRE_STYLE], _Style, _StyleParams.back());
|
||||||
|
|
||||||
|
|
||||||
_PRE.push_back(true);
|
_PRE.push_back(true);
|
||||||
|
@ -2319,7 +2415,7 @@ namespace NLGUI
|
||||||
if (present[MY_HTML_TABLE_CELLPADDING] && value[MY_HTML_TABLE_CELLPADDING])
|
if (present[MY_HTML_TABLE_CELLPADDING] && value[MY_HTML_TABLE_CELLPADDING])
|
||||||
fromString(value[MY_HTML_TABLE_CELLPADDING], table->CellPadding);
|
fromString(value[MY_HTML_TABLE_CELLPADDING], table->CellPadding);
|
||||||
if (present[MY_HTML_TABLE_STYLE] && value[MY_HTML_TABLE_STYLE])
|
if (present[MY_HTML_TABLE_STYLE] && value[MY_HTML_TABLE_STYLE])
|
||||||
getStyleParams(value[MY_HTML_TABLE_STYLE], _Style);
|
getStyleParams(value[MY_HTML_TABLE_STYLE], _Style, _StyleParams.back());
|
||||||
|
|
||||||
table->setMarginLeft(getIndent());
|
table->setMarginLeft(getIndent());
|
||||||
addHtmlGroup (table, 0);
|
addHtmlGroup (table, 0);
|
||||||
|
@ -2349,7 +2445,7 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
|
|
||||||
if (present[MY_HTML_TD_STYLE] && value[MY_HTML_TD_STYLE])
|
if (present[MY_HTML_TD_STYLE] && value[MY_HTML_TD_STYLE])
|
||||||
getStyleParams(value[MY_HTML_TD_STYLE], _Style);
|
getStyleParams(value[MY_HTML_TD_STYLE], _Style, _StyleParams.back());
|
||||||
|
|
||||||
CGroupTable *table = getTable();
|
CGroupTable *table = getTable();
|
||||||
if (table)
|
if (table)
|
||||||
|
@ -2439,9 +2535,12 @@ namespace NLGUI
|
||||||
_Style.FontOblique = false;
|
_Style.FontOblique = false;
|
||||||
_Style.FontSize = TextFontSize;
|
_Style.FontSize = TextFontSize;
|
||||||
_Style.TextShadow = STextShadow(true);
|
_Style.TextShadow = STextShadow(true);
|
||||||
|
_Style.Width = -1;
|
||||||
|
_Style.Height = -1;
|
||||||
|
_Style.BackgroundColor.A = 0;
|
||||||
|
|
||||||
if (present[MY_HTML_TEXTAREA_STYLE] && value[MY_HTML_TEXTAREA_STYLE])
|
if (present[MY_HTML_TEXTAREA_STYLE] && value[MY_HTML_TEXTAREA_STYLE])
|
||||||
getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style);
|
getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style, _StyleParams.back());
|
||||||
|
|
||||||
// Got one form ?
|
// Got one form ?
|
||||||
if (!(_Forms.empty()))
|
if (!(_Forms.empty()))
|
||||||
|
@ -2497,7 +2596,7 @@ namespace NLGUI
|
||||||
|
|
||||||
pushStyle();
|
pushStyle();
|
||||||
if (present[MY_HTML_TR_STYLE] && value[MY_HTML_TR_STYLE])
|
if (present[MY_HTML_TR_STYLE] && value[MY_HTML_TR_STYLE])
|
||||||
getStyleParams(value[MY_HTML_TR_STYLE], _Style);
|
getStyleParams(value[MY_HTML_TR_STYLE], _Style, _StyleParams.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTML_UL:
|
case HTML_UL:
|
||||||
|
@ -2514,7 +2613,7 @@ namespace NLGUI
|
||||||
|
|
||||||
pushStyle();
|
pushStyle();
|
||||||
if (present[HTML_UL_STYLE] && value[HTML_UL_STYLE])
|
if (present[HTML_UL_STYLE] && value[HTML_UL_STYLE])
|
||||||
getStyleParams(value[HTML_UL_STYLE], _Style);
|
getStyleParams(value[HTML_UL_STYLE], _Style, _StyleParams.back());
|
||||||
break;
|
break;
|
||||||
case HTML_OBJECT:
|
case HTML_OBJECT:
|
||||||
_ObjectType.clear();
|
_ObjectType.clear();
|
||||||
|
@ -2537,7 +2636,7 @@ namespace NLGUI
|
||||||
pushStyle();
|
pushStyle();
|
||||||
|
|
||||||
if (present[MY_HTML_SPAN_STYLE] && value[MY_HTML_SPAN_STYLE])
|
if (present[MY_HTML_SPAN_STYLE] && value[MY_HTML_SPAN_STYLE])
|
||||||
getStyleParams(value[MY_HTML_SPAN_STYLE], _Style);
|
getStyleParams(value[MY_HTML_SPAN_STYLE], _Style, _StyleParams.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTML_DEL:
|
case HTML_DEL:
|
||||||
|
@ -2581,7 +2680,7 @@ namespace NLGUI
|
||||||
endParagraph();
|
endParagraph();
|
||||||
pushStyle();
|
pushStyle();
|
||||||
if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE])
|
if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE])
|
||||||
getStyleParams(value[HTML_GEN_STYLE], _Style);
|
getStyleParams(value[HTML_GEN_STYLE], _Style, _StyleParams.back());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTML_DT:
|
case HTML_DT:
|
||||||
|
@ -2604,7 +2703,7 @@ namespace NLGUI
|
||||||
pushStyle();
|
pushStyle();
|
||||||
_Style.FontWeight = FONT_WEIGHT_BOLD;
|
_Style.FontWeight = FONT_WEIGHT_BOLD;
|
||||||
if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE])
|
if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE])
|
||||||
getStyleParams(value[HTML_GEN_STYLE], _Style);
|
getStyleParams(value[HTML_GEN_STYLE], _Style, _StyleParams.back());
|
||||||
|
|
||||||
if (!_LI)
|
if (!_LI)
|
||||||
{
|
{
|
||||||
|
@ -2639,7 +2738,7 @@ namespace NLGUI
|
||||||
|
|
||||||
pushStyle();
|
pushStyle();
|
||||||
if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE])
|
if (present[HTML_GEN_STYLE] && value[HTML_GEN_STYLE])
|
||||||
getStyleParams(value[HTML_GEN_STYLE], _Style);
|
getStyleParams(value[HTML_GEN_STYLE], _Style, _StyleParams.back());
|
||||||
|
|
||||||
if (!_LI)
|
if (!_LI)
|
||||||
{
|
{
|
||||||
|
@ -2663,7 +2762,7 @@ namespace NLGUI
|
||||||
if (present[HTML_OL_TYPE] && value[HTML_OL_TYPE])
|
if (present[HTML_OL_TYPE] && value[HTML_OL_TYPE])
|
||||||
type = value[HTML_OL_TYPE];
|
type = value[HTML_OL_TYPE];
|
||||||
if (present[HTML_OL_STYLE] && value[HTML_OL_STYLE])
|
if (present[HTML_OL_STYLE] && value[HTML_OL_STYLE])
|
||||||
getStyleParams(value[HTML_OL_STYLE], _Style);
|
getStyleParams(value[HTML_OL_STYLE], _Style, _StyleParams.back());
|
||||||
|
|
||||||
_UL.push_back(HTMLOListElement(start, type));
|
_UL.push_back(HTMLOListElement(start, type));
|
||||||
// if LI is already present
|
// if LI is already present
|
||||||
|
@ -2680,12 +2779,13 @@ namespace NLGUI
|
||||||
if (sep)
|
if (sep)
|
||||||
{
|
{
|
||||||
CStyleParams style;
|
CStyleParams style;
|
||||||
|
style.FontSize = _Style.FontSize;
|
||||||
style.TextColor = CRGBA(120, 120, 120, 255);
|
style.TextColor = CRGBA(120, 120, 120, 255);
|
||||||
style.Height = 0;
|
style.Height = 0;
|
||||||
style.Width = 0;
|
style.Width = 0;
|
||||||
|
|
||||||
if (present[HTML_HR_STYLE] && value[HTML_HR_STYLE])
|
if (present[HTML_HR_STYLE] && value[HTML_HR_STYLE])
|
||||||
getStyleParams(value[HTML_HR_STYLE], style);
|
getStyleParams(value[HTML_HR_STYLE], style, _Style);
|
||||||
|
|
||||||
CViewBitmap *bitmap = dynamic_cast<CViewBitmap*>(sep->getView("hr"));
|
CViewBitmap *bitmap = dynamic_cast<CViewBitmap*>(sep->getView("hr"));
|
||||||
if (bitmap)
|
if (bitmap)
|
||||||
|
@ -2725,6 +2825,9 @@ namespace NLGUI
|
||||||
case HTML_HEAD:
|
case HTML_HEAD:
|
||||||
_ReadingHeadTag = false;
|
_ReadingHeadTag = false;
|
||||||
break;
|
break;
|
||||||
|
case HTML_BODY:
|
||||||
|
popStyle();
|
||||||
|
break;
|
||||||
case HTML_FONT:
|
case HTML_FONT:
|
||||||
popStyle();
|
popStyle();
|
||||||
break;
|
break;
|
||||||
|
@ -4469,6 +4572,8 @@ namespace NLGUI
|
||||||
// Translate the tooltip
|
// Translate the tooltip
|
||||||
ctrlButton->setDefaultContextHelp(ucstring::makeFromUtf8(getLinkTitle()));
|
ctrlButton->setDefaultContextHelp(ucstring::makeFromUtf8(getLinkTitle()));
|
||||||
ctrlButton->setText(tmpStr);
|
ctrlButton->setText(tmpStr);
|
||||||
|
|
||||||
|
setTextButtonStyle(ctrlButton, _Style);
|
||||||
}
|
}
|
||||||
getParagraph()->addChild (buttonGroup);
|
getParagraph()->addChild (buttonGroup);
|
||||||
paragraphChange ();
|
paragraphChange ();
|
||||||
|
@ -4491,23 +4596,10 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newLink->setText(tmpStr);
|
newLink->setText(tmpStr);
|
||||||
newLink->setColor(_Style.TextColor);
|
|
||||||
newLink->setFontName(_Style.FontFamily);
|
|
||||||
newLink->setFontSize(_Style.FontSize);
|
|
||||||
newLink->setEmbolden(embolden);
|
|
||||||
newLink->setOblique(_Style.FontOblique);
|
|
||||||
newLink->setUnderlined(_Style.Underlined);
|
|
||||||
newLink->setStrikeThrough(_Style.StrikeThrough);
|
|
||||||
newLink->setMultiLineSpace((uint)((float)(_Style.FontSize)*LineSpaceFontFactor));
|
newLink->setMultiLineSpace((uint)((float)(_Style.FontSize)*LineSpaceFontFactor));
|
||||||
newLink->setMultiLine(true);
|
newLink->setMultiLine(true);
|
||||||
newLink->setModulateGlobalColor(_Style.GlobalColor);
|
newLink->setModulateGlobalColor(_Style.GlobalColor);
|
||||||
if (_Style.TextShadow.Enabled)
|
setTextStyle(newLink, _Style);
|
||||||
{
|
|
||||||
newLink->setShadow(true);
|
|
||||||
newLink->setShadowColor(_Style.TextShadow.Color);
|
|
||||||
newLink->setShadowOutline(_Style.TextShadow.Outline);
|
|
||||||
newLink->setShadowOffset(_Style.TextShadow.X, _Style.TextShadow.Y);
|
|
||||||
}
|
|
||||||
// newLink->setLineAtBottom (true);
|
// newLink->setLineAtBottom (true);
|
||||||
|
|
||||||
registerAnchor(newLink);
|
registerAnchor(newLink);
|
||||||
|
@ -4528,7 +4620,7 @@ namespace NLGUI
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
|
||||||
void CGroupHTML::addImage(const char *img, bool reloadImg, const CStyleParams &style)
|
void CGroupHTML::addImage(const std::string &id, const char *img, bool reloadImg, const CStyleParams &style)
|
||||||
{
|
{
|
||||||
// In a paragraph ?
|
// In a paragraph ?
|
||||||
if (!_Paragraph)
|
if (!_Paragraph)
|
||||||
|
@ -4544,6 +4636,7 @@ namespace NLGUI
|
||||||
|
|
||||||
// Not added ?
|
// Not added ?
|
||||||
CViewBitmap *newImage = new CViewBitmap (TCtorParam());
|
CViewBitmap *newImage = new CViewBitmap (TCtorParam());
|
||||||
|
newImage->setId(id);
|
||||||
|
|
||||||
//
|
//
|
||||||
// 1/ try to load the image with the old system (local files in bnp)
|
// 1/ try to load the image with the old system (local files in bnp)
|
||||||
|
@ -4612,6 +4705,10 @@ namespace NLGUI
|
||||||
_CurrentViewLink = NULL;
|
_CurrentViewLink = NULL;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// override cols/rows values from style
|
||||||
|
if (_Style.Width > 0) cols = _Style.Width / _Style.FontSize;
|
||||||
|
if (_Style.Height > 0) rows = _Style.Height / _Style.FontSize;
|
||||||
|
|
||||||
// Not added ?
|
// Not added ?
|
||||||
std::vector<std::pair<std::string,std::string> > templateParams;
|
std::vector<std::pair<std::string,std::string> > templateParams;
|
||||||
templateParams.push_back (std::pair<std::string,std::string> ("w", toString (cols*_Style.FontSize)));
|
templateParams.push_back (std::pair<std::string,std::string> ("w", toString (cols*_Style.FontSize)));
|
||||||
|
@ -4649,7 +4746,18 @@ namespace NLGUI
|
||||||
// Set the content
|
// Set the content
|
||||||
CGroupEditBox *eb = dynamic_cast<CGroupEditBox*>(textArea->getGroup("eb"));
|
CGroupEditBox *eb = dynamic_cast<CGroupEditBox*>(textArea->getGroup("eb"));
|
||||||
if (eb)
|
if (eb)
|
||||||
|
{
|
||||||
eb->setInputString(decodeHTMLEntities(content));
|
eb->setInputString(decodeHTMLEntities(content));
|
||||||
|
if (_Style.BackgroundColor.A > 0)
|
||||||
|
{
|
||||||
|
CViewBitmap *bg = dynamic_cast<CViewBitmap*>(eb->getView("bg"));
|
||||||
|
if (bg)
|
||||||
|
{
|
||||||
|
bg->setTexture("blank.tga");
|
||||||
|
bg->setColor(_Style.BackgroundColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
textArea->invalidateCoords();
|
textArea->invalidateCoords();
|
||||||
getParagraph()->addChild (textArea);
|
getParagraph()->addChild (textArea);
|
||||||
|
@ -4746,7 +4854,7 @@ namespace NLGUI
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
|
||||||
CCtrlButton *CGroupHTML::addButton(CCtrlButton::EType type, const std::string &/* name */, const std::string &normalBitmap, const std::string &pushedBitmap,
|
CCtrlButton *CGroupHTML::addButton(CCtrlButton::EType type, const std::string &name, const std::string &normalBitmap, const std::string &pushedBitmap,
|
||||||
const std::string &overBitmap, const char *actionHandler, const char *actionHandlerParams,
|
const std::string &overBitmap, const char *actionHandler, const char *actionHandlerParams,
|
||||||
const char *tooltip, const CStyleParams &style)
|
const char *tooltip, const CStyleParams &style)
|
||||||
{
|
{
|
||||||
|
@ -4759,6 +4867,10 @@ namespace NLGUI
|
||||||
|
|
||||||
// Add the ctrl button
|
// Add the ctrl button
|
||||||
CCtrlButton *ctrlButton = new CCtrlButton(TCtorParam());
|
CCtrlButton *ctrlButton = new CCtrlButton(TCtorParam());
|
||||||
|
if (!name.empty())
|
||||||
|
{
|
||||||
|
ctrlButton->setId(name);
|
||||||
|
}
|
||||||
|
|
||||||
// Load only tga files.. (conversion in dds filename is done in the lookup procedure)
|
// Load only tga files.. (conversion in dds filename is done in the lookup procedure)
|
||||||
string normal = normalBitmap.empty()?"":CFile::getPath(normalBitmap) + CFile::getFilenameWithoutExtension(normalBitmap) + ".tga";
|
string normal = normalBitmap.empty()?"":CFile::getPath(normalBitmap) + CFile::getFilenameWithoutExtension(normalBitmap) + ".tga";
|
||||||
|
@ -4855,7 +4967,7 @@ namespace NLGUI
|
||||||
|
|
||||||
getParagraph()->addChild (ctrlButton);
|
getParagraph()->addChild (ctrlButton);
|
||||||
paragraphChange ();
|
paragraphChange ();
|
||||||
|
|
||||||
setImageSize(ctrlButton, style);
|
setImageSize(ctrlButton, style);
|
||||||
|
|
||||||
return ctrlButton;
|
return ctrlButton;
|
||||||
|
@ -4898,9 +5010,7 @@ namespace NLGUI
|
||||||
_IgnoreBaseUrlTag = false;
|
_IgnoreBaseUrlTag = false;
|
||||||
|
|
||||||
// reset style
|
// reset style
|
||||||
_StyleDefault = CStyleParams();
|
resetCssStyle();
|
||||||
_Style = _StyleDefault;
|
|
||||||
_StyleParams.clear();
|
|
||||||
|
|
||||||
// TR
|
// TR
|
||||||
|
|
||||||
|
@ -5043,6 +5153,25 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGroupHTML::setTitle(const std::string &title)
|
||||||
|
{
|
||||||
|
ucstring uctitle;
|
||||||
|
uctitle.fromUtf8(title);
|
||||||
|
|
||||||
|
_TitleString.clear();
|
||||||
|
if(!_TitlePrefix.empty())
|
||||||
|
{
|
||||||
|
_TitleString = _TitlePrefix + " - ";
|
||||||
|
}
|
||||||
|
_TitleString += uctitle;
|
||||||
|
|
||||||
|
setTitle(_TitleString);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CGroupHTML::getTitle() const {
|
||||||
|
return _TitleString.toUtf8();
|
||||||
|
};
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
|
||||||
bool CGroupHTML::lookupLocalFile (string &result, const char *url, bool isUrl)
|
bool CGroupHTML::lookupLocalFile (string &result, const char *url, bool isUrl)
|
||||||
|
@ -5572,6 +5701,22 @@ namespace NLGUI
|
||||||
// create html code with image url inside and do the request again
|
// create html code with image url inside and do the request again
|
||||||
renderHtmlString("<html><head><title>"+_URL+"</title></head><body><img src=\"" + _URL + "\"></body></html>");
|
renderHtmlString("<html><head><title>"+_URL+"</title></head><body><img src=\"" + _URL + "\"></body></html>");
|
||||||
}
|
}
|
||||||
|
else if (_TrustedDomain && type.find("text/lua") == 0)
|
||||||
|
{
|
||||||
|
setTitle(_TitleString);
|
||||||
|
|
||||||
|
_LuaScript = "\nlocal __CURRENT_WINDOW__=\""+this->_Id+"\" \n"+content;
|
||||||
|
CLuaManager::getInstance().executeLuaScript(_LuaScript, true);
|
||||||
|
_LuaScript.clear();
|
||||||
|
|
||||||
|
_Browsing = false;
|
||||||
|
_Connecting = false;
|
||||||
|
|
||||||
|
// disable refresh button
|
||||||
|
clearRefresh();
|
||||||
|
// disable redo into this url
|
||||||
|
_AskedUrl.clear();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
renderHtmlString(content);
|
renderHtmlString(content);
|
||||||
|
@ -5770,6 +5915,13 @@ namespace NLGUI
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
void CGroupHTML::clearRefresh()
|
||||||
|
{
|
||||||
|
_URL.clear();
|
||||||
|
updateRefreshButton();
|
||||||
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
void CGroupHTML::clearUndoRedo()
|
void CGroupHTML::clearUndoRedo()
|
||||||
{
|
{
|
||||||
|
@ -5809,7 +5961,9 @@ namespace NLGUI
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// push to redo, pop undo, and set current
|
// push to redo, pop undo, and set current
|
||||||
_BrowseRedo.push_front(_AskedUrl);
|
if (!_AskedUrl.empty())
|
||||||
|
_BrowseRedo.push_front(_AskedUrl);
|
||||||
|
|
||||||
_AskedUrl= _BrowseUndo.back();
|
_AskedUrl= _BrowseUndo.back();
|
||||||
_BrowseUndo.pop_back();
|
_BrowseUndo.pop_back();
|
||||||
|
|
||||||
|
@ -5856,7 +6010,7 @@ namespace NLGUI
|
||||||
{
|
{
|
||||||
CCtrlBaseButton *butRefresh = dynamic_cast<CCtrlBaseButton *>(CWidgetManager::getInstance()->getElementFromId(_BrowseRefreshButton));
|
CCtrlBaseButton *butRefresh = dynamic_cast<CCtrlBaseButton *>(CWidgetManager::getInstance()->getElementFromId(_BrowseRefreshButton));
|
||||||
|
|
||||||
bool enabled = !_Browsing && !_Connecting;
|
bool enabled = !_Browsing && !_Connecting && !_URL.empty();
|
||||||
if(butRefresh)
|
if(butRefresh)
|
||||||
butRefresh->setFrozen(!enabled);
|
butRefresh->setFrozen(!enabled);
|
||||||
}
|
}
|
||||||
|
@ -5895,6 +6049,25 @@ namespace NLGUI
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CGroupHTML::luaClearRefresh(CLuaState &ls)
|
||||||
|
{
|
||||||
|
const char *funcName = "clearRefresh";
|
||||||
|
CLuaIHM::checkArgCount(ls, funcName, 0);
|
||||||
|
|
||||||
|
clearRefresh();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CGroupHTML::luaClearUndoRedo(CLuaState &ls)
|
||||||
|
{
|
||||||
|
const char *funcName = "clearUndoRedo";
|
||||||
|
CLuaIHM::checkArgCount(ls, funcName, 0);
|
||||||
|
|
||||||
|
clearUndoRedo();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
int CGroupHTML::luaBrowse(CLuaState &ls)
|
int CGroupHTML::luaBrowse(CLuaState &ls)
|
||||||
{
|
{
|
||||||
|
@ -6004,12 +6177,12 @@ namespace NLGUI
|
||||||
if (!url.empty())
|
if (!url.empty())
|
||||||
{
|
{
|
||||||
string params = "name=" + getId() + "|url=" + getLink ();
|
string params = "name=" + getId() + "|url=" + getLink ();
|
||||||
addButton(CCtrlButton::PushButton, ls.toString(1), ls.toString(1), ls.toString(1),
|
addButton(CCtrlButton::PushButton, "", ls.toString(1), ls.toString(1),
|
||||||
"", "browse", params.c_str(), "", style);
|
"", "browse", params.c_str(), "", style);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addImage(ls.toString(1), false, style);
|
addImage("", ls.toString(1), false, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6209,40 +6382,82 @@ namespace NLGUI
|
||||||
return uri.toString();
|
return uri.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
void CGroupHTML::resetCssStyle()
|
||||||
|
{
|
||||||
|
_StyleDefault = CStyleParams();
|
||||||
|
_StyleDefault.TextColor = TextColor;
|
||||||
|
_StyleDefault.FontSize = TextFontSize;
|
||||||
|
_StyleDefault.BackgroundColor = BgColor;
|
||||||
|
|
||||||
|
_Style = _StyleDefault;
|
||||||
|
_StyleParams.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
// CGroupHTML::CStyleParams style;
|
// CGroupHTML::CStyleParams style;
|
||||||
// style.FontSize; // font-size: 10px;
|
// style.FontSize; // font-size: 10px;
|
||||||
// style.TextColor; // color: #ABCDEF;
|
// style.TextColor; // color: #ABCDEF;
|
||||||
// style.Underlined; // text-decoration: underline; text-decoration-line: underline;
|
// style.Underlined; // text-decoration: underline; text-decoration-line: underline;
|
||||||
// style.StrikeThrough; // text-decoration: line-through; text-decoration-line: line-through;
|
// style.StrikeThrough; // text-decoration: line-through; text-decoration-line: line-through;
|
||||||
void CGroupHTML::getStyleParams(const std::string &styleString, CStyleParams &style, bool inherit)
|
void CGroupHTML::getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams ¤t)
|
||||||
{
|
{
|
||||||
const CStyleParams current = _Style;
|
|
||||||
|
|
||||||
if (inherit)
|
|
||||||
{
|
|
||||||
style.Underlined = current.Underlined;
|
|
||||||
style.StrikeThrough = current.StrikeThrough;
|
|
||||||
}
|
|
||||||
|
|
||||||
float tmpf;
|
float tmpf;
|
||||||
TStyle styles = parseStyle(styleString);
|
TStyle styles = parseStyle(styleString);
|
||||||
TStyle::iterator it;
|
TStyle::iterator it;
|
||||||
|
|
||||||
|
// first pass: get font-size for 'em' sizes
|
||||||
for (it=styles.begin(); it != styles.end(); ++it)
|
for (it=styles.begin(); it != styles.end(); ++it)
|
||||||
{
|
{
|
||||||
|
if (it->first == "font")
|
||||||
|
{
|
||||||
|
if (it->second == "inherit")
|
||||||
|
{
|
||||||
|
style.FontSize = current.FontSize;
|
||||||
|
style.FontFamily = current.FontFamily;
|
||||||
|
style.FontWeight = current.FontWeight;
|
||||||
|
style.FontOblique = current.FontOblique;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
if (it->first == "font-size")
|
if (it->first == "font-size")
|
||||||
{
|
{
|
||||||
if (it->second == "inherit")
|
if (it->second == "inherit")
|
||||||
|
{
|
||||||
style.FontSize = current.FontSize;
|
style.FontSize = current.FontSize;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float tmp;
|
std::string unit;
|
||||||
sint size = 0;
|
if (getCssLength(tmpf, unit, it->second.c_str()))
|
||||||
getPercentage (size, tmp, it->second.c_str());
|
{
|
||||||
if (size > 0)
|
if (unit == "rem")
|
||||||
style.FontSize = size;
|
style.FontSize = _StyleDefault.FontSize * tmpf;
|
||||||
|
else if (unit == "em")
|
||||||
|
style.FontSize = current.FontSize * tmpf;
|
||||||
|
else if (unit == "pt")
|
||||||
|
style.FontSize = tmpf / 0.75f;
|
||||||
|
else if (unit == "%")
|
||||||
|
style.FontSize = current.FontSize * tmpf / 100.f;
|
||||||
|
else
|
||||||
|
style.FontSize = tmpf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// second pass: rest of style
|
||||||
|
for (it=styles.begin(); it != styles.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->first == "border")
|
||||||
|
{
|
||||||
|
sint32 b;
|
||||||
|
if (it->second == "none")
|
||||||
|
style.BorderWidth = 0;
|
||||||
|
else
|
||||||
|
if (fromString(it->second, b))
|
||||||
|
style.BorderWidth = b;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (it->first == "font-style")
|
if (it->first == "font-style")
|
||||||
{
|
{
|
||||||
|
@ -6258,10 +6473,7 @@ namespace NLGUI
|
||||||
if (it->second == "inherit")
|
if (it->second == "inherit")
|
||||||
style.FontFamily = current.FontFamily;
|
style.FontFamily = current.FontFamily;
|
||||||
else
|
else
|
||||||
if (it->second == "monospace")
|
style.FontFamily = it->second;
|
||||||
style.FontFamily = "monospace";
|
|
||||||
else
|
|
||||||
style.FontFamily.clear();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (it->first == "font-weight")
|
if (it->first == "font-weight")
|
||||||
|
@ -6425,16 +6637,68 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (it->first == "width")
|
if (it->first == "width")
|
||||||
getPercentage(style.Width, tmpf, it->second.c_str());
|
{
|
||||||
|
std::string unit;
|
||||||
|
if (getCssLength(tmpf, unit, it->second.c_str()))
|
||||||
|
{
|
||||||
|
if (unit == "rem")
|
||||||
|
style.Width = tmpf * _StyleDefault.FontSize;
|
||||||
|
else if (unit == "em")
|
||||||
|
style.Width = tmpf * style.FontSize;
|
||||||
|
else if (unit == "pt")
|
||||||
|
style.FontSize = tmpf / 0.75f;
|
||||||
|
else
|
||||||
|
style.Width = tmpf;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (it->first == "height")
|
if (it->first == "height")
|
||||||
getPercentage(style.Height, tmpf, it->second.c_str());
|
{
|
||||||
|
std::string unit;
|
||||||
|
if (getCssLength(tmpf, unit, it->second.c_str()))
|
||||||
|
{
|
||||||
|
if (unit == "rem")
|
||||||
|
style.Height = tmpf * _StyleDefault.FontSize;
|
||||||
|
else if (unit == "em")
|
||||||
|
style.Height = tmpf * style.FontSize;
|
||||||
|
else if (unit == "pt")
|
||||||
|
style.FontSize = tmpf / 0.75f;
|
||||||
|
else
|
||||||
|
style.Height = tmpf;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (it->first == "max-width")
|
if (it->first == "max-width")
|
||||||
getPercentage(style.MaxWidth, tmpf, it->second.c_str());
|
{
|
||||||
|
std::string unit;
|
||||||
|
if (getCssLength(tmpf, unit, it->second.c_str()))
|
||||||
|
{
|
||||||
|
if (unit == "rem")
|
||||||
|
style.MaxWidth = tmpf * _StyleDefault.FontSize;
|
||||||
|
else if (unit == "em")
|
||||||
|
style.MaxWidth = tmpf * style.FontSize;
|
||||||
|
else if (unit == "pt")
|
||||||
|
style.FontSize = tmpf / 0.75f;
|
||||||
|
else
|
||||||
|
style.MaxWidth = tmpf;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (it->first == "max-height")
|
if (it->first == "max-height")
|
||||||
getPercentage(style.MaxHeight, tmpf, it->second.c_str());
|
{
|
||||||
|
std::string unit;
|
||||||
|
if (getCssLength(tmpf, unit, it->second.c_str()))
|
||||||
|
{
|
||||||
|
if (unit == "rem")
|
||||||
|
style.MaxHeight = tmpf * _StyleDefault.FontSize;
|
||||||
|
else if (unit == "em")
|
||||||
|
style.MaxHeight = tmpf * style.FontSize;
|
||||||
|
else if (unit == "pt")
|
||||||
|
style.FontSize = tmpf / 0.75f;
|
||||||
|
else
|
||||||
|
style.MaxHeight = tmpf;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (it->first == "-ryzom-modulate-color")
|
if (it->first == "-ryzom-modulate-color")
|
||||||
{
|
{
|
||||||
|
@ -6445,7 +6709,31 @@ namespace NLGUI
|
||||||
if (fromString(it->second, b))
|
if (fromString(it->second, b))
|
||||||
style.GlobalColor = b;
|
style.GlobalColor = b;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
if (it->first == "background-color")
|
||||||
|
{
|
||||||
|
if (it->second == "inherit")
|
||||||
|
style.BackgroundColor = current.BackgroundColor;
|
||||||
|
else
|
||||||
|
scanHTMLColor(it->second.c_str(), style.BackgroundColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (it->first == "-ryzom-background-color-over")
|
||||||
|
{
|
||||||
|
if (it->second == "inherit")
|
||||||
|
style.BackgroundColorOver = current.BackgroundColorOver;
|
||||||
|
else
|
||||||
|
scanHTMLColor(it->second.c_str(), style.BackgroundColorOver);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if outer element has underline set, then inner element cannot remove it
|
||||||
|
if (current.Underlined)
|
||||||
|
style.Underlined = current.Underlined;
|
||||||
|
|
||||||
|
// if outer element has line-through set, then inner element cannot remove it
|
||||||
|
if (current.StrikeThrough)
|
||||||
|
style.StrikeThrough = current.StrikeThrough;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
|
|
@ -327,6 +327,7 @@ namespace NLGUI
|
||||||
nlwarning("html root node failed");
|
nlwarning("html root node failed");
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
xmlFreeDoc(parser->myDoc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -2561,6 +2561,12 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CGroupMenu::setFontSize(uint fontSize)
|
||||||
|
{
|
||||||
|
_FontSize = fontSize;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
uint CGroupMenu::getNumLine() const
|
uint CGroupMenu::getNumLine() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,6 +52,7 @@ namespace NLGUI
|
||||||
_MinW= 0;
|
_MinW= 0;
|
||||||
_MinH= 0;
|
_MinH= 0;
|
||||||
_Over = false;
|
_Over = false;
|
||||||
|
_TempOver = false;
|
||||||
_OverColor = CRGBA(255,255,255,32);
|
_OverColor = CRGBA(255,255,255,32);
|
||||||
_OverElt = -1;
|
_OverElt = -1;
|
||||||
_LastW = 0;
|
_LastW = 0;
|
||||||
|
@ -967,7 +968,7 @@ namespace NLGUI
|
||||||
// TEMP TEMP
|
// TEMP TEMP
|
||||||
//CViewRenderer &rVR = *CViewRenderer::getInstance();
|
//CViewRenderer &rVR = *CViewRenderer::getInstance();
|
||||||
//rVR.drawRotFlipBitmap _RenderLayer, (_XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,0,255) );
|
//rVR.drawRotFlipBitmap _RenderLayer, (_XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,0,255) );
|
||||||
if (_Over)
|
if (_Over || _TempOver)
|
||||||
{
|
{
|
||||||
CViewRenderer &rVR = *CViewRenderer::getInstance();
|
CViewRenderer &rVR = *CViewRenderer::getInstance();
|
||||||
|
|
||||||
|
@ -1052,7 +1053,10 @@ namespace NLGUI
|
||||||
|
|
||||||
_OverElt = -1;
|
_OverElt = -1;
|
||||||
if (!isIn(eventDesc.getX(), eventDesc.getY()))
|
if (!isIn(eventDesc.getX(), eventDesc.getY()))
|
||||||
|
{
|
||||||
|
_TempOver = false;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32 i = 0; i < _Elements.size(); ++i)
|
for (uint32 i = 0; i < _Elements.size(); ++i)
|
||||||
if (_Elements[i].Element->getActive())
|
if (_Elements[i].Element->getActive())
|
||||||
|
|
|
@ -47,6 +47,15 @@ namespace NLGUI
|
||||||
#undef HTML_ATTR
|
#undef HTML_ATTR
|
||||||
#define HTML_ATTR(a,b) { (char*) #b }
|
#define HTML_ATTR(a,b) { (char*) #b }
|
||||||
|
|
||||||
|
HTAttr html_attr[] =
|
||||||
|
{
|
||||||
|
HTML_ATTR(HTML,DIR),
|
||||||
|
HTML_ATTR(HTML,LANG),
|
||||||
|
HTML_ATTR(HTML,VERSION),
|
||||||
|
HTML_ATTR(HTML,STYLE),
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
HTAttr a_attr[] =
|
HTAttr a_attr[] =
|
||||||
{
|
{
|
||||||
HTML_ATTR(A,ACCESSKEY),
|
HTML_ATTR(A,ACCESSKEY),
|
||||||
|
@ -213,6 +222,7 @@ namespace NLGUI
|
||||||
HTML_ATTR(P,QUICK_HELP_EVENTS),
|
HTML_ATTR(P,QUICK_HELP_EVENTS),
|
||||||
HTML_ATTR(P,QUICK_HELP_LINK),
|
HTML_ATTR(P,QUICK_HELP_LINK),
|
||||||
HTML_ATTR(P,NAME),
|
HTML_ATTR(P,NAME),
|
||||||
|
HTML_ATTR(P,STYLE),
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -283,6 +293,37 @@ namespace NLGUI
|
||||||
};
|
};
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
bool getCssLength (float &value, std::string &unit, const std::string &str)
|
||||||
|
{
|
||||||
|
std::string::size_type pos = 0;
|
||||||
|
std::string::size_type len = str.size();
|
||||||
|
if (len == 1 && str[0] == '.')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(pos < len)
|
||||||
|
{
|
||||||
|
bool isNumeric = (str[pos] >= '0' && str[pos] <= '9')
|
||||||
|
|| (pos == 0 && str[pos] == '.')
|
||||||
|
|| (pos > 0 && str[pos] == '.' && str[pos-1] >= '0' && str[pos-1] <= '9');
|
||||||
|
if (!isNumeric)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
unit = toLower(str.substr(pos));
|
||||||
|
if (unit == "%" || unit == "rem" || unit == "em" || unit == "px" || unit == "pt")
|
||||||
|
{
|
||||||
|
std::string tmpstr = str.substr(0, pos);
|
||||||
|
return fromString(tmpstr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Read a width HTML parameter. "100" or "100%". Returns true if percent (0 ~ 1) else false
|
// Read a width HTML parameter. "100" or "100%". Returns true if percent (0 ~ 1) else false
|
||||||
bool getPercentage (sint32 &width, float &percent, const char *str)
|
bool getPercentage (sint32 &width, float &percent, const char *str)
|
||||||
|
@ -468,6 +509,8 @@ namespace NLGUI
|
||||||
|
|
||||||
// Change the HTML DTD
|
// Change the HTML DTD
|
||||||
SGML_dtd *HTML_DTD = HTML_dtd ();
|
SGML_dtd *HTML_DTD = HTML_dtd ();
|
||||||
|
HTML_DTD->tags[HTML_HTML].attributes = html_attr;
|
||||||
|
HTML_DTD->tags[HTML_HTML].number_of_attributes = sizeof(html_attr) / sizeof(HTAttr) - 1;
|
||||||
HTML_DTD->tags[HTML_TABLE].attributes = table_attr;
|
HTML_DTD->tags[HTML_TABLE].attributes = table_attr;
|
||||||
HTML_DTD->tags[HTML_TABLE].number_of_attributes = sizeof(table_attr) / sizeof(HTAttr) - 1;
|
HTML_DTD->tags[HTML_TABLE].number_of_attributes = sizeof(table_attr) / sizeof(HTAttr) - 1;
|
||||||
HTML_DTD->tags[HTML_TR].attributes = tr_attr;
|
HTML_DTD->tags[HTML_TR].attributes = tr_attr;
|
||||||
|
|
|
@ -96,16 +96,13 @@ namespace NLGUI
|
||||||
if(w!=0 && h!=0)
|
if(w!=0 && h!=0)
|
||||||
{
|
{
|
||||||
_IsMinimized= false;
|
_IsMinimized= false;
|
||||||
_ScreenW = w;
|
if (w != _ScreenW || h != _ScreenH)
|
||||||
_ScreenH = h;
|
{
|
||||||
if(_ScreenW>0)
|
_ScreenW = w;
|
||||||
_OneOverScreenW = 1.0f / (float)_ScreenW;
|
_ScreenH = h;
|
||||||
else
|
|
||||||
_OneOverScreenW = 1000;
|
updateInterfaceScale();
|
||||||
if(_ScreenH>0)
|
}
|
||||||
_OneOverScreenH = 1.0f / (float)_ScreenH;
|
|
||||||
else
|
|
||||||
_OneOverScreenH = 1000;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -114,14 +111,48 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CViewRenderer::updateInterfaceScale()
|
||||||
|
{
|
||||||
|
if(_ScreenW>0)
|
||||||
|
_OneOverScreenW = 1.0f / (float)_ScreenW;
|
||||||
|
else
|
||||||
|
_OneOverScreenW = 1000;
|
||||||
|
if(_ScreenH>0)
|
||||||
|
_OneOverScreenH = 1.0f / (float)_ScreenH;
|
||||||
|
else
|
||||||
|
_OneOverScreenH = 1000;
|
||||||
|
|
||||||
|
_InterfaceScale = _InterfaceUserScale;
|
||||||
|
if (_InterfaceBaseW > 0 && _InterfaceBaseH > 0)
|
||||||
|
{
|
||||||
|
float wRatio = (float)_ScreenW / _InterfaceBaseW;
|
||||||
|
float rRatio = (float)_ScreenH / _InterfaceBaseH;
|
||||||
|
_InterfaceScale *= std::min(wRatio, rRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_InterfaceScale != 1.0f)
|
||||||
|
{
|
||||||
|
_OneOverScreenW *= _InterfaceScale;
|
||||||
|
_OneOverScreenH *= _InterfaceScale;
|
||||||
|
|
||||||
|
_EffectiveScreenW = sint(_ScreenW / _InterfaceScale);
|
||||||
|
_EffectiveScreenH = sint(_ScreenH / _InterfaceScale);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_EffectiveScreenW = _ScreenW;
|
||||||
|
_EffectiveScreenH = _ScreenH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* getScreenSize : get the screen window size
|
* getScreenSize : get the screen window size
|
||||||
*/
|
*/
|
||||||
void CViewRenderer::getScreenSize (uint32 &w, uint32 &h)
|
void CViewRenderer::getScreenSize (uint32 &w, uint32 &h)
|
||||||
{
|
{
|
||||||
w = _ScreenW;
|
w = _EffectiveScreenW;
|
||||||
h = _ScreenH;
|
h = _EffectiveScreenH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -133,6 +164,20 @@ namespace NLGUI
|
||||||
ooh= _OneOverScreenH;
|
ooh= _OneOverScreenH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CViewRenderer::setInterfaceScale(float scale, sint32 width/*=0*/, sint32 height/*=0*/)
|
||||||
|
{
|
||||||
|
// prevent #div/0
|
||||||
|
if (sint(scale*100) > 0)
|
||||||
|
_InterfaceUserScale = scale;
|
||||||
|
else
|
||||||
|
_InterfaceUserScale = 1.0f;
|
||||||
|
|
||||||
|
_InterfaceBaseW = width;
|
||||||
|
_InterfaceBaseH = height;
|
||||||
|
|
||||||
|
updateInterfaceScale();
|
||||||
|
}
|
||||||
|
|
||||||
void CViewRenderer::setup()
|
void CViewRenderer::setup()
|
||||||
{
|
{
|
||||||
_ClipX = _ClipY = 0;
|
_ClipX = _ClipY = 0;
|
||||||
|
@ -140,8 +185,10 @@ namespace NLGUI
|
||||||
_ClipH = 600;
|
_ClipH = 600;
|
||||||
_ScreenW = 800;
|
_ScreenW = 800;
|
||||||
_ScreenH = 600;
|
_ScreenH = 600;
|
||||||
_OneOverScreenW= 1.0f / (float)_ScreenW;
|
_InterfaceScale = 1.0f;
|
||||||
_OneOverScreenH= 1.0f / (float)_ScreenH;
|
_InterfaceUserScale = 1.0f;
|
||||||
|
_InterfaceBaseW = 0;
|
||||||
|
_InterfaceBaseH = 0;
|
||||||
_IsMinimized= false;
|
_IsMinimized= false;
|
||||||
_WFigurTexture= 0;
|
_WFigurTexture= 0;
|
||||||
_HFigurTexture= 0;
|
_HFigurTexture= 0;
|
||||||
|
@ -157,6 +204,9 @@ namespace NLGUI
|
||||||
_EmptyLayer[i]= true;
|
_EmptyLayer[i]= true;
|
||||||
}
|
}
|
||||||
_BlankGlobalTexture = NULL;
|
_BlankGlobalTexture = NULL;
|
||||||
|
_Bilinear = false;
|
||||||
|
|
||||||
|
updateInterfaceScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -499,7 +549,7 @@ namespace NLGUI
|
||||||
/*
|
/*
|
||||||
* drawBitmap
|
* drawBitmap
|
||||||
*/
|
*/
|
||||||
void CViewRenderer::drawRotFlipBitmap (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height,
|
void CViewRenderer::drawRotFlipBitmap (sint layerId, float x, float y, float width, float height,
|
||||||
uint8 rot, bool flipv, sint32 nTxId, const CRGBA &col)
|
uint8 rot, bool flipv, sint32 nTxId, const CRGBA &col)
|
||||||
{
|
{
|
||||||
if (width <= 0 || height <= 0) return;
|
if (width <= 0 || height <= 0) return;
|
||||||
|
@ -1283,7 +1333,7 @@ namespace NLGUI
|
||||||
_Material.setTexture(0, ite->Texture);
|
_Material.setTexture(0, ite->Texture);
|
||||||
|
|
||||||
// Special Case if _WorldSpaceTransformation and _WorldSpaceScale, enable bilinear
|
// Special Case if _WorldSpaceTransformation and _WorldSpaceScale, enable bilinear
|
||||||
if(_WorldSpaceTransformation && _WorldSpaceScale)
|
if(_Bilinear || (_WorldSpaceTransformation && _WorldSpaceScale))
|
||||||
ite->Texture->setFilterMode(UTexture::Linear, UTexture::LinearMipMapOff);
|
ite->Texture->setFilterMode(UTexture::Linear, UTexture::LinearMipMapOff);
|
||||||
|
|
||||||
// draw quads and empty list
|
// draw quads and empty list
|
||||||
|
@ -1300,7 +1350,7 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special Case if _WorldSpaceTransformation and _WorldSpaceScale, reset
|
// Special Case if _WorldSpaceTransformation and _WorldSpaceScale, reset
|
||||||
if(_WorldSpaceTransformation && _WorldSpaceScale)
|
if(_Bilinear || (_WorldSpaceTransformation && _WorldSpaceScale))
|
||||||
ite->Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff);
|
ite->Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff);
|
||||||
}
|
}
|
||||||
if (!layer.FilteredAlphaBlendedQuads.empty() ||
|
if (!layer.FilteredAlphaBlendedQuads.empty() ||
|
||||||
|
@ -1942,6 +1992,25 @@ namespace NLGUI
|
||||||
|
|
||||||
void CViewRenderer::drawText (sint layerId, float x, float y, uint wordIndex, float xmin, float ymin, float xmax, float ymax, UTextContext &textContext)
|
void CViewRenderer::drawText (sint layerId, float x, float y, uint wordIndex, float xmin, float ymin, float xmax, float ymax, UTextContext &textContext)
|
||||||
{
|
{
|
||||||
|
xmin = xmin * _OneOverScreenW;
|
||||||
|
ymin = ymin * _OneOverScreenH;
|
||||||
|
xmax = xmax * _OneOverScreenW;
|
||||||
|
ymax = ymax * _OneOverScreenH;
|
||||||
|
|
||||||
|
if (_InterfaceScale != 1.0f && _InterfaceScale != 2.0f)
|
||||||
|
{
|
||||||
|
// align to screen pixel
|
||||||
|
x *= _OneOverScreenW * _ScreenW;
|
||||||
|
y *= _OneOverScreenH * _ScreenH;
|
||||||
|
x = floorf(x) * 1.f / (float) _ScreenW;
|
||||||
|
y = floorf(y) * 1.f / (float) _ScreenH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = floorf(x) * _OneOverScreenW;
|
||||||
|
y = floorf(y) * _OneOverScreenH;
|
||||||
|
}
|
||||||
|
|
||||||
if (_WorldSpaceTransformation)
|
if (_WorldSpaceTransformation)
|
||||||
{
|
{
|
||||||
textContext.printClipAtUnProjected(*getStringRenderBuffer(layerId), _CameraFrustum, _WorldSpaceMatrix, x, y, _CurrentZ, wordIndex, xmin, ymin, xmax, ymax);
|
textContext.printClipAtUnProjected(*getStringRenderBuffer(layerId), _CameraFrustum, _WorldSpaceMatrix, x, y, _CurrentZ, wordIndex, xmin, ymin, xmax, ymax);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1850,7 +1850,7 @@ namespace NLGUI
|
||||||
class InvalidateTextVisitor : public CInterfaceElementVisitor
|
class InvalidateTextVisitor : public CInterfaceElementVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InvalidateTextVisitor( bool reset )
|
InvalidateTextVisitor( bool reset)
|
||||||
{
|
{
|
||||||
this->reset = reset;
|
this->reset = reset;
|
||||||
}
|
}
|
||||||
|
@ -1893,6 +1893,13 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
CViewRenderer::getInstance()->setClipWindow(0, 0, w, h);
|
CViewRenderer::getInstance()->setClipWindow(0, 0, w, h);
|
||||||
|
|
||||||
|
bool scaleChanged = _InterfaceScale != CViewRenderer::getInstance()->getInterfaceScale();
|
||||||
|
if (scaleChanged)
|
||||||
|
{
|
||||||
|
_InterfaceScale = CViewRenderer::getInstance()->getInterfaceScale();
|
||||||
|
notifyInterfaceScaleWatchers();
|
||||||
|
}
|
||||||
|
|
||||||
// If all conditions are OK, move windows so they fit correctly with new screen size
|
// If all conditions are OK, move windows so they fit correctly with new screen size
|
||||||
// Do this work only InGame when Config is loaded
|
// Do this work only InGame when Config is loaded
|
||||||
moveAllWindowsToNewScreenSize(w,h,true);
|
moveAllWindowsToNewScreenSize(w,h,true);
|
||||||
|
@ -1902,7 +1909,7 @@ namespace NLGUI
|
||||||
{
|
{
|
||||||
SMasterGroup &rMG = _MasterGroups[nMasterGroup];
|
SMasterGroup &rMG = _MasterGroups[nMasterGroup];
|
||||||
|
|
||||||
InvalidateTextVisitor inv( false );
|
InvalidateTextVisitor inv( false);
|
||||||
|
|
||||||
rMG.Group->visitGroupAndChildren( &inv );
|
rMG.Group->visitGroupAndChildren( &inv );
|
||||||
rMG.Group->invalidateCoords ();
|
rMG.Group->invalidateCoords ();
|
||||||
|
@ -3688,6 +3695,42 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CWidgetManager::notifyInterfaceScaleWatchers()
|
||||||
|
{
|
||||||
|
std::vector< IInterfaceScaleWatcher* >::iterator itr = scaleWatchers.begin();
|
||||||
|
while( itr != scaleWatchers.end() )
|
||||||
|
{
|
||||||
|
(*itr)->onInterfaceScaleChanged();
|
||||||
|
++itr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CWidgetManager::registerInterfaceScaleWatcher( IInterfaceScaleWatcher *watcher )
|
||||||
|
{
|
||||||
|
std::vector< IInterfaceScaleWatcher* >::const_iterator itr
|
||||||
|
= std::find( scaleWatchers.begin(), scaleWatchers.end(), watcher );
|
||||||
|
|
||||||
|
if( itr != scaleWatchers.end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
scaleWatchers.push_back( watcher );
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void CWidgetManager::unregisterInterfaceScaleWatcher( IInterfaceScaleWatcher *watcher )
|
||||||
|
{
|
||||||
|
std::vector< IInterfaceScaleWatcher* >::iterator itr
|
||||||
|
= std::find( scaleWatchers.begin(), scaleWatchers.end(), watcher );
|
||||||
|
|
||||||
|
if( itr == scaleWatchers.end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
scaleWatchers.erase( itr );
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
CWidgetManager::CWidgetManager()
|
CWidgetManager::CWidgetManager()
|
||||||
{
|
{
|
||||||
LinkHack();
|
LinkHack();
|
||||||
|
@ -3724,6 +3767,7 @@ namespace NLGUI
|
||||||
inGame = false;
|
inGame = false;
|
||||||
|
|
||||||
setScreenWH(0, 0);
|
setScreenWH(0, 0);
|
||||||
|
_InterfaceScale = 1.0f;
|
||||||
|
|
||||||
_GroupSelection = false;
|
_GroupSelection = false;
|
||||||
multiSelection = false;
|
multiSelection = false;
|
||||||
|
|
|
@ -591,6 +591,22 @@ NLMISC_CATEGORISED_COMMAND(nel,stohr, "Convert a second number into an human rea
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string toLower(const char *str)
|
||||||
|
{
|
||||||
|
if (!str) return "";
|
||||||
|
|
||||||
|
uint len = strlen(str);
|
||||||
|
string res;
|
||||||
|
res.reserve(len);
|
||||||
|
for(uint i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if( (str[i] >= 'A') && (str[i] <= 'Z') )
|
||||||
|
res += str[i] - 'A' + 'a';
|
||||||
|
else
|
||||||
|
res += str[i];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
std::string toLower(const std::string &str)
|
std::string toLower(const std::string &str)
|
||||||
{
|
{
|
||||||
|
@ -1720,12 +1736,12 @@ static bool openDocWithExtension (const std::string &document, const std::string
|
||||||
const char *previousEnv = getenv("LD_LIBRARY_PATH");
|
const char *previousEnv = getenv("LD_LIBRARY_PATH");
|
||||||
|
|
||||||
// clear LD_LIBRARY_PATH to avoid problems with Steam Runtime
|
// clear LD_LIBRARY_PATH to avoid problems with Steam Runtime
|
||||||
setenv("LD_LIBRARY_PATH", "", 1);
|
if (previousEnv) setenv("LD_LIBRARY_PATH", "", 1);
|
||||||
|
|
||||||
bool res = launchProgram(command, document);
|
bool res = launchProgram(command, document);
|
||||||
|
|
||||||
// restore previous LD_LIBRARY_PATH
|
// restore previous LD_LIBRARY_PATH
|
||||||
setenv("LD_LIBRARY_PATH", previousEnv, 1);
|
if (previousEnv) setenv("LD_LIBRARY_PATH", previousEnv, 1);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
#endif // NL_OS_WINDOWS
|
#endif // NL_OS_WINDOWS
|
||||||
|
|
|
@ -185,7 +185,7 @@ bool CIFile::open(const std::string &path, bool text)
|
||||||
|
|
||||||
// Bigfile or xml pack access requested ?
|
// Bigfile or xml pack access requested ?
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
if ((pos = path.find('@')) != string::npos)
|
if (!CFile::fileExists(path) && (pos = path.find('@')) != string::npos)
|
||||||
{
|
{
|
||||||
// check for a double @ to identify XML pack file
|
// check for a double @ to identify XML pack file
|
||||||
if (pos+1 < path.size() && path[pos+1] == '@')
|
if (pos+1 < path.size() && path[pos+1] == '@')
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
FILE(GLOB SRC *.cpp *.h)
|
FILE(GLOB SRC *.cpp *.h)
|
||||||
FILE(GLOB HEADERS ../../include/nel/sound/*.h)
|
FILE(GLOB HEADERS ../../include/nel/sound/*.h)
|
||||||
|
|
||||||
|
IF(NOT FFMPEG_FOUND)
|
||||||
|
LIST(REMOVE_ITEM SRC ${CMAKE_CURRENT_SOURCE_DIR}/audio_decoder_ffmpeg.cpp)
|
||||||
|
LIST(REMOVE_ITEM HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../../include/nel/sound/audio_decoder_ffmpeg.h)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
FILE(GLOB ANIMATION
|
FILE(GLOB ANIMATION
|
||||||
sound_anim_manager.cpp ../../include/nel/sound/sound_anim_manager.h
|
sound_anim_manager.cpp ../../include/nel/sound/sound_anim_manager.h
|
||||||
|
@ -58,6 +62,8 @@ FILE(GLOB STREAM
|
||||||
FILE(GLOB STREAM_FILE
|
FILE(GLOB STREAM_FILE
|
||||||
audio_decoder.cpp ../../include/nel/sound/audio_decoder.h
|
audio_decoder.cpp ../../include/nel/sound/audio_decoder.h
|
||||||
audio_decoder_vorbis.cpp ../../include/nel/sound/audio_decoder_vorbis.h
|
audio_decoder_vorbis.cpp ../../include/nel/sound/audio_decoder_vorbis.h
|
||||||
|
audio_decoder_mp3.cpp ../../include/nel/sound/audio_decoder_mp3.h
|
||||||
|
audio_decoder_ffmpeg.cpp ../../include/nel/sound/audio_decoder_ffmpeg.h
|
||||||
stream_file_sound.cpp ../../include/nel/sound/stream_file_sound.h
|
stream_file_sound.cpp ../../include/nel/sound/stream_file_sound.h
|
||||||
stream_file_source.cpp ../../include/nel/sound/stream_file_source.h
|
stream_file_source.cpp ../../include/nel/sound/stream_file_source.h
|
||||||
)
|
)
|
||||||
|
@ -95,6 +101,12 @@ IF(WITH_STATIC)
|
||||||
TARGET_LINK_LIBRARIES(nelsound ${OGG_LIBRARY})
|
TARGET_LINK_LIBRARIES(nelsound ${OGG_LIBRARY})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
IF(FFMPEG_FOUND)
|
||||||
|
ADD_DEFINITIONS(-DFFMPEG_ENABLED)
|
||||||
|
INCLUDE_DIRECTORIES(${FFMPEG_INCLUDE_DIRS})
|
||||||
|
TARGET_LINK_LIBRARIES(nelsound ${FFMPEG_LIBRARIES})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
|
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,11 @@
|
||||||
|
|
||||||
// Project includes
|
// Project includes
|
||||||
#include <nel/sound/audio_decoder_vorbis.h>
|
#include <nel/sound/audio_decoder_vorbis.h>
|
||||||
|
#include <nel/sound/audio_decoder_mp3.h>
|
||||||
|
|
||||||
|
#ifdef FFMPEG_ENABLED
|
||||||
|
#include <nel/sound/audio_decoder_ffmpeg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace NLMISC;
|
using namespace NLMISC;
|
||||||
|
@ -82,43 +87,78 @@ IAudioDecoder *IAudioDecoder::createAudioDecoder(const std::string &type, NLMISC
|
||||||
nlwarning("Stream is NULL");
|
nlwarning("Stream is NULL");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#ifdef FFMPEG_ENABLED
|
||||||
|
try {
|
||||||
|
CAudioDecoderFfmpeg *decoder = new CAudioDecoderFfmpeg(stream, loop);
|
||||||
|
return static_cast<IAudioDecoder *>(decoder);
|
||||||
|
}
|
||||||
|
catch(const Exception &e)
|
||||||
|
{
|
||||||
|
nlwarning("Exception %s during ffmpeg setup", e.what());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
std::string type_lower = toLower(type);
|
std::string type_lower = toLower(type);
|
||||||
if (type_lower == "ogg")
|
if (type_lower == "ogg")
|
||||||
{
|
{
|
||||||
return new CAudioDecoderVorbis(stream, loop);
|
return new CAudioDecoderVorbis(stream, loop);
|
||||||
}
|
}
|
||||||
|
else if (type_lower == "mp3")
|
||||||
|
{
|
||||||
|
return new CAudioDecoderMP3(stream, loop);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nlwarning("Music file type unknown: '%s'", type_lower.c_str());
|
nlwarning("Music file type unknown: '%s'", type_lower.c_str());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, std::string &title, float &length)
|
bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, std::string &title, float &length)
|
||||||
{
|
{
|
||||||
std::string lookup = CPath::lookup(filepath, false);
|
std::string lookup = CPath::lookup(filepath, false);
|
||||||
if (lookup.empty())
|
if (lookup.empty())
|
||||||
{
|
{
|
||||||
nlwarning("Music file %s does not exist!", filepath.c_str());
|
nlwarning("Music file %s does not exist!", filepath.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FFMPEG_ENABLED
|
||||||
|
CIFile ifile;
|
||||||
|
ifile.setCacheFileOnOpen(false);
|
||||||
|
ifile.allowBNPCacheFileOnOpen(false);
|
||||||
|
if (ifile.open(lookup))
|
||||||
|
return CAudioDecoderFfmpeg::getInfo(&ifile, artist, title, length);
|
||||||
|
#else
|
||||||
std::string type = CFile::getExtension(filepath);
|
std::string type = CFile::getExtension(filepath);
|
||||||
std::string type_lower = NLMISC::toLower(type);
|
std::string type_lower = NLMISC::toLower(type);
|
||||||
|
|
||||||
if (type_lower == "ogg")
|
if (type_lower == "ogg")
|
||||||
{
|
{
|
||||||
CIFile ifile;
|
CIFile ifile;
|
||||||
ifile.setCacheFileOnOpen(false);
|
ifile.setCacheFileOnOpen(false);
|
||||||
ifile.allowBNPCacheFileOnOpen(false);
|
ifile.allowBNPCacheFileOnOpen(false);
|
||||||
if (ifile.open(lookup))
|
if (ifile.open(lookup))
|
||||||
return CAudioDecoderVorbis::getInfo(&ifile, artist, title, length);
|
return CAudioDecoderVorbis::getInfo(&ifile, artist, title, length);
|
||||||
|
|
||||||
nlwarning("Unable to open: '%s'", filepath.c_str());
|
nlwarning("Unable to open: '%s'", filepath.c_str());
|
||||||
}
|
}
|
||||||
|
else if (type_lower == "mp3")
|
||||||
|
{
|
||||||
|
CIFile ifile;
|
||||||
|
ifile.setCacheFileOnOpen(false);
|
||||||
|
ifile.allowBNPCacheFileOnOpen(false);
|
||||||
|
if (ifile.open(lookup))
|
||||||
|
return CAudioDecoderMP3::getInfo(&ifile, artist, title, length);
|
||||||
|
|
||||||
|
nlwarning("Unable to open: '%s'", filepath.c_str());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nlwarning("Music file type unknown: '%s'", type_lower.c_str());
|
nlwarning("Music file type unknown: '%s'", type_lower.c_str());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
artist.clear(); title.clear();
|
artist.clear(); title.clear();
|
||||||
return false;
|
return false;
|
||||||
|
@ -132,6 +172,15 @@ void IAudioDecoder::getMusicExtensions(std::vector<std::string> &extensions)
|
||||||
{
|
{
|
||||||
extensions.push_back("ogg");
|
extensions.push_back("ogg");
|
||||||
}
|
}
|
||||||
|
if (std::find(extensions.begin(), extensions.end(), "mp3") == extensions.end())
|
||||||
|
{
|
||||||
|
extensions.push_back("mp3");
|
||||||
|
}
|
||||||
|
#ifdef FFMPEG_ENABLED
|
||||||
|
extensions.push_back("mp3");
|
||||||
|
extensions.push_back("flac");
|
||||||
|
extensions.push_back("aac");
|
||||||
|
#endif
|
||||||
|
|
||||||
// extensions.push_back("wav"); // TODO: Easy.
|
// extensions.push_back("wav"); // TODO: Easy.
|
||||||
}
|
}
|
||||||
|
@ -139,7 +188,11 @@ void IAudioDecoder::getMusicExtensions(std::vector<std::string> &extensions)
|
||||||
/// Return if a music extension is supported by the nel sound library.
|
/// Return if a music extension is supported by the nel sound library.
|
||||||
bool IAudioDecoder::isMusicExtensionSupported(const std::string &extension)
|
bool IAudioDecoder::isMusicExtensionSupported(const std::string &extension)
|
||||||
{
|
{
|
||||||
|
#ifdef FFMPEG_ENABLED
|
||||||
|
return (extension == "ogg" || extension == "mp3" || extension == "flac" || extension == "aac");
|
||||||
|
#else
|
||||||
return (extension == "ogg");
|
return (extension == "ogg");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace NLSOUND */
|
} /* namespace NLSOUND */
|
||||||
|
|
431
code/nel/src/sound/audio_decoder_ffmpeg.cpp
Normal file
431
code/nel/src/sound/audio_decoder_ffmpeg.cpp
Normal file
|
@ -0,0 +1,431 @@
|
||||||
|
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||||
|
// Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#include "stdsound.h"
|
||||||
|
|
||||||
|
#include <nel/sound/audio_decoder_ffmpeg.h>
|
||||||
|
|
||||||
|
#define __STDC_CONSTANT_MACROS
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libswresample/swresample.h>
|
||||||
|
#include <libavutil/opt.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace NLMISC;
|
||||||
|
using namespace NLSOUND;
|
||||||
|
|
||||||
|
// Visual Studio does not support AV_TIME_BASE_Q macro in C++
|
||||||
|
#undef AV_TIME_BASE_Q
|
||||||
|
static const AVRational AV_TIME_BASE_Q = {1, AV_TIME_BASE};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const std::string av_err2string(sint err)
|
||||||
|
{
|
||||||
|
char buf[AV_ERROR_MAX_STRING_SIZE];
|
||||||
|
av_strerror(err, buf, AV_ERROR_MAX_STRING_SIZE);
|
||||||
|
return (std::string)buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nel_logger(void *ptr, int level, const char *fmt, va_list vargs)
|
||||||
|
{
|
||||||
|
static char msg[1024];
|
||||||
|
|
||||||
|
const char *module = NULL;
|
||||||
|
|
||||||
|
// AV_LOG_DEBUG, AV_LOG_TRACE
|
||||||
|
if (level >= AV_LOG_DEBUG) return;
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
AVClass *avc = *(AVClass**) ptr;
|
||||||
|
module = avc->item_name(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
vsnprintf(msg, sizeof(msg), fmt, vargs);
|
||||||
|
msg[sizeof(msg)-1] = '\0';
|
||||||
|
|
||||||
|
switch(level)
|
||||||
|
{
|
||||||
|
case AV_LOG_PANIC:
|
||||||
|
// ffmpeg is about to crash so lets throw
|
||||||
|
nlerror("FFMPEG(P): (%s) %s", module, msg);
|
||||||
|
break;
|
||||||
|
case AV_LOG_FATAL:
|
||||||
|
// ffmpeg had unrecoverable error, corrupted stream or such
|
||||||
|
nlerrornoex("FFMPEG(F): (%s) %s", module, msg);
|
||||||
|
break;
|
||||||
|
case AV_LOG_ERROR:
|
||||||
|
nlwarning("FFMPEG(E): (%s) %s", module, msg);
|
||||||
|
break;
|
||||||
|
case AV_LOG_WARNING:
|
||||||
|
nlwarning("FFMPEG(W): (%s) %s", module, msg);
|
||||||
|
break;
|
||||||
|
case AV_LOG_INFO:
|
||||||
|
nlinfo("FFMPEG(I): (%s) %s", module, msg);
|
||||||
|
break;
|
||||||
|
case AV_LOG_VERBOSE:
|
||||||
|
nldebug("FFMPEG(V): (%s) %s", module, msg);
|
||||||
|
break;
|
||||||
|
case AV_LOG_DEBUG:
|
||||||
|
nldebug("FFMPEG(D): (%s) %s", module, msg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nlinfo("FFMPEG: invalid log level:%d (%s) %s", level, module, msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CFfmpegInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CFfmpegInstance()
|
||||||
|
{
|
||||||
|
av_log_set_level(AV_LOG_DEBUG);
|
||||||
|
av_log_set_callback(nel_logger);
|
||||||
|
|
||||||
|
av_register_all();
|
||||||
|
|
||||||
|
//avformat_network_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~CFfmpegInstance()
|
||||||
|
{
|
||||||
|
//avformat_network_deinit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CFfmpegInstance ffmpeg;
|
||||||
|
|
||||||
|
// Send bytes to ffmpeg
|
||||||
|
int avio_read_packet(void *opaque, uint8 *buf, int buf_size)
|
||||||
|
{
|
||||||
|
NLSOUND::CAudioDecoderFfmpeg *decoder = static_cast<NLSOUND::CAudioDecoderFfmpeg *>(opaque);
|
||||||
|
NLMISC::IStream *stream = decoder->getStream();
|
||||||
|
nlassert(stream->isReading());
|
||||||
|
|
||||||
|
uint32 available = decoder->getStreamSize() - stream->getPos();
|
||||||
|
if (available == 0) return 0;
|
||||||
|
|
||||||
|
buf_size = FFMIN(buf_size, available);
|
||||||
|
stream->serialBuffer((uint8 *)buf, buf_size);
|
||||||
|
return buf_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
sint64 avio_seek(void *opaque, sint64 offset, int whence)
|
||||||
|
{
|
||||||
|
NLSOUND::CAudioDecoderFfmpeg *decoder = static_cast<NLSOUND::CAudioDecoderFfmpeg *>(opaque);
|
||||||
|
NLMISC::IStream *stream = decoder->getStream();
|
||||||
|
nlassert(stream->isReading());
|
||||||
|
|
||||||
|
NLMISC::IStream::TSeekOrigin origin;
|
||||||
|
switch(whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
origin = NLMISC::IStream::begin;
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
origin = NLMISC::IStream::current;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
origin = NLMISC::IStream::end;
|
||||||
|
break;
|
||||||
|
case AVSEEK_SIZE:
|
||||||
|
return decoder->getStreamSize();
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->seek((sint32) offset, origin);
|
||||||
|
return stream->getPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
}//ns
|
||||||
|
|
||||||
|
namespace NLSOUND {
|
||||||
|
|
||||||
|
// swresample will convert audio to this format
|
||||||
|
#define FFMPEG_SAMPLE_RATE 44100
|
||||||
|
#define FFMPEG_CHANNELS 2
|
||||||
|
#define FFMPEG_CHANNEL_LAYOUT AV_CH_LAYOUT_STEREO
|
||||||
|
#define FFMPEG_BITS_PER_SAMPLE 16
|
||||||
|
#define FFMPEG_SAMPLE_FORMAT AV_SAMPLE_FMT_S16
|
||||||
|
|
||||||
|
CAudioDecoderFfmpeg::CAudioDecoderFfmpeg(NLMISC::IStream *stream, bool loop)
|
||||||
|
: IAudioDecoder(),
|
||||||
|
_Stream(stream), _Loop(loop), _IsMusicEnded(false), _StreamSize(0), _IsSupported(false),
|
||||||
|
_AvioContext(NULL), _FormatContext(NULL),
|
||||||
|
_AudioContext(NULL), _AudioStreamIndex(0),
|
||||||
|
_SwrContext(NULL)
|
||||||
|
{
|
||||||
|
_StreamOffset = stream->getPos();
|
||||||
|
stream->seek(0, NLMISC::IStream::end);
|
||||||
|
_StreamSize = stream->getPos();
|
||||||
|
stream->seek(_StreamOffset, NLMISC::IStream::begin);
|
||||||
|
|
||||||
|
try {
|
||||||
|
_FormatContext = avformat_alloc_context();
|
||||||
|
if (!_FormatContext)
|
||||||
|
throw Exception("Can't create AVFormatContext");
|
||||||
|
|
||||||
|
// avio_ctx_buffer can be reallocated by ffmpeg and assigned to avio_ctx->buffer
|
||||||
|
uint8 *avio_ctx_buffer = NULL;
|
||||||
|
size_t avio_ctx_buffer_size = 4096;
|
||||||
|
avio_ctx_buffer = static_cast<uint8 *>(av_malloc(avio_ctx_buffer_size));
|
||||||
|
if (!avio_ctx_buffer)
|
||||||
|
throw Exception("Can't allocate avio context buffer");
|
||||||
|
|
||||||
|
_AvioContext = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, 0, this, &avio_read_packet, NULL, &avio_seek);
|
||||||
|
if (!_AvioContext)
|
||||||
|
throw Exception("Can't allocate avio context");
|
||||||
|
|
||||||
|
_FormatContext->pb = _AvioContext;
|
||||||
|
sint ret = avformat_open_input(&_FormatContext, NULL, NULL, NULL);
|
||||||
|
if (ret < 0)
|
||||||
|
throw Exception("avformat_open_input: %d", ret);
|
||||||
|
|
||||||
|
// find stream and then audio codec to see if ffmpeg supports this
|
||||||
|
_IsSupported = false;
|
||||||
|
if (avformat_find_stream_info(_FormatContext, NULL) >= 0)
|
||||||
|
{
|
||||||
|
_AudioStreamIndex = av_find_best_stream(_FormatContext, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
|
||||||
|
if (_AudioStreamIndex >= 0)
|
||||||
|
{
|
||||||
|
_AudioContext = _FormatContext->streams[_AudioStreamIndex]->codec;
|
||||||
|
av_opt_set_int(_AudioContext, "refcounted_frames", 1, 0);
|
||||||
|
|
||||||
|
AVCodec *codec = avcodec_find_decoder(_AudioContext->codec_id);
|
||||||
|
if (codec != NULL && avcodec_open2(_AudioContext, codec, NULL) >= 0)
|
||||||
|
{
|
||||||
|
_IsSupported = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_IsSupported)
|
||||||
|
{
|
||||||
|
nlwarning("FFMPEG: Decoder created, unknown stream format / codec");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CAudioDecoderFfmpeg::~CAudioDecoderFfmpeg()
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAudioDecoderFfmpeg::release()
|
||||||
|
{
|
||||||
|
if (_SwrContext)
|
||||||
|
swr_free(&_SwrContext);
|
||||||
|
|
||||||
|
if (_AudioContext)
|
||||||
|
avcodec_close(_AudioContext);
|
||||||
|
|
||||||
|
if (_FormatContext)
|
||||||
|
avformat_close_input(&_FormatContext);
|
||||||
|
|
||||||
|
if (_AvioContext && _AvioContext->buffer)
|
||||||
|
av_freep(&_AvioContext->buffer);
|
||||||
|
|
||||||
|
if (_AvioContext)
|
||||||
|
av_freep(&_AvioContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CAudioDecoderFfmpeg::isFormatSupported() const
|
||||||
|
{
|
||||||
|
return _IsSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get information on a music file.
|
||||||
|
bool CAudioDecoderFfmpeg::getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length)
|
||||||
|
{
|
||||||
|
CAudioDecoderFfmpeg ffmpeg(stream, false);
|
||||||
|
if (!ffmpeg.isFormatSupported())
|
||||||
|
{
|
||||||
|
title.clear();
|
||||||
|
artist.clear();
|
||||||
|
length = 0.f;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVDictionaryEntry *tag = NULL;
|
||||||
|
while((tag = av_dict_get(ffmpeg._FormatContext->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
|
||||||
|
{
|
||||||
|
if (!strcmp(tag->key, "artist"))
|
||||||
|
{
|
||||||
|
artist = tag->value;
|
||||||
|
}
|
||||||
|
else if (!strcmp(tag->key, "title"))
|
||||||
|
{
|
||||||
|
title = tag->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
length = ffmpeg.getLength();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CAudioDecoderFfmpeg::getRequiredBytes()
|
||||||
|
{
|
||||||
|
return 0; // no minimum requirement of bytes to buffer out
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CAudioDecoderFfmpeg::getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum)
|
||||||
|
{
|
||||||
|
if (_IsMusicEnded) return 0;
|
||||||
|
nlassert(minimum <= maximum); // can't have this..
|
||||||
|
|
||||||
|
// TODO: CStreamFileSource::play() will stall when there is no frames on warmup
|
||||||
|
// supported can be set false if there is an issue creating converter
|
||||||
|
if (!_IsSupported)
|
||||||
|
{
|
||||||
|
_IsMusicEnded = true;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 bytes_read = 0;
|
||||||
|
|
||||||
|
AVFrame frame = {0};
|
||||||
|
AVPacket packet = {0};
|
||||||
|
|
||||||
|
if (!_SwrContext)
|
||||||
|
{
|
||||||
|
sint64 in_channel_layout = av_get_default_channel_layout(_AudioContext->channels);
|
||||||
|
_SwrContext = swr_alloc_set_opts(NULL,
|
||||||
|
// output
|
||||||
|
FFMPEG_CHANNEL_LAYOUT, FFMPEG_SAMPLE_FORMAT, FFMPEG_SAMPLE_RATE,
|
||||||
|
// input
|
||||||
|
in_channel_layout, _AudioContext->sample_fmt, _AudioContext->sample_rate,
|
||||||
|
0, NULL);
|
||||||
|
swr_init(_SwrContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
sint ret;
|
||||||
|
while(bytes_read < minimum)
|
||||||
|
{
|
||||||
|
// read packet from stream
|
||||||
|
if ((ret = av_read_frame(_FormatContext, &packet)) < 0)
|
||||||
|
{
|
||||||
|
_IsMusicEnded = true;
|
||||||
|
// TODO: looping
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet.stream_index == _AudioStreamIndex)
|
||||||
|
{
|
||||||
|
// packet can contain multiple frames
|
||||||
|
AVPacket first = packet;
|
||||||
|
int got_frame = 0;
|
||||||
|
do {
|
||||||
|
got_frame = 0;
|
||||||
|
ret = avcodec_decode_audio4(_AudioContext, &frame, &got_frame, &packet);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
nlwarning("FFMPEG: error decoding audio frame: %s", av_err2string(ret).c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
packet.size -= ret;
|
||||||
|
packet.data += ret;
|
||||||
|
|
||||||
|
if (got_frame)
|
||||||
|
{
|
||||||
|
uint32 out_bps = av_get_bytes_per_sample(FFMPEG_SAMPLE_FORMAT) * FFMPEG_CHANNELS;
|
||||||
|
uint32 max_samples = (maximum - bytes_read) / out_bps;
|
||||||
|
|
||||||
|
uint32 out_samples = av_rescale_rnd(swr_get_delay(_SwrContext, _AudioContext->sample_rate) + frame.nb_samples,
|
||||||
|
FFMPEG_SAMPLE_RATE, _AudioContext->sample_rate, AV_ROUND_UP);
|
||||||
|
|
||||||
|
if (max_samples > out_samples)
|
||||||
|
max_samples = out_samples;
|
||||||
|
|
||||||
|
uint32 converted = swr_convert(_SwrContext, &buffer, max_samples, (const uint8 **)frame.extended_data, frame.nb_samples);
|
||||||
|
uint32 size = out_bps * converted;
|
||||||
|
|
||||||
|
bytes_read += size;
|
||||||
|
buffer += size;
|
||||||
|
|
||||||
|
av_frame_unref(&frame);
|
||||||
|
}
|
||||||
|
} while (got_frame && packet.size > 0);
|
||||||
|
|
||||||
|
av_packet_unref(&first);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
av_packet_unref(&packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 CAudioDecoderFfmpeg::getChannels()
|
||||||
|
{
|
||||||
|
return FFMPEG_CHANNELS;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint CAudioDecoderFfmpeg::getSamplesPerSec()
|
||||||
|
{
|
||||||
|
return FFMPEG_SAMPLE_RATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 CAudioDecoderFfmpeg::getBitsPerSample()
|
||||||
|
{
|
||||||
|
return FFMPEG_BITS_PER_SAMPLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CAudioDecoderFfmpeg::isMusicEnded()
|
||||||
|
{
|
||||||
|
return _IsMusicEnded;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CAudioDecoderFfmpeg::getLength()
|
||||||
|
{
|
||||||
|
float length = 0.f;
|
||||||
|
if (_FormatContext->duration != AV_NOPTS_VALUE)
|
||||||
|
{
|
||||||
|
length = _FormatContext->duration * av_q2d(AV_TIME_BASE_Q);
|
||||||
|
}
|
||||||
|
else if (_FormatContext->streams[_AudioStreamIndex]->duration != AV_NOPTS_VALUE)
|
||||||
|
{
|
||||||
|
length = _FormatContext->streams[_AudioStreamIndex]->duration * av_q2d(_FormatContext->streams[_AudioStreamIndex]->time_base);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAudioDecoderFfmpeg::setLooping(bool loop)
|
||||||
|
{
|
||||||
|
_Loop = loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace NLSOUND */
|
||||||
|
|
||||||
|
/* end of file */
|
224
code/nel/src/sound/audio_decoder_mp3.cpp
Normal file
224
code/nel/src/sound/audio_decoder_mp3.cpp
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||||
|
// Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#include "stdsound.h"
|
||||||
|
|
||||||
|
#include <nel/sound/audio_decoder_mp3.h>
|
||||||
|
|
||||||
|
#define DR_MP3_IMPLEMENTATION
|
||||||
|
#include <nel/sound/decoder/dr_mp3.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace NLMISC;
|
||||||
|
using namespace NLSOUND;
|
||||||
|
|
||||||
|
namespace NLSOUND {
|
||||||
|
|
||||||
|
// callback for drmp3
|
||||||
|
static size_t drmp3_read(void* pUserData, void* pBufferOut, size_t bytesToRead)
|
||||||
|
{
|
||||||
|
NLSOUND::CAudioDecoderMP3 *decoder = static_cast<NLSOUND::CAudioDecoderMP3 *>(pUserData);
|
||||||
|
NLMISC::IStream *stream = decoder->getStream();
|
||||||
|
nlassert(stream->isReading());
|
||||||
|
|
||||||
|
uint32 available = decoder->getStreamSize() - stream->getPos();
|
||||||
|
if (available == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (bytesToRead > available)
|
||||||
|
bytesToRead = available;
|
||||||
|
|
||||||
|
stream->serialBuffer((uint8 *)pBufferOut, bytesToRead);
|
||||||
|
return bytesToRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
// callback for drmp3
|
||||||
|
static drmp3_bool32 drmp3_seek(void* pUserData, int offset, drmp3_seek_origin origin)
|
||||||
|
{
|
||||||
|
NLSOUND::CAudioDecoderMP3 *decoder = static_cast<NLSOUND::CAudioDecoderMP3 *>(pUserData);
|
||||||
|
NLMISC::IStream *stream = decoder->getStream();
|
||||||
|
nlassert(stream->isReading());
|
||||||
|
|
||||||
|
NLMISC::IStream::TSeekOrigin seekOrigin;
|
||||||
|
if (origin == drmp3_seek_origin_start)
|
||||||
|
seekOrigin = NLMISC::IStream::begin;
|
||||||
|
else if (origin == drmp3_seek_origin_current)
|
||||||
|
seekOrigin = NLMISC::IStream::current;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
stream->seek((sint32) offset, seekOrigin);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// these should always be 44100Hz/16bit/2ch
|
||||||
|
#define MP3_SAMPLE_RATE 44100
|
||||||
|
#define MP3_BITS_PER_SAMPLE 16
|
||||||
|
#define MP3_CHANNELS 2
|
||||||
|
|
||||||
|
CAudioDecoderMP3::CAudioDecoderMP3(NLMISC::IStream *stream, bool loop)
|
||||||
|
: IAudioDecoder(),
|
||||||
|
_Stream(stream), _Loop(loop), _IsMusicEnded(false), _StreamSize(0), _IsSupported(false), _PCMFrameCount(0)
|
||||||
|
{
|
||||||
|
_StreamOffset = stream->getPos();
|
||||||
|
stream->seek(0, NLMISC::IStream::end);
|
||||||
|
_StreamSize = stream->getPos();
|
||||||
|
stream->seek(_StreamOffset, NLMISC::IStream::begin);
|
||||||
|
|
||||||
|
drmp3_config config;
|
||||||
|
config.outputChannels = MP3_CHANNELS;
|
||||||
|
config.outputSampleRate = MP3_SAMPLE_RATE;
|
||||||
|
|
||||||
|
_IsSupported = drmp3_init(&_Decoder, &drmp3_read, &drmp3_seek, this, &config);
|
||||||
|
if (!_IsSupported)
|
||||||
|
{
|
||||||
|
nlwarning("MP3: Decoder failed to read stream");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CAudioDecoderMP3::~CAudioDecoderMP3()
|
||||||
|
{
|
||||||
|
if (_IsSupported)
|
||||||
|
{
|
||||||
|
drmp3_uninit(&_Decoder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CAudioDecoderMP3::isFormatSupported() const
|
||||||
|
{
|
||||||
|
return _IsSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get information on a music file.
|
||||||
|
bool CAudioDecoderMP3::getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length)
|
||||||
|
{
|
||||||
|
CAudioDecoderMP3 mp3(stream, false);
|
||||||
|
if (!mp3.isFormatSupported())
|
||||||
|
{
|
||||||
|
title.clear();
|
||||||
|
artist.clear();
|
||||||
|
length = 0.f;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
length = mp3.getLength();
|
||||||
|
|
||||||
|
// ID3v1
|
||||||
|
stream->seek(-128, NLMISC::IStream::end);
|
||||||
|
{
|
||||||
|
uint8 buf[128];
|
||||||
|
stream->serialBuffer(buf, 128);
|
||||||
|
|
||||||
|
if(buf[0] == 'T' && buf[1] == 'A' && buf[2] == 'G')
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
for(i = 0; i < 30; ++i) if (buf[3+i] == '\0') break;
|
||||||
|
artist.assign((char *)&buf[3], i);
|
||||||
|
|
||||||
|
for(i = 0; i < 30; ++i) if (buf[33+i] == '\0') break;
|
||||||
|
title.assign((char *)&buf[33], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CAudioDecoderMP3::getRequiredBytes()
|
||||||
|
{
|
||||||
|
return 0; // no minimum requirement of bytes to buffer out
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CAudioDecoderMP3::getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum)
|
||||||
|
{
|
||||||
|
if (_IsMusicEnded) return 0;
|
||||||
|
nlassert(minimum <= maximum); // can't have this..
|
||||||
|
|
||||||
|
// TODO: CStreamFileSource::play() will stall when there is no frames on warmup
|
||||||
|
// supported can be set false if there is an issue creating converter
|
||||||
|
if (!_IsSupported)
|
||||||
|
{
|
||||||
|
_IsMusicEnded = true;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sint16 *pFrameBufferOut = (sint16 *)buffer;
|
||||||
|
uint32 bytesPerFrame = MP3_BITS_PER_SAMPLE / 8 * _Decoder.channels;
|
||||||
|
|
||||||
|
uint32 totalFramesRead = 0;
|
||||||
|
uint32 framesToRead = minimum / bytesPerFrame;
|
||||||
|
while(framesToRead > 0)
|
||||||
|
{
|
||||||
|
float tempBuffer[4096];
|
||||||
|
uint64 tempFrames = drmp3_countof(tempBuffer) / _Decoder.channels;
|
||||||
|
|
||||||
|
if (tempFrames > framesToRead)
|
||||||
|
tempFrames = framesToRead;
|
||||||
|
|
||||||
|
tempFrames = drmp3_read_pcm_frames_f32(&_Decoder, tempFrames, tempBuffer);
|
||||||
|
if (tempFrames == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
drmp3dec_f32_to_s16(tempBuffer, pFrameBufferOut, tempFrames * _Decoder.channels);
|
||||||
|
pFrameBufferOut += tempFrames * _Decoder.channels;
|
||||||
|
|
||||||
|
framesToRead -= tempFrames;
|
||||||
|
totalFramesRead += tempFrames;
|
||||||
|
}
|
||||||
|
|
||||||
|
_IsMusicEnded = (framesToRead > 0);
|
||||||
|
return totalFramesRead * bytesPerFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 CAudioDecoderMP3::getChannels()
|
||||||
|
{
|
||||||
|
return _Decoder.channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint CAudioDecoderMP3::getSamplesPerSec()
|
||||||
|
{
|
||||||
|
return _Decoder.sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 CAudioDecoderMP3::getBitsPerSample()
|
||||||
|
{
|
||||||
|
return MP3_BITS_PER_SAMPLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CAudioDecoderMP3::isMusicEnded()
|
||||||
|
{
|
||||||
|
return _IsMusicEnded;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CAudioDecoderMP3::getLength()
|
||||||
|
{
|
||||||
|
// cached because drmp3_get_pcm_frame_count is reading full file
|
||||||
|
if (_PCMFrameCount == 0)
|
||||||
|
{
|
||||||
|
_PCMFrameCount = drmp3_get_pcm_frame_count(&_Decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _PCMFrameCount / (float) _Decoder.sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAudioDecoderMP3::setLooping(bool loop)
|
||||||
|
{
|
||||||
|
_Loop = loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace NLSOUND */
|
||||||
|
|
||||||
|
/* end of file */
|
|
@ -2759,7 +2759,7 @@ void CAudioMixerUser::setEventMusicVolume(float gain)
|
||||||
bool CAudioMixerUser::isEventMusicEnded()
|
bool CAudioMixerUser::isEventMusicEnded()
|
||||||
{
|
{
|
||||||
if (_MusicChannelFaders[EventMusicChannel].isInitOk())
|
if (_MusicChannelFaders[EventMusicChannel].isInitOk())
|
||||||
_MusicChannelFaders[EventMusicChannel].isEnded();
|
return _MusicChannelFaders[EventMusicChannel].isEnded();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -704,7 +704,9 @@ void CComplexSource::checkup()
|
||||||
for (; first != last; ++first)
|
for (; first != last; ++first)
|
||||||
{
|
{
|
||||||
USource *source = *first;
|
USource *source = *first;
|
||||||
if (source != NULL && source->getSound()->getLooping() && !source->isPlaying())
|
if (source == NULL)
|
||||||
|
continue;
|
||||||
|
if (source->getSound()->getLooping() && !source->isPlaying())
|
||||||
source->play();
|
source->play();
|
||||||
if (source->getSound()->getSoundType() != CSound::SOUND_SIMPLE)
|
if (source->getSound()->getSoundType() != CSound::SOUND_SIMPLE)
|
||||||
static_cast<CSourceCommon*>(source)->checkup();
|
static_cast<CSourceCommon*>(source)->checkup();
|
||||||
|
|
|
@ -121,6 +121,11 @@ void CSourceAL::setStreaming(bool streaming)
|
||||||
alTestError();
|
alTestError();
|
||||||
_Buffer = NULL;
|
_Buffer = NULL;
|
||||||
_IsStreaming = streaming;
|
_IsStreaming = streaming;
|
||||||
|
if (_IsStreaming)
|
||||||
|
{
|
||||||
|
// make sure looping is disabled on OpenAL side
|
||||||
|
setLooping(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the buffer that will be played (no streaming)
|
/* Set the buffer that will be played (no streaming)
|
||||||
|
@ -194,7 +199,11 @@ uint CSourceAL::countStreamingBuffers() const
|
||||||
// a bit ugly here, but makes a much easier/simpler implementation on both drivers
|
// a bit ugly here, but makes a much easier/simpler implementation on both drivers
|
||||||
ALint buffersProcessed;
|
ALint buffersProcessed;
|
||||||
alGetSourcei(_Source, AL_BUFFERS_PROCESSED, &buffersProcessed);
|
alGetSourcei(_Source, AL_BUFFERS_PROCESSED, &buffersProcessed);
|
||||||
while (buffersProcessed)
|
if (buffersProcessed && _QueuedBuffers.empty())
|
||||||
|
{
|
||||||
|
nlwarning("AL: QueuedBuffers is empty, but OpenAL buffers processed > 0");
|
||||||
|
}
|
||||||
|
while (buffersProcessed && !_QueuedBuffers.empty())
|
||||||
{
|
{
|
||||||
ALuint bufferName = _QueuedBuffers.front()->bufferName();
|
ALuint bufferName = _QueuedBuffers.front()->bufferName();
|
||||||
alSourceUnqueueBuffers(_Source, 1, &bufferName);
|
alSourceUnqueueBuffers(_Source, 1, &bufferName);
|
||||||
|
|
|
@ -82,13 +82,14 @@ void CSampleBankManager::init(NLGEORGES::UFormElm *mixerConfig)
|
||||||
TFilteredBank fb;
|
TFilteredBank fb;
|
||||||
std::string bankName;
|
std::string bankName;
|
||||||
NLGEORGES::UFormElm *realBank = NULL;
|
NLGEORGES::UFormElm *realBank = NULL;
|
||||||
realBank->getArrayNode(&realBank, j);
|
realBanks->getArrayNode(&realBank, j);
|
||||||
|
if (realBank != 0)
|
||||||
realBank->getValueByName(bankName, ".SampleBank");
|
{
|
||||||
fb.BankName = CStringMapper::map(bankName);
|
realBank->getValueByName(bankName, ".SampleBank");
|
||||||
realBank->getValueByName(fb.Filter, ".Filter");
|
fb.BankName = CStringMapper::map(bankName);
|
||||||
|
realBank->getValueByName(fb.Filter, ".Filter");
|
||||||
vfb.push_back(fb);
|
vfb.push_back(fb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ using namespace std;
|
||||||
namespace NLSOUND {
|
namespace NLSOUND {
|
||||||
|
|
||||||
CStreamFileSource::CStreamFileSource(CStreamFileSound *streamFileSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController)
|
CStreamFileSource::CStreamFileSource(CStreamFileSound *streamFileSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController)
|
||||||
: CStreamSource(streamFileSound, spawn, cb, cbUserParam, cluster, groupController), m_AudioDecoder(NULL), m_Paused(false)
|
: CStreamSource(streamFileSound, spawn, cb, cbUserParam, cluster, groupController), m_AudioDecoder(NULL), m_Paused(false), m_DecodingEnded(false)
|
||||||
{
|
{
|
||||||
m_Thread = NLMISC::IThread::create(this);
|
m_Thread = NLMISC::IThread::create(this);
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ void CStreamFileSource::resume()
|
||||||
|
|
||||||
bool CStreamFileSource::isEnded()
|
bool CStreamFileSource::isEnded()
|
||||||
{
|
{
|
||||||
return (!m_Thread->isRunning() && !_Playing && !m_WaitingForPlay && !m_Paused);
|
return m_DecodingEnded || (!m_Thread->isRunning() && !_Playing && !m_WaitingForPlay && !m_Paused);
|
||||||
}
|
}
|
||||||
|
|
||||||
float CStreamFileSource::getLength()
|
float CStreamFileSource::getLength()
|
||||||
|
@ -319,6 +319,7 @@ void CStreamFileSource::run()
|
||||||
this->getRecommendedBufferSize(samples, bytes);
|
this->getRecommendedBufferSize(samples, bytes);
|
||||||
uint32 recSleep = 40;
|
uint32 recSleep = 40;
|
||||||
uint32 doSleep = 10;
|
uint32 doSleep = 10;
|
||||||
|
m_DecodingEnded = false;
|
||||||
while (_Playing || m_WaitingForPlay)
|
while (_Playing || m_WaitingForPlay)
|
||||||
{
|
{
|
||||||
if (!m_AudioDecoder->isMusicEnded())
|
if (!m_AudioDecoder->isMusicEnded())
|
||||||
|
@ -369,6 +370,9 @@ void CStreamFileSource::run()
|
||||||
{
|
{
|
||||||
delete m_AudioDecoder;
|
delete m_AudioDecoder;
|
||||||
m_AudioDecoder = NULL;
|
m_AudioDecoder = NULL;
|
||||||
|
// _Playing cannot be used to detect play state because its required in cleanup
|
||||||
|
// Using m_AudioDecoder in isEnded() may result race condition (decoder is only created after thread is started)
|
||||||
|
m_DecodingEnded = !m_WaitingForPlay;
|
||||||
}
|
}
|
||||||
// drop buffers
|
// drop buffers
|
||||||
m_FreeBuffers = 3;
|
m_FreeBuffers = 3;
|
||||||
|
|
|
@ -92,7 +92,7 @@ void CStreamSource::releasePhysicalSource()
|
||||||
// free the track
|
// free the track
|
||||||
pSource->stop();
|
pSource->stop();
|
||||||
pSource->setStreaming(false);
|
pSource->setStreaming(false);
|
||||||
mixer->freeTrack(m_Track);
|
if (mixer) mixer->freeTrack(m_Track);
|
||||||
m_Track = NULL;
|
m_Track = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,7 @@ int main(int argc, char **argv)
|
||||||
args.addArg("x", "extract", "", "Extract all interface elements from <output_filename> to <input_path>.");
|
args.addArg("x", "extract", "", "Extract all interface elements from <output_filename> to <input_path>.");
|
||||||
args.addAdditionalArg("output_filename", "PNG or TGA file to generate", true);
|
args.addAdditionalArg("output_filename", "PNG or TGA file to generate", true);
|
||||||
args.addAdditionalArg("input_path", "Path that containts interfaces elements", false);
|
args.addAdditionalArg("input_path", "Path that containts interfaces elements", false);
|
||||||
|
args.addArg("", "no-border", "", "Disable border duplication. Enabled by default");
|
||||||
|
|
||||||
if (!args.parse(argc, argv)) return 1;
|
if (!args.parse(argc, argv)) return 1;
|
||||||
|
|
||||||
|
@ -227,6 +228,13 @@ int main(int argc, char **argv)
|
||||||
existingUVfilename = args.getArg("s").front();
|
existingUVfilename = args.getArg("s").front();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
uint borderSize = 1;
|
||||||
|
if (args.haveLongArg("no-border"))
|
||||||
|
{
|
||||||
|
borderSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// extract all interface elements
|
// extract all interface elements
|
||||||
bool extractElements = args.haveArg("x");
|
bool extractElements = args.haveArg("x");
|
||||||
|
|
||||||
|
@ -407,6 +415,27 @@ int main(int argc, char **argv)
|
||||||
pBtmp->convertToType(CBitmap::RGBA);
|
pBtmp->convertToType(CBitmap::RGBA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// duplicate icon border
|
||||||
|
if (borderSize > 0)
|
||||||
|
{
|
||||||
|
NLMISC::CBitmap *tmp = new NLMISC::CBitmap;
|
||||||
|
tmp->resize(pBtmp->getWidth(), pBtmp->getHeight());
|
||||||
|
tmp->blit(pBtmp, 0, 0);
|
||||||
|
// corners
|
||||||
|
tmp->resample(tmp->getWidth() + borderSize * 2, tmp->getHeight() + borderSize * 2);
|
||||||
|
// top, bottom
|
||||||
|
tmp->blit(pBtmp, borderSize, 0);
|
||||||
|
tmp->blit(pBtmp, borderSize, borderSize*2);
|
||||||
|
// left, right
|
||||||
|
tmp->blit(pBtmp, 0, borderSize);
|
||||||
|
tmp->blit(pBtmp, borderSize*2, borderSize);
|
||||||
|
// center
|
||||||
|
tmp->blit(pBtmp, borderSize, borderSize);
|
||||||
|
|
||||||
|
delete pBtmp;
|
||||||
|
pBtmp = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
AllMaps[i] = pBtmp;
|
AllMaps[i] = pBtmp;
|
||||||
}
|
}
|
||||||
catch (const NLMISC::Exception &e)
|
catch (const NLMISC::Exception &e)
|
||||||
|
@ -461,10 +490,10 @@ int main(int argc, char **argv)
|
||||||
putIn (AllMaps[i], &GlobalTexture, x, y);
|
putIn (AllMaps[i], &GlobalTexture, x, y);
|
||||||
putIn (AllMaps[i], &GlobalMask, x, y, false);
|
putIn (AllMaps[i], &GlobalMask, x, y, false);
|
||||||
|
|
||||||
UVMin[i].U = (float)x;
|
UVMin[i].U = (float)x + borderSize;
|
||||||
UVMin[i].V = (float)y;
|
UVMin[i].V = (float)y + borderSize;
|
||||||
UVMax[i].U = (float)x+AllMaps[i]->getWidth();
|
UVMax[i].U = (float)x + AllMaps[i]->getWidth() - borderSize;
|
||||||
UVMax[i].V = (float)y+AllMaps[i]->getHeight();
|
UVMax[i].V = (float)y + AllMaps[i]->getHeight() - borderSize;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Do not remove this is useful for debugging
|
// Do not remove this is useful for debugging
|
||||||
|
|
|
@ -41,20 +41,19 @@ Gamma_max = 1.0;
|
||||||
|
|
||||||
Application = { "Lirria", "./client_ryzom_r.exe", "./" };
|
Application = { "Lirria", "./client_ryzom_r.exe", "./" };
|
||||||
BackgroundDownloader = 0;
|
BackgroundDownloader = 0;
|
||||||
PatchWanted = 0;
|
PatchWanted = 1;
|
||||||
PatchUrl = "http://lirria.khaganat.net:43435";
|
PatchUrl = "http://lirria.khaganat.net:43435";
|
||||||
RingReleaseNotePath = "http://lirria.khaganat.net/patch/index.php";
|
RingReleaseNotePath = "http://lirria.khaganat.net/patch/index.php";
|
||||||
|
SignUpURL = "";
|
||||||
StartupHost = "lirria.khaganat.net:40916";
|
StartupHost = "lirria.khaganat.net:40916";
|
||||||
StartupPage = "/login/r2_login.php";
|
StartupPage = "/login/r2_login.php";
|
||||||
InstallStatsUrl = "https://lirria.khaganat.net:50000/stats/stats.php";
|
InstallStatsUrl = "http://lirria.khaganat.net:50000/stats/stats.php";
|
||||||
|
CreateAccountURL = "http://lirria.khaganat.net/ams/?page=register";
|
||||||
CreateAccountURL = "https://lirria.khaganat.net/ams/?page=register";
|
EditAccountURL = "http://lirria.khaganat.net/ams/?page=settings";
|
||||||
EditAccountURL = "https://lirria.khaganat.net/";
|
ConditionsTermsURL = "http://www.gnu.org/licenses/agpl-3.0.html";
|
||||||
ForgetPwdURL = "https://lirria.khaganat.net/ams/index.php?page=forgot_password";
|
ForgetPwdURL = "http://lirria.khaganat.net/ams/?page=forgot_password";
|
||||||
//FreeTrialURL = "https://lirria.khaganat.net/";
|
LoginSupportURL = "https://lirria.khaganat.net/";
|
||||||
LoginSupportURL = "https://www.khaganat.net/irc";
|
InstallWebPage = "";
|
||||||
ConditionsTermsURL = "khaganat.net/wikhan/fr:charte";
|
|
||||||
|
|
||||||
|
|
||||||
// Full path and filename where cURL can find certificate bundle file
|
// Full path and filename where cURL can find certificate bundle file
|
||||||
// cacert.pem file can be downloaded from https://curl.haxx.se/docs/caextract.html
|
// cacert.pem file can be downloaded from https://curl.haxx.se/docs/caextract.html
|
||||||
|
@ -67,7 +66,7 @@ ConditionsTermsURL = "khaganat.net/wikhan/fr:charte";
|
||||||
////////////////
|
////////////////
|
||||||
|
|
||||||
// the language to use as in ISO 639-2
|
// the language to use as in ISO 639-2
|
||||||
LanguageCode = "fr"; // english
|
LanguageCode = "en"; // english
|
||||||
|
|
||||||
XMLInputFile = "input_config_v3.xml";
|
XMLInputFile = "input_config_v3.xml";
|
||||||
|
|
||||||
|
@ -236,7 +235,7 @@ FXAA_ps3 = 1;
|
||||||
|
|
||||||
AnisotropicFilter = 0;
|
AnisotropicFilter = 0;
|
||||||
|
|
||||||
Bloom = 1;
|
Bloom = 0;
|
||||||
Bloom_ps0 = 0;
|
Bloom_ps0 = 0;
|
||||||
Bloom_ps1 = 1;
|
Bloom_ps1 = 1;
|
||||||
Bloom_ps2 = 1;
|
Bloom_ps2 = 1;
|
||||||
|
@ -325,12 +324,22 @@ CameraDistance = 3.0; // Camera Distance(in meter) from the user (for the Third
|
||||||
CameraDistStep = 1.0;
|
CameraDistStep = 1.0;
|
||||||
CameraDistMin = 1.0;
|
CameraDistMin = 1.0;
|
||||||
CameraDistMax = 25.0;
|
CameraDistMax = 25.0;
|
||||||
CameraDistMax = 250.0;
|
|
||||||
CameraAccel = 5.0;
|
CameraAccel = 5.0;
|
||||||
CameraSpeedMin = 2.0;
|
CameraSpeedMin = 2.0;
|
||||||
CameraSpeedMax = 100.0;
|
CameraSpeedMax = 100.0;
|
||||||
CameraResetSpeed = 10.0; // Speed in radian/s
|
CameraResetSpeed = 10.0; // Speed in radian/s
|
||||||
|
|
||||||
|
// Values for UI Scale
|
||||||
|
InterfaceScale = 1.0;
|
||||||
|
InterfaceScale_min = 0.8;
|
||||||
|
InterfaceScale_max = 2.0;
|
||||||
|
InterfaceScale_step = 0.05;
|
||||||
|
|
||||||
|
// Enable biliner filtering for UI textures
|
||||||
|
// Texture atlas needs to be generated with border duplication
|
||||||
|
// or there will be visible texture bleeding
|
||||||
|
BilinearUI = 1;
|
||||||
|
|
||||||
// Default values for map
|
// Default values for map
|
||||||
MaxMapScale = 2.0;
|
MaxMapScale = 2.0;
|
||||||
R2EDMaxMapScale = 8.0;
|
R2EDMaxMapScale = 8.0;
|
||||||
|
@ -419,28 +428,28 @@ SystemInfoColors =
|
||||||
};
|
};
|
||||||
|
|
||||||
PrintfCommands = {
|
PrintfCommands = {
|
||||||
"52", "15", "55 55 0 255", "28", "uiEon", "624",
|
"52", "15", "55 55 0 255", "28", "uiEon", "624",
|
||||||
"428", "0 0 0 255", "18", "", "624", "378",
|
"428", "0 0 0 255", "18", "", "624", "378",
|
||||||
"0 0 0 255", "14", "", "644", "278", "0 0 0 255",
|
"0 0 0 255", "14", "", "644", "278", "0 0 0 255",
|
||||||
"18", "", "52", "17", "255 255 255 255", "28",
|
"18", "", "52", "17", "255 255 255 255", "28",
|
||||||
"uiEon", "622", "430", "255 255 255 255", "18", "",
|
"uiEon", "622", "430", "255 255 255 255", "18", "",
|
||||||
"622", "380", "255 255 255 255", "14", "", "642",
|
"622", "380", "255 255 255 255", "14", "", "642",
|
||||||
"280", "255 255 255 255", "18", ""
|
"280", "255 255 255 255", "18", ""
|
||||||
};
|
};
|
||||||
|
|
||||||
PrintfCommandsFreeTrial = {
|
PrintfCommandsFreeTrial = {
|
||||||
"52", "15", "55 55 0 255", "28", "uiEon", "624",
|
"52", "15", "55 55 0 255", "28", "uiEon", "624",
|
||||||
"428", "0 0 0 255", "18", "", "624", "378",
|
"428", "0 0 0 255", "18", "", "624", "378",
|
||||||
"0 0 0 255", "14", "", "644", "278", "0 0 0 255",
|
"0 0 0 255", "14", "", "644", "278", "0 0 0 255",
|
||||||
"18", "", "52", "17", "255 255 255 255", "28",
|
"18", "", "52", "17", "255 255 255 255", "28",
|
||||||
"uiEon", "622", "430", "255 255 255 255", "18", "",
|
"uiEon", "622", "430", "255 255 255 255", "18", "",
|
||||||
"622", "380", "255 255 255 255", "14", "", "642",
|
"622", "380", "255 255 255 255", "14", "", "642",
|
||||||
"280", "255 255 255 255", "18", ""
|
"280", "255 255 255 255", "18", ""
|
||||||
};
|
};
|
||||||
|
|
||||||
DisplayMissingAnimFile = 0;
|
DisplayMissingAnimFile = 0;
|
||||||
|
|
||||||
LoadingStringCount = 54;
|
LoadingStringCount = 0;
|
||||||
|
|
||||||
|
|
||||||
// Some R2 parameters ...
|
// Some R2 parameters ...
|
||||||
|
@ -573,7 +582,7 @@ ScenarioSavePath = "./my_scenarios/";
|
||||||
// note : we add a dot in the name to be sure that there cannot be a conflict with character keyset name
|
// note : we add a dot in the name to be sure that there cannot be a conflict with character keyset name
|
||||||
BuiltInKeySets =
|
BuiltInKeySets =
|
||||||
{
|
{
|
||||||
"", // default khanat keyboard layout
|
"", // default ryzom keyboard layout
|
||||||
"bi.zqsd", // european keyboard fps displacement style (NB : don't change this layout name, ryzom will automatically select it if keyboard is french or belgian)
|
"bi.zqsd", // european keyboard fps displacement style (NB : don't change this layout name, ryzom will automatically select it if keyboard is french or belgian)
|
||||||
"bi.wasd", // english keyboard fps displacement style (NB : don't change this layout name, ryzom will automatically select it if keyboard is not french nor belgian)
|
"bi.wasd", // english keyboard fps displacement style (NB : don't change this layout name, ryzom will automatically select it if keyboard is not french nor belgian)
|
||||||
"bi.wow_alike" // 'world of warcraft' like keyboard style. (NB : not available for ring)
|
"bi.wow_alike" // 'world of warcraft' like keyboard style. (NB : not available for ring)
|
||||||
|
@ -587,19 +596,21 @@ ScenarioLanguages = {"fr","de","en","other_lang"};
|
||||||
// Map each language to a forum help page
|
// Map each language to a forum help page
|
||||||
HelpPages =
|
HelpPages =
|
||||||
{
|
{
|
||||||
"fr=https://khaganat.net/wikhan/fr:error",
|
"fr=http://forums.khaganat.net/",
|
||||||
"en=https://khaganat.net/wikhan/fr:error",
|
"en=http://forums.lirria.khaganat.net",
|
||||||
"wk=https://khaganat.net/wikhan/fr:error",
|
"wk=http://forums.lirria.khaganat.net",
|
||||||
"de=https://khaganat.net/wikhan/fr:error",
|
"de=http://forums.lirria.khaganat.net",
|
||||||
"es=https://khaganat.net/wikhan/fr:error",
|
"es=http://forums.lirria.khaganat.net",
|
||||||
"ru=https://khaganat.net/wikhan/fr:error"
|
"ru=http://forums.lirria.khaganat.net"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// interval in minutes for webig notify thread to run
|
||||||
|
WebIgNotifInterval = 10;
|
||||||
WebIgMainDomain = "app.lirria.khaganat.net";
|
WebIgMainDomain = "app.lirria.khaganat.net";
|
||||||
WebIgTrustedDomains = {
|
WebIgTrustedDomains = {
|
||||||
"api.lirria.khaganat.net", "app.lirria.khaganat.net", "lirria.khaganat.net"
|
"api.lirria.khaganat.net", "app.lirria.khaganat.net"
|
||||||
};
|
};
|
||||||
//PatchletUrl = "";
|
|
||||||
|
|
||||||
SelectedSlot = 0;
|
SelectedSlot = 0;
|
||||||
|
|
||||||
|
|
|
@ -78,17 +78,11 @@
|
||||||
|
|
||||||
<command name="self" action="self_target" params="" />
|
<command name="self" action="self_target" params="" />
|
||||||
|
|
||||||
<command name="target" action="target" params="entity=$" />
|
<command name="target" action="target" params="entity=+" ctrlchar="false" />
|
||||||
<command name="tar" action="target" params="entity=$" />
|
<command name="tar" action="target" params="entity=+" ctrlchar="false" />
|
||||||
|
|
||||||
<command name="target_quiet" action="target" params="entity=$|quiet=true" />
|
<command name="target_quiet" action="target" params="entity=+|quiet=true" ctrlchar="false" />
|
||||||
<command name="tarq" action="target" params="entity=$|quiet=true" />
|
<command name="tarq" action="target" params="entity=+|quiet=true" ctrlchar="false" />
|
||||||
|
|
||||||
<command name="target" action="target" params="entity=$|prefer_complete_match=$" />
|
|
||||||
<command name="tar" action="target" params="entity=$|prefer_complete_match=$" />
|
|
||||||
|
|
||||||
<command name="target_quiet" action="target" params="entity=$|prefer_complete_match=$|quiet=true" />
|
|
||||||
<command name="tarq" action="target" params="entity=$|prefer_complete_match=$|quiet=true" />
|
|
||||||
|
|
||||||
<command name="target" action="no_target" params="" />
|
<command name="target" action="no_target" params="" />
|
||||||
<command name="tar" action="no_target" params="" />
|
<command name="tar" action="no_target" params="" />
|
||||||
|
@ -122,6 +116,8 @@
|
||||||
|
|
||||||
<command name="loot" action="inv_temp_all" params="" />
|
<command name="loot" action="inv_temp_all" params="" />
|
||||||
|
|
||||||
|
<command name="setuiscale" action="set_ui_scale" params="scale=$"/>
|
||||||
|
|
||||||
<command name="mapsearch" action="proc" params="map_search_show_set|+" />
|
<command name="mapsearch" action="proc" params="map_search_show_set|+" />
|
||||||
<command name="mapsearch" action="proc" params="map_search_show" />
|
<command name="mapsearch" action="proc" params="map_search_show" />
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,15 @@
|
||||||
<variable entry="UI:SAVE:MP3_VOLUME"
|
<variable entry="UI:SAVE:MP3_VOLUME"
|
||||||
type="sint64"
|
type="sint64"
|
||||||
value="255" />
|
value="255" />
|
||||||
|
<variable entry="UI:SAVE:MP3_REPEAT"
|
||||||
|
type="sint32"
|
||||||
|
value="1" />
|
||||||
|
<variable entry="UI:SAVE:MP3_SHUFFLE"
|
||||||
|
type="sint32"
|
||||||
|
value="0" />
|
||||||
|
<variable entry="UI:TEMP:MP3_PLAYING"
|
||||||
|
type="sint32"
|
||||||
|
value="0" />
|
||||||
<!--******************-->
|
<!--******************-->
|
||||||
<!--* MP3 PLAYER *-->
|
<!--* MP3 PLAYER *-->
|
||||||
<!--******************-->
|
<!--******************-->
|
||||||
|
@ -31,13 +40,30 @@
|
||||||
<ctrl type="button" id="btn" button_type="toggle_button" sizeref="wh" tx_normal="blank.tga" tx_pushed="blank.tga" tx_over="blank.tga" scale="true"
|
<ctrl type="button" id="btn" button_type="toggle_button" sizeref="wh" tx_normal="blank.tga" tx_pushed="blank.tga" tx_over="blank.tga" scale="true"
|
||||||
color="255 255 255 0" col_pushed="255 255 255 0" col_over="255 255 255 90"
|
color="255 255 255 0" col_pushed="255 255 255 0" col_over="255 255 255 90"
|
||||||
global_color_normal="true" global_color_pushed="true" global_color_over="true"
|
global_color_normal="true" global_color_pushed="true" global_color_over="true"
|
||||||
ondblclick_l="music_player" params_dblclick_l="song=#index" />
|
ondblclick_l="music_player" params_dblclick_l="song=#index" />
|
||||||
|
|
||||||
|
<view type="bitmap" id="bg" posref="MM MM" sizeref="wh" color="200 200 200 50" texture="blank.tga" scale="true" active="false" />
|
||||||
<view type="text" id="title" posref="ML ML" x="0" line_maxw="#line_maxw" fontsize="8" shadow="true" multi_line="true" multi_line_space="0" />
|
<view type="text" id="title" posref="ML ML" x="0" line_maxw="#line_maxw" fontsize="8" shadow="true" multi_line="true" multi_line_space="0" />
|
||||||
<view type="text" id="duration" posref="MR MR" x="0" fontsize="8" shadow="true" color="255 255 255 128" />
|
<view type="text" id="duration" posref="MR MR" x="0" fontsize="8" shadow="true" color="255 255 255 150" />
|
||||||
</group>
|
</group>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<proc id="proc_mp3_toggle_shuffle">
|
||||||
|
<action handler="set" params="dblink=UI:SAVE:MP3_SHUFFLE|value=not(@UI:SAVE:MP3_SHUFFLE)" />
|
||||||
|
<action handler="music_player" params="update_playlist" />
|
||||||
|
</proc>
|
||||||
|
|
||||||
|
<proc id="proc_mp3_update_tooltip">
|
||||||
|
<action handler="lua" params="getUI('ui:interface:mp3_player:controls:but_play').tooltip = i18n.get('uiMP3Play')" cond="eq(@UI:TEMP:MP3_PLAYING,0)" />
|
||||||
|
<action handler="lua" params="getUI('ui:interface:mp3_player:controls:but_play').tooltip = i18n.get('uiMP3Pause')" cond="eq(@UI:TEMP:MP3_PLAYING,1)" />
|
||||||
|
</proc>
|
||||||
|
|
||||||
|
<proc id="proc_mp3_but_play">
|
||||||
|
<action handler="set" params="dblink=UI:TEMP:MP3_PLAYING|value=not(@UI:TEMP:MP3_PLAYING)" />
|
||||||
|
<action handler="music_player" params="play" cond="eq(@UI:TEMP:MP3_PLAYING,1)" />
|
||||||
|
<action handler="music_player" params="pause" cond="eq(@UI:TEMP:MP3_PLAYING,0)" />
|
||||||
|
</proc>
|
||||||
|
|
||||||
<group type="modal"
|
<group type="modal"
|
||||||
id="playlist"
|
id="playlist"
|
||||||
posparent="mp3_player"
|
posparent="mp3_player"
|
||||||
|
@ -82,6 +108,30 @@
|
||||||
hardtext="uiPlaylistRefresh"
|
hardtext="uiPlaylistRefresh"
|
||||||
onclick_l="music_player"
|
onclick_l="music_player"
|
||||||
params_l="play_songs" />
|
params_l="play_songs" />
|
||||||
|
<ctrl style="text_button_header"
|
||||||
|
button_type="toggle_button"
|
||||||
|
id="shuffle"
|
||||||
|
posparent="refresh"
|
||||||
|
posref="ML MR"
|
||||||
|
x="-4"
|
||||||
|
y="0"
|
||||||
|
hardtext="S"
|
||||||
|
onclick_l="proc"
|
||||||
|
params_l="proc_mp3_toggle_shuffle" />
|
||||||
|
<ctrl style="text_button_header"
|
||||||
|
button_type="toggle_button"
|
||||||
|
id="repeat"
|
||||||
|
posparent="shuffle"
|
||||||
|
posref="ML MR"
|
||||||
|
x="-4"
|
||||||
|
y="0"
|
||||||
|
hardtext="R"
|
||||||
|
onclick_l="set"
|
||||||
|
params_l="dblink=UI:SAVE:MP3_REPEAT|value=not(@UI:SAVE:MP3_REPEAT)" />
|
||||||
|
|
||||||
|
<!-- change button state when variable chaanged -->
|
||||||
|
<link expr="@UI:SAVE:MP3_REPEAT" target="repeat:pushed" />
|
||||||
|
<link expr="@UI:SAVE:MP3_SHUFFLE" target="shuffle:pushed" />
|
||||||
|
|
||||||
<group id="content" x="8" y="-24" over="true" sizeref="w" posref="TL TL" child_resize_h="true" child_resize_hmargin="4">
|
<group id="content" x="8" y="-24" over="true" sizeref="w" posref="TL TL" child_resize_h="true" child_resize_hmargin="4">
|
||||||
<group id="songs" x="10" y="0" sizeref="w" posref="TL TL" child_resize_h="true" max_h="215">
|
<group id="songs" x="10" y="0" sizeref="w" posref="TL TL" child_resize_h="true" max_h="215">
|
||||||
|
@ -167,26 +217,30 @@
|
||||||
tooltip="uiMP3Prev" />
|
tooltip="uiMP3Prev" />
|
||||||
<ctrl type="button"
|
<ctrl type="button"
|
||||||
id="but_play"
|
id="but_play"
|
||||||
button_type="push_button"
|
button_type="toggle_button"
|
||||||
posref="MM MM"
|
posref="MM MM"
|
||||||
posparent="slot2"
|
posparent="slot2"
|
||||||
tx_normal="mp3_button_play.tga"
|
tx_normal="mp3_button_play.tga"
|
||||||
tx_pushed="mp3_button_play.tga"
|
tx_pushed="mp3_button_pause.tga"
|
||||||
tx_over="mp3_button_over.tga"
|
tx_over="mp3_button_over.tga"
|
||||||
onclick_l="music_player"
|
onclick_l="proc"
|
||||||
params_l="play"
|
params_l="proc_mp3_but_play"
|
||||||
tooltip="uiMP3Play" />
|
tooltip="uiMP3Play" />
|
||||||
|
<!-- TODO: but_stop is using placeholder texture -->
|
||||||
<ctrl type="button"
|
<ctrl type="button"
|
||||||
id="but_pause"
|
id="but_stop"
|
||||||
button_type="push_button"
|
button_type="push_button"
|
||||||
posref="MM MM"
|
posref="MM MM"
|
||||||
posparent="slot3"
|
posparent="slot3"
|
||||||
tx_normal="mp3_button_pause.tga"
|
tx_normal="w_button_10_choice.tga"
|
||||||
tx_pushed="mp3_button_pause.tga"
|
tx_pushed="w_button_10_choice.tga"
|
||||||
tx_over="mp3_button_over.tga"
|
tx_over="mp3_button_over.tga"
|
||||||
|
scale="true"
|
||||||
|
w="20"
|
||||||
|
h="16"
|
||||||
onclick_l="music_player"
|
onclick_l="music_player"
|
||||||
params_l="pause"
|
params_l="stop"
|
||||||
tooltip="uiMP3Pause" />
|
tooltip="uiMP3Stop" />
|
||||||
<ctrl type="button"
|
<ctrl type="button"
|
||||||
id="but_next"
|
id="but_next"
|
||||||
button_type="push_button"
|
button_type="push_button"
|
||||||
|
@ -276,6 +330,8 @@
|
||||||
posref="TL TL"
|
posref="TL TL"
|
||||||
w="48"
|
w="48"
|
||||||
h="20" />
|
h="20" />
|
||||||
|
|
||||||
|
<link expr="@UI:TEMP:MP3_PLAYING" target="but_play:pushed" action="proc" params="proc_mp3_update_tooltip" />
|
||||||
</group>
|
</group>
|
||||||
<!-- SCREEN -->
|
<!-- SCREEN -->
|
||||||
<group id="screen"
|
<group id="screen"
|
||||||
|
|
|
@ -876,10 +876,17 @@
|
||||||
posparent="lum"
|
posparent="lum"
|
||||||
x="0"
|
x="0"
|
||||||
y="-2" />
|
y="-2" />
|
||||||
|
<instance template="tgcw_scrollbarfloat"
|
||||||
|
id="scale"
|
||||||
|
text="uiInterfaceScale"
|
||||||
|
posref="BL TL"
|
||||||
|
posparent="gam"
|
||||||
|
x="0"
|
||||||
|
y="-2" />
|
||||||
<instance template="tgcw_checkbox"
|
<instance template="tgcw_checkbox"
|
||||||
id="waitvbl"
|
id="waitvbl"
|
||||||
text="uiWaitVBL"
|
text="uiWaitVBL"
|
||||||
posparent="gam"
|
posparent="scale"
|
||||||
posref="BL TL"
|
posref="BL TL"
|
||||||
x="-20"
|
x="-20"
|
||||||
y="-28" />
|
y="-28" />
|
||||||
|
@ -3091,6 +3098,13 @@
|
||||||
realtime="true"
|
realtime="true"
|
||||||
widget="sbfloat"
|
widget="sbfloat"
|
||||||
link="Gamma" />
|
link="Gamma" />
|
||||||
|
<param ui="general:scale:c"
|
||||||
|
type="cfg"
|
||||||
|
realtime="false"
|
||||||
|
ui_view="general:scale:c_res"
|
||||||
|
ui_decimal="2"
|
||||||
|
widget="sbfloat"
|
||||||
|
link="InterfaceScale" />
|
||||||
<param ui="general:waitvbl:c"
|
<param ui="general:waitvbl:c"
|
||||||
type="cfg"
|
type="cfg"
|
||||||
realtime="true"
|
realtime="true"
|
||||||
|
|
|
@ -1042,7 +1042,9 @@
|
||||||
h="24"
|
h="24"
|
||||||
posref="TL TL"
|
posref="TL TL"
|
||||||
x="0"
|
x="0"
|
||||||
y="-4">
|
y="-4"
|
||||||
|
max_w="0"
|
||||||
|
max_sizeref="w">
|
||||||
<ctrl style="tab_button_new"
|
<ctrl style="tab_button_new"
|
||||||
id="tab0"
|
id="tab0"
|
||||||
x="0"
|
x="0"
|
||||||
|
@ -1183,6 +1185,22 @@
|
||||||
texture="blank.tga"
|
texture="blank.tga"
|
||||||
color="166 166 166 255" />
|
color="166 166 166 255" />
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
<!-- scroll target element will be set from c++ code: it does not exist on template build time -->
|
||||||
|
<ctrl type="scroll"
|
||||||
|
id="channel_scroll"
|
||||||
|
vertical="false"
|
||||||
|
align="L"
|
||||||
|
y="-1"
|
||||||
|
h="4"
|
||||||
|
scale="true"
|
||||||
|
posref="BL TL"
|
||||||
|
posparent="header_opened"
|
||||||
|
tx_bottomleft="skin_scroll_l.tga"
|
||||||
|
tx_middle="skin_scroll_h.tga"
|
||||||
|
tx_topright="skin_scroll_r.tga"
|
||||||
|
target="" />
|
||||||
|
|
||||||
<group id="content"
|
<group id="content"
|
||||||
x="0"
|
x="0"
|
||||||
y="0"
|
y="0"
|
||||||
|
@ -3155,4 +3173,13 @@
|
||||||
params="game:chatUrlBrowse()" />
|
params="game:chatUrlBrowse()" />
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
<group type="menu"
|
||||||
|
id="chat_copy_action_menu"
|
||||||
|
extends="base_menu">
|
||||||
|
<action id="copy"
|
||||||
|
name="uiCopy"
|
||||||
|
handler="copy_chat"
|
||||||
|
params="from_modal" />
|
||||||
|
</group>
|
||||||
|
|
||||||
</interface_config>
|
</interface_config>
|
||||||
|
|
42
code/ryzom/client/data/gamedev/interfaces_v3/map.lua
Normal file
42
code/ryzom/client/data/gamedev/interfaces_v3/map.lua
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
--
|
||||||
|
-- custom maps
|
||||||
|
--
|
||||||
|
|
||||||
|
if (game==nil) then
|
||||||
|
game= {};
|
||||||
|
end
|
||||||
|
|
||||||
|
-- alternative textures for maps
|
||||||
|
game.mapTextures = {}
|
||||||
|
-- game.mapTextures["zorai_map.tga"] = "tryker_map.tga"
|
||||||
|
|
||||||
|
-- register alternative texture for map
|
||||||
|
function game:setAltMap(mapName, altMap)
|
||||||
|
self.mapTextures[mapName] = altMap
|
||||||
|
end
|
||||||
|
|
||||||
|
-- remove alternative map texture
|
||||||
|
function game:removeAltMap(mapName)
|
||||||
|
self.mapTextures[mapName] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- map = getUI("ui:interface:map:content:map_content:actual_map")
|
||||||
|
function game:onLoadMap(map)
|
||||||
|
-- debugInfo("onLoadMap(id=".. map.id ..", texture=".. map.texture ..")");
|
||||||
|
|
||||||
|
-- if alt view not enabled
|
||||||
|
if getDbProp("UI:VARIABLES:SHOW_ALT_MAP") == 0 or map:isIsland() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local texture = map.texture
|
||||||
|
if self.mapTextures[texture] ~= nil then
|
||||||
|
-- debugInfo("-- using ".. self.mapTextures[texture] .." for " .. texture)
|
||||||
|
return self.mapTextures[texture]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- register map overrride
|
||||||
|
-- game:setAltMap("fyros_map.tga", "fyros_map_sp.tga")
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
<root id="interface" x="0" y="0" w="800" h="600" active="true" />
|
<root id="interface" x="0" y="0" w="800" h="600" active="true" />
|
||||||
|
|
||||||
|
<lua file="map.lua" />
|
||||||
|
|
||||||
|
<!-- flag for game:onLoadMap() handler to override map texture or not -->
|
||||||
|
<variable entry="UI:VARIABLES:SHOW_ALT_MAP" type="bool" value="0" />
|
||||||
|
|
||||||
<!-- base menu of landmark -->
|
<!-- base menu of landmark -->
|
||||||
<group type="menu" id="land_mark_menu" extends="base_menu">
|
<group type="menu" id="land_mark_menu" extends="base_menu">
|
||||||
|
|
|
@ -2625,6 +2625,7 @@
|
||||||
<!-- * EDIT BOX WIDGET * -->
|
<!-- * EDIT BOX WIDGET * -->
|
||||||
<!-- ********************* -->
|
<!-- ********************* -->
|
||||||
<template name="edit_box_widget"
|
<template name="edit_box_widget"
|
||||||
|
active="true"
|
||||||
posref="TL TL"
|
posref="TL TL"
|
||||||
text_x="0"
|
text_x="0"
|
||||||
text_y="0"
|
text_y="0"
|
||||||
|
@ -2669,8 +2670,10 @@
|
||||||
max_float_prec="5"
|
max_float_prec="5"
|
||||||
tooltip=""
|
tooltip=""
|
||||||
tooltip_parent=""
|
tooltip_parent=""
|
||||||
negative_filter="">
|
negative_filter=""
|
||||||
|
render_layer="0">
|
||||||
<group id="#id"
|
<group id="#id"
|
||||||
|
active="#active"
|
||||||
posref="#posref"
|
posref="#posref"
|
||||||
x="#x"
|
x="#x"
|
||||||
y="#y"
|
y="#y"
|
||||||
|
@ -2679,7 +2682,8 @@
|
||||||
child_resize_hmargin="#child_resize_hmargin"
|
child_resize_hmargin="#child_resize_hmargin"
|
||||||
sizeref="#sizeref"
|
sizeref="#sizeref"
|
||||||
w="#w"
|
w="#w"
|
||||||
h="#h">
|
h="#h"
|
||||||
|
render_layer="#render_layer">
|
||||||
<group type="edit_box"
|
<group type="edit_box"
|
||||||
sizeref="w"
|
sizeref="w"
|
||||||
w="-8"
|
w="-8"
|
||||||
|
@ -2708,7 +2712,8 @@
|
||||||
max_float_prec="#max_float_prec"
|
max_float_prec="#max_float_prec"
|
||||||
tooltip="#tooltip"
|
tooltip="#tooltip"
|
||||||
tooltip_parent="#tooltip_parent"
|
tooltip_parent="#tooltip_parent"
|
||||||
negative_filter="#negative_filter">
|
negative_filter="#negative_filter"
|
||||||
|
render_layer="#render_layer">
|
||||||
<view type="bitmap"
|
<view type="bitmap"
|
||||||
id="bg"
|
id="bg"
|
||||||
scale="true"
|
scale="true"
|
||||||
|
@ -2716,7 +2721,8 @@
|
||||||
h="0"
|
h="0"
|
||||||
w="0"
|
w="0"
|
||||||
texture="#bg_texture"
|
texture="#bg_texture"
|
||||||
inherit_gc_alpha="true" />
|
inherit_gc_alpha="true"
|
||||||
|
render_layer="#render_layer" />
|
||||||
<view id="edit_text"
|
<view id="edit_text"
|
||||||
type="text"
|
type="text"
|
||||||
continuous_update="#continuous_text_update"
|
continuous_update="#continuous_text_update"
|
||||||
|
@ -2733,7 +2739,8 @@
|
||||||
shadow_color="#shadow_color"
|
shadow_color="#shadow_color"
|
||||||
shadow_outline="#shadow_outline"
|
shadow_outline="#shadow_outline"
|
||||||
hardtext=""
|
hardtext=""
|
||||||
global_color="false" />
|
global_color="false"
|
||||||
|
render_layer="#render_layer" />
|
||||||
</group>
|
</group>
|
||||||
<!-- border around the list -->
|
<!-- border around the list -->
|
||||||
<view type="bitmap"
|
<view type="bitmap"
|
||||||
|
@ -2741,25 +2748,29 @@
|
||||||
texture="W_box_top_left.tga"
|
texture="W_box_top_left.tga"
|
||||||
posparent="eb"
|
posparent="eb"
|
||||||
posref="TL BR"
|
posref="TL BR"
|
||||||
inherit_gc_alpha="true" />
|
inherit_gc_alpha="true"
|
||||||
|
render_layer="#render_layer" />
|
||||||
<view type="bitmap"
|
<view type="bitmap"
|
||||||
id="trb"
|
id="trb"
|
||||||
texture="W_box_top_right.tga"
|
texture="W_box_top_right.tga"
|
||||||
posparent="eb"
|
posparent="eb"
|
||||||
posref="TR BL"
|
posref="TR BL"
|
||||||
inherit_gc_alpha="true" />
|
inherit_gc_alpha="true"
|
||||||
|
render_layer="#render_layer" />
|
||||||
<view type="bitmap"
|
<view type="bitmap"
|
||||||
id="brb"
|
id="brb"
|
||||||
texture="W_box_bot_right.tga"
|
texture="W_box_bot_right.tga"
|
||||||
posparent="eb"
|
posparent="eb"
|
||||||
posref="BR TL"
|
posref="BR TL"
|
||||||
inherit_gc_alpha="true" />
|
inherit_gc_alpha="true"
|
||||||
|
render_layer="#render_layer" />
|
||||||
<view type="bitmap"
|
<view type="bitmap"
|
||||||
id="blb"
|
id="blb"
|
||||||
texture="W_box_bot_left.tga"
|
texture="W_box_bot_left.tga"
|
||||||
posparent="eb"
|
posparent="eb"
|
||||||
posref="BL TR"
|
posref="BL TR"
|
||||||
inherit_gc_alpha="true" />
|
inherit_gc_alpha="true"
|
||||||
|
render_layer="#render_layer" />
|
||||||
<view type="bitmap"
|
<view type="bitmap"
|
||||||
id="tb"
|
id="tb"
|
||||||
texture="W_box_top.tga"
|
texture="W_box_top.tga"
|
||||||
|
@ -2769,7 +2780,8 @@
|
||||||
sizeref="w"
|
sizeref="w"
|
||||||
w="0"
|
w="0"
|
||||||
h="4"
|
h="4"
|
||||||
inherit_gc_alpha="true" />
|
inherit_gc_alpha="true"
|
||||||
|
render_layer="#render_layer" />
|
||||||
<view type="bitmap"
|
<view type="bitmap"
|
||||||
id="bb"
|
id="bb"
|
||||||
texture="W_box_bot.tga"
|
texture="W_box_bot.tga"
|
||||||
|
@ -2779,7 +2791,8 @@
|
||||||
sizeref="w"
|
sizeref="w"
|
||||||
w="0"
|
w="0"
|
||||||
h="4"
|
h="4"
|
||||||
inherit_gc_alpha="true" />
|
inherit_gc_alpha="true"
|
||||||
|
render_layer="#render_layer" />
|
||||||
<view type="bitmap"
|
<view type="bitmap"
|
||||||
id="lb"
|
id="lb"
|
||||||
texture="W_box_left.tga"
|
texture="W_box_left.tga"
|
||||||
|
@ -2789,7 +2802,8 @@
|
||||||
sizeref="h"
|
sizeref="h"
|
||||||
h="0"
|
h="0"
|
||||||
w="4"
|
w="4"
|
||||||
inherit_gc_alpha="true" />
|
inherit_gc_alpha="true"
|
||||||
|
render_layer="#render_layer" />
|
||||||
<view type="bitmap"
|
<view type="bitmap"
|
||||||
id="rb"
|
id="rb"
|
||||||
texture="W_box_right.tga"
|
texture="W_box_right.tga"
|
||||||
|
@ -2799,7 +2813,8 @@
|
||||||
sizeref="h"
|
sizeref="h"
|
||||||
h="0"
|
h="0"
|
||||||
w="4"
|
w="4"
|
||||||
inherit_gc_alpha="true" />
|
inherit_gc_alpha="true"
|
||||||
|
render_layer="#render_layer" />
|
||||||
</group>
|
</group>
|
||||||
</template>
|
</template>
|
||||||
<!-- ******************************* -->
|
<!-- ******************************* -->
|
||||||
|
@ -6337,6 +6352,7 @@
|
||||||
x="0"
|
x="0"
|
||||||
y="0"
|
y="0"
|
||||||
posref="BL BL"
|
posref="BL BL"
|
||||||
|
posparent=""
|
||||||
dblink=""
|
dblink=""
|
||||||
texture=""
|
texture=""
|
||||||
tooltip=""
|
tooltip=""
|
||||||
|
@ -6345,6 +6361,7 @@
|
||||||
id="but_#id"
|
id="but_#id"
|
||||||
button_type="toggle_button"
|
button_type="toggle_button"
|
||||||
posref="#posref"
|
posref="#posref"
|
||||||
|
posparent="but_#posparent"
|
||||||
x="#x"
|
x="#x"
|
||||||
y="#y"
|
y="#y"
|
||||||
tx_normal="w_button_filter_off.tga"
|
tx_normal="w_button_filter_off.tga"
|
||||||
|
@ -6371,6 +6388,7 @@
|
||||||
x="0"
|
x="0"
|
||||||
y="0"
|
y="0"
|
||||||
posref="BL BL"
|
posref="BL BL"
|
||||||
|
posparent=""
|
||||||
dblink=""
|
dblink=""
|
||||||
texture=""
|
texture=""
|
||||||
tooltip=""
|
tooltip=""
|
||||||
|
@ -6379,6 +6397,7 @@
|
||||||
id="but_#id"
|
id="but_#id"
|
||||||
button_type="toggle_button"
|
button_type="toggle_button"
|
||||||
posref="#posref"
|
posref="#posref"
|
||||||
|
posparent="but_#posparent"
|
||||||
x="#x"
|
x="#x"
|
||||||
y="#y"
|
y="#y"
|
||||||
tx_normal="w_button_filter_off.tga"
|
tx_normal="w_button_filter_off.tga"
|
||||||
|
@ -6553,83 +6572,109 @@
|
||||||
texture="W_line_hor.tga" />
|
texture="W_line_hor.tga" />
|
||||||
<link expr="eq(@UI:SAVE:#inv_type:ICON_LIST, 0)"
|
<link expr="eq(@UI:SAVE:#inv_type:ICON_LIST, 0)"
|
||||||
target="bag_list:active,sep2:active" />
|
target="bag_list:active,sep2:active" />
|
||||||
|
<!-- details -->
|
||||||
|
<instance template="tinv_item_list_icon_swap"
|
||||||
|
id="detail"
|
||||||
|
x="-2"
|
||||||
|
y="10"
|
||||||
|
posref="BR MR"
|
||||||
|
dblink="UI:SAVE:#inv_type:ICON_LIST"
|
||||||
|
texture="details_on.tga"
|
||||||
|
tooltip="uittDetail" />
|
||||||
|
<link expr="ifthenelse(@UI:SAVE:#inv_type:ICON_LIST, 'details_off.tga', 'details_on.tga')"
|
||||||
|
target="bit_detail:texture" />
|
||||||
|
<!-- filter -->
|
||||||
<instance template="tinv_item_list_filter"
|
<instance template="tinv_item_list_filter"
|
||||||
id="filter_tp"
|
id="filter_tp"
|
||||||
x="-35"
|
x="-8"
|
||||||
y="1"
|
posref="ML MR"
|
||||||
posref="BR BR"
|
posparent="detail"
|
||||||
inv_type="#inv_type"
|
inv_type="#inv_type"
|
||||||
dblink="UI:SAVE:#inv_type:FILTER_TP"
|
dblink="UI:SAVE:#inv_type:FILTER_TP"
|
||||||
texture="filter_tp.tga"
|
texture="filter_tp.tga"
|
||||||
tooltip="uittFilterTP" />
|
tooltip="uittFilterTP" />
|
||||||
<instance template="tinv_item_list_filter"
|
<instance template="tinv_item_list_filter"
|
||||||
id="filter_missmp"
|
id="filter_missmp"
|
||||||
x="-60"
|
x="-2"
|
||||||
y="1"
|
posref="ML MR"
|
||||||
posref="BR BR"
|
posparent="filter_tp"
|
||||||
inv_type="#inv_type"
|
inv_type="#inv_type"
|
||||||
dblink="UI:SAVE:#inv_type:FILTER_MISSMP"
|
dblink="UI:SAVE:#inv_type:FILTER_MISSMP"
|
||||||
texture="filter_mission.tga"
|
texture="filter_mission.tga"
|
||||||
tooltip="uittFilterMissMP" />
|
tooltip="uittFilterMissMP" />
|
||||||
<instance template="tinv_item_list_filter"
|
<instance template="tinv_item_list_filter"
|
||||||
id="filter_mp"
|
id="filter_mp"
|
||||||
x="-85"
|
x="-2"
|
||||||
y="1"
|
posref="ML MR"
|
||||||
posref="BR BR"
|
posparent="filter_missmp"
|
||||||
inv_type="#inv_type"
|
inv_type="#inv_type"
|
||||||
dblink="UI:SAVE:#inv_type:FILTER_MP"
|
dblink="UI:SAVE:#inv_type:FILTER_MP"
|
||||||
texture="filter_mps.tga"
|
texture="filter_mps.tga"
|
||||||
tooltip="uittFilterMP" />
|
tooltip="uittFilterMP" />
|
||||||
<instance template="tinv_item_list_filter"
|
<instance template="tinv_item_list_filter"
|
||||||
id="filter_tool"
|
id="filter_tool"
|
||||||
x="-110"
|
x="-2"
|
||||||
y="1"
|
posref="ML MR"
|
||||||
posref="BR BR"
|
posparent="filter_mp"
|
||||||
inv_type="#inv_type"
|
inv_type="#inv_type"
|
||||||
dblink="UI:SAVE:#inv_type:FILTER_TOOL"
|
dblink="UI:SAVE:#inv_type:FILTER_TOOL"
|
||||||
texture="filter_tools.tga"
|
texture="filter_tools.tga"
|
||||||
tooltip="uittFilterTool" />
|
tooltip="uittFilterTool" />
|
||||||
<instance template="tinv_item_list_filter"
|
<instance template="tinv_item_list_filter"
|
||||||
id="filter_weapon"
|
id="filter_weapon"
|
||||||
x="-135"
|
x="-2"
|
||||||
y="1"
|
posref="ML MR"
|
||||||
posref="BR BR"
|
posparent="filter_tool"
|
||||||
inv_type="#inv_type"
|
inv_type="#inv_type"
|
||||||
dblink="UI:SAVE:#inv_type:FILTER_WEAPON"
|
dblink="UI:SAVE:#inv_type:FILTER_WEAPON"
|
||||||
texture="filter_weapon.tga"
|
texture="filter_weapon.tga"
|
||||||
tooltip="uittFilterWeapon" />
|
tooltip="uittFilterWeapon" />
|
||||||
<instance template="tinv_item_list_filter"
|
<instance template="tinv_item_list_filter"
|
||||||
id="filter_armor"
|
id="filter_armor"
|
||||||
x="-160"
|
x="-2"
|
||||||
y="1"
|
posref="ML MR"
|
||||||
posref="BR BR"
|
posparent="filter_weapon"
|
||||||
inv_type="#inv_type"
|
inv_type="#inv_type"
|
||||||
dblink="UI:SAVE:#inv_type:FILTER_ARMOR"
|
dblink="UI:SAVE:#inv_type:FILTER_ARMOR"
|
||||||
texture="filter_armor.tga"
|
texture="filter_armor.tga"
|
||||||
tooltip="uittFilterArmor" />
|
tooltip="uittFilterArmor" />
|
||||||
|
<!-- search -->
|
||||||
|
<ctrl type="button"
|
||||||
|
id="but_inv_search"
|
||||||
|
button_type="toggle_button"
|
||||||
|
x="-2"
|
||||||
|
posref="ML MR"
|
||||||
|
posparent="but_filter_armor"
|
||||||
|
tx_normal="w_button_filter_off.tga"
|
||||||
|
tx_pushed="w_button_filter_on.tga"
|
||||||
|
tx_over=""
|
||||||
|
tooltip="uittInventorySearch"
|
||||||
|
onclick_l="inv_search_button"
|
||||||
|
params_l="inv_query_eb" />
|
||||||
|
<view type="bitmap"
|
||||||
|
id="bit_inv_search"
|
||||||
|
posref="MM MM"
|
||||||
|
posparent="but_inv_search"
|
||||||
|
texture="w_help_1.tga"
|
||||||
|
global_color="false"
|
||||||
|
color="255 255 255 150" />
|
||||||
<instance template="edit_box_widget"
|
<instance template="edit_box_widget"
|
||||||
id="inv_query_eb"
|
id="inv_query_eb"
|
||||||
posref="BR BR"
|
active="false"
|
||||||
x="-190"
|
posref="TR BR"
|
||||||
y="1"
|
posparent="but_detail"
|
||||||
|
x="0"
|
||||||
|
y="8"
|
||||||
w="100"
|
w="100"
|
||||||
|
render_layer="9"
|
||||||
clear_on_escape="true"
|
clear_on_escape="true"
|
||||||
enter_recover_focus="false"
|
enter_recover_focus="false"
|
||||||
max_num_chars="20"
|
max_num_chars="20"
|
||||||
max_historic="0"
|
max_historic="0"
|
||||||
onenter="inv_set_search"
|
onenter="inv_set_search"
|
||||||
onchange="inv_set_search" onchange_params="#inv_type" />
|
onchange="inv_set_search"
|
||||||
<!-- details -->
|
on_focus_lost="inv_search_unfocus"
|
||||||
<instance template="tinv_item_list_icon_swap"
|
on_focus_lost_params="but_inv_search" />
|
||||||
id="detail"
|
|
||||||
x="-4"
|
|
||||||
y="1"
|
|
||||||
posref="BR BR"
|
|
||||||
dblink="UI:SAVE:#inv_type:ICON_LIST"
|
|
||||||
texture="details_on.tga"
|
|
||||||
tooltip="uittDetail" />
|
|
||||||
<link expr="ifthenelse(@UI:SAVE:#inv_type:ICON_LIST, 'details_off.tga', 'details_on.tga')"
|
|
||||||
target="bit_detail:texture" />
|
|
||||||
</group>
|
</group>
|
||||||
</template>
|
</template>
|
||||||
<!-- Link to trig brick action message. don't play when 0 (avoid flying text at startup) -->
|
<!-- Link to trig brick action message. don't play when 0 (avoid flying text at startup) -->
|
||||||
|
|
|
@ -300,6 +300,12 @@ CClientConfig::CClientConfig()
|
||||||
Luminosity = 0.f; // Default Monitor Luminosity.
|
Luminosity = 0.f; // Default Monitor Luminosity.
|
||||||
Gamma = 0.f; // Default Monitor Gamma.
|
Gamma = 0.f; // Default Monitor Gamma.
|
||||||
|
|
||||||
|
InterfaceScale = 1.0f; // Resize UI
|
||||||
|
InterfaceScale_min = 0.8f;
|
||||||
|
InterfaceScale_max = 2.0f;
|
||||||
|
InterfaceScale_step = 0.05;
|
||||||
|
BilinearUI = true;
|
||||||
|
|
||||||
VREnable = false;
|
VREnable = false;
|
||||||
VRDisplayDevice = "Auto";
|
VRDisplayDevice = "Auto";
|
||||||
VRDisplayDeviceId = "";
|
VRDisplayDeviceId = "";
|
||||||
|
@ -424,6 +430,7 @@ CClientConfig::CClientConfig()
|
||||||
|
|
||||||
WebIgMainDomain = "atys.ryzom.com";
|
WebIgMainDomain = "atys.ryzom.com";
|
||||||
WebIgTrustedDomains.push_back(WebIgMainDomain);
|
WebIgTrustedDomains.push_back(WebIgMainDomain);
|
||||||
|
WebIgNotifInterval = 10; // time in minutes
|
||||||
|
|
||||||
CurlMaxConnections = 2;
|
CurlMaxConnections = 2;
|
||||||
CurlCABundle.clear();
|
CurlCABundle.clear();
|
||||||
|
@ -834,6 +841,13 @@ void CClientConfig::setValues()
|
||||||
READ_FLOAT_FV(Luminosity)
|
READ_FLOAT_FV(Luminosity)
|
||||||
// Gamma
|
// Gamma
|
||||||
READ_FLOAT_FV(Gamma)
|
READ_FLOAT_FV(Gamma)
|
||||||
|
// UI scaling
|
||||||
|
READ_FLOAT_FV(InterfaceScale);
|
||||||
|
READ_FLOAT_FV(InterfaceScale_min);
|
||||||
|
READ_FLOAT_FV(InterfaceScale_max);
|
||||||
|
READ_FLOAT_FV(InterfaceScale_step);
|
||||||
|
clamp(ClientCfg.InterfaceScale, ClientCfg.InterfaceScale_min, ClientCfg.InterfaceScale_max);
|
||||||
|
READ_BOOL_FV(BilinearUI);
|
||||||
// 3D Driver
|
// 3D Driver
|
||||||
varPtr = ClientCfg.ConfigFile.getVarPtr ("Driver3D");
|
varPtr = ClientCfg.ConfigFile.getVarPtr ("Driver3D");
|
||||||
if (varPtr)
|
if (varPtr)
|
||||||
|
@ -1074,6 +1088,7 @@ void CClientConfig::setValues()
|
||||||
// WEBIG //
|
// WEBIG //
|
||||||
READ_STRING_FV(WebIgMainDomain);
|
READ_STRING_FV(WebIgMainDomain);
|
||||||
READ_STRINGVECTOR_FV(WebIgTrustedDomains);
|
READ_STRINGVECTOR_FV(WebIgTrustedDomains);
|
||||||
|
READ_INT_FV(WebIgNotifInterval);
|
||||||
READ_INT_FV(CurlMaxConnections);
|
READ_INT_FV(CurlMaxConnections);
|
||||||
if (ClientCfg.CurlMaxConnections < 0)
|
if (ClientCfg.CurlMaxConnections < 0)
|
||||||
ClientCfg.CurlMaxConnections = 2;
|
ClientCfg.CurlMaxConnections = 2;
|
||||||
|
|
|
@ -46,7 +46,6 @@ using NLMISC::CVector;
|
||||||
using NLMISC::CRGBA;
|
using NLMISC::CRGBA;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------
|
//---------------------------------------------------
|
||||||
// CClientConfig :
|
// CClientConfig :
|
||||||
// Struct to manage a config file for the client.
|
// Struct to manage a config file for the client.
|
||||||
|
@ -146,6 +145,13 @@ struct CClientConfig
|
||||||
/// Monitor Gamma [-1 ~ 1], default 0
|
/// Monitor Gamma [-1 ~ 1], default 0
|
||||||
float Gamma;
|
float Gamma;
|
||||||
|
|
||||||
|
// UI scaling
|
||||||
|
float InterfaceScale;
|
||||||
|
float InterfaceScale_min;
|
||||||
|
float InterfaceScale_max;
|
||||||
|
float InterfaceScale_step;
|
||||||
|
bool BilinearUI;
|
||||||
|
|
||||||
// VR
|
// VR
|
||||||
bool VREnable;
|
bool VREnable;
|
||||||
std::string VRDisplayDevice;
|
std::string VRDisplayDevice;
|
||||||
|
@ -306,6 +312,7 @@ struct CClientConfig
|
||||||
|
|
||||||
std::string WebIgMainDomain;
|
std::string WebIgMainDomain;
|
||||||
std::vector<string> WebIgTrustedDomains;
|
std::vector<string> WebIgTrustedDomains;
|
||||||
|
uint WebIgNotifInterval; // value in minutes for notification thread
|
||||||
|
|
||||||
sint32 CurlMaxConnections;
|
sint32 CurlMaxConnections;
|
||||||
string CurlCABundle;
|
string CurlCABundle;
|
||||||
|
|
|
@ -475,14 +475,17 @@ bool randomFromString(std::string const& str, sint16& val, sint16 min = -32768,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NLMISC_COMMAND(random, "Roll a dice and say the result around","[<min>] <max>")
|
NLMISC_COMMAND(random, "Roll a dice and say the result around","[<min>] <max> [h|ide]")
|
||||||
{
|
{
|
||||||
// Check parameters.
|
// Check parameters.
|
||||||
if (args.size()<1 || args.size()>2)
|
if (args.size() < 1 || args.size() > 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
sint16 min = 1;
|
sint16 min = 1;
|
||||||
sint16 max;
|
sint16 max;
|
||||||
|
|
||||||
|
bool hide = args[args.size()-1][0] == 'h';
|
||||||
|
|
||||||
if (!randomFromString(args[0], max))
|
if (!randomFromString(args[0], max))
|
||||||
{
|
{
|
||||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
||||||
|
@ -491,13 +494,13 @@ NLMISC_COMMAND(random, "Roll a dice and say the result around","[<min>] <max>")
|
||||||
pIM->displaySystemInfo(msg);
|
pIM->displaySystemInfo(msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (args.size()==2)
|
if (args.size() > 1 && args[1][0] != 'h')
|
||||||
{
|
{
|
||||||
if (!randomFromString(args[1], min))
|
if (!randomFromString(args[1], min))
|
||||||
{
|
{
|
||||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
||||||
ucstring msg = CI18N::get("uiRandomBadParameter");
|
ucstring msg = CI18N::get("uiRandomBadParameter");
|
||||||
strFindReplace(msg, "%s", args[0] );
|
strFindReplace(msg, "%s", args[1] );
|
||||||
pIM->displaySystemInfo(msg);
|
pIM->displaySystemInfo(msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -506,7 +509,7 @@ NLMISC_COMMAND(random, "Roll a dice and say the result around","[<min>] <max>")
|
||||||
std::swap(min, max);
|
std::swap(min, max);
|
||||||
|
|
||||||
if (UserEntity != NULL)
|
if (UserEntity != NULL)
|
||||||
UserEntity->rollDice(min, max);
|
UserEntity->rollDice(min, max, hide);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,6 +227,9 @@ void connectionRestoreVideoMode ()
|
||||||
SetMouseCursor ();
|
SetMouseCursor ();
|
||||||
SetMouseSpeed (ClientCfg.CursorSpeed);
|
SetMouseSpeed (ClientCfg.CursorSpeed);
|
||||||
SetMouseAcceleration (ClientCfg.CursorAcceleration);
|
SetMouseAcceleration (ClientCfg.CursorAcceleration);
|
||||||
|
|
||||||
|
// Restore user UI scaling
|
||||||
|
CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -262,6 +265,8 @@ void setOutGameFullScreen()
|
||||||
InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached);
|
InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable auto scaling in login window
|
||||||
|
CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -427,6 +432,9 @@ bool connection (const string &cookie, const string &fsaddr)
|
||||||
|
|
||||||
firstConnection = false;
|
firstConnection = false;
|
||||||
|
|
||||||
|
// Restore user UI scaling
|
||||||
|
CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
|
||||||
|
|
||||||
// Disable inputs
|
// Disable inputs
|
||||||
Actions.enable(false);
|
Actions.enable(false);
|
||||||
EditActions.enable(false);
|
EditActions.enable(false);
|
||||||
|
@ -558,6 +566,9 @@ bool reconnection()
|
||||||
InterfaceState = globalMenu();
|
InterfaceState = globalMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore user UI scaling
|
||||||
|
CViewRenderer::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
|
||||||
|
|
||||||
// Disable inputs
|
// Disable inputs
|
||||||
Actions.enable(false);
|
Actions.enable(false);
|
||||||
EditActions.enable(false);
|
EditActions.enable(false);
|
||||||
|
|
|
@ -488,8 +488,177 @@ CContinent *CContinentManager::get(const std::string &contName)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CContinentManager::serialUserLandMarks(NLMISC::IStream &f)
|
void CContinentManager::writeTo(xmlNodePtr node) const
|
||||||
{
|
{
|
||||||
|
// <landmarks continent="bagne" type="user" />
|
||||||
|
// <landmarks continent="tryker" type="user">
|
||||||
|
// <landmark type="0" x="0" y="0" title="landmark title"/>
|
||||||
|
// ...
|
||||||
|
// </landmarks>
|
||||||
|
for(TContinents::const_iterator it = _Continents.begin(); it != _Continents.end(); ++it)
|
||||||
|
{
|
||||||
|
std::string name = it->first;
|
||||||
|
xmlNodePtr contNode = xmlNewChild(node, NULL, (const xmlChar*)"landmarks", NULL);
|
||||||
|
xmlSetProp(contNode, (const xmlChar*)"continent", (const xmlChar*)name.c_str());
|
||||||
|
xmlSetProp(contNode, (const xmlChar*)"type", (const xmlChar*)"user");
|
||||||
|
|
||||||
|
if (it->second && it->second->UserLandMarks.size() > 0)
|
||||||
|
{
|
||||||
|
for(uint i = 0; i< it->second->UserLandMarks.size(); ++i)
|
||||||
|
{
|
||||||
|
const CUserLandMark& lm = it->second->UserLandMarks[i];
|
||||||
|
|
||||||
|
xmlNodePtr lmNode = xmlNewChild(contNode, NULL, (const xmlChar*)"landmark", NULL);
|
||||||
|
xmlSetProp(lmNode, (const xmlChar*)"type", (const xmlChar*)toString("%d", (uint32)lm.Type).c_str());
|
||||||
|
xmlSetProp(lmNode, (const xmlChar*)"x", (const xmlChar*)toString("%.2f", lm.Pos.x).c_str());
|
||||||
|
xmlSetProp(lmNode, (const xmlChar*)"y", (const xmlChar*)toString("%.2f", lm.Pos.y).c_str());
|
||||||
|
|
||||||
|
// sanitize ascii control chars
|
||||||
|
// libxml will encode other special chars itself
|
||||||
|
std::string title = lm.Title.toUtf8();
|
||||||
|
for(uint i = 0; i< title.size(); i++)
|
||||||
|
{
|
||||||
|
if (title[i] >= '\0' && title[i] < ' ' && title[i] != '\n' && title[i] != '\t')
|
||||||
|
{
|
||||||
|
title[i] = '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlSetProp(lmNode, (const xmlChar*)"title", (const xmlChar*)title.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CContinentManager::readFrom(xmlNodePtr node)
|
||||||
|
{
|
||||||
|
CXMLAutoPtr prop;
|
||||||
|
|
||||||
|
// <landmarks continent="bagne" type="user">
|
||||||
|
// <landmark type="0" x="0" y="0" title="landmark title" />
|
||||||
|
// ...
|
||||||
|
// </landmarks>
|
||||||
|
std::string continent;
|
||||||
|
prop = xmlGetProp(node, (xmlChar*)"continent");
|
||||||
|
if (!prop)
|
||||||
|
{
|
||||||
|
nlwarning("Ignore landmarks group 'continent' attribute.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
continent = (const char*)prop;
|
||||||
|
|
||||||
|
TContinents::iterator itContinent = _Continents.find(continent);
|
||||||
|
if (itContinent == _Continents.end() || !itContinent->second)
|
||||||
|
{
|
||||||
|
nlwarning("Ignore landmarks group with unknown 'continent' '%s'", continent.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string lmtype;
|
||||||
|
prop = xmlGetProp(node, (xmlChar*)"type");
|
||||||
|
if (!prop)
|
||||||
|
{
|
||||||
|
nlwarning("Ignore landmarks group without 'type' attribute.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lmtype = toLower((const char*)prop);
|
||||||
|
if (lmtype != "user")
|
||||||
|
{
|
||||||
|
nlwarning("Ignore landmarks group with type '%s', expected 'user'.", lmtype.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->children;
|
||||||
|
while(node)
|
||||||
|
{
|
||||||
|
if (stricmp((char*)node->name, "landmark") != 0)
|
||||||
|
{
|
||||||
|
nlwarning("Ignore invalid node '%s' under landmarks group", (const char*)node->name);
|
||||||
|
|
||||||
|
node = node->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add = true;
|
||||||
|
CUserLandMark lm;
|
||||||
|
|
||||||
|
prop = xmlGetProp(node, (xmlChar*)"type");
|
||||||
|
if (prop)
|
||||||
|
fromString((const char*)prop, lm.Type);
|
||||||
|
else
|
||||||
|
nlwarning("Using default value for landmark type");
|
||||||
|
|
||||||
|
prop = xmlGetProp(node, (xmlChar*)"x");
|
||||||
|
if (prop)
|
||||||
|
{
|
||||||
|
fromString((const char*)prop, lm.Pos.x);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("Landmark missing 'x' attribute");
|
||||||
|
add = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop = xmlGetProp(node, (xmlChar*)"y");
|
||||||
|
if (prop)
|
||||||
|
{
|
||||||
|
fromString((const char*)prop, lm.Pos.y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("Landmark missing 'y' attribute");
|
||||||
|
add = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop = xmlGetProp(node, (xmlChar*)"title");
|
||||||
|
if (prop)
|
||||||
|
{
|
||||||
|
lm.Title.fromUtf8((const char*)prop);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("Landmark missing 'title' attribute");
|
||||||
|
add = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add)
|
||||||
|
{
|
||||||
|
// before adding, check for duplicate
|
||||||
|
// duplicates might be read from .icfg before .xml is read
|
||||||
|
add = true;
|
||||||
|
for(uint i = 0; i< itContinent->second->UserLandMarks.size(); ++i)
|
||||||
|
{
|
||||||
|
const CUserLandMark& test = itContinent->second->UserLandMarks[i];
|
||||||
|
uint xdiff = abs(test.Pos.x - lm.Pos.x) * 100;
|
||||||
|
uint ydiff = abs(test.Pos.y - lm.Pos.y) * 100;
|
||||||
|
if (xdiff == 0 && ydiff == 0)
|
||||||
|
{
|
||||||
|
add = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add)
|
||||||
|
{
|
||||||
|
itContinent->second->UserLandMarks.push_back(lm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("Ignore landmark with duplicate pos (continent:'%s', x:%.2f, y:%.2f, type:%d, title:'%s')", continent.c_str(), lm.Pos.x, lm.Pos.y, (uint8)lm.Type, lm.Title.toUtf8().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("Landmark not added");
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CContinentManager::serialUserLandMarks(NLMISC::IStream &f)
|
||||||
|
{
|
||||||
|
uint32 totalLandmarks = 0;
|
||||||
|
|
||||||
f.serialVersion(1);
|
f.serialVersion(1);
|
||||||
if (!f.isReading())
|
if (!f.isReading())
|
||||||
{
|
{
|
||||||
|
@ -502,6 +671,7 @@ void CContinentManager::serialUserLandMarks(NLMISC::IStream &f)
|
||||||
if (it->second)
|
if (it->second)
|
||||||
{
|
{
|
||||||
f.serialCont(it->second->UserLandMarks);
|
f.serialCont(it->second->UserLandMarks);
|
||||||
|
totalLandmarks += it->second->UserLandMarks.size();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -522,6 +692,7 @@ void CContinentManager::serialUserLandMarks(NLMISC::IStream &f)
|
||||||
if (it != _Continents.end() && it->second)
|
if (it != _Continents.end() && it->second)
|
||||||
{
|
{
|
||||||
f.serialCont(it->second->UserLandMarks);
|
f.serialCont(it->second->UserLandMarks);
|
||||||
|
totalLandmarks += it->second->UserLandMarks.size();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -530,6 +701,8 @@ void CContinentManager::serialUserLandMarks(NLMISC::IStream &f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return totalLandmarks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -109,8 +109,13 @@ public:
|
||||||
|
|
||||||
const std::string &getCurrentContinentSelectName();
|
const std::string &getCurrentContinentSelectName();
|
||||||
|
|
||||||
|
// load / save all user landmarks in xml format
|
||||||
|
void writeTo(xmlNodePtr node) const;
|
||||||
|
void readFrom(xmlNodePtr node);
|
||||||
|
|
||||||
// load / saves all user landMarks
|
// load / saves all user landMarks
|
||||||
void serialUserLandMarks(NLMISC::IStream &f);
|
// \return number of landmarks loaded or saved
|
||||||
|
uint32 serialUserLandMarks(NLMISC::IStream &f);
|
||||||
|
|
||||||
// rebuild visible landmarks on current map
|
// rebuild visible landmarks on current map
|
||||||
void updateUserLandMarks();
|
void updateUserLandMarks();
|
||||||
|
|
|
@ -2334,7 +2334,63 @@ CEntityCL *CEntityManager::getEntityByName (uint32 stringId) const
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
|
CEntityCL *CEntityManager::getEntityByKeywords (const std::vector<ucstring> &keywords, bool onlySelectable) const
|
||||||
|
{
|
||||||
|
if (keywords.empty()) return NULL;
|
||||||
|
|
||||||
|
std::vector<ucstring> lcKeywords;
|
||||||
|
lcKeywords.resize(keywords.size());
|
||||||
|
for(uint k = 0; k < keywords.size(); k++)
|
||||||
|
{
|
||||||
|
lcKeywords[k] = toLower(keywords[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NLMISC::CVectorD &userPosD = UserEntity->pos();
|
||||||
|
const uint count = (uint)_Entities.size();
|
||||||
|
uint selectedEntityId = 0;
|
||||||
|
float selectedEntityDist = FLT_MAX;
|
||||||
|
for(uint i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
if (!_Entities[i]) continue;
|
||||||
|
|
||||||
|
if (onlySelectable && !_Entities[i]->properties().selectable()) continue;
|
||||||
|
|
||||||
|
ucstring lcName;
|
||||||
|
lcName = toLower(_Entities[i]->getDisplayName());
|
||||||
|
if (lcName.empty()) continue;
|
||||||
|
|
||||||
|
bool match = true;
|
||||||
|
for (uint k = 0; k < lcKeywords.size(); ++k)
|
||||||
|
{
|
||||||
|
if (lcName.find(lcKeywords[k]) == ucstring::npos)
|
||||||
|
{
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match)
|
||||||
|
{
|
||||||
|
const NLMISC::CVectorD &targetPosD = _Entities[i]->pos();
|
||||||
|
|
||||||
|
float deltaX = (float) targetPosD.x - (float) userPosD.x;
|
||||||
|
float deltaY = (float) targetPosD.y - (float) userPosD.y;
|
||||||
|
float dist = (float)sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||||
|
if (dist < selectedEntityDist)
|
||||||
|
{
|
||||||
|
selectedEntityDist = dist;
|
||||||
|
selectedEntityId = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedEntityDist != FLT_MAX)
|
||||||
|
return _Entities[selectedEntityId];
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------
|
||||||
CEntityCL *CEntityManager::getEntityByName (const ucstring &name, bool caseSensitive, bool complete) const
|
CEntityCL *CEntityManager::getEntityByName (const ucstring &name, bool caseSensitive, bool complete) const
|
||||||
{
|
{
|
||||||
ucstring source = name;
|
ucstring source = name;
|
||||||
|
|
|
@ -302,6 +302,12 @@ public:
|
||||||
* \param complete : if true, the name must match the full name of the entity.
|
* \param complete : if true, the name must match the full name of the entity.
|
||||||
*/
|
*/
|
||||||
CEntityCL *getEntityByName (const ucstring &name, bool caseSensitive, bool complete) const;
|
CEntityCL *getEntityByName (const ucstring &name, bool caseSensitive, bool complete) const;
|
||||||
|
/**
|
||||||
|
* Case insensitive match against entity name. All listed keywords must match.
|
||||||
|
* \param keywords to match
|
||||||
|
* \param onlySelectable : if true, match only entity that can be selected
|
||||||
|
*/
|
||||||
|
CEntityCL *getEntityByKeywords (const std::vector<ucstring> &keywords, bool onlySelectable) const;
|
||||||
CEntityCL *getEntityBySheetName (const std::string &sheet) const;
|
CEntityCL *getEntityBySheetName (const std::string &sheet) const;
|
||||||
/// Get an entity by dataset index. Returns NULL if the entity is not found.
|
/// Get an entity by dataset index. Returns NULL if the entity is not found.
|
||||||
CEntityCL *getEntityByCompressedIndex(TDataSetIndex compressedIndex) const;
|
CEntityCL *getEntityByCompressedIndex(TDataSetIndex compressedIndex) const;
|
||||||
|
|
|
@ -1298,6 +1298,7 @@ void CFarTP::sendReady()
|
||||||
pIM->loadKeys();
|
pIM->loadKeys();
|
||||||
CWidgetManager::getInstance()->hideAllWindows();
|
CWidgetManager::getInstance()->hideAllWindows();
|
||||||
pIM->loadInterfaceConfig();
|
pIM->loadInterfaceConfig();
|
||||||
|
pIM->loadLandmarks();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1096,23 +1096,21 @@ void prelogInit()
|
||||||
|
|
||||||
UDriver::CMode mode;
|
UDriver::CMode mode;
|
||||||
|
|
||||||
bool forceWindowed1024x768 = true;
|
|
||||||
|
|
||||||
if (Driver->getCurrentScreenMode(mode))
|
if (Driver->getCurrentScreenMode(mode))
|
||||||
{
|
{
|
||||||
// if screen mode lower than 1024x768, use same mode in fullscreen
|
// use current mode if its smaller than 1024x768
|
||||||
if (mode.Width <= 1024 && mode.Height <= 768)
|
// mode should be windowed already, but incase its not, use the mode as is
|
||||||
|
if (mode.Windowed && (mode.Width > 1024 && mode.Height > 768))
|
||||||
{
|
{
|
||||||
mode.Windowed = false;
|
mode.Width = 1024;
|
||||||
forceWindowed1024x768 = false;
|
mode.Height = 768;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (forceWindowed1024x768)
|
|
||||||
{
|
{
|
||||||
mode.Width = 1024;
|
mode.Width = 1024;
|
||||||
mode.Height = 768;
|
mode.Height = 768;
|
||||||
mode.Windowed = true;
|
mode.Windowed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable Hardware Vertex Program.
|
// Disable Hardware Vertex Program.
|
||||||
|
@ -1332,6 +1330,8 @@ void prelogInit()
|
||||||
|
|
||||||
|
|
||||||
CInterfaceManager::getInstance();
|
CInterfaceManager::getInstance();
|
||||||
|
CViewRenderer::getInstance()->setInterfaceScale(1.0f, 1024, 768);
|
||||||
|
CViewRenderer::getInstance()->setBilinearFiltering(ClientCfg.BilinearUI);
|
||||||
|
|
||||||
// Yoyo: initialize NOW the InputHandler for Event filtering.
|
// Yoyo: initialize NOW the InputHandler for Event filtering.
|
||||||
CInputHandlerManager *InputHandlerManager = CInputHandlerManager::getInstance();
|
CInputHandlerManager *InputHandlerManager = CInputHandlerManager::getInstance();
|
||||||
|
|
|
@ -84,9 +84,6 @@ bool InitMouseWithCursor (bool hardware)
|
||||||
MouseHardware = hardware;
|
MouseHardware = hardware;
|
||||||
CViewPointer::setHWMouse( hardware );
|
CViewPointer::setHWMouse( hardware );
|
||||||
|
|
||||||
// Update mouse information
|
|
||||||
UpdateMouse ();
|
|
||||||
|
|
||||||
if (InitMouseFirstTime)
|
if (InitMouseFirstTime)
|
||||||
{
|
{
|
||||||
InitMouseFirstTime = false;
|
InitMouseFirstTime = false;
|
||||||
|
@ -129,16 +126,6 @@ bool IsMouseCursorHardware ()
|
||||||
return MouseHardware;
|
return MouseHardware;
|
||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************************************
|
|
||||||
// Set the mouse mode. Call this method once per frame to update window size
|
|
||||||
void UpdateMouse ()
|
|
||||||
{
|
|
||||||
if (!Driver->isSystemCursorCaptured())
|
|
||||||
{
|
|
||||||
DownMouseButtons = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// *********************************************************************************
|
// *********************************************************************************
|
||||||
// Use this method to toggle the mouse (freelook <- cursor)
|
// Use this method to toggle the mouse (freelook <- cursor)
|
||||||
void SetMouseFreeLook ()
|
void SetMouseFreeLook ()
|
||||||
|
@ -160,7 +147,6 @@ void SetMouseFreeLook ()
|
||||||
pointer->show (false);
|
pointer->show (false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UpdateMouse ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,9 +165,9 @@ void SetMouseCursor (bool updatePos)
|
||||||
// Get the last cursor
|
// Get the last cursor
|
||||||
float x = 0.5f, y = 0.5f;
|
float x = 0.5f, y = 0.5f;
|
||||||
|
|
||||||
// Window size
|
// Screen size
|
||||||
uint width = Driver->getWindowWidth();
|
uint width, height;
|
||||||
uint height = Driver->getWindowHeight();
|
CViewRenderer::getInstance()->getScreenSize(width, height);
|
||||||
|
|
||||||
// Update the interface pointer
|
// Update the interface pointer
|
||||||
CInterfaceManager *instance = CInterfaceManager::getInstance();
|
CInterfaceManager *instance = CInterfaceManager::getInstance();
|
||||||
|
@ -202,7 +188,6 @@ void SetMouseCursor (bool updatePos)
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseFreeLook = false;
|
MouseFreeLook = false;
|
||||||
UpdateMouse ();
|
|
||||||
|
|
||||||
// Integer coordinates
|
// Integer coordinates
|
||||||
sint ix = (sint)(x*(float)width+0.5f);
|
sint ix = (sint)(x*(float)width+0.5f);
|
||||||
|
@ -253,7 +238,6 @@ void SetMouseCursor (bool updatePos)
|
||||||
void SetMouseSpeed (float speed)
|
void SetMouseSpeed (float speed)
|
||||||
{
|
{
|
||||||
MouseCursorSpeed = speed;
|
MouseCursorSpeed = speed;
|
||||||
UpdateMouse ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************************************
|
// *********************************************************************************
|
||||||
|
@ -261,12 +245,27 @@ void SetMouseSpeed (float speed)
|
||||||
void SetMouseAcceleration (uint accel)
|
void SetMouseAcceleration (uint accel)
|
||||||
{
|
{
|
||||||
MouseCursorAcceleration = accel;
|
MouseCursorAcceleration = accel;
|
||||||
UpdateMouse ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************************************
|
// *********************************************************************************
|
||||||
void HandleSystemCursorCapture(const CEvent &event)
|
void HandleSystemCursorCapture(const CEvent &event)
|
||||||
{
|
{
|
||||||
|
static bool mouseCaptured = false;
|
||||||
|
|
||||||
|
// capture on first move event after button is held down or free look is activated
|
||||||
|
if (event == EventMouseMoveId && !mouseCaptured && (MouseFreeLook || DownMouseButtons != 0))
|
||||||
|
{
|
||||||
|
mouseCaptured = true;
|
||||||
|
Driver->setCapture(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// release when button is released and not in free look
|
||||||
|
if (mouseCaptured && !MouseFreeLook && DownMouseButtons == 0)
|
||||||
|
{
|
||||||
|
mouseCaptured = false;
|
||||||
|
Driver->setCapture(false);
|
||||||
|
}
|
||||||
|
|
||||||
if (event == EventMouseDownId)
|
if (event == EventMouseDownId)
|
||||||
{
|
{
|
||||||
CEventMouseDown &em = (CEventMouseDown &) event;
|
CEventMouseDown &em = (CEventMouseDown &) event;
|
||||||
|
@ -279,8 +278,6 @@ void HandleSystemCursorCapture(const CEvent &event)
|
||||||
cursor->setPointerMiddleDown(em.Button == middleButton);
|
cursor->setPointerMiddleDown(em.Button == middleButton);
|
||||||
cursor->setPointerRightDown(em.Button == rightButton);
|
cursor->setPointerRightDown(em.Button == rightButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
Driver->setCapture(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event == EventMouseUpId)
|
if (event == EventMouseUpId)
|
||||||
|
@ -297,7 +294,6 @@ void HandleSystemCursorCapture(const CEvent &event)
|
||||||
cursor->setPointerMiddleDown(false);
|
cursor->setPointerMiddleDown(false);
|
||||||
cursor->setPointerRightDown(false);
|
cursor->setPointerRightDown(false);
|
||||||
}
|
}
|
||||||
Driver->setCapture(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,6 @@ bool InitMouseWithCursor (bool hardware);
|
||||||
// Is mouse cursor hardware ?
|
// Is mouse cursor hardware ?
|
||||||
bool IsMouseCursorHardware ();
|
bool IsMouseCursorHardware ();
|
||||||
|
|
||||||
// Set the mouse mode. Call this method once per frame to update window size
|
|
||||||
void UpdateMouse ();
|
|
||||||
|
|
||||||
// Use this method to toggle the mouse (freelook <- cursor)
|
// Use this method to toggle the mouse (freelook <- cursor)
|
||||||
void SetMouseFreeLook ();
|
void SetMouseFreeLook ();
|
||||||
|
|
||||||
|
|
|
@ -383,10 +383,10 @@ class CAHEditPreviousLine : public CAHEdit
|
||||||
// .. so do nothing
|
// .. so do nothing
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sint cx, cy;
|
float cx, cy;
|
||||||
sint height;
|
float height;
|
||||||
_GroupEdit->getViewText()->getCharacterPositionFromIndex(cursorPosInText, _GroupEdit->isCursorAtPreviousLineEnd(), cx, cy, height);
|
_GroupEdit->getViewText()->getCharacterPositionFromIndex(cursorPosInText, _GroupEdit->isCursorAtPreviousLineEnd(), cx, cy, height);
|
||||||
cy += height + _GroupEdit->getViewText()->getMultiLineSpace();
|
cy += _GroupEdit->getViewText()->getLineHeight();
|
||||||
uint newCharIndex;
|
uint newCharIndex;
|
||||||
bool newLineEnd;
|
bool newLineEnd;
|
||||||
_GroupEdit->getViewText()->getCharacterIndexFromPosition(cx, cy, newCharIndex, newLineEnd);
|
_GroupEdit->getViewText()->getCharacterIndexFromPosition(cx, cy, newCharIndex, newLineEnd);
|
||||||
|
@ -401,8 +401,8 @@ class CAHEditPreviousLine : public CAHEdit
|
||||||
}
|
}
|
||||||
_GroupEdit->setCursorAtPreviousLineEnd(false);
|
_GroupEdit->setCursorAtPreviousLineEnd(false);
|
||||||
// takes character whose X is closer to the current X
|
// takes character whose X is closer to the current X
|
||||||
sint cx0, cx1;
|
float cx0, cx1;
|
||||||
sint cy0, cy1;
|
float cy0, cy1;
|
||||||
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex, _GroupEdit->isCursorAtPreviousLineEnd(), cx0, cy0, height);
|
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex, _GroupEdit->isCursorAtPreviousLineEnd(), cx0, cy0, height);
|
||||||
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex + 1, _GroupEdit->isCursorAtPreviousLineEnd(), cx1, cy1, height);
|
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex + 1, _GroupEdit->isCursorAtPreviousLineEnd(), cx1, cy1, height);
|
||||||
if (abs(cx0 - cx) < abs(cx1 - cx) || cy0 != cy1)
|
if (abs(cx0 - cx) < abs(cx1 - cx) || cy0 != cy1)
|
||||||
|
@ -446,8 +446,8 @@ class CAHEditNextLine : public CAHEdit
|
||||||
}
|
}
|
||||||
else if (_GroupEdit->getViewText()->getMultiLine())
|
else if (_GroupEdit->getViewText()->getMultiLine())
|
||||||
{
|
{
|
||||||
sint cx, cy;
|
float cx, cy;
|
||||||
sint height;
|
float height;
|
||||||
_GroupEdit->getViewText()->getCharacterPositionFromIndex(_GroupEdit->getCursorPos() + (sint)_GroupEdit->getPrompt().length(), _GroupEdit->isCursorAtPreviousLineEnd(), cx, cy, height);
|
_GroupEdit->getViewText()->getCharacterPositionFromIndex(_GroupEdit->getCursorPos() + (sint)_GroupEdit->getPrompt().length(), _GroupEdit->isCursorAtPreviousLineEnd(), cx, cy, height);
|
||||||
if (cy != 0)
|
if (cy != 0)
|
||||||
{
|
{
|
||||||
|
@ -466,8 +466,8 @@ class CAHEditNextLine : public CAHEdit
|
||||||
}
|
}
|
||||||
_GroupEdit->setCursorAtPreviousLineEnd(false);
|
_GroupEdit->setCursorAtPreviousLineEnd(false);
|
||||||
// takes character whose X is closer to the current X
|
// takes character whose X is closer to the current X
|
||||||
sint cx0, cx1;
|
float cx0, cx1;
|
||||||
sint cy0, cy1;
|
float cy0, cy1;
|
||||||
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex, _GroupEdit->isCursorAtPreviousLineEnd(), cx0, cy0, height);
|
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex, _GroupEdit->isCursorAtPreviousLineEnd(), cx0, cy0, height);
|
||||||
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex + 1, _GroupEdit->isCursorAtPreviousLineEnd(), cx1, cy1, height);
|
_GroupEdit->getViewText()->getCharacterPositionFromIndex(newCharIndex + 1, _GroupEdit->isCursorAtPreviousLineEnd(), cx1, cy1, height);
|
||||||
if (abs(cx0 - cx) < abs(cx1 - cx) || cy0 != cy1)
|
if (abs(cx0 - cx) < abs(cx1 - cx) || cy0 != cy1)
|
||||||
|
|
|
@ -1532,7 +1532,8 @@ public:
|
||||||
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
|
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
|
||||||
{
|
{
|
||||||
// free with no confirm
|
// free with no confirm
|
||||||
beastOrder ("free", Params, false);
|
if (!UserEntity->isBusy())
|
||||||
|
beastOrder ("free", Params, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_ACTION_HANDLER( CHandlerDoBeastFree, "do_beast_free")
|
REGISTER_ACTION_HANDLER( CHandlerDoBeastFree, "do_beast_free")
|
||||||
|
@ -2415,70 +2416,66 @@ class CAHTarget : public IActionHandler
|
||||||
{
|
{
|
||||||
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
|
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
|
||||||
{
|
{
|
||||||
// Get the entity name to target
|
|
||||||
ucstring entityName;
|
ucstring entityName;
|
||||||
entityName.fromUtf8 (getParam (Params, "entity"));
|
entityName.fromUtf8(getParam(Params, "entity"));
|
||||||
bool preferCompleteMatch = (getParam (Params, "prefer_complete_match") != "0");
|
if (entityName.empty()) return;
|
||||||
|
|
||||||
|
string completeMatch = getParam(Params, "prefer_complete_match");
|
||||||
bool quiet = (getParam (Params, "quiet") == "true");
|
bool quiet = (getParam (Params, "quiet") == "true");
|
||||||
|
|
||||||
if (!entityName.empty())
|
vector<ucstring> keywords;
|
||||||
|
NLMISC::splitUCString(entityName, ucstring(" "), keywords);
|
||||||
|
if (!keywords.empty() && keywords[0].size() > 0 && keywords[0][0] == (ucchar)'"')
|
||||||
{
|
{
|
||||||
CEntityCL *entity = NULL;
|
// entity name is in quotes, do old style match with 'starts with' filter
|
||||||
if (preferCompleteMatch)
|
// search for optional second parameter from old command for prefer_complete_match param
|
||||||
{
|
keywords.clear();
|
||||||
// Try to get the entity with complete match first
|
|
||||||
entity = EntitiesMngr.getEntityByName (entityName, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity == NULL)
|
|
||||||
{
|
|
||||||
// Get the entity with a partial match
|
|
||||||
entity = EntitiesMngr.getEntityByName (entityName, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity == NULL)
|
ucstring::size_type lastOf = entityName.rfind(ucstring("\""));
|
||||||
{
|
if (lastOf == 0)
|
||||||
//Get the entity with a sheetName
|
lastOf = ucstring::npos;
|
||||||
entity = EntitiesMngr.getEntityBySheetName(entityName.toUtf8());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity)
|
|
||||||
{
|
|
||||||
CCharacterCL *character = dynamic_cast<CCharacterCL*>(entity);
|
|
||||||
if (character != NULL)
|
|
||||||
{
|
|
||||||
if(character->isSelectableBySpace())
|
|
||||||
{
|
|
||||||
nldebug("isSelectableBySpace");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nldebug("is not isSelectableBySpace");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(entity->properties().selectable())
|
|
||||||
{
|
|
||||||
nldebug("is prop selectable");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// to avoid campfire selection exploit #316
|
|
||||||
nldebug("is not prop selectable");
|
|
||||||
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
||||||
if(!quiet)
|
|
||||||
pIM->displaySystemInfo(CI18N::get("uiTargetErrorCmd"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select the entity
|
// override the value only when there is no 'prefer_complete_match' parameter set
|
||||||
UserEntity->selection(entity->slot());
|
if (completeMatch.empty() && lastOf < entityName.size())
|
||||||
}
|
completeMatch = trim(entityName.substr(lastOf+1).toUtf8());
|
||||||
else
|
|
||||||
{
|
entityName = entityName.substr(1, lastOf-1);
|
||||||
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
}
|
||||||
if(!quiet)
|
|
||||||
pIM->displaySystemInfo(CI18N::get("uiTargetErrorCmd"));
|
// late check because only possible if doing 'starts-with' search
|
||||||
}
|
bool preferCompleteMatch = (completeMatch != "0");
|
||||||
|
|
||||||
|
CEntityCL *entity = NULL;
|
||||||
|
if (preferCompleteMatch)
|
||||||
|
{
|
||||||
|
// Try to get the entity with complete match first
|
||||||
|
entity = EntitiesMngr.getEntityByName (entityName, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity == NULL && !keywords.empty())
|
||||||
|
{
|
||||||
|
entity = EntitiesMngr.getEntityByKeywords(keywords, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity == NULL)
|
||||||
|
{
|
||||||
|
// Get the entity with a partial match using 'starts with' search
|
||||||
|
entity = EntitiesMngr.getEntityByName(entityName, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity == NULL)
|
||||||
|
{
|
||||||
|
//Get the entity with a sheetName
|
||||||
|
entity = EntitiesMngr.getEntityBySheetName(entityName.toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity && entity->properties().selectable() && !entity->getDisplayName().empty())
|
||||||
|
{
|
||||||
|
UserEntity->selection(entity->slot());
|
||||||
|
}
|
||||||
|
else if (!quiet)
|
||||||
|
{
|
||||||
|
CInterfaceManager::getInstance()->displaySystemInfo(CI18N::get("uiTargetErrorCmd"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -3732,6 +3729,34 @@ class CHandlerGameConfigChangeScreenRatioCustom : public IActionHandler
|
||||||
};
|
};
|
||||||
REGISTER_ACTION_HANDLER (CHandlerGameConfigChangeScreenRatioCustom, "game_config_change_screen_ratio_custom");
|
REGISTER_ACTION_HANDLER (CHandlerGameConfigChangeScreenRatioCustom, "game_config_change_screen_ratio_custom");
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
class CHandlerSetInterfaceScale : public IActionHandler
|
||||||
|
{
|
||||||
|
virtual void execute (CCtrlBase *pCaller, const string &Params)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
s = getParam(Params, "scale");
|
||||||
|
if (!s.empty()) {
|
||||||
|
float scale;
|
||||||
|
if (fromString(s, scale))
|
||||||
|
{
|
||||||
|
if (scale >= ClientCfg.InterfaceScale_min && scale <= ClientCfg.InterfaceScale_max)
|
||||||
|
{
|
||||||
|
ClientCfg.InterfaceScale = scale;
|
||||||
|
ClientCfg.writeDouble("InterfaceScale", ClientCfg.InterfaceScale);
|
||||||
|
|
||||||
|
ClientCfg.IsInvalidated = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ucstring help("/setuiscale "+toString("%.1f .. %.1f", ClientCfg.InterfaceScale_min, ClientCfg.InterfaceScale_max));
|
||||||
|
CInterfaceManager::getInstance()->displaySystemInfo(help);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REGISTER_ACTION_HANDLER (CHandlerSetInterfaceScale, "set_ui_scale");
|
||||||
|
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
class CHandlerGameMissionAbandon : public IActionHandler
|
class CHandlerGameMissionAbandon : public IActionHandler
|
||||||
|
@ -4209,7 +4234,7 @@ public:
|
||||||
string fileName = getParam(sParams, "music");
|
string fileName = getParam(sParams, "music");
|
||||||
|
|
||||||
// don't play if db is in init stage
|
// don't play if db is in init stage
|
||||||
if (IngameDbMngr.initInProgress()) return;
|
if (!ClientCfg.Local && IngameDbMngr.initInProgress()) return;
|
||||||
|
|
||||||
if(SoundMngr)
|
if(SoundMngr)
|
||||||
SoundMngr->playEventMusic(fileName, xFade, loop);
|
SoundMngr->playEventMusic(fileName, xFade, loop);
|
||||||
|
@ -4231,7 +4256,7 @@ public:
|
||||||
string fileName= getParam(sParams, "music");
|
string fileName= getParam(sParams, "music");
|
||||||
|
|
||||||
// don't play if db is in init stage
|
// don't play if db is in init stage
|
||||||
if (IngameDbMngr.initInProgress()) return;
|
if (!ClientCfg.Local && IngameDbMngr.initInProgress()) return;
|
||||||
|
|
||||||
if(SoundMngr)
|
if(SoundMngr)
|
||||||
SoundMngr->stopEventMusic(fileName, xFade);
|
SoundMngr->stopEventMusic(fileName, xFade);
|
||||||
|
|
|
@ -28,6 +28,9 @@ using namespace NLMISC;
|
||||||
|
|
||||||
CChatTextManager* CChatTextManager::_Instance = NULL;
|
CChatTextManager* CChatTextManager::_Instance = NULL;
|
||||||
|
|
||||||
|
// last selected chat from 'copy_chat_popup' action handler
|
||||||
|
static std::string LastSelectedChat;
|
||||||
|
|
||||||
//=================================================================================
|
//=================================================================================
|
||||||
CChatTextManager::CChatTextManager() :
|
CChatTextManager::CChatTextManager() :
|
||||||
_TextFontSize(NULL),
|
_TextFontSize(NULL),
|
||||||
|
@ -402,6 +405,10 @@ CViewBase *CChatTextManager::createMsgTextComplex(const ucstring &msg, NLMISC::C
|
||||||
para->setSizeRef("w");
|
para->setSizeRef("w");
|
||||||
para->setResizeFromChildH(true);
|
para->setResizeFromChildH(true);
|
||||||
|
|
||||||
|
// use right click because left click might be used to activate chat window
|
||||||
|
para->setRightClickHandler("copy_chat_popup");
|
||||||
|
para->setRightClickHandlerParams(msg.toUtf8());
|
||||||
|
|
||||||
if (plaintext)
|
if (plaintext)
|
||||||
{
|
{
|
||||||
CViewBase *vt = createMsgTextSimple(msg, col, justified, NULL);
|
CViewBase *vt = createMsgTextSimple(msg, col, justified, NULL);
|
||||||
|
@ -522,3 +529,41 @@ void CChatTextManager::reset ()
|
||||||
_TextShadowed = NULL;
|
_TextShadowed = NULL;
|
||||||
_ShowTimestamps = NULL;
|
_ShowTimestamps = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
// Called when we right click on a chat line
|
||||||
|
class CHandlerCopyChatPopup: public IActionHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void execute(CCtrlBase *pCaller, const string ¶ms )
|
||||||
|
{
|
||||||
|
if (pCaller == NULL) return;
|
||||||
|
|
||||||
|
LastSelectedChat = params;
|
||||||
|
|
||||||
|
CGroupParagraph *pGP = dynamic_cast<CGroupParagraph *>(pCaller);
|
||||||
|
if (pGP) pGP->enableTempOver();
|
||||||
|
|
||||||
|
CWidgetManager::getInstance()->enableModalWindow (pCaller, "ui:interface:chat_copy_action_menu");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REGISTER_ACTION_HANDLER( CHandlerCopyChatPopup, "copy_chat_popup");
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
// Called when we right click on a chat line and choose 'copy' from context menu
|
||||||
|
class CHandlerCopyChat: public IActionHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void execute(CCtrlBase *pCaller, const string ¶ms )
|
||||||
|
{
|
||||||
|
if (pCaller == NULL) return;
|
||||||
|
|
||||||
|
CGroupParagraph *pGP = dynamic_cast<CGroupParagraph *>(pCaller);
|
||||||
|
if (pGP) pGP->disableTempOver();
|
||||||
|
|
||||||
|
CAHManager::getInstance()->runActionHandler("copy_to_clipboard", NULL, LastSelectedChat);
|
||||||
|
CWidgetManager::getInstance()->disableModalWindow();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REGISTER_ACTION_HANDLER( CHandlerCopyChat, "copy_chat");
|
||||||
|
|
||||||
|
|
|
@ -1142,6 +1142,15 @@ CChatWindow *CChatWindowManager::createChatGroupWindow(const CChatWindowDesc &de
|
||||||
if (!desc.HeaderColor.empty())
|
if (!desc.HeaderColor.empty())
|
||||||
w->setHeaderColor(desc.HeaderColor);
|
w->setHeaderColor(desc.HeaderColor);
|
||||||
|
|
||||||
|
|
||||||
|
// because root group was created from template, element from scrollbar target attribute was not created yet
|
||||||
|
CInterfaceGroup *pIG = w->getContainer()->getGroup("header_opened:channel_select");
|
||||||
|
if (pIG)
|
||||||
|
{
|
||||||
|
CCtrlScroll *sb = dynamic_cast<CCtrlScroll*>(w->getContainer()->getCtrl("channel_scroll"));
|
||||||
|
if (sb) sb->setTarget(pIG);
|
||||||
|
}
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "group_html_webig.h"
|
#include "group_html_webig.h"
|
||||||
#include "nel/misc/xml_auto_ptr.h"
|
#include "nel/misc/xml_auto_ptr.h"
|
||||||
|
#include "nel/gui/lua_manager.h"
|
||||||
#include "../client_cfg.h"
|
#include "../client_cfg.h"
|
||||||
#include "../user_entity.h"
|
#include "../user_entity.h"
|
||||||
#include "../entities.h"
|
#include "../entities.h"
|
||||||
|
@ -54,7 +55,7 @@ REGISTER_ACTION_HANDLER( CHandlerBrowseHome, "browse_home");
|
||||||
|
|
||||||
static string getWebAuthKey()
|
static string getWebAuthKey()
|
||||||
{
|
{
|
||||||
if(!UserEntity) return "";
|
if(!UserEntity || !NetMngr.getLoginCookie().isValid()) return "";
|
||||||
|
|
||||||
// authkey = <sharid><name><cid><cookie>
|
// authkey = <sharid><name><cid><cookie>
|
||||||
uint32 cid = NetMngr.getLoginCookie().getUserId() * 16 + PlayerSelectedSlot;
|
uint32 cid = NetMngr.getLoginCookie().getUserId() * 16 + PlayerSelectedSlot;
|
||||||
|
@ -83,7 +84,7 @@ void addWebIGParams (string &url, bool trustedDomain)
|
||||||
{
|
{
|
||||||
url += string("&cid=") + toString(cid) +
|
url += string("&cid=") + toString(cid) +
|
||||||
string("&authkey=") + getWebAuthKey();
|
string("&authkey=") + getWebAuthKey();
|
||||||
|
|
||||||
if (url.find('$') != string::npos)
|
if (url.find('$') != string::npos)
|
||||||
{
|
{
|
||||||
strFindReplace(url, "$gender$", GSGENDER::toString(UserEntity->getGender()));
|
strFindReplace(url, "$gender$", GSGENDER::toString(UserEntity->getGender()));
|
||||||
|
@ -149,13 +150,21 @@ size_t writeDataFromCurl(void *buffer, size_t size, size_t nmemb, void *pcl)
|
||||||
return size*nmemb;
|
return size*nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CWebigNotificationThread : public NLMISC::IRunnable
|
||||||
struct CWebigNotificationThread : public NLMISC::IRunnable
|
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
CURL *Curl;
|
CURL *Curl;
|
||||||
|
bool _Running;
|
||||||
|
IThread *_Thread;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
CWebigNotificationThread()
|
CWebigNotificationThread()
|
||||||
{
|
{
|
||||||
|
_Running = false;
|
||||||
|
_Thread = NULL;
|
||||||
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
|
|
||||||
Curl = curl_easy_init();
|
Curl = curl_easy_init();
|
||||||
if(!Curl) return;
|
if(!Curl) return;
|
||||||
curl_easy_setopt(Curl, CURLOPT_COOKIEFILE, "");
|
curl_easy_setopt(Curl, CURLOPT_COOKIEFILE, "");
|
||||||
|
@ -173,6 +182,12 @@ struct CWebigNotificationThread : public NLMISC::IRunnable
|
||||||
curl_easy_cleanup(Curl);
|
curl_easy_cleanup(Curl);
|
||||||
Curl = 0;
|
Curl = 0;
|
||||||
}
|
}
|
||||||
|
if (_Thread)
|
||||||
|
{
|
||||||
|
_Thread->terminate();
|
||||||
|
delete _Thread;
|
||||||
|
_Thread = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void get(const std::string &url)
|
void get(const std::string &url)
|
||||||
|
@ -186,61 +201,24 @@ struct CWebigNotificationThread : public NLMISC::IRunnable
|
||||||
curl_easy_getinfo(Curl, CURLINFO_RESPONSE_CODE, &r);
|
curl_easy_getinfo(Curl, CURLINFO_RESPONSE_CODE, &r);
|
||||||
//nlwarning("result : '%s'", curlresult.c_str());
|
//nlwarning("result : '%s'", curlresult.c_str());
|
||||||
|
|
||||||
vector<string> notifs;
|
char *ch;
|
||||||
explode(curlresult, string("|"), notifs);
|
std::string contentType;
|
||||||
|
res = curl_easy_getinfo(Curl, CURLINFO_CONTENT_TYPE, &ch);
|
||||||
// Update the mail notification icon
|
if (res == CURLE_OK && ch != NULL)
|
||||||
|
|
||||||
uint32 nbmail = 0;
|
|
||||||
if(!notifs.empty() && fromString(notifs[0], nbmail))
|
|
||||||
{
|
{
|
||||||
//nlinfo("nb mail is a number %d", nbmail);
|
contentType = ch;
|
||||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
}
|
||||||
if(pIM)
|
|
||||||
{
|
// "text/lua; charset=utf8"
|
||||||
CCDBNodeLeaf *_CheckMailNode = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:MAIL_WAITING");
|
if (contentType.find("text/lua") == 0)
|
||||||
if(_CheckMailNode)
|
{
|
||||||
{
|
std::string script;
|
||||||
_CheckMailNode->setValue32(nbmail==0?0:1);
|
script = "\nlocal __WEBIG_NOTIF__= true\n" + curlresult;
|
||||||
CInterfaceElement *elm = CWidgetManager::getInstance()->getElementFromId("ui:interface:compass:mail:mail_nb");
|
CInterfaceManager::getInstance()->queueLuaScript(script);
|
||||||
if (elm)
|
|
||||||
{
|
|
||||||
CViewText *vt = dynamic_cast<CViewText*>(elm);
|
|
||||||
vt->setText(toString("%d", nbmail));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nlwarning("this is not a number '%s'", curlresult.c_str());
|
nlwarning("Invalid content-type '%s', expected 'text/lua'", contentType.c_str());
|
||||||
}
|
|
||||||
|
|
||||||
// Update the forum notification icon
|
|
||||||
|
|
||||||
uint32 nbforum = 0;
|
|
||||||
if(notifs.size() > 1 && fromString(notifs[1], nbforum))
|
|
||||||
{
|
|
||||||
//nlinfo("nb forum this is a number %d", nbforum);
|
|
||||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
||||||
if(pIM)
|
|
||||||
{
|
|
||||||
CCDBNodeLeaf *_CheckForumNode = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:FORUM_UPDATED");
|
|
||||||
if(_CheckForumNode)
|
|
||||||
{
|
|
||||||
_CheckForumNode->setValue32(nbforum==0?0:1);
|
|
||||||
CInterfaceElement *elm = CWidgetManager::getInstance()->getElementFromId("ui:interface:compass:forum:forum_nb");
|
|
||||||
if (elm)
|
|
||||||
{
|
|
||||||
CViewText *vt = dynamic_cast<CViewText*>(elm);
|
|
||||||
vt->setText(toString("%d", nbforum));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nlwarning("this is not a number '%s'", curlresult.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,30 +235,93 @@ struct CWebigNotificationThread : public NLMISC::IRunnable
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
// first time, we wait a small amount of time to be sure everything is initialized
|
if (ClientCfg.WebIgNotifInterval == 0)
|
||||||
nlSleep(1*60*1000);
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
string url = "http://"+ClientCfg.WebIgMainDomain+"/index.php?app=notif&rnd="+randomString();
|
_Running = false;
|
||||||
|
nlwarning("ClientCfg.WebIgNotifInterval == 0, notification thread not running");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string domain = ClientCfg.WebIgMainDomain;
|
||||||
|
uint32 ms = ClientCfg.WebIgNotifInterval*60*1000;
|
||||||
|
|
||||||
|
_Running = true;
|
||||||
|
// first time, we wait a small amount of time to be sure everything is initialized
|
||||||
|
nlSleep(30*1000);
|
||||||
|
uint c = 0;
|
||||||
|
while (_Running)
|
||||||
|
{
|
||||||
|
string url = "https://"+domain+"/index.php?app=notif&format=lua&rnd="+randomString();
|
||||||
addWebIGParams(url, true);
|
addWebIGParams(url, true);
|
||||||
get(url);
|
get(url);
|
||||||
nlSleep(10*60*1000);
|
|
||||||
|
sleepLoop(ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sleepLoop(uint ms)
|
||||||
|
{
|
||||||
|
// use smaller sleep time so stopThread() will not block too long
|
||||||
|
// tick == 100ms
|
||||||
|
uint32 ticks = ms / 100;
|
||||||
|
while (_Running && ticks > 0) {
|
||||||
|
nlSleep(100);
|
||||||
|
ticks--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void startThread()
|
||||||
|
{
|
||||||
|
if (!_Thread)
|
||||||
|
{
|
||||||
|
_Thread = IThread::create(this);
|
||||||
|
nlassert(_Thread != NULL);
|
||||||
|
_Thread->start();
|
||||||
|
nlwarning("WebIgNotification thread started");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("WebIgNotification thread already started");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopThread()
|
||||||
|
{
|
||||||
|
_Running = false;
|
||||||
|
if (_Thread)
|
||||||
|
{
|
||||||
|
_Thread->wait();
|
||||||
|
delete _Thread;
|
||||||
|
_Thread = NULL;
|
||||||
|
nlwarning("WebIgNotification thread stopped");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("WebIgNotification thread already stopped");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isRunning() const
|
||||||
|
{
|
||||||
|
return _Running;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void startWebigNotificationThread()
|
static CWebigNotificationThread webigThread;
|
||||||
|
void startWebIgNotificationThread()
|
||||||
{
|
{
|
||||||
static bool startedWebigNotificationThread = false;
|
if (!webigThread.isRunning())
|
||||||
if(!startedWebigNotificationThread)
|
|
||||||
{
|
{
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
webigThread.startThread();
|
||||||
//nlinfo("startStatThread");
|
}
|
||||||
CWebigNotificationThread *webigThread = new CWebigNotificationThread();
|
}
|
||||||
IThread *thread = IThread::create (webigThread);
|
|
||||||
nlassert (thread != NULL);
|
void stopWebIgNotificationThread()
|
||||||
thread->start ();
|
{
|
||||||
startedWebigNotificationThread = true;
|
if (webigThread.isRunning())
|
||||||
|
{
|
||||||
|
webigThread.stopThread();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,6 +345,8 @@ CGroupHTMLAuth::~CGroupHTMLAuth()
|
||||||
|
|
||||||
void CGroupHTMLAuth::addHTTPGetParams (string &url, bool trustedDomain)
|
void CGroupHTMLAuth::addHTTPGetParams (string &url, bool trustedDomain)
|
||||||
{
|
{
|
||||||
|
if(!UserEntity || !NetMngr.getLoginCookie().isValid()) return;
|
||||||
|
|
||||||
addWebIGParams(url, trustedDomain);
|
addWebIGParams(url, trustedDomain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +354,7 @@ void CGroupHTMLAuth::addHTTPGetParams (string &url, bool trustedDomain)
|
||||||
|
|
||||||
void CGroupHTMLAuth::addHTTPPostParams (SFormFields &formfields, bool trustedDomain)
|
void CGroupHTMLAuth::addHTTPPostParams (SFormFields &formfields, bool trustedDomain)
|
||||||
{
|
{
|
||||||
if(!UserEntity) return;
|
if(!UserEntity || !NetMngr.getLoginCookie().isValid()) return;
|
||||||
|
|
||||||
uint32 cid = NetMngr.getLoginCookie().getUserId() * 16 + PlayerSelectedSlot;
|
uint32 cid = NetMngr.getLoginCookie().getUserId() * 16 + PlayerSelectedSlot;
|
||||||
formfields.add("shardid", toString(CharacterHomeSessionId));
|
formfields.add("shardid", toString(CharacterHomeSessionId));
|
||||||
|
@ -349,7 +392,6 @@ NLMISC_REGISTER_OBJECT(CViewBase, CGroupHTMLWebIG, std::string, "webig_html");
|
||||||
CGroupHTMLWebIG::CGroupHTMLWebIG(const TCtorParam ¶m)
|
CGroupHTMLWebIG::CGroupHTMLWebIG(const TCtorParam ¶m)
|
||||||
: CGroupHTMLAuth(param)
|
: CGroupHTMLAuth(param)
|
||||||
{
|
{
|
||||||
startWebigNotificationThread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
#include "nel/misc/types_nl.h"
|
#include "nel/misc/types_nl.h"
|
||||||
#include "nel/gui/group_html.h"
|
#include "nel/gui/group_html.h"
|
||||||
|
|
||||||
|
void startWebIgNotificationThread();
|
||||||
|
void stopWebIgNotificationThread();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auth HTML group
|
* Auth HTML group
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -86,8 +86,10 @@ void CGroupInScene::computeWindowPos(sint32 &newX, sint32 &newY, CVector &newPro
|
||||||
tmp = pVR.getFrustum().projectZ (tmp);
|
tmp = pVR.getFrustum().projectZ (tmp);
|
||||||
|
|
||||||
// Get the width and height
|
// Get the width and height
|
||||||
tmp.x *= (float)CViewRenderer::getInstance()->getDriver()->getWindowWidth();
|
uint32 width, height;
|
||||||
tmp.y *= (float)CViewRenderer::getInstance()->getDriver()->getWindowHeight();
|
CViewRenderer::getInstance()->getScreenSize(width, height);
|
||||||
|
tmp.x *= width;
|
||||||
|
tmp.y *= height;
|
||||||
|
|
||||||
// position without offset, in float
|
// position without offset, in float
|
||||||
newProjCenter.x= tmp.x;
|
newProjCenter.x= tmp.x;
|
||||||
|
|
|
@ -680,9 +680,8 @@ CGroupInSceneBubbleManager::CPopupContext *CGroupInSceneBubbleManager::buildCont
|
||||||
if (target)
|
if (target)
|
||||||
{
|
{
|
||||||
// Find a position
|
// Find a position
|
||||||
NL3D::UDriver *Driver = CViewRenderer::getInstance()->getDriver();
|
uint32 width, height;
|
||||||
const uint width = Driver->getWindowWidth();
|
CViewRenderer::getInstance()->getScreenSize(width, height);
|
||||||
const uint height = Driver->getWindowHeight();
|
|
||||||
h = (target->getXReal() < ((sint)width-target->getXReal()-target->getWReal()))?"l":"r";
|
h = (target->getXReal() < ((sint)width-target->getXReal()-target->getWReal()))?"l":"r";
|
||||||
v = (target->getYReal() < ((sint)height-target->getYReal()-target->getHReal()))?"b":"t";
|
v = (target->getYReal() < ((sint)height-target->getYReal()-target->getHReal()))?"b":"t";
|
||||||
target->setActive(true);
|
target->setActive(true);
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "../sheet_manager.h" // for MaxNumPeopleInTeam
|
#include "../sheet_manager.h" // for MaxNumPeopleInTeam
|
||||||
#include "../global.h"
|
#include "../global.h"
|
||||||
#include "nel/gui/ctrl_quad.h"
|
#include "nel/gui/ctrl_quad.h"
|
||||||
|
#include "nel/gui/lua_ihm.h"
|
||||||
//
|
//
|
||||||
#include "nel/misc/xml_auto_ptr.h"
|
#include "nel/misc/xml_auto_ptr.h"
|
||||||
#include "game_share/mission_desc.h"
|
#include "game_share/mission_desc.h"
|
||||||
|
@ -403,6 +404,7 @@ CGroupMap::CGroupMap(const TCtorParam ¶m)
|
||||||
_MaxH = 2000;
|
_MaxH = 2000;
|
||||||
//_MinW = 50;
|
//_MinW = 50;
|
||||||
_MapTF = NULL;
|
_MapTF = NULL;
|
||||||
|
_MapTexture.clear();
|
||||||
_PlayerPosMaterial = NULL;
|
_PlayerPosMaterial = NULL;
|
||||||
_PlayerPosTF = NULL;
|
_PlayerPosTF = NULL;
|
||||||
_MapTexW = 0;
|
_MapTexW = 0;
|
||||||
|
@ -462,6 +464,8 @@ CGroupMap::CGroupMap(const TCtorParam ¶m)
|
||||||
_PanStartDateInMs = 0;
|
_PanStartDateInMs = 0;
|
||||||
_DeltaTimeBeforePanInMs = 0;
|
_DeltaTimeBeforePanInMs = 0;
|
||||||
_DeltaPosBeforePan = 0;
|
_DeltaPosBeforePan = 0;
|
||||||
|
//
|
||||||
|
_LuaLoadMapEntered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================================================
|
//============================================================================================================
|
||||||
|
@ -2070,16 +2074,62 @@ void CGroupMap::loadPlayerPos()
|
||||||
_PlayerPosMaterial.setTexture(_PlayerPosTF);
|
_PlayerPosMaterial.setTexture(_PlayerPosTF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================================================
|
||||||
|
void CGroupMap::reload()
|
||||||
|
{
|
||||||
|
if (!_CurMap || !getActive()) return;
|
||||||
|
|
||||||
|
SMap* current = _CurMap;
|
||||||
|
_CurMap = NULL;
|
||||||
|
|
||||||
|
setMap(current);
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================================================
|
//============================================================================================================
|
||||||
void CGroupMap::loadMap()
|
void CGroupMap::loadMap()
|
||||||
{
|
{
|
||||||
_MapLoadFailure = true;
|
_MapLoadFailure = true;
|
||||||
if (!_CurMap) return;
|
if (!_CurMap) return;
|
||||||
const std::string &mapName = _CurMap->BitmapName;
|
|
||||||
std::string fullName = NLMISC::CPath::lookup(mapName, false, false);
|
_MapTexture = _CurMap->BitmapName;
|
||||||
|
|
||||||
|
// call lua game:onLoadMap() function if present
|
||||||
|
// avoid deadlock if called recursively
|
||||||
|
if (!_LuaLoadMapEntered)
|
||||||
|
{
|
||||||
|
_LuaLoadMapEntered = true;
|
||||||
|
CLuaState *ls = CLuaManager::getInstance().getLuaState();
|
||||||
|
|
||||||
|
CLuaStackRestorer lsr(ls, ls->getTop());
|
||||||
|
ls->pushGlobalTable();
|
||||||
|
|
||||||
|
CLuaObject game(*ls);
|
||||||
|
game = game["game"];
|
||||||
|
if (!game["onLoadMap"].isNil())
|
||||||
|
{
|
||||||
|
uint numArg = 1;
|
||||||
|
uint numResult = 1;
|
||||||
|
|
||||||
|
CLuaIHM::pushReflectableOnStack(*ls, this);
|
||||||
|
if (game.callMethodByNameNoThrow("onLoadMap", numArg, numResult))
|
||||||
|
{
|
||||||
|
if (ls->isString(1))
|
||||||
|
{
|
||||||
|
if (!NLMISC::CPath::lookup(ls->toString(1), false, false).empty())
|
||||||
|
_MapTexture = ls->toString(1);
|
||||||
|
else
|
||||||
|
nlwarning("Custom map texture not found '%s' for map '%s'", ls->toString(1), _MapTexture.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_LuaLoadMapEntered = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fullName = NLMISC::CPath::lookup(_MapTexture, false, false);
|
||||||
if (fullName.empty())
|
if (fullName.empty())
|
||||||
{
|
{
|
||||||
nlwarning("Can't find map %s", mapName.c_str());
|
nlwarning("Can't find map %s", _MapTexture.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32 w, h;
|
uint32 w, h;
|
||||||
|
@ -2098,7 +2148,7 @@ void CGroupMap::loadMap()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nlwarning("Can't open map %s", mapName.c_str());
|
nlwarning("Can't open map %s", _MapTexture.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_MapTF = Driver->createTextureFile(fullName);
|
_MapTF = Driver->createTextureFile(fullName);
|
||||||
|
@ -2665,7 +2715,7 @@ CCtrlButton *CGroupMap::addUserLandMark(const NLMISC::CVector2f &pos, const ucst
|
||||||
addLandMark(_UserLM, pos, title, getUserLandMarkOptions((uint32)_CurContinent->UserLandMarks.size() - 1));
|
addLandMark(_UserLM, pos, title, getUserLandMarkOptions((uint32)_CurContinent->UserLandMarks.size() - 1));
|
||||||
|
|
||||||
// Save the config file each time a user landmark is created
|
// Save the config file each time a user landmark is created
|
||||||
CInterfaceManager::getInstance()->saveConfig();
|
CInterfaceManager::getInstance()->saveLandmarks();
|
||||||
|
|
||||||
return _UserLM.back();
|
return _UserLM.back();
|
||||||
}
|
}
|
||||||
|
@ -2689,6 +2739,7 @@ void CGroupMap::removeUserLandMark(CCtrlButton *button)
|
||||||
updateUserLandMarks();
|
updateUserLandMarks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CInterfaceManager::getInstance()->saveLandmarks();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2708,6 +2759,8 @@ void CGroupMap::updateUserLandMark(CCtrlButton *button, const ucstring &newTitle
|
||||||
|
|
||||||
updateLandMarkButton(_UserLM[k], getUserLandMarkOptions(k));
|
updateLandMarkButton(_UserLM[k], getUserLandMarkOptions(k));
|
||||||
button->setDefaultContextHelp(newTitle);
|
button->setDefaultContextHelp(newTitle);
|
||||||
|
|
||||||
|
CInterfaceManager::getInstance()->saveLandmarks();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3322,6 +3375,36 @@ SMap *CGroupMap::getParentMap(SMap *map)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=========================================================================================================
|
||||||
|
std::string CGroupMap::getContinentName() const
|
||||||
|
{
|
||||||
|
if (_CurMap == NULL) return "";
|
||||||
|
|
||||||
|
return toLower(_CurMap->ContinentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================================================================
|
||||||
|
std::string CGroupMap::getMapTexture() const
|
||||||
|
{
|
||||||
|
return toLower(_MapTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================================================================
|
||||||
|
int CGroupMap::luaReload(CLuaState &ls)
|
||||||
|
{
|
||||||
|
CLuaIHM::checkArgCount(ls, "reload", 0);
|
||||||
|
reload();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================================================================
|
||||||
|
int CGroupMap::luaIsIsland(CLuaState &ls)
|
||||||
|
{
|
||||||
|
CLuaIHM::checkArgCount(ls, "isIsland", 0);
|
||||||
|
ls.push(_IsIsland);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// ACTION HANDLERS //
|
// ACTION HANDLERS //
|
||||||
|
|
|
@ -114,6 +114,17 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void onUpdate(CGroupMap &/* owner */) {}
|
virtual void onUpdate(CGroupMap &/* owner */) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
REFLECT_EXPORT_START(CGroupMap, CInterfaceGroup)
|
||||||
|
REFLECT_STRING("continent", getContinentName, dummySet);
|
||||||
|
REFLECT_STRING("texture", getMapTexture, dummySet);
|
||||||
|
REFLECT_LUA_METHOD("isIsland", luaIsIsland);
|
||||||
|
REFLECT_LUA_METHOD("reload", luaReload);
|
||||||
|
REFLECT_EXPORT_END
|
||||||
|
|
||||||
|
int luaReload(CLuaState &ls);
|
||||||
|
int luaIsIsland(CLuaState &ls);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CGroupMap(const TCtorParam ¶m);
|
CGroupMap(const TCtorParam ¶m);
|
||||||
virtual ~CGroupMap();
|
virtual ~CGroupMap();
|
||||||
|
@ -134,6 +145,14 @@ public:
|
||||||
void setMap(const std::string &mapName);
|
void setMap(const std::string &mapName);
|
||||||
void setMap(SMap *map);
|
void setMap(SMap *map);
|
||||||
|
|
||||||
|
// return current continent
|
||||||
|
std::string getContinentName() const;
|
||||||
|
// return currently displayed map texture
|
||||||
|
std::string getMapTexture() const;
|
||||||
|
|
||||||
|
// reload current map texture
|
||||||
|
void reload();
|
||||||
|
|
||||||
// pan the map of the given number of pixels
|
// pan the map of the given number of pixels
|
||||||
void pan(sint32 dx, sint32 dy);
|
void pan(sint32 dx, sint32 dy);
|
||||||
|
|
||||||
|
@ -323,6 +342,7 @@ private:
|
||||||
CContinent *_CurContinent; // the last continent for which the map was displayed (can be NULL if world)
|
CContinent *_CurContinent; // the last continent for which the map was displayed (can be NULL if world)
|
||||||
NLMISC::CVector2f _MapMinCorner; // In world coordinates
|
NLMISC::CVector2f _MapMinCorner; // In world coordinates
|
||||||
NLMISC::CVector2f _MapMaxCorner;
|
NLMISC::CVector2f _MapMaxCorner;
|
||||||
|
std::string _MapTexture; // currently displayed map texture
|
||||||
|
|
||||||
bool _IsIsland; // true if current map is an island (island bitmap need not to be raised to the next
|
bool _IsIsland; // true if current map is an island (island bitmap need not to be raised to the next
|
||||||
// power of 2
|
// power of 2
|
||||||
|
@ -499,6 +519,8 @@ private:
|
||||||
// r2 islands
|
// r2 islands
|
||||||
std::vector<SMap> _Islands;
|
std::vector<SMap> _Islands;
|
||||||
|
|
||||||
|
// guard against recursive calls
|
||||||
|
bool _LuaLoadMapEntered;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadPlayerPos();
|
void loadPlayerPos();
|
||||||
|
|
|
@ -297,6 +297,49 @@ void CGroupQuickHelp::beginElement (uint element_number, const std::vector<bool>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
std::string CGroupQuickHelp::getLanguageUrl(const std::string &href, std::string lang) const
|
||||||
|
{
|
||||||
|
std::string uri = href;
|
||||||
|
|
||||||
|
if (uri.size() < 5 || uri.substr(0, 5) == "http://" || uri.substr(0, 6) == "https://")
|
||||||
|
{
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
// modify uri such that '_??.html' ending contains current user language
|
||||||
|
if (uri.substr(uri.size()-5) == ".html")
|
||||||
|
{
|
||||||
|
if (uri.rfind("_") == uri.size() - 8)
|
||||||
|
{
|
||||||
|
uri = uri.substr(0, uri.size() - 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uri = uri.substr(0, uri.size() - 5);
|
||||||
|
}
|
||||||
|
uri += "_" + lang + ".html";
|
||||||
|
|
||||||
|
// files inside bnp (file:/gamedev.bnp@help_en.html) will always match with CPath::lookup()
|
||||||
|
std::string fname;
|
||||||
|
size_t pos = uri.find("@");
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
fname = uri.substr(pos+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fname = uri;
|
||||||
|
}
|
||||||
|
if (CPath::lookup(fname, false) == "" && lang != "en")
|
||||||
|
{
|
||||||
|
uri = getLanguageUrl(href, "en");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
|
||||||
void CGroupQuickHelp::browse (const char *url)
|
void CGroupQuickHelp::browse (const char *url)
|
||||||
|
@ -307,12 +350,7 @@ void CGroupQuickHelp::browse (const char *url)
|
||||||
|
|
||||||
_IsQuickHelp = false;
|
_IsQuickHelp = false;
|
||||||
|
|
||||||
string completeURL = url;
|
string completeURL = getLanguageUrl(url, ClientCfg.getHtmlLanguageCode());
|
||||||
if (completeURL.substr(completeURL.size()-5, 5) == ".html")
|
|
||||||
{
|
|
||||||
completeURL = completeURL.substr(0, completeURL.size()-5); // Substract the ".html"
|
|
||||||
completeURL += "_" + ClientCfg.getHtmlLanguageCode() + ".html";
|
|
||||||
}
|
|
||||||
|
|
||||||
CGroupHTML::browse (completeURL.c_str());
|
CGroupHTML::browse (completeURL.c_str());
|
||||||
}
|
}
|
||||||
|
@ -321,9 +359,7 @@ void CGroupQuickHelp::browse (const char *url)
|
||||||
|
|
||||||
std::string CGroupQuickHelp::home()
|
std::string CGroupQuickHelp::home()
|
||||||
{
|
{
|
||||||
string completeURL = Home;
|
string completeURL = getLanguageUrl(Home, ClientCfg.getHtmlLanguageCode());
|
||||||
completeURL = completeURL.substr(0, completeURL.size()-5); // Substract the ".html"
|
|
||||||
completeURL += "_" + ClientCfg.getHtmlLanguageCode() + ".html";
|
|
||||||
|
|
||||||
return completeURL;
|
return completeURL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,11 @@ private:
|
||||||
virtual void browse (const char *url);
|
virtual void browse (const char *url);
|
||||||
virtual std::string home();
|
virtual std::string home();
|
||||||
|
|
||||||
|
// Modify uri with '.html' or '_??.html' ending to have current user language,
|
||||||
|
// If the uri is not found locally, then try "en" as fallback language
|
||||||
|
// ie. 'help_ru.html' does not exists, return 'help_en.html'
|
||||||
|
std::string getLanguageUrl(const std::string &href, std::string lang) const;
|
||||||
|
|
||||||
// Init parsing value
|
// Init parsing value
|
||||||
void initParameters();
|
void initParameters();
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,8 @@ using namespace NLGUI;
|
||||||
#include "../global.h"
|
#include "../global.h"
|
||||||
#include "user_agent.h"
|
#include "user_agent.h"
|
||||||
|
|
||||||
|
#include "group_html_webig.h"
|
||||||
|
|
||||||
using namespace NLMISC;
|
using namespace NLMISC;
|
||||||
|
|
||||||
namespace NLGUI
|
namespace NLGUI
|
||||||
|
@ -457,6 +459,7 @@ CInterfaceManager::CInterfaceManager()
|
||||||
parser->addModule( "command", new CCommandParser() );
|
parser->addModule( "command", new CCommandParser() );
|
||||||
parser->addModule( "key", new CKeyParser() );
|
parser->addModule( "key", new CKeyParser() );
|
||||||
parser->addModule( "macro", new CMacroParser() );
|
parser->addModule( "macro", new CMacroParser() );
|
||||||
|
parser->addModule( "landmarks", new CLandmarkParser() );
|
||||||
parser->setCacheUIParsing( ClientCfg.CacheUIParsing );
|
parser->setCacheUIParsing( ClientCfg.CacheUIParsing );
|
||||||
|
|
||||||
CViewRenderer::setDriver( Driver );
|
CViewRenderer::setDriver( Driver );
|
||||||
|
@ -483,6 +486,8 @@ CInterfaceManager::CInterfaceManager()
|
||||||
interfaceLinkUpdater = new CInterfaceLink::CInterfaceLinkUpdater();
|
interfaceLinkUpdater = new CInterfaceLink::CInterfaceLinkUpdater();
|
||||||
_ScreenW = _ScreenH = 0;
|
_ScreenW = _ScreenH = 0;
|
||||||
_LastInGameScreenW = _LastInGameScreenH = 0;
|
_LastInGameScreenW = _LastInGameScreenH = 0;
|
||||||
|
_InterfaceScaleChanged = false;
|
||||||
|
_InterfaceScale = 1.0f;
|
||||||
_DescTextTarget = NULL;
|
_DescTextTarget = NULL;
|
||||||
_ConfigLoaded = false;
|
_ConfigLoaded = false;
|
||||||
_LogState = false;
|
_LogState = false;
|
||||||
|
@ -979,6 +984,9 @@ void CInterfaceManager::initInGame()
|
||||||
// Interface config
|
// Interface config
|
||||||
loadInterfaceConfig();
|
loadInterfaceConfig();
|
||||||
|
|
||||||
|
//Load user landmarks
|
||||||
|
loadLandmarks();
|
||||||
|
|
||||||
// Must do extra init for people interaction after load
|
// Must do extra init for people interaction after load
|
||||||
PeopleInterraction.initAfterLoad();
|
PeopleInterraction.initAfterLoad();
|
||||||
|
|
||||||
|
@ -1043,6 +1051,8 @@ void CInterfaceManager::initInGame()
|
||||||
{
|
{
|
||||||
displaySystemInfo(CI18N::get("uiLogTurnedOff"));
|
displaySystemInfo(CI18N::get("uiLogTurnedOff"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startWebIgNotificationThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1214,6 +1224,22 @@ void CInterfaceManager::configureQuitDialogBox()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
std::string CInterfaceManager::getSaveFileName(const std::string &module, const std::string &ext, bool useShared) const
|
||||||
|
{
|
||||||
|
string filename = "save/" + module + "_" + PlayerSelectedFileName + "." + ext;
|
||||||
|
if (useShared && !CFile::fileExists(filename))
|
||||||
|
{
|
||||||
|
string sharedFile = "save/shared_" + module + "." + ext;
|
||||||
|
if (CFile::fileExists(sharedFile))
|
||||||
|
{
|
||||||
|
return sharedFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void CInterfaceManager::loadKeys()
|
void CInterfaceManager::loadKeys()
|
||||||
{
|
{
|
||||||
|
@ -1225,26 +1251,19 @@ void CInterfaceManager::loadKeys()
|
||||||
vector<string> xmlFilesToParse;
|
vector<string> xmlFilesToParse;
|
||||||
|
|
||||||
// Does the keys file exist ?
|
// Does the keys file exist ?
|
||||||
string userKeyFileName = "save/keys_"+PlayerSelectedFileName+".xml";
|
string userKeyFileName = getSaveFileName("keys", "xml");
|
||||||
if (CFile::fileExists(userKeyFileName) && CFile::getFileSize(userKeyFileName) > 0)
|
if (CFile::fileExists(userKeyFileName) && CFile::getFileSize(userKeyFileName) > 0)
|
||||||
{
|
{
|
||||||
// Load the user key file
|
// Load the user key file
|
||||||
xmlFilesToParse.push_back (userKeyFileName);
|
xmlFilesToParse.push_back (userKeyFileName);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
string filename = "save/shared_keys.xml";
|
|
||||||
if(CFile::fileExists(filename) && CFile::getFileSize(filename) > 0)
|
|
||||||
{
|
|
||||||
xmlFilesToParse.push_back(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Load the default key (but don't replace existings bounds, see keys.xml "key_def_no_replace")
|
// Load the default key (but don't replace existings bounds, see keys.xml "key_def_no_replace")
|
||||||
xmlFilesToParse.push_back ("keys.xml");
|
xmlFilesToParse.push_back ("keys.xml");
|
||||||
|
|
||||||
if (!parseInterface (xmlFilesToParse, true))
|
if (!parseInterface (xmlFilesToParse, true))
|
||||||
{
|
{
|
||||||
badXMLParseMessageBox();
|
createFileBackup("Error loading keys", userKeyFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
_KeysLoaded = true;
|
_KeysLoaded = true;
|
||||||
|
@ -1257,10 +1276,7 @@ void CInterfaceManager::loadInterfaceConfig()
|
||||||
if (ClientCfg.R2EDEnabled) // in R2ED mode the CEditor class deals with it
|
if (ClientCfg.R2EDEnabled) // in R2ED mode the CEditor class deals with it
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string filename = "save/interface_" + PlayerSelectedFileName + ".icfg";
|
string filename = getSaveFileName("interface", "icfg");
|
||||||
if (!CFile::fileExists(filename))
|
|
||||||
filename = "save/shared_interface.icfg";
|
|
||||||
|
|
||||||
loadConfig(filename); // Invalidate coords of changed groups
|
loadConfig(filename); // Invalidate coords of changed groups
|
||||||
|
|
||||||
_ConfigLoaded = true;
|
_ConfigLoaded = true;
|
||||||
|
@ -1290,6 +1306,7 @@ void CInterfaceManager::uninitInGame0 ()
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void CInterfaceManager::uninitInGame1 ()
|
void CInterfaceManager::uninitInGame1 ()
|
||||||
{
|
{
|
||||||
|
stopWebIgNotificationThread();
|
||||||
|
|
||||||
// release Bar Manager (ChaScore1, ChaScore2 etc... Bars)
|
// release Bar Manager (ChaScore1, ChaScore2 etc... Bars)
|
||||||
CBarManager::getInstance()->releaseInGame();
|
CBarManager::getInstance()->releaseInGame();
|
||||||
|
@ -1363,6 +1380,8 @@ void CInterfaceManager::uninitInGame1 ()
|
||||||
reset();
|
reset();
|
||||||
CInterfaceLink::removeAllLinks();
|
CInterfaceLink::removeAllLinks();
|
||||||
|
|
||||||
|
CWidgetManager::getInstance()->setPointer( NULL );
|
||||||
|
|
||||||
// Release DDX manager, before DB remove
|
// Release DDX manager, before DB remove
|
||||||
CDDXManager::getInstance()->release();
|
CDDXManager::getInstance()->release();
|
||||||
|
|
||||||
|
@ -1451,6 +1470,9 @@ void CInterfaceManager::updateFrameEvents()
|
||||||
|
|
||||||
H_AUTO_USE ( RZ_Client_Update_Frame_Events )
|
H_AUTO_USE ( RZ_Client_Update_Frame_Events )
|
||||||
|
|
||||||
|
// lua scripts from different thread
|
||||||
|
flushScriptQueue();
|
||||||
|
|
||||||
flushDebugWindow();
|
flushDebugWindow();
|
||||||
|
|
||||||
// Handle anims done in 2 times because some AH can add or remove anims
|
// Handle anims done in 2 times because some AH can add or remove anims
|
||||||
|
@ -1675,6 +1697,7 @@ bool CInterfaceManager::loadConfig (const string &filename)
|
||||||
uint32 nNbMode;
|
uint32 nNbMode;
|
||||||
CInterfaceConfig ic;
|
CInterfaceConfig ic;
|
||||||
bool lastInGameScreenResLoaded= false;
|
bool lastInGameScreenResLoaded= false;
|
||||||
|
uint32 nbLandmarks = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
sint ver = f.serialVersion(ICFG_STREAM_VERSION);
|
sint ver = f.serialVersion(ICFG_STREAM_VERSION);
|
||||||
|
@ -1770,7 +1793,7 @@ bool CInterfaceManager::loadConfig (const string &filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load user landmarks
|
// Load user landmarks
|
||||||
ContinentMngr.serialUserLandMarks(f);
|
nbLandmarks = ContinentMngr.serialUserLandMarks(f);
|
||||||
|
|
||||||
CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp( "SERVER:INTERFACES:NB_BONUS_LANDMARKS" );
|
CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp( "SERVER:INTERFACES:NB_BONUS_LANDMARKS" );
|
||||||
if ( pNL )
|
if ( pNL )
|
||||||
|
@ -1804,10 +1827,9 @@ bool CInterfaceManager::loadConfig (const string &filename)
|
||||||
catch(const NLMISC::EStream &)
|
catch(const NLMISC::EStream &)
|
||||||
{
|
{
|
||||||
f.close();
|
f.close();
|
||||||
string sFileNameBackup = sFileName+"backup";
|
|
||||||
if (CFile::fileExists(sFileNameBackup))
|
createFileBackup("Config loading failed", sFileName);
|
||||||
CFile::deleteFile(sFileNameBackup);
|
|
||||||
CFile::moveFile(sFileNameBackup, sFileName);
|
|
||||||
nlwarning("Config loading failed : restore default");
|
nlwarning("Config loading failed : restore default");
|
||||||
vector<string> v;
|
vector<string> v;
|
||||||
if (!ClientCfg.R2EDEnabled)
|
if (!ClientCfg.R2EDEnabled)
|
||||||
|
@ -1818,6 +1840,35 @@ bool CInterfaceManager::loadConfig (const string &filename)
|
||||||
}
|
}
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
|
if (nbLandmarks > 0)
|
||||||
|
{
|
||||||
|
// use copy for backup so on save proper shared/player icfg file is used
|
||||||
|
createFileBackup("Landmarks will be migrated to xml", sFileName, true);
|
||||||
|
|
||||||
|
// if icfg is interface_player.icfg, then landmarks must also be loaded/saved to player file
|
||||||
|
if (nlstricmp(sFileName.substr(0, 12), "save/shared_") != 0)
|
||||||
|
{
|
||||||
|
string lmfile = getSaveFileName("landmarks", "xml", false);
|
||||||
|
if (!CFile::fileExists(lmfile))
|
||||||
|
{
|
||||||
|
// create placeholder player landmarks file so saveLandmarks will use it
|
||||||
|
// even if shared landmarks file exists
|
||||||
|
COFile f;
|
||||||
|
if (f.open(lmfile, false, false, true))
|
||||||
|
{
|
||||||
|
std::string xml;
|
||||||
|
xml = "<?xml version=\"1.0\"?>\n<interface_config />";
|
||||||
|
f.serialBuffer((uint8 *)xml.c_str(), xml.size());
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge .icfg landmarks with landmarks.xml
|
||||||
|
loadLandmarks();
|
||||||
|
saveLandmarks();
|
||||||
|
}
|
||||||
|
|
||||||
// *** If saved resolution is different from the current one setuped, must fix positions in _Modes
|
// *** If saved resolution is different from the current one setuped, must fix positions in _Modes
|
||||||
if(lastInGameScreenResLoaded)
|
if(lastInGameScreenResLoaded)
|
||||||
{
|
{
|
||||||
|
@ -1825,8 +1876,12 @@ bool CInterfaceManager::loadConfig (const string &filename)
|
||||||
CWidgetManager::getInstance()->setScreenWH(_LastInGameScreenW, _LastInGameScreenH);
|
CWidgetManager::getInstance()->setScreenWH(_LastInGameScreenW, _LastInGameScreenH);
|
||||||
// NB: we are typically InGame here (even though the _InGame flag is not yet set)
|
// NB: we are typically InGame here (even though the _InGame flag is not yet set)
|
||||||
// Use the screen size of the config file. Don't update current UI, just _Modes
|
// Use the screen size of the config file. Don't update current UI, just _Modes
|
||||||
CWidgetManager::getInstance()->moveAllWindowsToNewScreenSize(ClientCfg.Width, ClientCfg.Height, false);
|
//
|
||||||
updateDesktops( ClientCfg.Width, ClientCfg.Height );
|
// ClientCfg has W/H set to screen size, but interface expects scaled size
|
||||||
|
sint32 scaledW = ClientCfg.Width / ClientCfg.InterfaceScale;
|
||||||
|
sint32 scaledH = ClientCfg.Height / ClientCfg.InterfaceScale;
|
||||||
|
CWidgetManager::getInstance()->moveAllWindowsToNewScreenSize(scaledW, scaledH, false);
|
||||||
|
updateDesktops(scaledW, scaledH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// *** apply the current mode
|
// *** apply the current mode
|
||||||
|
@ -1868,6 +1923,88 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool CInterfaceManager::saveLandmarks(bool verbose) const
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if (!ClientCfg.R2EDEnabled)
|
||||||
|
{
|
||||||
|
uint8 currMode = getMode();
|
||||||
|
|
||||||
|
string filename = getSaveFileName("landmarks", "xml");
|
||||||
|
if (verbose) CInterfaceManager::getInstance()->displaySystemInfo("Saving " + filename);
|
||||||
|
ret = saveLandmarks(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CInterfaceManager::loadLandmarks()
|
||||||
|
{
|
||||||
|
// Does the keys file exist ?
|
||||||
|
string filename = getSaveFileName("landmarks", "xml");
|
||||||
|
|
||||||
|
CIFile f;
|
||||||
|
string sFileName;
|
||||||
|
sFileName = NLMISC::CPath::lookup (filename, false);
|
||||||
|
if (sFileName.empty() || !f.open(sFileName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
vector<string> xmlFilesToParse;
|
||||||
|
xmlFilesToParse.push_back (filename);
|
||||||
|
|
||||||
|
//ContinentMngr.serialUserLandMarks(node);
|
||||||
|
if (!parseInterface (xmlFilesToParse, true))
|
||||||
|
{
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
createFileBackup("Error while loading landmarks", filename);
|
||||||
|
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CInterfaceManager::saveLandmarks(const std::string &filename) const
|
||||||
|
{
|
||||||
|
nlinfo( "Saving landmarks : %s", filename.c_str() );
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
COFile f;
|
||||||
|
|
||||||
|
// using temporary file, so no f.close() unless its a success
|
||||||
|
if (f.open(filename, false, false, true))
|
||||||
|
{
|
||||||
|
COXml xmlStream;
|
||||||
|
xmlStream.init (&f);
|
||||||
|
|
||||||
|
xmlDocPtr doc = xmlStream.getDocument ();
|
||||||
|
xmlNodePtr node = xmlNewDocNode(doc, NULL, (const xmlChar*)"interface_config", NULL);
|
||||||
|
xmlDocSetRootElement (doc, node);
|
||||||
|
|
||||||
|
ContinentMngr.writeTo(node);
|
||||||
|
|
||||||
|
// Flush the stream
|
||||||
|
xmlStream.flush();
|
||||||
|
|
||||||
|
// Close the stream
|
||||||
|
f.close ();
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const Exception &e)
|
||||||
|
{
|
||||||
|
nlwarning ("Error while writing the file %s : %s.", filename.c_str(), e.what ());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
bool CInterfaceManager::saveConfig (bool verbose)
|
bool CInterfaceManager::saveConfig (bool verbose)
|
||||||
|
@ -1878,9 +2015,7 @@ bool CInterfaceManager::saveConfig (bool verbose)
|
||||||
{
|
{
|
||||||
uint8 currMode = getMode();
|
uint8 currMode = getMode();
|
||||||
|
|
||||||
string filename = "save/interface_" + PlayerSelectedFileName + ".icfg";
|
string filename = getSaveFileName("interface", "icfg");
|
||||||
if (!CFile::fileExists(filename) && CFile::fileExists("save/shared_interface.icfg"))
|
|
||||||
filename = "save/shared_interface.icfg";
|
|
||||||
|
|
||||||
if (verbose) CInterfaceManager::getInstance()->displaySystemInfo("Saving " + filename);
|
if (verbose) CInterfaceManager::getInstance()->displaySystemInfo("Saving " + filename);
|
||||||
ret = saveConfig(filename);
|
ret = saveConfig(filename);
|
||||||
|
@ -1995,8 +2130,13 @@ bool CInterfaceManager::saveConfig (const string &filename)
|
||||||
CTaskBarManager *pTBM= CTaskBarManager::getInstance();
|
CTaskBarManager *pTBM= CTaskBarManager::getInstance();
|
||||||
pTBM->serial(f);
|
pTBM->serial(f);
|
||||||
|
|
||||||
// Save user landmarks
|
//ContinentMngr.serialUserLandMarks(f);
|
||||||
ContinentMngr.serialUserLandMarks(f);
|
// empty landmarks block for compatibility
|
||||||
|
{
|
||||||
|
f.serialVersion(1);
|
||||||
|
uint32 numCont = 0;
|
||||||
|
f.serial(numCont);
|
||||||
|
}
|
||||||
|
|
||||||
// Info Windows position.
|
// Info Windows position.
|
||||||
CInterfaceHelp::serialInfoWindows(f);
|
CInterfaceHelp::serialInfoWindows(f);
|
||||||
|
@ -2047,6 +2187,13 @@ void CInterfaceManager::drawViews(NL3D::UCamera camera)
|
||||||
_CurrentPlayerCharac[i] = node ? node->getValue32() : 0;
|
_CurrentPlayerCharac[i] = node ? node->getValue32() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scale must be updated right before widget manager checks it
|
||||||
|
if (_InterfaceScaleChanged)
|
||||||
|
{
|
||||||
|
CViewRenderer::getInstance()->setInterfaceScale(_InterfaceScale);
|
||||||
|
_InterfaceScaleChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
CWidgetManager::getInstance()->drawViews( camera );
|
CWidgetManager::getInstance()->drawViews( camera );
|
||||||
|
|
||||||
// flush obs
|
// flush obs
|
||||||
|
@ -2935,7 +3082,6 @@ NLMISC_COMMAND(loadui, "Load an interface file", "<loadui [all]/interface.xml>")
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
void CInterfaceManager::displayWebWindow(const string & name, const string & url)
|
void CInterfaceManager::displayWebWindow(const string & name, const string & url)
|
||||||
{
|
{
|
||||||
|
@ -3344,6 +3490,24 @@ void CInterfaceManager::notifyForumUpdated()
|
||||||
_CheckForumNode->setValue32(1);
|
_CheckForumNode->setValue32(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CInterfaceManager::queueLuaScript(const std::string &script)
|
||||||
|
{
|
||||||
|
CAutoMutex<CMutex> autoMutex(_ScriptQueueMutex);
|
||||||
|
|
||||||
|
_ScriptQueue.push(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInterfaceManager::flushScriptQueue()
|
||||||
|
{
|
||||||
|
CAutoMutex<CMutex> autoMutex(_ScriptQueueMutex);
|
||||||
|
|
||||||
|
while(!_ScriptQueue.empty())
|
||||||
|
{
|
||||||
|
CLuaManager::getInstance().executeLuaScript(_ScriptQueue.front());
|
||||||
|
_ScriptQueue.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
void CInterfaceManager::resetTextIndex()
|
void CInterfaceManager::resetTextIndex()
|
||||||
|
@ -4120,3 +4284,40 @@ bool CInterfaceManager::parseTokens(ucstring& ucstr)
|
||||||
ucstr = str;
|
ucstr = str;
|
||||||
return true;;
|
return true;;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CInterfaceManager::getNextBackupName(std::string filename)
|
||||||
|
{
|
||||||
|
std::string ts = getTimestampHuman("%Y-%m-%d");
|
||||||
|
|
||||||
|
if (!ts.empty())
|
||||||
|
{
|
||||||
|
std::string::size_type pos = filename.find_last_of('.');
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
filename = filename + "_" + ts + "_";
|
||||||
|
else
|
||||||
|
filename = filename.substr(0, pos) + "_" + ts + "_" + filename.substr(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// filename_YYYY-MM-DD_000.ext
|
||||||
|
return CFile::findNewFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInterfaceManager::createFileBackup(const std::string &message, const std::string &filename, bool useCopy)
|
||||||
|
{
|
||||||
|
std::string backupName = getNextBackupName(filename);
|
||||||
|
nlwarning("%s: '%s'.", message.c_str(), filename.c_str());
|
||||||
|
if (!backupName.empty())
|
||||||
|
{
|
||||||
|
if (useCopy)
|
||||||
|
{
|
||||||
|
nlwarning("Backup copy saved as '%s'", backupName.c_str());
|
||||||
|
CFile::copyFile(backupName, filename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("File renamed to '%s'", backupName.c_str());
|
||||||
|
CFile::moveFile(backupName, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,11 @@
|
||||||
#ifndef NL_INTERFACE_MANAGER_H
|
#ifndef NL_INTERFACE_MANAGER_H
|
||||||
#define NL_INTERFACE_MANAGER_H
|
#define NL_INTERFACE_MANAGER_H
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#include "nel/misc/types_nl.h"
|
#include "nel/misc/types_nl.h"
|
||||||
#include "nel/misc/cdb_manager.h"
|
#include "nel/misc/cdb_manager.h"
|
||||||
|
#include "nel/misc/mutex.h"
|
||||||
#include "nel/3d/u_texture.h"
|
#include "nel/3d/u_texture.h"
|
||||||
#include "nel/3d/u_text_context.h"
|
#include "nel/3d/u_text_context.h"
|
||||||
#include "nel/gui/interface_group.h"
|
#include "nel/gui/interface_group.h"
|
||||||
|
@ -203,6 +206,19 @@ public:
|
||||||
/// Load a set of xml files
|
/// Load a set of xml files
|
||||||
bool parseInterface (const std::vector<std::string> &xmlFileNames, bool reload, bool isFilename = true);
|
bool parseInterface (const std::vector<std::string> &xmlFileNames, bool reload, bool isFilename = true);
|
||||||
|
|
||||||
|
/// return new filename that can be used to backup original file
|
||||||
|
std::string getNextBackupName(std::string filename);
|
||||||
|
/// copy/rename filename for backup and show error in log
|
||||||
|
void createFileBackup(const std::string &message, const std::string &filename, bool useCopy = false);
|
||||||
|
|
||||||
|
/// select player/shared file name from 'save' folder'
|
||||||
|
std::string getSaveFileName(const std::string &module, const std::string &ext, bool useShared = true) const;
|
||||||
|
|
||||||
|
/// Load / save user landmarks in .xml format
|
||||||
|
bool loadLandmarks ();
|
||||||
|
bool saveLandmarks (bool verbose = false) const;
|
||||||
|
bool saveLandmarks (const std::string &filename) const;
|
||||||
|
|
||||||
// Load/Save position, size, etc.. of windows
|
// Load/Save position, size, etc.. of windows
|
||||||
bool loadConfig (const std::string &filename);
|
bool loadConfig (const std::string &filename);
|
||||||
// Save config to default location, if verbose is true, display message in game sysinfo
|
// Save config to default location, if verbose is true, display message in game sysinfo
|
||||||
|
@ -414,6 +430,10 @@ public:
|
||||||
void notifyMailAvailable();
|
void notifyMailAvailable();
|
||||||
void notifyForumUpdated();
|
void notifyForumUpdated();
|
||||||
|
|
||||||
|
/** Queue up lua script to be run on next frame update
|
||||||
|
*/
|
||||||
|
void queueLuaScript(const std::string &script);
|
||||||
|
|
||||||
/** Return true if 12-hour clock should be used
|
/** Return true if 12-hour clock should be used
|
||||||
*/
|
*/
|
||||||
static bool use12hClock();
|
static bool use12hClock();
|
||||||
|
@ -549,6 +569,7 @@ public:
|
||||||
NLMISC::CCDBNodeLeaf *_DB_UI_DUMMY_FACTION_TYPE;
|
NLMISC::CCDBNodeLeaf *_DB_UI_DUMMY_FACTION_TYPE;
|
||||||
|
|
||||||
void updateDesktops( uint32 newScreenW, uint32 newScreenH );
|
void updateDesktops( uint32 newScreenW, uint32 newScreenH );
|
||||||
|
void setInterfaceScale( float scale ) { _InterfaceScaleChanged = true; _InterfaceScale = scale; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -556,6 +577,12 @@ private:
|
||||||
NLMISC::CCDBNodeLeaf *_CheckForumNode;
|
NLMISC::CCDBNodeLeaf *_CheckForumNode;
|
||||||
sint64 _UpdateWeatherTime;
|
sint64 _UpdateWeatherTime;
|
||||||
|
|
||||||
|
// WebIG notify thread is pushing lua code here
|
||||||
|
std::queue<std::string> _ScriptQueue;
|
||||||
|
NLMISC::CMutex _ScriptQueueMutex;
|
||||||
|
|
||||||
|
void flushScriptQueue();
|
||||||
|
|
||||||
// @}
|
// @}
|
||||||
|
|
||||||
/** This is the GLOBAL Action counter used to synchronize some systems (including INVENTORY) with the server.
|
/** This is the GLOBAL Action counter used to synchronize some systems (including INVENTORY) with the server.
|
||||||
|
@ -587,6 +614,8 @@ private:
|
||||||
|
|
||||||
uint32 _ScreenW, _ScreenH; // Change res detection
|
uint32 _ScreenW, _ScreenH; // Change res detection
|
||||||
sint32 _LastInGameScreenW, _LastInGameScreenH; // Resolution used for last InGame interface
|
sint32 _LastInGameScreenW, _LastInGameScreenH; // Resolution used for last InGame interface
|
||||||
|
float _InterfaceScale;
|
||||||
|
bool _InterfaceScaleChanged;
|
||||||
|
|
||||||
// Modes
|
// Modes
|
||||||
std::vector<CInterfaceConfig::CDesktopImage> _Modes;
|
std::vector<CInterfaceConfig::CDesktopImage> _Modes;
|
||||||
|
|
|
@ -2003,6 +2003,9 @@ bool SBagOptions::parse(xmlNodePtr cur, CInterfaceGroup * /* parentGroup */)
|
||||||
prop = xmlGetProp (cur, (xmlChar*)"filter_tool");
|
prop = xmlGetProp (cur, (xmlChar*)"filter_tool");
|
||||||
if (prop) DbFilterTool = NLGUI::CDBManager::getInstance()->getDbProp(prop.str());
|
if (prop) DbFilterTool = NLGUI::CDBManager::getInstance()->getDbProp(prop.str());
|
||||||
|
|
||||||
|
prop = xmlGetProp (cur, (xmlChar*)"filter_pet");
|
||||||
|
if (prop) DbFilterPet = NLGUI::CDBManager::getInstance()->getDbProp(prop.str());
|
||||||
|
|
||||||
prop = xmlGetProp (cur, (xmlChar*)"filter_mp");
|
prop = xmlGetProp (cur, (xmlChar*)"filter_mp");
|
||||||
if (prop) DbFilterMP = NLGUI::CDBManager::getInstance()->getDbProp(prop.str());
|
if (prop) DbFilterMP = NLGUI::CDBManager::getInstance()->getDbProp(prop.str());
|
||||||
|
|
||||||
|
@ -2079,6 +2082,13 @@ bool SBagOptions::isSomethingChanged()
|
||||||
LastDbFilterTool = (DbFilterTool->getValue8() != 0);
|
LastDbFilterTool = (DbFilterTool->getValue8() != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DbFilterPet != NULL)
|
||||||
|
if ((DbFilterPet->getValue8() != 0) != LastDbFilterPet)
|
||||||
|
{
|
||||||
|
bRet = true;
|
||||||
|
LastDbFilterPet = (DbFilterPet->getValue8() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (DbFilterMP != NULL)
|
if (DbFilterMP != NULL)
|
||||||
if ((DbFilterMP->getValue8() != 0) != LastDbFilterMP)
|
if ((DbFilterMP->getValue8() != 0) != LastDbFilterMP)
|
||||||
{
|
{
|
||||||
|
@ -2117,6 +2127,7 @@ bool SBagOptions::canDisplay(CDBCtrlSheet *pCS) const
|
||||||
bool bFilterArmor = getFilterArmor();
|
bool bFilterArmor = getFilterArmor();
|
||||||
bool bFilterWeapon = getFilterWeapon();
|
bool bFilterWeapon = getFilterWeapon();
|
||||||
bool bFilterTool = getFilterTool();
|
bool bFilterTool = getFilterTool();
|
||||||
|
bool bFilterPet = getFilterPet();
|
||||||
bool bFilterMP = getFilterMP();
|
bool bFilterMP = getFilterMP();
|
||||||
bool bFilterMissMP = getFilterMissMP();
|
bool bFilterMissMP = getFilterMissMP();
|
||||||
bool bFilterTP = getFilterTP();
|
bool bFilterTP = getFilterTP();
|
||||||
|
@ -2169,10 +2180,13 @@ bool SBagOptions::canDisplay(CDBCtrlSheet *pCS) const
|
||||||
(pIS->Family == ITEMFAMILY::HARVEST_TOOL) ||
|
(pIS->Family == ITEMFAMILY::HARVEST_TOOL) ||
|
||||||
(pIS->Family == ITEMFAMILY::TAMING_TOOL) ||
|
(pIS->Family == ITEMFAMILY::TAMING_TOOL) ||
|
||||||
(pIS->Family == ITEMFAMILY::TRAINING_TOOL) ||
|
(pIS->Family == ITEMFAMILY::TRAINING_TOOL) ||
|
||||||
(pIS->Family == ITEMFAMILY::BAG) ||
|
(pIS->Family == ITEMFAMILY::BAG))
|
||||||
(pIS->Family == ITEMFAMILY::PET_ANIMAL_TICKET) )
|
|
||||||
if (!bFilterTool) bDisplay = false;
|
if (!bFilterTool) bDisplay = false;
|
||||||
|
|
||||||
|
// Pet
|
||||||
|
if (pIS->Family == ITEMFAMILY::PET_ANIMAL_TICKET)
|
||||||
|
if (!bFilterPet) bDisplay = false;
|
||||||
|
|
||||||
// MP
|
// MP
|
||||||
if ((pIS->Family == ITEMFAMILY::RAW_MATERIAL) && pIS->canBuildSomeItemPart())
|
if ((pIS->Family == ITEMFAMILY::RAW_MATERIAL) && pIS->canBuildSomeItemPart())
|
||||||
if (!bFilterMP) bDisplay = false;
|
if (!bFilterMP) bDisplay = false;
|
||||||
|
@ -2529,25 +2543,92 @@ class CHandlerInvDrag : public IActionHandler
|
||||||
};
|
};
|
||||||
REGISTER_ACTION_HANDLER( CHandlerInvDrag, "inv_drag" );
|
REGISTER_ACTION_HANDLER( CHandlerInvDrag, "inv_drag" );
|
||||||
|
|
||||||
// **********************************************************************************************************
|
// ***************************************************************************
|
||||||
class CHandlerInvSetSearch : public IActionHandler
|
// show/hide edit box, set keyboard focus if 'show'
|
||||||
|
class CHandlerInvSearchButton : public IActionHandler
|
||||||
{
|
{
|
||||||
void execute (CCtrlBase *pCaller, const std::string &sParams)
|
virtual void execute (CCtrlBase *pCaller, const string &sParams)
|
||||||
|
{
|
||||||
|
if (sParams.empty())
|
||||||
|
{
|
||||||
|
nlwarning("inv_search_button: missing edit box shortid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCtrlBaseButton* btn = dynamic_cast<CCtrlBaseButton *>(pCaller);
|
||||||
|
if (!btn)
|
||||||
|
{
|
||||||
|
nlwarning("inv_search_button pCaller == NULL, caller must be CCtrlBaseButton with 'toggle_button' type");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ucstring filter;
|
||||||
|
std::string id = btn->getParent()->getId() + ":" + sParams + ":eb";
|
||||||
|
CGroupEditBox *eb = dynamic_cast<CGroupEditBox*>(CWidgetManager::getInstance()->getElementFromId(id));
|
||||||
|
if (!eb)
|
||||||
|
{
|
||||||
|
nlwarning("inv_search_button: editbox (%s) not found\n", id.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eb->getParent()->setActive(btn->getPushed());
|
||||||
|
if (eb->getParent()->getActive())
|
||||||
|
{
|
||||||
|
CWidgetManager::getInstance()->setCaptureKeyboard(eb);
|
||||||
|
eb->setSelectionAll();
|
||||||
|
filter = eb->getInputString();
|
||||||
|
}
|
||||||
|
|
||||||
|
CDBGroupListSheetBag *pList = dynamic_cast<CDBGroupListSheetBag*>(CWidgetManager::getInstance()->getElementFromId(btn->getParent()->getId() + ":bag_list"));
|
||||||
|
if (pList != NULL) pList->setSearchFilter(filter);
|
||||||
|
|
||||||
|
CDBGroupIconListBag *pIcons = dynamic_cast<CDBGroupIconListBag*>(CWidgetManager::getInstance()->getElementFromId(btn->getParent()->getId() + ":bag_icons"));
|
||||||
|
if (pIcons != NULL) pIcons->setSearchFilter(filter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REGISTER_ACTION_HANDLER( CHandlerInvSearchButton, "inv_search_button" );
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
// if :eb is empty then hide edit box, unpush search button
|
||||||
|
class CHandlerInvSearchUnfocus : public IActionHandler
|
||||||
|
{
|
||||||
|
virtual void execute (CCtrlBase *pCaller, const string &sParams)
|
||||||
{
|
{
|
||||||
if (!pCaller) return;
|
if (!pCaller) return;
|
||||||
|
|
||||||
CGroupEditBox *eb = dynamic_cast<CGroupEditBox *>(pCaller);
|
CGroupEditBox *eb = dynamic_cast<CGroupEditBox *>(pCaller);
|
||||||
if (!eb) return;
|
if (!eb || !eb->getInputString().empty()) return;
|
||||||
|
|
||||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
||||||
|
|
||||||
// ui:interface:inventory:content:bag:iil:inv_query_eb:eb
|
// ui:interface:inventory:content:bag:iil:inv_query_eb:eb
|
||||||
string invId = pCaller->getParent()->getParent()->getId();
|
std::string id = pCaller->getParent()->getParent()->getId() + ":" + sParams;
|
||||||
|
CCtrlBaseButton *btn = dynamic_cast<CCtrlBaseButton*>(CWidgetManager::getInstance()->getElementFromId(id));
|
||||||
|
if (btn) btn->setPushed(false);
|
||||||
|
|
||||||
CDBGroupListSheetBag *pList = dynamic_cast<CDBGroupListSheetBag*>(CWidgetManager::getInstance()->getElementFromId(invId + ":bag_list"));
|
// hide :inv_query_eb
|
||||||
|
pCaller->getParent()->setActive(false);
|
||||||
|
|
||||||
|
// clear filter
|
||||||
|
CAHManager::getInstance()->runActionHandler("inv_set_search", pCaller, "");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REGISTER_ACTION_HANDLER( CHandlerInvSearchUnfocus, "inv_search_unfocus" );
|
||||||
|
|
||||||
|
// **********************************************************************************************************
|
||||||
|
// set inventory search string
|
||||||
|
class CHandlerInvSetSearch : public IActionHandler
|
||||||
|
{
|
||||||
|
void execute (CCtrlBase *pCaller, const std::string &sParams)
|
||||||
|
{
|
||||||
|
CGroupEditBox *eb = dynamic_cast<CGroupEditBox *>(pCaller);
|
||||||
|
if (!eb) return;
|
||||||
|
|
||||||
|
// ui:interface:inventory:content:bag:iil:inv_query_eb:eb
|
||||||
|
std::string id = pCaller->getParent()->getParent()->getId();
|
||||||
|
|
||||||
|
CDBGroupListSheetBag *pList = dynamic_cast<CDBGroupListSheetBag*>(CWidgetManager::getInstance()->getElementFromId(id + ":bag_list"));
|
||||||
if (pList != NULL) pList->setSearchFilter(eb->getInputString());
|
if (pList != NULL) pList->setSearchFilter(eb->getInputString());
|
||||||
|
|
||||||
CDBGroupIconListBag *pIcons = dynamic_cast<CDBGroupIconListBag*>(CWidgetManager::getInstance()->getElementFromId(invId + ":bag_icons"));
|
CDBGroupIconListBag *pIcons = dynamic_cast<CDBGroupIconListBag*>(CWidgetManager::getInstance()->getElementFromId(id + ":bag_icons"));
|
||||||
if (pIcons != NULL) pIcons->setSearchFilter(eb->getInputString());
|
if (pIcons != NULL) pIcons->setSearchFilter(eb->getInputString());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -509,6 +509,7 @@ struct SBagOptions
|
||||||
NLMISC::CCDBNodeLeaf *DbFilterArmor;
|
NLMISC::CCDBNodeLeaf *DbFilterArmor;
|
||||||
NLMISC::CCDBNodeLeaf *DbFilterWeapon;
|
NLMISC::CCDBNodeLeaf *DbFilterWeapon;
|
||||||
NLMISC::CCDBNodeLeaf *DbFilterTool;
|
NLMISC::CCDBNodeLeaf *DbFilterTool;
|
||||||
|
NLMISC::CCDBNodeLeaf *DbFilterPet;
|
||||||
NLMISC::CCDBNodeLeaf *DbFilterMP;
|
NLMISC::CCDBNodeLeaf *DbFilterMP;
|
||||||
NLMISC::CCDBNodeLeaf *DbFilterMissMP;
|
NLMISC::CCDBNodeLeaf *DbFilterMissMP;
|
||||||
NLMISC::CCDBNodeLeaf *DbFilterTP;
|
NLMISC::CCDBNodeLeaf *DbFilterTP;
|
||||||
|
@ -516,6 +517,7 @@ struct SBagOptions
|
||||||
bool LastDbFilterArmor;
|
bool LastDbFilterArmor;
|
||||||
bool LastDbFilterWeapon;
|
bool LastDbFilterWeapon;
|
||||||
bool LastDbFilterTool;
|
bool LastDbFilterTool;
|
||||||
|
bool LastDbFilterPet;
|
||||||
bool LastDbFilterMP;
|
bool LastDbFilterMP;
|
||||||
bool LastDbFilterMissMP;
|
bool LastDbFilterMissMP;
|
||||||
bool LastDbFilterTP;
|
bool LastDbFilterTP;
|
||||||
|
@ -529,8 +531,8 @@ struct SBagOptions
|
||||||
SBagOptions()
|
SBagOptions()
|
||||||
{
|
{
|
||||||
InvType = CInventoryManager::InvUnknown;
|
InvType = CInventoryManager::InvUnknown;
|
||||||
DbFilterArmor = DbFilterWeapon = DbFilterTool = DbFilterMP = DbFilterMissMP = DbFilterTP = NULL;
|
DbFilterArmor = DbFilterWeapon = DbFilterTool = DbFilterPet = DbFilterMP = DbFilterMissMP = DbFilterTP = NULL;
|
||||||
LastDbFilterArmor = LastDbFilterWeapon = LastDbFilterTool = LastDbFilterMP = LastDbFilterMissMP = LastDbFilterTP = false;
|
LastDbFilterArmor = LastDbFilterWeapon = LastDbFilterTool = LastDbFilterPet = LastDbFilterMP = LastDbFilterMissMP = LastDbFilterTP = false;
|
||||||
SearchFilterChanged = false;
|
SearchFilterChanged = false;
|
||||||
SearchQualityMin = 0;
|
SearchQualityMin = 0;
|
||||||
SearchQualityMax = 999;
|
SearchQualityMax = 999;
|
||||||
|
@ -561,6 +563,12 @@ struct SBagOptions
|
||||||
return (DbFilterTool->getValue8()!=0);
|
return (DbFilterTool->getValue8()!=0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getFilterPet() const
|
||||||
|
{
|
||||||
|
if (DbFilterPet == NULL) return true;
|
||||||
|
return (DbFilterPet->getValue8()!=0);
|
||||||
|
}
|
||||||
|
|
||||||
bool getFilterMP() const
|
bool getFilterMP() const
|
||||||
{
|
{
|
||||||
if (DbFilterMP == NULL) return true;
|
if (DbFilterMP == NULL) return true;
|
||||||
|
|
|
@ -540,6 +540,7 @@ void CLuaIHMRyzom::RegisterRyzomFunctions(NLGUI::CLuaState &ls)
|
||||||
LUABIND_FUNC(getClientCfg),
|
LUABIND_FUNC(getClientCfg),
|
||||||
LUABIND_FUNC(sendMsgToServer),
|
LUABIND_FUNC(sendMsgToServer),
|
||||||
LUABIND_FUNC(sendMsgToServerPvpTag),
|
LUABIND_FUNC(sendMsgToServerPvpTag),
|
||||||
|
LUABIND_FUNC(sendMsgToServerUseItem),
|
||||||
LUABIND_FUNC(isGuildQuitAvailable),
|
LUABIND_FUNC(isGuildQuitAvailable),
|
||||||
LUABIND_FUNC(sortGuildMembers),
|
LUABIND_FUNC(sortGuildMembers),
|
||||||
LUABIND_FUNC(getNbGuildMembers),
|
LUABIND_FUNC(getNbGuildMembers),
|
||||||
|
@ -1687,7 +1688,13 @@ int CLuaIHMRyzom::getWeatherValue(CLuaState &ls)
|
||||||
CLuaIHM::checkArgCount(ls, funcName, 0);
|
CLuaIHM::checkArgCount(ls, funcName, 0);
|
||||||
uint64 currDay = RT.getRyzomDay();
|
uint64 currDay = RT.getRyzomDay();
|
||||||
float currHour = (float) RT.getRyzomTime();
|
float currHour = (float) RT.getRyzomTime();
|
||||||
ls.push(::getBlendedWeather(currDay, currHour, *WeatherFunctionParams, ContinentMngr.cur()->WeatherFunction));
|
float weather = 0.f;
|
||||||
|
if (ContinentMngr.cur())
|
||||||
|
{
|
||||||
|
weather = ::getBlendedWeather(currDay, currHour, *WeatherFunctionParams, ContinentMngr.cur()->WeatherFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
ls.push(weather);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3326,6 +3333,16 @@ void CLuaIHMRyzom::sendMsgToServerPvpTag(bool pvpTag)
|
||||||
::sendMsgToServer("PVP:PVP_TAG", tag);
|
::sendMsgToServer("PVP:PVP_TAG", tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
void CLuaIHMRyzom::sendMsgToServerUseItem(sint32 slot)
|
||||||
|
{
|
||||||
|
//H_AUTO(Lua_CLuaIHM_sendMsgToServerUseItem)
|
||||||
|
uint8 u8n1 = (uint8)((uint16)slot >> 8);
|
||||||
|
uint8 u8n2 = (uint8)((uint16)slot & 0x00FF);
|
||||||
|
|
||||||
|
::sendMsgToServer("ITEM:USE_ITEM", u8n1, u8n2);
|
||||||
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
bool CLuaIHMRyzom::isGuildQuitAvailable()
|
bool CLuaIHMRyzom::isGuildQuitAvailable()
|
||||||
{
|
{
|
||||||
|
|
|
@ -198,6 +198,7 @@ private:
|
||||||
static std::string getClientCfg(const std::string &varName);
|
static std::string getClientCfg(const std::string &varName);
|
||||||
static void sendMsgToServer(const std::string &msgName);
|
static void sendMsgToServer(const std::string &msgName);
|
||||||
static void sendMsgToServerPvpTag(bool pvpTag);
|
static void sendMsgToServerPvpTag(bool pvpTag);
|
||||||
|
static void sendMsgToServerUseItem(sint32 slot);
|
||||||
static bool isGuildQuitAvailable();
|
static bool isGuildQuitAvailable();
|
||||||
static void sortGuildMembers();
|
static void sortGuildMembers();
|
||||||
static sint32 getNbGuildMembers();
|
static sint32 getNbGuildMembers();
|
||||||
|
|
|
@ -39,6 +39,9 @@ extern UDriver *Driver;
|
||||||
#define TEMPLATE_PLAYLIST_SONG "playlist_song"
|
#define TEMPLATE_PLAYLIST_SONG "playlist_song"
|
||||||
#define TEMPLATE_PLAYLIST_SONG_TITLE "title"
|
#define TEMPLATE_PLAYLIST_SONG_TITLE "title"
|
||||||
#define TEMPLATE_PLAYLIST_SONG_DURATION "duration"
|
#define TEMPLATE_PLAYLIST_SONG_DURATION "duration"
|
||||||
|
// ui state
|
||||||
|
#define MP3_SAVE_SHUFFLE "UI:SAVE:MP3_SHUFFLE"
|
||||||
|
#define MP3_SAVE_REPEAT "UI:SAVE:MP3_REPEAT"
|
||||||
|
|
||||||
static const std::string MediaPlayerDirectory("music/");
|
static const std::string MediaPlayerDirectory("music/");
|
||||||
|
|
||||||
|
@ -48,8 +51,20 @@ CMusicPlayer MusicPlayer;
|
||||||
|
|
||||||
CMusicPlayer::CMusicPlayer ()
|
CMusicPlayer::CMusicPlayer ()
|
||||||
{
|
{
|
||||||
_CurrentSong = 0;
|
_CurrentSongIndex = 0;
|
||||||
_State = Stopped;
|
_State = Stopped;
|
||||||
|
_PlayStart = 0;
|
||||||
|
_PauseTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMusicPlayer::isRepeatEnabled() const
|
||||||
|
{
|
||||||
|
return (NLGUI::CDBManager::getInstance()->getDbProp(MP3_SAVE_REPEAT)->getValue32() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMusicPlayer::isShuffleEnabled() const
|
||||||
|
{
|
||||||
|
return (NLGUI::CDBManager::getInstance()->getDbProp(MP3_SAVE_SHUFFLE)->getValue32() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,16 +74,61 @@ void CMusicPlayer::playSongs (const std::vector<CSongs> &songs)
|
||||||
_Songs = songs;
|
_Songs = songs;
|
||||||
|
|
||||||
// reset song index if out of bounds
|
// reset song index if out of bounds
|
||||||
if (_CurrentSong > _Songs.size())
|
if (_CurrentSongIndex > _Songs.size())
|
||||||
_CurrentSong = 0;
|
_CurrentSongIndex = 0;
|
||||||
|
|
||||||
|
if (isShuffleEnabled())
|
||||||
|
shuffleAndRebuildPlaylist();
|
||||||
|
else
|
||||||
|
rebuildPlaylist();
|
||||||
|
|
||||||
|
// If pause, stop, else play will resume
|
||||||
|
if (_State == Paused)
|
||||||
|
_State = Stopped;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
void CMusicPlayer::updatePlaylist(sint prevIndex)
|
||||||
|
{
|
||||||
|
CInterfaceElement *pIE;
|
||||||
|
std::string rowId;
|
||||||
|
|
||||||
|
if (prevIndex >= 0 && prevIndex < _Songs.size())
|
||||||
|
{
|
||||||
|
rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, prevIndex);
|
||||||
|
pIE = dynamic_cast<CInterfaceElement*>(CWidgetManager::getInstance()->getElementFromId(rowId));
|
||||||
|
if (pIE) pIE->setActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, _CurrentSongIndex);
|
||||||
|
pIE = dynamic_cast<CInterfaceElement*>(CWidgetManager::getInstance()->getElementFromId(rowId));
|
||||||
|
if (pIE) pIE->setActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
void CMusicPlayer::shuffleAndRebuildPlaylist()
|
||||||
|
{
|
||||||
|
std::random_shuffle(_Songs.begin(), _Songs.end());
|
||||||
|
rebuildPlaylist();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
void CMusicPlayer::rebuildPlaylist()
|
||||||
|
{
|
||||||
CGroupList *pList = dynamic_cast<CGroupList *>(CWidgetManager::getInstance()->getElementFromId(MP3_PLAYER_PLAYLIST_LIST));
|
CGroupList *pList = dynamic_cast<CGroupList *>(CWidgetManager::getInstance()->getElementFromId(MP3_PLAYER_PLAYLIST_LIST));
|
||||||
if (pList)
|
if (pList)
|
||||||
{
|
{
|
||||||
pList->clearGroups();
|
pList->clearGroups();
|
||||||
pList->setDynamicDisplaySize(true);
|
pList->setDynamicDisplaySize(true);
|
||||||
|
bool found = _CurrentSong.Filename.empty();
|
||||||
for (uint i=0; i < _Songs.size(); ++i)
|
for (uint i=0; i < _Songs.size(); ++i)
|
||||||
{
|
{
|
||||||
|
if (!found && _CurrentSong.Filename == _Songs[i].Filename)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
_CurrentSongIndex = i;
|
||||||
|
}
|
||||||
|
|
||||||
uint min = (sint32)(_Songs[i].Length / 60) % 60;
|
uint min = (sint32)(_Songs[i].Length / 60) % 60;
|
||||||
uint sec = (sint32)(_Songs[i].Length) % 60;
|
uint sec = (sint32)(_Songs[i].Length) % 60;
|
||||||
uint hour = _Songs[i].Length / 3600;
|
uint hour = _Songs[i].Length / 3600;
|
||||||
|
@ -103,9 +163,7 @@ void CMusicPlayer::playSongs (const std::vector<CSongs> &songs)
|
||||||
pList->invalidateCoords();
|
pList->invalidateCoords();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If pause, stop, else play will resume
|
updatePlaylist();
|
||||||
if (_State == Paused)
|
|
||||||
_State = Stopped;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,31 +174,43 @@ void CMusicPlayer::play (sint index)
|
||||||
if(!SoundMngr)
|
if(!SoundMngr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
sint prevSongIndex = _CurrentSongIndex;
|
||||||
|
|
||||||
if (index >= 0 && index < (sint)_Songs.size())
|
if (index >= 0 && index < (sint)_Songs.size())
|
||||||
{
|
{
|
||||||
if (_State == Paused)
|
if (_State == Paused)
|
||||||
|
{
|
||||||
stop();
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
_CurrentSong = index;
|
_CurrentSongIndex = index;
|
||||||
|
_PauseTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_Songs.empty())
|
if (!_Songs.empty())
|
||||||
{
|
{
|
||||||
nlassert (_CurrentSong<_Songs.size());
|
nlassert (_CurrentSongIndex<_Songs.size());
|
||||||
|
|
||||||
/* If the player is paused, resume, else, play the current song */
|
/* If the player is paused, resume, else, play the current song */
|
||||||
if (_State == Paused)
|
if (_State == Paused)
|
||||||
|
{
|
||||||
SoundMngr->resumeMusic();
|
SoundMngr->resumeMusic();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
SoundMngr->playMusic(_Songs[_CurrentSong].Filename, 0, true, false, false);
|
{
|
||||||
|
SoundMngr->playMusic(_Songs[_CurrentSongIndex].Filename, 0, true, false, false);
|
||||||
|
_PauseTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
_State = Playing;
|
_State = Playing;
|
||||||
|
_PlayStart = CTime::getLocalTime() - _PauseTime;
|
||||||
|
|
||||||
/* Show the song title */
|
_CurrentSong = _Songs[_CurrentSongIndex];
|
||||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
|
||||||
CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text"));
|
updatePlaylist(prevSongIndex);
|
||||||
if (pVT)
|
|
||||||
pVT->setText (ucstring::makeFromUtf8(_Songs[_CurrentSong].Title));
|
NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MP3_PLAYING")->setValueBool(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,11 +220,17 @@ void CMusicPlayer::pause ()
|
||||||
{
|
{
|
||||||
if(!SoundMngr)
|
if(!SoundMngr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// pause the music only if we are really playing (else risk to pause a background music!)
|
// pause the music only if we are really playing (else risk to pause a background music!)
|
||||||
if(_State==Playing)
|
if(_State==Playing)
|
||||||
{
|
{
|
||||||
SoundMngr->pauseMusic();
|
SoundMngr->pauseMusic();
|
||||||
_State = Paused;
|
_State = Paused;
|
||||||
|
|
||||||
|
if (_PlayStart > 0)
|
||||||
|
_PauseTime = CTime::getLocalTime() - _PlayStart;
|
||||||
|
|
||||||
|
NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MP3_PLAYING")->setValueBool(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,9 +240,14 @@ void CMusicPlayer::stop ()
|
||||||
{
|
{
|
||||||
if(!SoundMngr)
|
if(!SoundMngr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// stop the music only if we are really playing (else risk to stop a background music!)
|
// stop the music only if we are really playing (else risk to stop a background music!)
|
||||||
SoundMngr->stopMusic(0);
|
SoundMngr->stopMusic(0);
|
||||||
_State = Stopped;
|
_State = Stopped;
|
||||||
|
_PlayStart = 0;
|
||||||
|
_PauseTime = 0;
|
||||||
|
|
||||||
|
NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MP3_PLAYING")->setValueBool(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
@ -176,12 +257,13 @@ void CMusicPlayer::previous ()
|
||||||
if (!_Songs.empty())
|
if (!_Songs.empty())
|
||||||
{
|
{
|
||||||
// Point the previous song
|
// Point the previous song
|
||||||
if (_CurrentSong == 0)
|
sint index;
|
||||||
_CurrentSong = (uint)_Songs.size()-1;
|
if (_CurrentSongIndex == 0)
|
||||||
|
index = (uint)_Songs.size()-1;
|
||||||
else
|
else
|
||||||
_CurrentSong--;
|
index = _CurrentSongIndex-1;
|
||||||
|
|
||||||
play ();
|
play(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,9 +273,11 @@ void CMusicPlayer::next ()
|
||||||
{
|
{
|
||||||
if (!_Songs.empty())
|
if (!_Songs.empty())
|
||||||
{
|
{
|
||||||
_CurrentSong++;
|
sint index = _CurrentSongIndex+1;
|
||||||
_CurrentSong%=_Songs.size();
|
if (index == _Songs.size())
|
||||||
play ();
|
index = 0;
|
||||||
|
|
||||||
|
play(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,17 +289,35 @@ void CMusicPlayer::update ()
|
||||||
return;
|
return;
|
||||||
if (_State == Playing)
|
if (_State == Playing)
|
||||||
{
|
{
|
||||||
|
CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text"));
|
||||||
|
if (pVT)
|
||||||
|
{
|
||||||
|
TTime dur = (CTime::getLocalTime() - _PlayStart) / 1000;
|
||||||
|
uint min = (dur / 60) % 60;
|
||||||
|
uint sec = dur % 60;
|
||||||
|
uint hour = dur / 3600;
|
||||||
|
|
||||||
|
std::string title(toString("%02d:%02d", min, sec));
|
||||||
|
if (hour > 0) title = toString("%02d:", hour) + title;
|
||||||
|
title += " " + _CurrentSong.Title;
|
||||||
|
pVT->setText(ucstring::makeFromUtf8(title));
|
||||||
|
}
|
||||||
|
|
||||||
if (SoundMngr->isMusicEnded ())
|
if (SoundMngr->isMusicEnded ())
|
||||||
{
|
{
|
||||||
// Point the next song
|
// select next song from playlist
|
||||||
_CurrentSong++;
|
sint index = _CurrentSongIndex + 1;
|
||||||
_CurrentSong%=_Songs.size();
|
if (isRepeatEnabled() || index < _Songs.size())
|
||||||
|
|
||||||
// End of the playlist ?
|
|
||||||
if (_CurrentSong != 0)
|
|
||||||
{
|
{
|
||||||
// No, play the next song
|
if (index == _Songs.size())
|
||||||
play ();
|
{
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
if (isShuffleEnabled())
|
||||||
|
shuffleAndRebuildPlaylist();
|
||||||
|
}
|
||||||
|
|
||||||
|
play(index);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -284,22 +386,10 @@ public:
|
||||||
// no format supported
|
// no format supported
|
||||||
if (extensions.empty()) return;
|
if (extensions.empty()) return;
|
||||||
|
|
||||||
bool oggSupported = false;
|
|
||||||
bool mp3Supported = false;
|
|
||||||
|
|
||||||
std::string message;
|
std::string message;
|
||||||
for(uint i = 0; i < extensions.size(); ++i)
|
for(uint i = 0; i < extensions.size(); ++i)
|
||||||
{
|
{
|
||||||
if (extensions[i] == "ogg")
|
message += " " + extensions[i];
|
||||||
{
|
|
||||||
oggSupported = true;
|
|
||||||
message += " ogg";
|
|
||||||
}
|
|
||||||
else if (extensions[i] == "mp3")
|
|
||||||
{
|
|
||||||
mp3Supported = true;
|
|
||||||
message += " mp3";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
message += " m3u m3u8";
|
message += " m3u m3u8";
|
||||||
nlinfo("Media player supports: '%s'", message.substr(1).c_str());
|
nlinfo("Media player supports: '%s'", message.substr(1).c_str());
|
||||||
|
@ -316,15 +406,9 @@ public:
|
||||||
for (i = 0; i < filesToProcess.size(); ++i)
|
for (i = 0; i < filesToProcess.size(); ++i)
|
||||||
{
|
{
|
||||||
std::string ext = toLower(CFile::getExtension(filesToProcess[i]));
|
std::string ext = toLower(CFile::getExtension(filesToProcess[i]));
|
||||||
if (ext == "ogg")
|
if (std::find(extensions.begin(), extensions.end(), ext) != extensions.end())
|
||||||
{
|
{
|
||||||
if (oggSupported)
|
filenames.push_back(filesToProcess[i]);
|
||||||
filenames.push_back(filesToProcess[i]);
|
|
||||||
}
|
|
||||||
else if (ext == "mp3" || ext == "mp2" || ext == "mp1")
|
|
||||||
{
|
|
||||||
if (mp3Supported)
|
|
||||||
filenames.push_back(filesToProcess[i]);
|
|
||||||
}
|
}
|
||||||
else if (ext == "m3u" || ext == "m3u8")
|
else if (ext == "m3u" || ext == "m3u8")
|
||||||
{
|
{
|
||||||
|
@ -345,14 +429,6 @@ public:
|
||||||
std::vector<CMusicPlayer::CSongs> songs;
|
std::vector<CMusicPlayer::CSongs> songs;
|
||||||
for (i=0; i<filenames.size(); i++)
|
for (i=0; i<filenames.size(); i++)
|
||||||
{
|
{
|
||||||
// '@' in filenames are reserved for .bnp files
|
|
||||||
// and sound system fails to open such file
|
|
||||||
if (filenames[i].find("@") != string::npos)
|
|
||||||
{
|
|
||||||
nlwarning("Ignore media file containing '@' in name: '%s'", filenames[i].c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CFile::fileExists(filenames[i])) {
|
if (!CFile::fileExists(filenames[i])) {
|
||||||
nlwarning("Ignore non-existing file '%s'", filenames[i].c_str());
|
nlwarning("Ignore non-existing file '%s'", filenames[i].c_str());
|
||||||
continue;
|
continue;
|
||||||
|
@ -360,16 +436,27 @@ public:
|
||||||
|
|
||||||
CMusicPlayer::CSongs song;
|
CMusicPlayer::CSongs song;
|
||||||
song.Filename = filenames[i];
|
song.Filename = filenames[i];
|
||||||
|
// TODO: cache the result for next refresh
|
||||||
SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title, song.Length);
|
SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title, song.Length);
|
||||||
songs.push_back (song);
|
if (song.Length > 0)
|
||||||
|
songs.push_back (song);
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicPlayer.playSongs(songs);
|
MusicPlayer.playSongs(songs);
|
||||||
}
|
}
|
||||||
|
else if (Params == "update_playlist")
|
||||||
|
{
|
||||||
|
if (MusicPlayer.isShuffleEnabled())
|
||||||
|
MusicPlayer.shuffleAndRebuildPlaylist();
|
||||||
|
|
||||||
|
MusicPlayer.rebuildPlaylist();
|
||||||
|
}
|
||||||
else if (Params == "previous")
|
else if (Params == "previous")
|
||||||
MusicPlayer.previous();
|
MusicPlayer.previous();
|
||||||
else if (Params == "play")
|
else if (Params == "play")
|
||||||
MusicPlayer.play();
|
MusicPlayer.play();
|
||||||
|
else if (Params == "stop")
|
||||||
|
MusicPlayer.stop();
|
||||||
else if (Params == "pause")
|
else if (Params == "pause")
|
||||||
MusicPlayer.pause();
|
MusicPlayer.pause();
|
||||||
else if (Params == "next")
|
else if (Params == "next")
|
||||||
|
|
|
@ -55,14 +55,28 @@ public:
|
||||||
|
|
||||||
void update ();
|
void update ();
|
||||||
|
|
||||||
|
bool isRepeatEnabled() const;
|
||||||
|
bool isShuffleEnabled() const;
|
||||||
|
|
||||||
|
// Build playlist UI from songs
|
||||||
|
void rebuildPlaylist();
|
||||||
|
// Randomize playlist and rebuild the ui
|
||||||
|
void shuffleAndRebuildPlaylist();
|
||||||
|
// Update playlist active row
|
||||||
|
void updatePlaylist(sint prevIndex = -1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// The playlist
|
// The playlist
|
||||||
uint _CurrentSong; // If (!_Songs.empty()) must always be <_Songs.size()
|
CSongs _CurrentSong;
|
||||||
|
uint _CurrentSongIndex; // If (!_Songs.empty()) must always be <_Songs.size()
|
||||||
std::vector<CSongs> _Songs;
|
std::vector<CSongs> _Songs;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
enum TState { Stopped, Playing, Paused } _State;
|
enum TState { Stopped, Playing, Paused } _State;
|
||||||
|
|
||||||
|
TTime _PlayStart;
|
||||||
|
TTime _PauseTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CMusicPlayer MusicPlayer;
|
extern CMusicPlayer MusicPlayer;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "../commands.h"
|
#include "../commands.h"
|
||||||
#include "interface_3d_scene.h"
|
#include "interface_3d_scene.h"
|
||||||
#include "nel/misc/i_xml.h"
|
#include "nel/misc/i_xml.h"
|
||||||
|
#include "../continent_manager.h"
|
||||||
|
|
||||||
using namespace NLMISC;
|
using namespace NLMISC;
|
||||||
|
|
||||||
|
@ -31,6 +32,8 @@ using namespace NLMISC;
|
||||||
#include "../client_cfg.h"
|
#include "../client_cfg.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern CContinentManager ContinentMngr;
|
||||||
|
|
||||||
CIF3DSceneParser::CIF3DSceneParser()
|
CIF3DSceneParser::CIF3DSceneParser()
|
||||||
{
|
{
|
||||||
parsingStage |= ( Resolved | GroupChildren );
|
parsingStage |= ( Resolved | GroupChildren );
|
||||||
|
@ -529,3 +532,21 @@ bool CMacroParser::parse( xmlNodePtr cur, NLGUI::CInterfaceGroup *parentGroup )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLandmarkParser::CLandmarkParser()
|
||||||
|
{
|
||||||
|
parsingStage |= Unresolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLandmarkParser::~CLandmarkParser()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CLandmarkParser::parse( xmlNodePtr cur, NLGUI::CInterfaceGroup *parentGroup )
|
||||||
|
{
|
||||||
|
H_AUTO(parseLandmark)
|
||||||
|
|
||||||
|
ContinentMngr.readFrom(cur);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,4 +76,13 @@ public:
|
||||||
bool parse( xmlNodePtr cur, CInterfaceGroup *parentGroup );
|
bool parse( xmlNodePtr cur, CInterfaceGroup *parentGroup );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CLandmarkParser : public CInterfaceParser::IParserModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CLandmarkParser();
|
||||||
|
~CLandmarkParser();
|
||||||
|
|
||||||
|
bool parse( xmlNodePtr cur, CInterfaceGroup *parentGroup );
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,6 +34,7 @@ void registerInterfaceElements()
|
||||||
CViewPointerRyzom::forceLinking();
|
CViewPointerRyzom::forceLinking();
|
||||||
|
|
||||||
REGISTER_REFLECTABLE_CLASS(CViewRadar, CViewBase);
|
REGISTER_REFLECTABLE_CLASS(CViewRadar, CViewBase);
|
||||||
|
REGISTER_REFLECTABLE_CLASS(CGroupMap, CInterfaceGroup);
|
||||||
REGISTER_REFLECTABLE_CLASS(CDBCtrlSheet, CCtrlDraggable);
|
REGISTER_REFLECTABLE_CLASS(CDBCtrlSheet, CCtrlDraggable);
|
||||||
REGISTER_REFLECTABLE_CLASS(IListSheetBase, CInterfaceGroup);
|
REGISTER_REFLECTABLE_CLASS(IListSheetBase, CInterfaceGroup);
|
||||||
REGISTER_REFLECTABLE_CLASS(CInterface3DScene, CInterfaceGroup);
|
REGISTER_REFLECTABLE_CLASS(CInterface3DScene, CInterfaceGroup);
|
||||||
|
|
|
@ -3419,6 +3419,22 @@ void displayDebugClusters()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NLMISC_COMMAND(dumpFontTexture, "Write font texture to file", "")
|
||||||
|
{
|
||||||
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
||||||
|
if (TextContext)
|
||||||
|
{
|
||||||
|
std::string fname = CFile::findNewFile("font-texture.tga");
|
||||||
|
TextContext->dumpCacheTexture(fname.c_str());
|
||||||
|
im->displaySystemInfo(ucstring(fname + " created"), "SYS");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
im->displaySystemInfo(ucstring("Error: TextContext == NULL"), "SYS");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
void inGamePatchUncompleteWarning()
|
void inGamePatchUncompleteWarning()
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "sound_manager.h"
|
#include "sound_manager.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
|
#include "interface_v3/interface_manager.h"
|
||||||
|
|
||||||
using namespace NLMISC;
|
using namespace NLMISC;
|
||||||
using namespace NL3D;
|
using namespace NL3D;
|
||||||
|
@ -100,6 +101,12 @@ void updateFromClientCfg()
|
||||||
Driver->forceTextureResize(1);
|
Driver->forceTextureResize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ClientCfg.InterfaceScale != LastClientCfg.InterfaceScale)
|
||||||
|
CInterfaceManager::getInstance()->setInterfaceScale(ClientCfg.InterfaceScale);
|
||||||
|
|
||||||
|
if (ClientCfg.BilinearUI != LastClientCfg.BilinearUI)
|
||||||
|
CViewRenderer::getInstance()->setBilinearFiltering(ClientCfg.BilinearUI);
|
||||||
|
|
||||||
//---------------------------------------------------
|
//---------------------------------------------------
|
||||||
if (ClientCfg.WaitVBL != LastClientCfg.WaitVBL)
|
if (ClientCfg.WaitVBL != LastClientCfg.WaitVBL)
|
||||||
{
|
{
|
||||||
|
@ -395,4 +402,4 @@ void updateFromClientCfg()
|
||||||
LastClientCfg = ClientCfg;
|
LastClientCfg = ClientCfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of file */
|
/* end of file */
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue