Merged changes in the trunk up to revision 40911.
Conflicts resolved: source/blender/blenloader/intern/readfile.c
This commit is contained in:
125
CMakeLists.txt
125
CMakeLists.txt
@@ -189,7 +189,6 @@ option(WITH_OPENCOLLADA "Enable OpenCollada Support (http://www.opencollada.org
|
||||
option(WITH_SDL "Enable SDL for sound and joystick support" ON)
|
||||
option(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON)
|
||||
option(WITH_JACK "Enable Jack Support (http://www.jackaudio.org)" OFF)
|
||||
option(WITH_SAMPLERATE "Enable samplerate conversion" ON)
|
||||
|
||||
# Compression
|
||||
option(WITH_LZO "Enable fast LZO compression (used for pointcache)" ON)
|
||||
@@ -273,7 +272,7 @@ if(WITH_PYTHON_MODULE)
|
||||
set(WITH_HEADLESS ON)
|
||||
endif()
|
||||
|
||||
TEST_SSE_SUPPORT()
|
||||
TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
|
||||
|
||||
# don't store paths to libs for portable distrobution
|
||||
if(WITH_INSTALL_PORTABLE)
|
||||
@@ -287,7 +286,7 @@ endif()
|
||||
set(WITH_BINRELOC OFF)
|
||||
|
||||
# MAXOSX only, set to avoid uninitialized
|
||||
set(EXETYPE)
|
||||
set(EXETYPE "")
|
||||
|
||||
# C/C++ flags
|
||||
set(PLATFORM_CFLAGS)
|
||||
@@ -298,13 +297,13 @@ set(CXX_WARNINGS)
|
||||
|
||||
# libraries to link the binary with passed to target_link_libraries()
|
||||
# known as LLIBS to scons
|
||||
set(PLATFORM_LINKLIBS)
|
||||
set(PLATFORM_LINKLIBS "")
|
||||
|
||||
# Added to linker flags in setup_liblinks
|
||||
# - CMAKE_EXE_LINKER_FLAGS
|
||||
# - CMAKE_EXE_LINKER_FLAGS_DEBUG
|
||||
set(PLATFORM_LINKFLAGS)
|
||||
set(PLATFORM_LINKFLAGS_DEBUG)
|
||||
set(PLATFORM_LINKFLAGS "")
|
||||
set(PLATFORM_LINKFLAGS_DEBUG "")
|
||||
|
||||
|
||||
# disabled for now, not supported
|
||||
@@ -381,10 +380,12 @@ if(UNIX AND NOT APPLE)
|
||||
|
||||
if(WITH_SDL)
|
||||
find_package(SDL)
|
||||
mark_as_advanced(SDLMAIN_LIBRARY)
|
||||
mark_as_advanced(SDL_INCLUDE_DIR)
|
||||
mark_as_advanced(SDL_LIBRARY)
|
||||
mark_as_advanced(SDL_LIBRARY_TEMP)
|
||||
mark_as_advanced(
|
||||
SDLMAIN_LIBRARY
|
||||
SDL_INCLUDE_DIR
|
||||
SDL_LIBRARY
|
||||
SDL_LIBRARY_TEMP
|
||||
)
|
||||
# unset(SDLMAIN_LIBRARY CACHE)
|
||||
if(NOT SDL_FOUND)
|
||||
set(WITH_SDL OFF)
|
||||
@@ -428,11 +429,13 @@ if(UNIX AND NOT APPLE)
|
||||
PATHS
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(ICONV_LIBRARY)
|
||||
mark_as_advanced(INTL_LIBRARY)
|
||||
mark_as_advanced(
|
||||
ICONV_LIBRARY
|
||||
INTL_LIBRARY
|
||||
)
|
||||
|
||||
if(INTL_LIBRARY AND ICONV_LIBRARY)
|
||||
set(GETTEXT_LIB ${INTL_LIBRARY} ${ICONV_LIBRARY})
|
||||
set(GETTEXT_LIBRARIES ${INTL_LIBRARY} ${ICONV_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -443,13 +446,6 @@ if(UNIX AND NOT APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_SAMPLERATE)
|
||||
find_package(Samplerate)
|
||||
if(NOT SAMPLERATE_FOUND)
|
||||
set(WITH_SAMPLERATE OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_OPENCOLLADA)
|
||||
find_package(OpenCOLLADA)
|
||||
if(OPENCOLLADA_FOUND)
|
||||
@@ -488,17 +484,17 @@ if(UNIX AND NOT APPLE)
|
||||
find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH})
|
||||
mark_as_advanced(X11_XF86keysym_INCLUDE_PATH)
|
||||
|
||||
list(APPEND PLATFORM_LINKLIBS ${X11_X11_LIB})
|
||||
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} ${X11_X11_LIB}")
|
||||
|
||||
if(WITH_X11_XINPUT)
|
||||
list(APPEND PLATFORM_LINKLIBS ${X11_Xinput_LIB})
|
||||
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} ${X11_Xinput_LIB}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
if(NOT WITH_PYTHON_MODULE)
|
||||
# BSD's dont use libdl.so
|
||||
list(APPEND PLATFORM_LINKLIBS -ldl)
|
||||
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} -ldl")
|
||||
# binreloc is linux only
|
||||
set(BINRELOC_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/binreloc/include)
|
||||
set(WITH_BINRELOC ON)
|
||||
@@ -561,13 +557,6 @@ elseif(WIN32)
|
||||
set(ICONV_LIBPATH ${ICONV}/lib)
|
||||
endif()
|
||||
|
||||
if(WITH_SAMPLERATE)
|
||||
set(SAMPLERATE ${LIBDIR}/samplerate)
|
||||
set(SAMPLERATE_INCLUDE_DIRS ${SAMPLERATE}/include)
|
||||
set(SAMPLERATE_LIBRARIES libsamplerate)
|
||||
set(SAMPLERATE_LIBPATH ${SAMPLERATE}/lib)
|
||||
endif()
|
||||
|
||||
set(PNG "${LIBDIR}/png")
|
||||
set(PNG_INCLUDE_DIR "${PNG}/include")
|
||||
set(PNG_LIBPATH ${PNG}/lib) # not cmake defined
|
||||
@@ -641,9 +630,9 @@ elseif(WIN32)
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
set(GETTEXT ${LIBDIR}/gettext)
|
||||
set(GETTEXT_INC ${GETTEXT}/include)
|
||||
set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include)
|
||||
set(GETTEXT_LIBPATH ${GETTEXT}/lib)
|
||||
set(GETTEXT_LIB gnu_gettext)
|
||||
set(GETTEXT_LIBRARIES gnu_gettext)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CL_64)
|
||||
@@ -800,9 +789,9 @@ elseif(WIN32)
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
set(GETTEXT ${LIBDIR}/gcc/gettext)
|
||||
set(GETTEXT_INC ${GETTEXT}/include)
|
||||
set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include)
|
||||
set(GETTEXT_LIBPATH ${GETTEXT}/lib)
|
||||
set(GETTEXT_LIB intl)
|
||||
set(GETTEXT_LIBRARIES intl)
|
||||
endif()
|
||||
|
||||
set(JPEG_LIBRARIES libjpeg)
|
||||
@@ -952,8 +941,8 @@ elseif(APPLE)
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
set(GETTEXT ${LIBDIR}/gettext)
|
||||
set(GETTEXT_INC "${GETTEXT}/include")
|
||||
set(GETTEXT_LIB intl iconv)
|
||||
set(GETTEXT_INCLUDE_DIRS "${GETTEXT}/include")
|
||||
set(GETTEXT_LIBRARIES intl iconv)
|
||||
set(GETTEXT_LIBPATH ${GETTEXT}/lib)
|
||||
endif()
|
||||
|
||||
@@ -991,13 +980,6 @@ elseif(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS")
|
||||
endif()
|
||||
|
||||
if(WITH_SAMPLERATE)
|
||||
set(SAMPLERATE ${LIBDIR}/samplerate)
|
||||
set(SAMPLERATE_INCLUDE_DIRS ${SAMPLERATE}/include)
|
||||
set(SAMPLERATE_LIBRARIES samplerate)
|
||||
set(SAMPLERATE_LIBPATH ${SAMPLERATE}/lib)
|
||||
endif()
|
||||
|
||||
find_library(SYSTEMSTUBS_LIBRARY
|
||||
NAMES
|
||||
SystemStubs
|
||||
@@ -1101,11 +1083,11 @@ elseif(APPLE)
|
||||
set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-fno-strict-aliasing -g")
|
||||
if(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O2 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller")
|
||||
elseif(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O2 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing")
|
||||
@@ -1124,35 +1106,25 @@ endif()
|
||||
# See TEST_SSE_SUPPORT() for how this is defined.
|
||||
|
||||
if(WITH_RAYOPTIMIZATION)
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(_sse "-msse")
|
||||
set(_sse2 "-msse2")
|
||||
elseif(MSVC)
|
||||
set(_sse "/arch:SSE")
|
||||
set(_sse2 "/arch:SSE2")
|
||||
else()
|
||||
message(WARNING "SSE flags for this compiler not known")
|
||||
set(_sse)
|
||||
set(_sse2)
|
||||
endif()
|
||||
|
||||
if(SUPPORT_SSE_BUILD)
|
||||
set(PLATFORM_CFLAGS " ${_sse} ${PLATFORM_CFLAGS}")
|
||||
set(PLATFORM_CFLAGS " ${COMPILER_SSE_FLAG} ${PLATFORM_CFLAGS}")
|
||||
add_definitions(-D__SSE__ -D__MMX__)
|
||||
endif()
|
||||
if(SUPPORT_SSE2_BUILD)
|
||||
set(PLATFORM_CFLAGS " ${_sse2} ${PLATFORM_CFLAGS}")
|
||||
set(PLATFORM_CFLAGS " ${COMPILER_SSE2_FLAG} ${PLATFORM_CFLAGS}")
|
||||
add_definitions(-D__SSE2__)
|
||||
if(NOT SUPPORT_SSE_BUILD) # dont double up
|
||||
add_definitions(-D__MMX__)
|
||||
endif()
|
||||
endif()
|
||||
unset(_sse)
|
||||
unset(_sse2)
|
||||
endif()
|
||||
|
||||
|
||||
# set the endian define
|
||||
if(MSVC)
|
||||
# for some reason this fails on msvc
|
||||
add_definitions(-D__LITTLE_ENDIAN__)
|
||||
else()
|
||||
include(TestBigEndian)
|
||||
test_big_endian(_SYSTEM_BIG_ENDIAN)
|
||||
if(_SYSTEM_BIG_ENDIAN)
|
||||
@@ -1161,6 +1133,7 @@ else()
|
||||
add_definitions(-D__LITTLE_ENDIAN__)
|
||||
endif()
|
||||
unset(_SYSTEM_BIG_ENDIAN)
|
||||
endif()
|
||||
|
||||
|
||||
if(WITH_IMAGE_OPENJPEG)
|
||||
@@ -1209,8 +1182,10 @@ if(WITH_OPENMP)
|
||||
set(WITH_OPENMP OFF)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(OpenMP_C_FLAGS)
|
||||
mark_as_advanced(OpenMP_CXX_FLAGS)
|
||||
mark_as_advanced(
|
||||
OpenMP_C_FLAGS
|
||||
OpenMP_CXX_FLAGS
|
||||
)
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
@@ -1226,8 +1201,10 @@ else()
|
||||
message(FATAL_ERROR "GLEW is required to build blender, install it or use WITH_BUILTIN_GLEW")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(GLEW_LIBRARY)
|
||||
mark_as_advanced(GLEW_INCLUDE_PATH)
|
||||
mark_as_advanced(
|
||||
GLEW_LIBRARY
|
||||
GLEW_INCLUDE_PATH
|
||||
)
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
@@ -1269,7 +1246,10 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_POINTER_ARITH -Wpointer-arith)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_WRITE_STRINGS -Wwrite-strings)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNDEFINED -Wundef)
|
||||
|
||||
# # this causes too many warnings, disable
|
||||
# ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNDEFINED -Wundef)
|
||||
|
||||
# disable because it gives warnings for printf() & friends.
|
||||
# ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_DOUBLE_PROMOTION -Wdouble-promotion -Wno-error=double-promotion)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_ERROR_UNUSED_BUT_SET_VARIABLE -Wno-error=unused-but-set-variable)
|
||||
@@ -1277,7 +1257,9 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEFINED -Wundef)
|
||||
|
||||
# # this causes too many warnings, disable
|
||||
# ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEFINED -Wundef)
|
||||
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
|
||||
|
||||
@@ -1289,6 +1271,10 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
|
||||
|
||||
# disable numbered, false positives
|
||||
set(C_WARNINGS "${C_WARNINGS} -wd188,186,144,913,556")
|
||||
set(CXX_WARNINGS "${CXX_WARNINGS} -wd188,186,144,913,556")
|
||||
|
||||
endif()
|
||||
|
||||
# MSVC2010 fails to links C++ libs right
|
||||
@@ -1428,7 +1414,6 @@ if(FIRST_RUN)
|
||||
info_cfg_option(WITH_JACK)
|
||||
info_cfg_option(WITH_CODEC_FFMPEG)
|
||||
info_cfg_option(WITH_CODEC_SNDFILE)
|
||||
info_cfg_option(WITH_SAMPLERATE)
|
||||
|
||||
info_cfg_text("Compression:")
|
||||
info_cfg_option(WITH_LZMA)
|
||||
|
||||
@@ -164,7 +164,7 @@ package_archive:
|
||||
# Other Targets
|
||||
#
|
||||
translations:
|
||||
$(BUILD_DIR)/bin/blender --background --python po/update_msg.py
|
||||
$(BUILD_DIR)/bin/blender --background --factory-startup --python po/update_msg.py
|
||||
python3 po/update_pot.py
|
||||
python3 po/update_po.py
|
||||
python3 po/update_mo.py
|
||||
|
||||
14
SConstruct
14
SConstruct
@@ -30,6 +30,7 @@
|
||||
# Then read all SConscripts and build
|
||||
#
|
||||
# TODO: fix /FORCE:MULTIPLE on windows to get proper debug builds.
|
||||
# TODO: cleanup CCFLAGS / CPPFLAGS use, often both are set when we only need one.
|
||||
|
||||
import platform as pltfrm
|
||||
|
||||
@@ -277,32 +278,27 @@ if env['OURPLATFORM']=='darwin':
|
||||
print "3D_CONNEXION_CLIENT_LIBRARY not found, disabling WITH_BF_3DMOUSE" # avoid build errors !
|
||||
env['WITH_BF_3DMOUSE'] = 0
|
||||
else:
|
||||
env.Append(LINKFLAGS=['-weak_framework','3DconnexionClient'])
|
||||
env.Append(LINKFLAGS=['-Xlinker','-weak_framework','-Xlinker','3DconnexionClient'])
|
||||
|
||||
if env['WITH_BF_OPENMP'] == 1:
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
|
||||
env['CCFLAGS'].append('/openmp')
|
||||
env['CPPFLAGS'].append('/openmp')
|
||||
env['CXXFLAGS'].append('/openmp')
|
||||
else:
|
||||
if env['CC'].endswith('icc'): # to be able to handle CC=/opt/bla/icc case
|
||||
env.Append(LINKFLAGS=['-openmp', '-static-intel'])
|
||||
env['CCFLAGS'].append('-openmp')
|
||||
env['CPPFLAGS'].append('-openmp')
|
||||
env['CXXFLAGS'].append('-openmp')
|
||||
else:
|
||||
env.Append(CCFLAGS=['-fopenmp'])
|
||||
env.Append(CPPFLAGS=['-fopenmp'])
|
||||
env.Append(CXXFLAGS=['-fopenmp'])
|
||||
|
||||
if env['WITH_GHOST_COCOA'] == True:
|
||||
env.Append(CFLAGS=['-DGHOST_COCOA'])
|
||||
env.Append(CXXFLAGS=['-DGHOST_COCOA'])
|
||||
env.Append(CPPFLAGS=['-DGHOST_COCOA'])
|
||||
|
||||
if env['USE_QTKIT'] == True:
|
||||
env.Append(CFLAGS=['-DUSE_QTKIT'])
|
||||
env.Append(CXXFLAGS=['-DUSE_QTKIT'])
|
||||
env.Append(CPPFLAGS=['-DUSE_QTKIT'])
|
||||
|
||||
#check for additional debug libnames
|
||||
@@ -334,23 +330,19 @@ if 'blendernogame' in B.targets:
|
||||
# disable elbeem (fluidsim) compilation?
|
||||
if env['BF_NO_ELBEEM'] == 1:
|
||||
env['CPPFLAGS'].append('-DDISABLE_ELBEEM')
|
||||
env['CXXFLAGS'].append('-DDISABLE_ELBEEM')
|
||||
env['CCFLAGS'].append('-DDISABLE_ELBEEM')
|
||||
|
||||
|
||||
if btools.ENDIAN == "big":
|
||||
env['CPPFLAGS'].append('-D__BIG_ENDIAN__')
|
||||
env['CXXFLAGS'].append('-D__BIG_ENDIAN__')
|
||||
env['CCFLAGS'].append('-D__BIG_ENDIAN__')
|
||||
else:
|
||||
env['CPPFLAGS'].append('-D__LITTLE_ENDIAN__')
|
||||
env['CXXFLAGS'].append('-D__LITTLE_ENDIAN__')
|
||||
env['CCFLAGS'].append('-D__LITTLE_ENDIAN__')
|
||||
|
||||
|
||||
# TODO, make optional
|
||||
env['CPPFLAGS'].append('-DWITH_AUDASPACE')
|
||||
env['CXXFLAGS'].append('-DWITH_AUDASPACE')
|
||||
env['CCFLAGS'].append('-DWITH_AUDASPACE')
|
||||
|
||||
# lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
|
||||
@@ -523,7 +515,7 @@ if env['OURPLATFORM']!='darwin':
|
||||
|
||||
for f in df:
|
||||
# This files aren't used anymore
|
||||
if f in ['.Blanguages', '.bfont.ttf']:
|
||||
if f in (".bfont.ttf", ):
|
||||
continue
|
||||
|
||||
if not env['WITH_BF_INTERNATIONAL']:
|
||||
|
||||
@@ -58,8 +58,6 @@ WITH_BF_PNG = True
|
||||
BF_PNG_LIB = 'libpng'
|
||||
BF_PNG_LIBPATH = '/home/sources/staticlibs/lib32'
|
||||
|
||||
WITH_BF_STATICLIBSAMPLERATE = True
|
||||
|
||||
WITH_BF_ZLIB = True
|
||||
WITH_BF_STATICZLIB = True
|
||||
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
|
||||
@@ -91,6 +89,9 @@ BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib32'
|
||||
WITH_BF_FFTW3 = True
|
||||
WITH_BF_STATICFFTW3 = True
|
||||
|
||||
# JACK
|
||||
WITH_BF_JACK = True
|
||||
|
||||
# Compilation and optimization
|
||||
BF_DEBUG = False
|
||||
REL_CFLAGS = ['-O2']
|
||||
|
||||
@@ -52,8 +52,6 @@ WITH_BF_PNG = True
|
||||
BF_PNG_LIB = 'libpng'
|
||||
BF_PNG_LIBPATH = '/home/sources/staticlibs/lib32'
|
||||
|
||||
WITH_BF_STATICLIBSAMPLERATE = True
|
||||
|
||||
WITH_BF_ZLIB = True
|
||||
WITH_BF_STATICZLIB = True
|
||||
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
|
||||
@@ -82,6 +80,9 @@ WITH_BF_STATIC3DMOUSE = True
|
||||
BF_3DMOUSE = '/home/sources/staticlibs/spnav'
|
||||
BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib32'
|
||||
|
||||
# JACK
|
||||
WITH_BF_JACK = True
|
||||
|
||||
# Compilation and optimization
|
||||
BF_DEBUG = False
|
||||
REL_CFLAGS = ['-O2']
|
||||
|
||||
@@ -52,8 +52,6 @@ WITH_BF_PNG = True
|
||||
BF_PNG_LIB = 'libpng'
|
||||
BF_PNG_LIBPATH = '/home/sources/staticlibs/lib64'
|
||||
|
||||
WITH_BF_STATICLIBSAMPLERATE = True
|
||||
|
||||
WITH_BF_ZLIB = True
|
||||
WITH_BF_STATICZLIB = True
|
||||
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
|
||||
@@ -82,6 +80,9 @@ WITH_BF_STATIC3DMOUSE = True
|
||||
BF_3DMOUSE = '/home/sources/staticlibs/spnav'
|
||||
BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib64'
|
||||
|
||||
# JACK
|
||||
WITH_BF_JACK = True
|
||||
|
||||
# Compilation and optimization
|
||||
BF_DEBUG = False
|
||||
REL_CFLAGS = ['-O2']
|
||||
|
||||
@@ -58,8 +58,6 @@ WITH_BF_PNG = True
|
||||
BF_PNG_LIB = 'libpng'
|
||||
BF_PNG_LIBPATH = '/home/sources/staticlibs/lib64'
|
||||
|
||||
WITH_BF_STATICLIBSAMPLERATE = True
|
||||
|
||||
WITH_BF_ZLIB = True
|
||||
WITH_BF_STATICZLIB = True
|
||||
BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
|
||||
@@ -91,6 +89,9 @@ BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib64'
|
||||
WITH_BF_FFTW3 = True
|
||||
WITH_BF_STATICFFTW3 = True
|
||||
|
||||
# JACK
|
||||
WITH_BF_JACK = True
|
||||
|
||||
# Compilation and optimization
|
||||
BF_DEBUG = False
|
||||
REL_CFLAGS = ['-O2']
|
||||
|
||||
@@ -34,16 +34,19 @@ IF(NOT PYTHON_ROOT_DIR AND NOT $ENV{PYTHON_ROOT_DIR} STREQUAL "")
|
||||
SET(PYTHON_ROOT_DIR $ENV{PYTHON_ROOT_DIR})
|
||||
ENDIF()
|
||||
|
||||
IF(DEFINED PYTHON_VERSION)
|
||||
SET(PYTHON_VERSION "${PYTHON_VERSION}" CACHE STRING "")
|
||||
ELSE()
|
||||
SET(PYTHON_VERSION 3.2 CACHE STRING "")
|
||||
ENDIF()
|
||||
SET(PYTHON_VERSION 3.2 CACHE STRING "Python Version (major and minor only)")
|
||||
MARK_AS_ADVANCED(PYTHON_VERSION)
|
||||
|
||||
SET(PYTHON_LINKFLAGS "-Xlinker -export-dynamic")
|
||||
|
||||
# See: http://docs.python.org/extending/embedding.html#linking-requirements
|
||||
# for why this is needed
|
||||
SET(PYTHON_LINKFLAGS "-Xlinker -export-dynamic" CACHE STRING "Linker flags for python")
|
||||
MARK_AS_ADVANCED(PYTHON_LINKFLAGS)
|
||||
|
||||
|
||||
# only search for the dirs if we havn't already
|
||||
IF((NOT DEFINED PYTHON_INCLUDE_DIR) OR (NOT DEFINED PYTHON_LIBRARY))
|
||||
|
||||
SET(_python_ABI_FLAGS
|
||||
"m;mu;u; " # release
|
||||
"md;mud;ud;d" # debug
|
||||
@@ -95,6 +98,7 @@ UNSET(_CURRENT_PATH)
|
||||
|
||||
UNSET(_python_ABI_FLAGS)
|
||||
UNSET(_python_SEARCH_DIRS)
|
||||
ENDIF()
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and SET PYTHONLIBSUNIX_FOUND to TRUE IF
|
||||
# all listed variables are TRUE
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
# - Find Samplerate library
|
||||
# Find the native Samplerate includes and library
|
||||
# This module defines
|
||||
# SAMPLERATE_INCLUDE_DIRS, where to find samplerate.h, Set when
|
||||
# SAMPLERATE_INCLUDE_DIR is found.
|
||||
# SAMPLERATE_LIBRARIES, libraries to link against to use Samplerate.
|
||||
# SAMPLERATE_ROOT_DIR, The base directory to search for Samplerate.
|
||||
# This can also be an environment variable.
|
||||
# SAMPLERATE_FOUND, If false, do not try to use Samplerate.
|
||||
#
|
||||
# also defined, but not for general use are
|
||||
# SAMPLERATE_LIBRARY, where to find the Samplerate library.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2011 Blender Foundation.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
|
||||
# If SAMPLERATE_ROOT_DIR was defined in the environment, use it.
|
||||
IF(NOT SAMPLERATE_ROOT_DIR AND NOT $ENV{SAMPLERATE_ROOT_DIR} STREQUAL "")
|
||||
SET(SAMPLERATE_ROOT_DIR $ENV{SAMPLERATE_ROOT_DIR})
|
||||
ENDIF()
|
||||
|
||||
SET(_samplerate_SEARCH_DIRS
|
||||
${SAMPLERATE_ROOT_DIR}
|
||||
/usr/local
|
||||
/sw # Fink
|
||||
/opt/local # DarwinPorts
|
||||
/opt/csw # Blastwave
|
||||
)
|
||||
|
||||
FIND_PATH(SAMPLERATE_INCLUDE_DIR
|
||||
NAMES
|
||||
samplerate.h
|
||||
HINTS
|
||||
${_samplerate_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(SAMPLERATE_LIBRARY
|
||||
NAMES
|
||||
samplerate
|
||||
HINTS
|
||||
${_samplerate_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
lib64 lib
|
||||
)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set SAMPLERATE_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Samplerate DEFAULT_MSG
|
||||
SAMPLERATE_LIBRARY SAMPLERATE_INCLUDE_DIR)
|
||||
|
||||
IF(SAMPLERATE_FOUND)
|
||||
SET(SAMPLERATE_LIBRARIES ${SAMPLERATE_LIBRARY})
|
||||
SET(SAMPLERATE_INCLUDE_DIRS ${SAMPLERATE_INCLUDE_DIR})
|
||||
ENDIF(SAMPLERATE_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
SAMPLERATE_INCLUDE_DIR
|
||||
SAMPLERATE_LIBRARY
|
||||
)
|
||||
@@ -58,8 +58,8 @@ def main():
|
||||
|
||||
check_commands.append((c, cmd))
|
||||
|
||||
|
||||
process_functions = []
|
||||
|
||||
def my_process(i, c, cmd):
|
||||
percent = 100.0 * (i / (len(check_commands) - 1))
|
||||
percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:"
|
||||
|
||||
@@ -11,7 +11,6 @@ set(WITH_GAMEENGINE OFF CACHE FORCE BOOL)
|
||||
# disable audio, its possible some devs may want this but for now disable
|
||||
# so the python module doesnt hold the audio device and loads quickly.
|
||||
set(WITH_AUDASPACE OFF CACHE FORCE BOOL)
|
||||
set(WITH_SAMPLERATE OFF CACHE FORCE BOOL)
|
||||
set(WITH_FFTW3 OFF CACHE FORCE BOOL)
|
||||
set(WITH_JACK OFF CACHE FORCE BOOL)
|
||||
set(WITH_SDL OFF CACHE FORCE BOOL)
|
||||
|
||||
@@ -38,6 +38,5 @@ set(WITH_OPENCOLLADA OFF CACHE FORCE BOOL)
|
||||
set(WITH_OPENMP OFF CACHE FORCE BOOL)
|
||||
set(WITH_PYTHON_INSTALL OFF CACHE FORCE BOOL)
|
||||
set(WITH_RAYOPTIMIZATION OFF CACHE FORCE BOOL)
|
||||
set(WITH_SAMPLERATE OFF CACHE FORCE BOOL)
|
||||
set(WITH_SDL OFF CACHE FORCE BOOL)
|
||||
set(WITH_X11_XINPUT OFF CACHE FORCE BOOL)
|
||||
|
||||
@@ -18,7 +18,6 @@ set(WITH_GAMEENGINE OFF CACHE FORCE BOOL)
|
||||
# disable audio, its possible some devs may want this but for now disable
|
||||
# so the python module doesnt hold the audio device and loads quickly.
|
||||
set(WITH_AUDASPACE OFF CACHE FORCE BOOL)
|
||||
set(WITH_SAMPLERATE OFF CACHE FORCE BOOL)
|
||||
set(WITH_FFTW3 OFF CACHE FORCE BOOL)
|
||||
set(WITH_JACK OFF CACHE FORCE BOOL)
|
||||
set(WITH_SDL OFF CACHE FORCE BOOL)
|
||||
|
||||
@@ -181,9 +181,6 @@ macro(SETUP_LIBDIRS)
|
||||
if(WITH_CODEC_SNDFILE)
|
||||
link_directories(${SNDFILE_LIBPATH})
|
||||
endif()
|
||||
if(WITH_SAMPLERATE)
|
||||
link_directories(${SAMPLERATE_LIBPATH})
|
||||
endif()
|
||||
if(WITH_FFTW3)
|
||||
link_directories(${FFTW3_LIBPATH})
|
||||
endif()
|
||||
@@ -213,6 +210,7 @@ macro(setup_liblinks
|
||||
${JPEG_LIBRARIES}
|
||||
${PNG_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${FREETYPE_LIBRARY}
|
||||
${PLATFORM_LINKLIBS})
|
||||
|
||||
# since we are using the local libs for python when compiling msvc projects, we need to add _d when compiling debug versions
|
||||
@@ -233,15 +231,8 @@ macro(setup_liblinks
|
||||
target_link_libraries(${target} ${GLEW_LIBRARY})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${target}
|
||||
${OPENGL_glu_LIBRARY}
|
||||
${JPEG_LIBRARIES}
|
||||
${PNG_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${FREETYPE_LIBRARY})
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
target_link_libraries(${target} ${GETTEXT_LIB})
|
||||
target_link_libraries(${target} ${GETTEXT_LIBRARIES})
|
||||
|
||||
if(WIN32 AND NOT UNIX)
|
||||
target_link_libraries(${target} ${ICONV_LIBRARIES})
|
||||
@@ -260,9 +251,6 @@ macro(setup_liblinks
|
||||
if(WITH_CODEC_SNDFILE)
|
||||
target_link_libraries(${target} ${SNDFILE_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_SAMPLERATE)
|
||||
target_link_libraries(${target} ${SAMPLERATE_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_SDL)
|
||||
target_link_libraries(${target} ${SDL_LIBRARY})
|
||||
endif()
|
||||
@@ -286,6 +274,11 @@ macro(setup_liblinks
|
||||
target_link_libraries(${target} ${OPENJPEG_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_CODEC_FFMPEG)
|
||||
|
||||
# Strange!, without this ffmpeg gives linking errors (on linux)
|
||||
# even though its linked above
|
||||
target_link_libraries(${target} ${OPENGL_glu_LIBRARY})
|
||||
|
||||
target_link_libraries(${target} ${FFMPEG_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_OPENCOLLADA)
|
||||
@@ -326,20 +319,35 @@ macro(setup_liblinks
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(TEST_SSE_SUPPORT)
|
||||
macro(TEST_SSE_SUPPORT
|
||||
_sse_flags
|
||||
_sse2_flags)
|
||||
|
||||
include(CheckCSourceRuns)
|
||||
|
||||
# message(STATUS "Detecting SSE support")
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_REQUIRED_FLAGS "-msse -msse2")
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang"))
|
||||
set(${_sse_flags} "-msse")
|
||||
set(${_sse2_flags} "-msse2")
|
||||
elseif(MSVC)
|
||||
set(CMAKE_REQUIRED_FLAGS "/arch:SSE2") # TODO, SSE 1 ?
|
||||
set(${_sse_flags} "/arch:SSE")
|
||||
set(${_sse2_flags} "/arch:SSE2")
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
|
||||
set(${_sse_flags} "") # icc defaults to -msse
|
||||
set(${_sse2_flags} "-msse2")
|
||||
else()
|
||||
message(WARNING "SSE flags for this compiler: '${CMAKE_C_COMPILER_ID}' not known")
|
||||
set(${_sse_flags})
|
||||
set(${_sse2_flags})
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED ${SUPPORT_SSE_BUILD})
|
||||
set(CMAKE_REQUIRED_FLAGS "${${_sse_flags}} ${${_sse2_flags}}")
|
||||
|
||||
if(NOT DEFINED SUPPORT_SSE_BUILD)
|
||||
# result cached
|
||||
check_c_source_runs("
|
||||
#include <xmmintrin.h>
|
||||
int main() { __m128 v = _mm_setzero_ps(); return 0; }"
|
||||
int main(void) { __m128 v = _mm_setzero_ps(); return 0; }"
|
||||
SUPPORT_SSE_BUILD)
|
||||
|
||||
if(SUPPORT_SSE_BUILD)
|
||||
@@ -347,13 +355,13 @@ macro(TEST_SSE_SUPPORT)
|
||||
else()
|
||||
message(STATUS "SSE Support: missing.")
|
||||
endif()
|
||||
set(${SUPPORT_SSE_BUILD} ${SUPPORT_SSE_BUILD} CACHE INTERNAL "SSE Test")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED ${SUPPORT_SSE2_BUILD})
|
||||
if(NOT DEFINED SUPPORT_SSE2_BUILD)
|
||||
# result cached
|
||||
check_c_source_runs("
|
||||
#include <emmintrin.h>
|
||||
int main() { __m128d v = _mm_setzero_pd(); return 0; }"
|
||||
int main(void) { __m128d v = _mm_setzero_pd(); return 0; }"
|
||||
SUPPORT_SSE2_BUILD)
|
||||
|
||||
if(SUPPORT_SSE2_BUILD)
|
||||
@@ -361,9 +369,9 @@ macro(TEST_SSE_SUPPORT)
|
||||
else()
|
||||
message(STATUS "SSE2 Support: missing.")
|
||||
endif()
|
||||
set(${SUPPORT_SSE2_BUILD} ${SUPPORT_SSE2_BUILD} CACHE INTERNAL "SSE2 Test")
|
||||
endif()
|
||||
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
endmacro()
|
||||
|
||||
# when we have warnings as errors applied globally this
|
||||
@@ -482,7 +490,7 @@ macro(get_blender_version)
|
||||
if(${_out_version_char_empty})
|
||||
set(BLENDER_VERSION_CHAR_INDEX "0")
|
||||
else()
|
||||
set(_char_ls a b c d e f g h i j k l m n o p q r s t u v w q y z)
|
||||
set(_char_ls a b c d e f g h i j k l m n o p q r s t u v w x y z)
|
||||
list(FIND _char_ls ${BLENDER_VERSION_CHAR} _out_version_char_index)
|
||||
math(EXPR BLENDER_VERSION_CHAR_INDEX "${_out_version_char_index} + 1")
|
||||
unset(_char_ls)
|
||||
@@ -541,8 +549,10 @@ macro(blender_project_hack_post)
|
||||
# have libs we define and that cmake & scons builds match.
|
||||
set(CMAKE_C_STANDARD_LIBRARIES "" CACHE STRING "" FORCE)
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "" CACHE STRING "" FORCE)
|
||||
mark_as_advanced(CMAKE_C_STANDARD_LIBRARIES)
|
||||
mark_as_advanced(CMAKE_CXX_STANDARD_LIBRARIES)
|
||||
mark_as_advanced(
|
||||
CMAKE_C_STANDARD_LIBRARIES
|
||||
CMAKE_CXX_STANDARD_LIBRARIES
|
||||
)
|
||||
endif()
|
||||
unset(_reset_standard_libraries)
|
||||
|
||||
|
||||
@@ -161,8 +161,6 @@ def queue_processes(process_funcs, job_total=-1):
|
||||
del multiprocessing
|
||||
|
||||
if job_total == 1:
|
||||
import os
|
||||
import sys
|
||||
for func, args in process_funcs:
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
@@ -171,7 +169,6 @@ def queue_processes(process_funcs, job_total=-1):
|
||||
process.wait()
|
||||
else:
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
processes = []
|
||||
for func, args in process_funcs:
|
||||
|
||||
@@ -2,7 +2,7 @@ Source: blender
|
||||
Section: graphics
|
||||
Priority: extra
|
||||
Maintainer: Dan Eicher <dan@trollwerks.org>
|
||||
Build-Depends: debhelper (>= 7.0.50~), cmake, python3, python, libfreetype6-dev, libglu1-mesa-dev, libilmbase-dev, libopenexr-dev, libjpeg62-dev, libopenal-dev, libpng12-dev, libsamplerate0-dev, libsdl-dev, libtiff4-dev, libx11-dev, libxi-dev, zlib1g-dev, python3.2-dev, libopenjpeg-dev
|
||||
Build-Depends: debhelper (>= 7.0.50~), cmake, python3, python, libfreetype6-dev, libglu1-mesa-dev, libilmbase-dev, libopenexr-dev, libjpeg62-dev, libopenal-dev, libpng12-dev, libsdl-dev, libtiff4-dev, libx11-dev, libxi-dev, zlib1g-dev, python3.2-dev, libopenjpeg-dev
|
||||
Standards-Version: 3.9.1
|
||||
Homepage: http://blender.org/
|
||||
X-Python3-Version: >= 3.2, << 3.3
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
blender_srcdir=$(dirname $startdir)"/../.."
|
||||
# value may be formatted: 35042:35051M
|
||||
blender_revision=$(svnversion $blender_srcdir | cut -d: -f2 | awk '{print $3}')
|
||||
blender_version=$(grep BLENDER_VERSION $blender_srcdir/source/blender/blenkernel/BKE_blender.h | awk '{print $3}')
|
||||
blender_version=$(grep "BLENDER_VERSION\s" $blender_srcdir/source/blender/blenkernel/BKE_blender.h | awk '{print $3}')
|
||||
blender_version=$(expr $blender_version / 100).$(expr $blender_version % 100) # 256 -> 2.56
|
||||
blender_version_char=$(sed -ne 's/.*BLENDER_VERSION_CHAR.*\([a-z]\)$/\1/p' $blender_srcdir/source/blender/blenkernel/BKE_blender.h)
|
||||
# blender_subversion=$(grep BLENDER_SUBVERSION $blender_srcdir/source/blender/blenkernel/BKE_blender.h | awk '{print $3}')
|
||||
@@ -12,10 +12,12 @@ blender_version_char=$(sed -ne 's/.*BLENDER_VERSION_CHAR.*\([a-z]\)$/\1/p' $blen
|
||||
# map the version a -> 1
|
||||
# not to be confused with blender's internal subversions
|
||||
if [ "$blender_version_char" ]; then
|
||||
blender_version=${blender_version}.$(expr index abcdefghijklmnopqrstuvwxyz $blender_version_char)
|
||||
blender_version_full=${blender_version}.$(expr index abcdefghijklmnopqrstuvwxyz $blender_version_char)
|
||||
else
|
||||
blender_version_full=${blender_version}
|
||||
fi
|
||||
|
||||
blender_ver_string=$blender_version+svn$blender_revision
|
||||
blender_ver_string=$blender_version+svn$blender_version_full
|
||||
|
||||
pkgname=blender-snapshot
|
||||
pkgver=$blender_ver_string
|
||||
@@ -25,7 +27,7 @@ arch=('i686' 'x86_64')
|
||||
url="www.blender.org"
|
||||
license=('GPL')
|
||||
groups=()
|
||||
depends=('libjpeg' 'libpng' 'openjpeg' 'libtiff' 'openexr' 'python>=3.2' 'gettext' 'libxi' 'libxmu' 'mesa' 'freetype2' 'openal' 'sdl' 'libsndfile' 'libsamplerate' 'ffmpeg')
|
||||
depends=('libjpeg' 'libpng' 'openjpeg' 'libtiff' 'openexr' 'python>=3.2' 'gettext' 'libxi' 'libxmu' 'mesa' 'freetype2' 'openal' 'sdl' 'libsndfile' 'ffmpeg')
|
||||
makedepends=('cmake' 'svn')
|
||||
optdepends=()
|
||||
provides=()
|
||||
@@ -61,5 +63,8 @@ build() {
|
||||
package() {
|
||||
cd $srcdir/build
|
||||
make DESTDIR="$pkgdir" install
|
||||
python -m compileall $pkgdir/usr/share/blender
|
||||
python -m compileall \
|
||||
$pkgdir/usr/share/blender/$blender_version/scripts/startup \
|
||||
$pkgdir/usr/share/blender/$blender_version/scripts/modules \
|
||||
$pkgdir/usr/share/blender/$blender_version/scripts/addons
|
||||
}
|
||||
|
||||
@@ -90,9 +90,10 @@ LIBDIR = '${LCGDIR}'
|
||||
################### Dependency settings ##################
|
||||
#############################################################################
|
||||
|
||||
#Defaults openMP to true if compiler handles it
|
||||
if CC == 'gcc-4.2' or CC == 'llvm-gcc-4.2':
|
||||
WITH_BF_OPENMP = True # multithreading for fluids, cloth and smoke
|
||||
#Defaults openMP to true if compiler handles it ( only gcc 4.6.1 and newer )
|
||||
# if your compiler does not have accurate suffix you may have to enable it by hand !
|
||||
if CC.endswith('4.6.1'):
|
||||
WITH_BF_OPENMP = True # multithreading for fluids, cloth, sculpt and smoke
|
||||
else:
|
||||
WITH_BF_OPENMP = False
|
||||
|
||||
@@ -147,11 +148,6 @@ BF_CXX = '/usr'
|
||||
WITH_BF_STATICCXX = False
|
||||
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
|
||||
|
||||
BF_LIBSAMPLERATE = LIBDIR + '/samplerate'
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'samplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
|
||||
# TODO - set proper paths here (add precompiled to lib/ ? )
|
||||
WITH_BF_JACK = False
|
||||
BF_JACK = '/usr'
|
||||
|
||||
@@ -25,11 +25,6 @@ BF_CXX = '/usr/local'
|
||||
WITH_BF_STATICCXX = False
|
||||
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
|
||||
|
||||
BF_LIBSAMPLERATE = '/usr/local'
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'samplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
|
||||
WITH_BF_JACK = True
|
||||
BF_JACK = '/usr/local'
|
||||
BF_JACK_INC = '${BF_JACK}/include/jack'
|
||||
|
||||
@@ -25,11 +25,6 @@ BF_CXX = '/usr/local'
|
||||
WITH_BF_STATICCXX = False
|
||||
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
|
||||
|
||||
BF_LIBSAMPLERATE = '/usr/local'
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'samplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
|
||||
WITH_BF_JACK = True
|
||||
BF_JACK = '/usr/local'
|
||||
BF_JACK_INC = '${BF_JACK}/include/jack'
|
||||
|
||||
@@ -25,11 +25,6 @@ BF_CXX = '/usr/local'
|
||||
WITH_BF_STATICCXX = False
|
||||
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
|
||||
|
||||
BF_LIBSAMPLERATE = '/usr/local'
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'samplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
|
||||
WITH_BF_JACK = True
|
||||
BF_JACK = '/usr/local'
|
||||
BF_JACK_INC = '${BF_JACK}/include/jack'
|
||||
|
||||
@@ -23,13 +23,6 @@ BF_CXX = '/usr'
|
||||
WITH_BF_STATICCXX = False
|
||||
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
|
||||
|
||||
BF_LIBSAMPLERATE = '/usr'
|
||||
WITH_BF_STATICLIBSAMPLERATE = False
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'samplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
BF_LIBSAMPLERATE_LIB_STATIC = '${BF_LIBSAMPLERATE}/lib/libsamplerate.a'
|
||||
|
||||
WITH_BF_JACK = False
|
||||
BF_JACK = '/usr'
|
||||
BF_JACK_INC = '${BF_JACK}/include/jack'
|
||||
|
||||
@@ -23,11 +23,6 @@ BF_CXX = '/usr'
|
||||
WITH_BF_STATICCXX = False
|
||||
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
|
||||
|
||||
BF_LIBSAMPLERATE = LIBDIR + '/samplerate'
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'samplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
|
||||
WITH_BF_SDL = True
|
||||
BF_SDL = LIBDIR + '/sdl'
|
||||
BF_SDL_INC = '${BF_SDL}/include'
|
||||
|
||||
@@ -16,11 +16,6 @@ WITH_BF_OPENAL = False
|
||||
#BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
|
||||
#BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
|
||||
|
||||
BF_LIBSAMPLERATE = '/usr/local'
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'samplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
|
||||
WITH_BF_SDL = True
|
||||
BF_SDL = '/usr/local' #$(shell sdl-config --prefix)
|
||||
BF_SDL_INC = '${BF_SDL}/include/SDL' #$(shell $(BF_SDL)/bin/sdl-config --cflags)
|
||||
|
||||
@@ -22,11 +22,6 @@ BF_CXX = '/usr'
|
||||
WITH_BF_STATICCXX = False
|
||||
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
|
||||
|
||||
BF_LIBSAMPLERATE = '/usr/local'
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'samplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
|
||||
WITH_BF_SDL = True
|
||||
BF_SDL = '/usr/local' #$(shell sdl-config --prefix)
|
||||
BF_SDL_INC = '${BF_SDL}/include/SDL' #$(shell $(BF_SDL)/bin/sdl-config --cflags)
|
||||
|
||||
@@ -23,11 +23,6 @@ BF_FFMPEG_LIBPATH = LIBDIR + '/ffmpeg/lib'
|
||||
BF_FFMPEG_INC = LIBDIR + '/ffmpeg/include'
|
||||
BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-53.dll ${BF_FFMPEG_LIBPATH}/avcodec-53.dll ${BF_FFMPEG_LIBPATH}/avdevice-53.dll ${BF_FFMPEG_LIBPATH}/avutil-51.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll'
|
||||
|
||||
BF_LIBSAMPLERATE = LIBDIR + '/samplerate'
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'libsamplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
|
||||
WITH_BF_JACK = False
|
||||
BF_JACK = LIBDIR + '/jack'
|
||||
BF_JACK_INC = '${BF_JACK}/include'
|
||||
|
||||
@@ -29,11 +29,6 @@ BF_ICONV_INC = '${BF_ICONV}/include'
|
||||
BF_ICONV_LIB = 'iconv'
|
||||
BF_ICONV_LIBPATH = '${BF_ICONV}/lib'
|
||||
|
||||
BF_LIBSAMPLERATE = LIBDIR + '/samplerate'
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'libsamplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
|
||||
WITH_BF_JACK = False
|
||||
BF_JACK = LIBDIR + '/jack'
|
||||
BF_JACK_INC = '${BF_JACK}/include ${BF_FFMPEG}/include/msvc'
|
||||
@@ -152,6 +147,8 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
|
||||
|
||||
WITH_BF_3DMOUSE = True
|
||||
|
||||
WITH_BF_OPENMP = True
|
||||
|
||||
#Ray trace optimization
|
||||
WITH_BF_RAYOPTIMIZATION = True
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE']
|
||||
|
||||
@@ -17,7 +17,7 @@ BF_PYTHON_LIB = 'python32'
|
||||
BF_PYTHON_DLL = '${BF_PYTHON_LIB}'
|
||||
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
|
||||
|
||||
WITH_BF_OPENAL = False
|
||||
WITH_BF_OPENAL = True
|
||||
BF_OPENAL = LIBDIR + '/openal'
|
||||
BF_OPENAL_INC = '${BF_OPENAL}/include '
|
||||
BF_OPENAL_LIB = 'wrap_oal'
|
||||
@@ -40,11 +40,6 @@ BF_ICONV_INC = '${BF_ICONV}/include'
|
||||
BF_ICONV_LIB = 'iconv'
|
||||
BF_ICONV_LIBPATH = '${BF_ICONV}/lib'
|
||||
|
||||
BF_LIBSAMPLERATE = LIBDIR + '/samplerate'
|
||||
BF_LIBSAMPLERATE_INC = '${BF_LIBSAMPLERATE}/include'
|
||||
BF_LIBSAMPLERATE_LIB = 'libsamplerate'
|
||||
BF_LIBSAMPLERATE_LIBPATH = '${BF_LIBSAMPLERATE}/lib'
|
||||
|
||||
WITH_BF_SDL = True
|
||||
BF_SDL = LIBDIR + '/sdl'
|
||||
BF_SDL_INC = '${BF_SDL}/include'
|
||||
@@ -156,6 +151,8 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
|
||||
|
||||
WITH_BF_3DMOUSE = True
|
||||
|
||||
WITH_BF_OPENMP = True
|
||||
|
||||
#Ray trace optimization
|
||||
WITH_BF_RAYOPTIMIZATION = True
|
||||
BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE','/arch:SSE2']
|
||||
|
||||
@@ -131,7 +131,6 @@ def setup_staticlibs(lenv):
|
||||
lenv['BF_JPEG_LIBPATH'],
|
||||
lenv['BF_ZLIB_LIBPATH'],
|
||||
lenv['BF_PNG_LIBPATH'],
|
||||
lenv['BF_LIBSAMPLERATE_LIBPATH'],
|
||||
lenv['BF_ICONV_LIBPATH']
|
||||
])
|
||||
|
||||
@@ -194,9 +193,6 @@ def setup_staticlibs(lenv):
|
||||
if lenv['OURPLATFORM'] == 'linuxcross':
|
||||
libincs += Split(lenv['BF_OPENMP_LIBPATH'])
|
||||
|
||||
if lenv['WITH_BF_STATICLIBSAMPLERATE']:
|
||||
statlibs += Split(lenv['BF_LIBSAMPLERATE_LIB_STATIC'])
|
||||
|
||||
# setting this last so any overriding of manually libs could be handled
|
||||
if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
|
||||
libincs.append('/usr/lib')
|
||||
@@ -270,9 +266,6 @@ def setup_syslibs(lenv):
|
||||
syslibs += Split(lenv['BF_OPENCOLLADA_LIB'])
|
||||
syslibs.append(lenv['BF_EXPAT_LIB'])
|
||||
|
||||
if not lenv['WITH_BF_STATICLIBSAMPLERATE']:
|
||||
syslibs += Split(lenv['BF_LIBSAMPLERATE_LIB'])
|
||||
|
||||
if lenv['WITH_BF_JEMALLOC']:
|
||||
if not lenv['WITH_BF_STATICJEMALLOC']:
|
||||
syslibs += Split(lenv['BF_JEMALLOC_LIB'])
|
||||
@@ -561,27 +554,26 @@ def AppIt(target=None, source=None, env=None):
|
||||
cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,installdir, binary, binary)
|
||||
commands.getoutput(cmd)
|
||||
cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/'%(installdir, binary, VERSION)
|
||||
# print cmd
|
||||
commands.getoutput(cmd)
|
||||
cmd = installdir + '/%s.app/Contents/MacOS/%s'%(binary,VERSION)
|
||||
|
||||
# blenderplayer doesn't need all the files
|
||||
if binary == 'blender':
|
||||
cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/datafiles'%(installdir, binary, VERSION)
|
||||
commands.getoutput(cmd)
|
||||
cmd = 'cp -R %s/release/bin/.blender/locale %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
|
||||
commands.getoutput(cmd)
|
||||
cmd = 'cp -R %s/release/bin/.blender/fonts %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
|
||||
commands.getoutput(cmd)
|
||||
cmd = 'cp %s/release/bin/%s/.Blanguages %s/%s.app/Contents/Resources/'%(bldroot,VERSION,installdir,binary)
|
||||
cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
|
||||
commands.getoutput(cmd)
|
||||
|
||||
if env['WITH_OSX_STATICPYTHON']:
|
||||
cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION)
|
||||
commands.getoutput(cmd)
|
||||
cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION)
|
||||
commands.getoutput(cmd)
|
||||
|
||||
if binary == 'blender':#not copy everything for blenderplayer
|
||||
cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
|
||||
commands.getoutput(cmd)
|
||||
|
||||
cmd = 'chmod +x %s/%s.app/Contents/MacOS/%s'%(installdir,binary, binary)
|
||||
commands.getoutput(cmd)
|
||||
cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(installdir, binary)
|
||||
@@ -633,7 +625,11 @@ def UnixPyBundle(target=None, source=None, env=None):
|
||||
run("rm -rf '%s/distutils'" % py_target)
|
||||
run("rm -rf '%s/lib2to3'" % py_target)
|
||||
run("rm -rf '%s/config'" % py_target)
|
||||
run("rm -rf '%s/config-*'" % py_target)
|
||||
|
||||
for f in os.listdir(py_target):
|
||||
if f.startswith("config-"):
|
||||
run("rm -rf '%s/%s'" % (py_target, f))
|
||||
|
||||
run("rm -rf '%s/site-packages'" % py_target)
|
||||
run("mkdir '%s/site-packages'" % py_target) # python needs it.'
|
||||
run("rm -rf '%s/idlelib'" % py_target)
|
||||
@@ -695,7 +691,7 @@ class BlenderEnvironment(SConsEnvironment):
|
||||
SConsEnvironment.Default(self, res)
|
||||
resources.append(res)
|
||||
|
||||
def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None):
|
||||
def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None, cc_compilerchange=None, cxx_compilerchange=None):
|
||||
global vcp
|
||||
if not self or not libname or not sources:
|
||||
print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
|
||||
@@ -733,6 +729,10 @@ class BlenderEnvironment(SConsEnvironment):
|
||||
lenv.Replace(CCFLAGS = cc_compileflags)
|
||||
if cxx_compileflags:
|
||||
lenv.Replace(CXXFLAGS = cxx_compileflags)
|
||||
if cc_compilerchange:
|
||||
lenv.Replace(CC = cc_compilerchange)
|
||||
if cxx_compilerchange:
|
||||
lenv.Replace(CXX = cxx_compilerchange)
|
||||
lenv.Append(CFLAGS = lenv['C_WARN'])
|
||||
lenv.Append(CCFLAGS = lenv['CC_WARN'])
|
||||
lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
|
||||
|
||||
@@ -99,7 +99,6 @@ def validate_arguments(args, bc):
|
||||
'WITH_BF_PYTHON', 'WITH_BF_PYTHON_SAFETY', 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'WITH_BF_STATICPYTHON', 'WITH_OSX_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', 'BF_PYTHON_DLL', 'BF_PYTHON_ABI_FLAGS',
|
||||
'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_STATICOPENAL', 'BF_OPENAL_LIB_STATIC',
|
||||
'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH',
|
||||
'BF_LIBSAMPLERATE', 'BF_LIBSAMPLERATE_INC', 'BF_LIBSAMPLERATE_LIB', 'BF_LIBSAMPLERATE_LIBPATH', 'WITH_BF_STATICLIBSAMPLERATE', 'BF_LIBSAMPLERATE_LIB_STATIC',
|
||||
'WITH_BF_JACK', 'BF_JACK', 'BF_JACK_INC', 'BF_JACK_LIB', 'BF_JACK_LIBPATH',
|
||||
'WITH_BF_SNDFILE', 'BF_SNDFILE', 'BF_SNDFILE_INC', 'BF_SNDFILE_LIB', 'BF_SNDFILE_LIBPATH', 'WITH_BF_STATICSNDFILE', 'BF_SNDFILE_LIB_STATIC',
|
||||
'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH',
|
||||
@@ -267,13 +266,6 @@ def read_opts(env, cfg, args):
|
||||
('BF_SDL_LIB', 'SDL library', ''),
|
||||
('BF_SDL_LIBPATH', 'SDL library path', ''),
|
||||
|
||||
('BF_LIBSAMPLERATE', 'libsamplerate aka SRC base path', ''),
|
||||
('BF_LIBSAMPLERATE_INC', 'libsamplerate aka SRC include path', ''),
|
||||
('BF_LIBSAMPLERATE_LIB', 'libsamplerate aka SRC library', ''),
|
||||
('BF_LIBSAMPLERATE_LIBPATH', 'libsamplerate aka SRC library path', ''),
|
||||
('BF_LIBSAMPLERATE_LIB_STATIC', 'Path to libsamplerate static library', ''),
|
||||
(BoolVariable('WITH_BF_STATICLIBSAMPLERATE', 'Staticly link to libsamplerate', False)),
|
||||
|
||||
(BoolVariable('WITH_BF_JACK', 'Enable jack support if true', True)),
|
||||
('BF_JACK', 'jack base path', ''),
|
||||
('BF_JACK_INC', 'jack include path', ''),
|
||||
|
||||
@@ -11,7 +11,7 @@ $Id$
|
||||
3. Obtaining Dependencies
|
||||
4. Deciding on a Build Environment
|
||||
5. Configuring the build for the first time
|
||||
6. Configuring the build after CVS updates
|
||||
6. Configuring the build after SVN updates
|
||||
7. Specify alternate Python library versions and locations
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ $Id$
|
||||
http://www.blender.org/cms/Getting_Dependencies.135.0.html that you
|
||||
have all dependencies needed for building Blender. Note that for
|
||||
windows many of these dependencies already come in the lib/windows
|
||||
module from CVS.
|
||||
module from SVN.
|
||||
|
||||
4. Deciding on a Build Environment
|
||||
----------------------------------
|
||||
@@ -47,8 +47,8 @@ $Id$
|
||||
have been successfully used to generate build files for the following
|
||||
environments:
|
||||
|
||||
1. Microsoft Visual Studio 2005. There is a free version available
|
||||
at http://msdn.microsoft.com/vstudio/express/visualc/.
|
||||
1. Microsoft Visual Studio 2008. There is a free version available
|
||||
at http://http://www.microsoft.com/visualstudio/en-us/products/2008-editions/express
|
||||
|
||||
2. Xcode on Mac OSX
|
||||
|
||||
@@ -65,7 +65,7 @@ $Id$
|
||||
with different Blender configurations (Audio/NoAudio, GameEngine/NoGameEngine etc.)
|
||||
while maintaining a clean source tree. It also makes it possible to generate files
|
||||
for different build systems on the same source tree. This also has benefits for
|
||||
general CVS management for the developer as patches and submit logs are much cleaner.
|
||||
general SVN management for the developer as patches and submit logs are much cleaner.
|
||||
|
||||
Create a directory outside the blender source tree where you would like to build
|
||||
Blender (from now on called $BLENDERBUILD). On the commandline you can then run
|
||||
@@ -114,15 +114,15 @@ $Id$
|
||||
It is also possible to use the commandline of 'cmake' to override certain
|
||||
of these settings.
|
||||
|
||||
6. Configuring the build after CVS updates
|
||||
6. Configuring the build after SVN updates
|
||||
------------------------------------------
|
||||
|
||||
The $BLENDERBUILD directory maintains a file called CMakeCache.txt which
|
||||
remembers the initial run's settings for subsequent generation runs. After
|
||||
every CVS update it may be a good idea to rerun the generation before building
|
||||
every SVN update it may be a good idea to rerun the generation before building
|
||||
Blender again. Just rerun the original 'cmake' run to do this, the settings
|
||||
will be remembered. For the example above the following will do after every
|
||||
'cvs up':
|
||||
'svn up':
|
||||
|
||||
% cmake -G Xcode $BLENDERSOURCE
|
||||
|
||||
@@ -132,9 +132,9 @@ $Id$
|
||||
The commandline can be used to override detected/default settings, e.g:
|
||||
|
||||
On Unix:
|
||||
cmake -D PYTHON_LIBRARY=/usr/local/lib/python3.1/config/libpython3.1.so -D PYTHON_INCLUDE_DIRS=/usr/local/include/python3.1 -G "Unix Makefiles" ../blender
|
||||
cmake -D PYTHON_LIBRARY=/usr/local/lib/python3.2/config/libpython3.2.so -D PYTHON_INCLUDE_DIR=/usr/local/include/python3.2 ../blender
|
||||
On Macs:
|
||||
cmake -D PYTHON_INCLUDE_DIRS=/System/Library/Frameworks/Python.framework/Versions/3.1/include/python3.1 -G Xcode ../blender
|
||||
cmake -D PYTHON_INCLUDE_DIRS=/System/Library/Frameworks/Python.framework/Versions/3.2/include/python3.2 -G Xcode ../blender
|
||||
|
||||
Mote that this should only be needed once per build directory generation because it will keep the overrides in CMakeCache.txt for subsequent runs.
|
||||
|
||||
@@ -153,4 +153,3 @@ $Id$
|
||||
on the various platforms.
|
||||
|
||||
/Jacques Beaurain (jbinto)
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ device = aud.device()
|
||||
factory = aud.Factory('music.ogg')
|
||||
|
||||
# play the audio, this return a handle to control play/pause
|
||||
handle = device.play(sound)
|
||||
handle = device.play(factory)
|
||||
# if the audio is not too big and will be used often you can buffer it
|
||||
factory_buffered = aud.Factory.buffer(sound)
|
||||
handle_buffered = device.play(buffered)
|
||||
factory_buffered = aud.Factory.buffer(factory)
|
||||
handle_buffered = device.play(factory_buffered)
|
||||
|
||||
# stop the sounds (otherwise they play until their ends)
|
||||
handle.stop()
|
||||
|
||||
@@ -909,3 +909,574 @@ Added
|
||||
|
||||
* :class:`bpy.types.SceneGameData.use_glsl_color_management`
|
||||
|
||||
|
||||
2.58 to 2.59
|
||||
============
|
||||
|
||||
bpy.types.Scene
|
||||
---------------
|
||||
|
||||
Function Arguments
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* :class:`bpy.types.Scene.collada_export` (filepath, selected), *was (filepath)*
|
||||
|
||||
bpy.types.MultiresModifier
|
||||
--------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.MultiresModifier.use_subsurf_uv`
|
||||
|
||||
bpy.types.KeyMap
|
||||
----------------
|
||||
|
||||
Removed
|
||||
^^^^^^^
|
||||
|
||||
* **copy_to_user**
|
||||
|
||||
Renamed
|
||||
^^^^^^^
|
||||
|
||||
* **is_user_defined** -> :class:`bpy.types.KeyMap.is_user_modified`
|
||||
|
||||
bpy.types.SceneRenderLayer
|
||||
--------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.SceneRenderLayer.use_pass_material_index`
|
||||
|
||||
bpy.types.ToolSettings
|
||||
----------------------
|
||||
|
||||
Renamed
|
||||
^^^^^^^
|
||||
|
||||
* **use_snap_project_self** -> :class:`bpy.types.ToolSettings.use_snap_self`
|
||||
|
||||
bpy.types.UserPreferencesInput
|
||||
------------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_fly_helicopter`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_lock_horizon`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_orbit_invert_axes`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_sensitivity`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_show_guide`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_zoom_invert`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_zoom_updown`
|
||||
|
||||
Removed
|
||||
^^^^^^^
|
||||
|
||||
* **edited_keymaps**
|
||||
* **ndof_pan_speed**
|
||||
* **ndof_rotate_speed**
|
||||
|
||||
bpy.types.IDMaterials
|
||||
---------------------
|
||||
|
||||
Function Arguments
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* :class:`bpy.types.IDMaterials.pop` (index, update_data), *was (index)*
|
||||
|
||||
bpy.types.Material
|
||||
------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Material.pass_index`
|
||||
|
||||
bpy.types.RenderLayer
|
||||
---------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.RenderLayer.use_pass_material_index`
|
||||
|
||||
bpy.types.Object
|
||||
----------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Object.closest_point_on_mesh`
|
||||
|
||||
bpy.types.ThemeNodeEditor
|
||||
-------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.ThemeNodeEditor.noodle_curving`
|
||||
|
||||
bpy.types.ChildOfConstraint
|
||||
---------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.ChildOfConstraint.inverse_matrix`
|
||||
|
||||
bpy.types.KeyConfigurations
|
||||
---------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.KeyConfigurations.addon`
|
||||
* :class:`bpy.types.KeyConfigurations.user`
|
||||
|
||||
bpy.types.Image
|
||||
---------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Image.use_generated_float`
|
||||
|
||||
bpy.types.KeyMapItem
|
||||
--------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.KeyMapItem.is_user_modified`
|
||||
|
||||
|
||||
2.59 to 2.60
|
||||
============
|
||||
|
||||
.. These have been manually added wait until RC to do final changelog!
|
||||
|
||||
bpy.types.MeshTextureFace
|
||||
-------------------------
|
||||
|
||||
Removed
|
||||
^^^^^^^
|
||||
|
||||
* **use_image**
|
||||
* **use_object_color**
|
||||
* **use_blend_shared**
|
||||
|
||||
Moved
|
||||
^^^^^
|
||||
|
||||
* **hide** -> :class:`bpy.types.Material.game_settings.invisible`
|
||||
* **use_collision** -> :class:`bpy.types.Material.game_settings.physics`
|
||||
* **use_light** -> :class:`bpy.types.Material.game_settings.use_shadeless`
|
||||
* **use_twoside** -> :class:`bpy.types.Material.game_settings.backface_culling`
|
||||
* **use_bitmap_text** -> :class:`bpy.types.Material.game_settings.text`
|
||||
* **blend_type** -> :class:`bpy.types.Material.game_settings.alpha_blend`
|
||||
* **use_alpha_sort** -> :class:`bpy.types.Material.game_settings.alpha_blend`
|
||||
* **use_billboard** -> :class:`bpy.types.Material.game_settings.face_orientation`
|
||||
* **use_halo** -> :class:`bpy.types.Material.game_settings.face_orientation`
|
||||
* **use_shadow_cast** -> :class:`bpy.types.Material.game_settings.face_orientation`
|
||||
|
||||
.. Automatically Generated, 2.59 -> r40804!
|
||||
|
||||
bpy.types.RenderSettings
|
||||
------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.RenderSettings.ffmpeg_audio_channels`
|
||||
|
||||
bpy.types.DriverTarget
|
||||
----------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.DriverTarget.transform_space`
|
||||
|
||||
Removed
|
||||
^^^^^^^
|
||||
|
||||
* **use_local_space_transform**
|
||||
|
||||
bpy.types.Sound
|
||||
---------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Sound.factory`
|
||||
* :class:`bpy.types.Sound.use_mono`
|
||||
|
||||
bpy.types.Camera
|
||||
----------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Camera.view_frame`
|
||||
|
||||
bpy.types.Scene
|
||||
---------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Scene.audio_volume`
|
||||
|
||||
bpy.types.KeyingSet
|
||||
-------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.KeyingSet.refresh`
|
||||
|
||||
bpy.types.Armature
|
||||
------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Armature.deform_method`
|
||||
|
||||
bpy.types.GameObjectSettings
|
||||
----------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.GameObjectSettings.obstacle_radius`
|
||||
* :class:`bpy.types.GameObjectSettings.use_obstacle_create`
|
||||
|
||||
bpy.types.BlendData
|
||||
-------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.BlendData.speakers`
|
||||
|
||||
bpy.types.SolidifyModifier
|
||||
--------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.SolidifyModifier.thickness_vertex_group`
|
||||
|
||||
bpy.types.ThemeGraphEditor
|
||||
--------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.ThemeGraphEditor.handle_auto_clamped`
|
||||
* :class:`bpy.types.ThemeGraphEditor.handle_sel_auto_clamped`
|
||||
|
||||
bpy.types.CompositorNodeIDMask
|
||||
------------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.CompositorNodeIDMask.use_smooth_mask`
|
||||
|
||||
bpy.types.Node
|
||||
--------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Node.parent`
|
||||
|
||||
bpy.types.Texture
|
||||
-----------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Texture.evaluate`
|
||||
|
||||
bpy.types.UILayout
|
||||
------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.UILayout.template_keymap_item_properties`
|
||||
|
||||
bpy.types.ToolSettings
|
||||
----------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.ToolSettings.use_multipaint`
|
||||
|
||||
bpy.types.UserPreferencesInput
|
||||
------------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_panx_invert_axis`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_pany_invert_axis`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_panz_invert_axis`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_roll_invert_axis`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_rotate_invert_axis`
|
||||
* :class:`bpy.types.UserPreferencesInput.ndof_tilt_invert_axis`
|
||||
|
||||
bpy.types.LockedTrackConstraint
|
||||
-------------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.LockedTrackConstraint.head_tail`
|
||||
|
||||
bpy.types.SpaceGraphEditor
|
||||
--------------------------
|
||||
|
||||
Moved
|
||||
^^^^^
|
||||
|
||||
* use_fancy_drawing -> :class:`bpy.types.SpaceGraphEditor.use_beauty_drawing`
|
||||
|
||||
bpy.types.ParticleSystem
|
||||
------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.ParticleSystem.dt_frac`
|
||||
|
||||
bpy.types.Mesh
|
||||
--------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Mesh.use_paint_mask_vertex`
|
||||
|
||||
bpy.types.FCurve
|
||||
----------------
|
||||
|
||||
Removed
|
||||
^^^^^^^
|
||||
|
||||
* **use_auto_handle_clamp**
|
||||
|
||||
bpy.types.DampedTrackConstraint
|
||||
-------------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.DampedTrackConstraint.head_tail`
|
||||
|
||||
bpy.types.ImageTexture
|
||||
----------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.ImageTexture.use_derivative_map`
|
||||
|
||||
bpy.types.SoundSequence
|
||||
-----------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.SoundSequence.pan`
|
||||
* :class:`bpy.types.SoundSequence.pitch`
|
||||
|
||||
Removed
|
||||
^^^^^^^
|
||||
|
||||
* **attenuation**
|
||||
|
||||
bpy.types.FModifier
|
||||
-------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.FModifier.blend_in`
|
||||
* :class:`bpy.types.FModifier.blend_out`
|
||||
* :class:`bpy.types.FModifier.frame_end`
|
||||
* :class:`bpy.types.FModifier.frame_start`
|
||||
* :class:`bpy.types.FModifier.influence`
|
||||
* :class:`bpy.types.FModifier.use_influence`
|
||||
* :class:`bpy.types.FModifier.use_restricted_range`
|
||||
|
||||
bpy.types.EnvironmentMap
|
||||
------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.EnvironmentMap.clear`
|
||||
* :class:`bpy.types.EnvironmentMap.is_valid`
|
||||
* :class:`bpy.types.EnvironmentMap.save`
|
||||
|
||||
bpy.types.UserPreferencesSystem
|
||||
-------------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.UserPreferencesSystem.use_translate_interface`
|
||||
|
||||
Removed
|
||||
^^^^^^^
|
||||
|
||||
* **use_translate_buttons**
|
||||
* **use_translate_toolbox**
|
||||
|
||||
bpy.types.LimitDistanceConstraint
|
||||
---------------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.LimitDistanceConstraint.head_tail`
|
||||
* :class:`bpy.types.LimitDistanceConstraint.use_transform_limit`
|
||||
|
||||
bpy.types.MovieSequence
|
||||
-----------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.MovieSequence.stream_index`
|
||||
|
||||
bpy.types.Material
|
||||
------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Material.game_settings`
|
||||
|
||||
bpy.types.Object
|
||||
----------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Object.matrix_parent_inverse`
|
||||
|
||||
bpy.types.SequenceProxy
|
||||
-----------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.SequenceProxy.build_100`
|
||||
* :class:`bpy.types.SequenceProxy.build_25`
|
||||
* :class:`bpy.types.SequenceProxy.build_50`
|
||||
* :class:`bpy.types.SequenceProxy.build_75`
|
||||
* :class:`bpy.types.SequenceProxy.build_free_run`
|
||||
* :class:`bpy.types.SequenceProxy.build_free_run_rec_date`
|
||||
* :class:`bpy.types.SequenceProxy.build_record_run`
|
||||
* :class:`bpy.types.SequenceProxy.quality`
|
||||
* :class:`bpy.types.SequenceProxy.timecode`
|
||||
|
||||
bpy.types.Sequence
|
||||
------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Sequence.waveform`
|
||||
|
||||
bpy.types.DopeSheet
|
||||
-------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.DopeSheet.show_datablock_filters`
|
||||
* :class:`bpy.types.DopeSheet.show_speakers`
|
||||
|
||||
bpy.types.ActionActuator
|
||||
------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.ActionActuator.apply_to_children`
|
||||
* :class:`bpy.types.ActionActuator.layer`
|
||||
* :class:`bpy.types.ActionActuator.layer_weight`
|
||||
* :class:`bpy.types.ActionActuator.use_additive`
|
||||
* :class:`bpy.types.ActionActuator.use_force`
|
||||
* :class:`bpy.types.ActionActuator.use_local`
|
||||
|
||||
bpy.types.VertexGroup
|
||||
---------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.VertexGroup.lock_weight`
|
||||
|
||||
bpy.types.ThemeView3D
|
||||
---------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.ThemeView3D.speaker`
|
||||
|
||||
bpy.types.Image
|
||||
---------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Image.pack`
|
||||
* :class:`bpy.types.Image.unpack`
|
||||
|
||||
bpy.types.Curve
|
||||
---------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.Curve.fill_mode`
|
||||
|
||||
Removed
|
||||
^^^^^^^
|
||||
|
||||
* **use_fill_back**
|
||||
* **use_fill_front**
|
||||
|
||||
bpy.types.ParticleSettings
|
||||
--------------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.ParticleSettings.adaptive_subframes`
|
||||
* :class:`bpy.types.ParticleSettings.courant_target`
|
||||
|
||||
bpy.types.SceneGameData
|
||||
-----------------------
|
||||
|
||||
Added
|
||||
^^^^^
|
||||
|
||||
* :class:`bpy.types.SceneGameData.level_height`
|
||||
* :class:`bpy.types.SceneGameData.obstacle_simulation`
|
||||
* :class:`bpy.types.SceneGameData.recast_data`
|
||||
* :class:`bpy.types.SceneGameData.restrict_animation_updates`
|
||||
* :class:`bpy.types.SceneGameData.show_obstacle_simulation`
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@ python doc/python_api/sphinx_changelog_gen.py \
|
||||
--api_to blender_api_2_57.py \
|
||||
--api_out changes.rst
|
||||
|
||||
# Save the latest API dump in this folder, renaming it with its revision.
|
||||
# This way the next person updating it doesn't need to build an old Blender only for that
|
||||
|
||||
"""
|
||||
|
||||
# format
|
||||
@@ -299,7 +302,7 @@ def api_changelog(api_from, api_to, api_out):
|
||||
for func_id, args_old, args_new in func_args:
|
||||
args_new = ", ".join(args_new)
|
||||
args_old = ", ".join(args_old)
|
||||
fw("* :class:`%s.%s.%s` (%s), *was (%s)*\n" % (mod_id, class_name, prop_id, args_new, args_old))
|
||||
fw("* :class:`%s.%s.%s` (%s), *was (%s)*\n" % (mod_id, class_name, func_id, args_new, args_old))
|
||||
fw("\n")
|
||||
|
||||
fout.close()
|
||||
|
||||
@@ -163,7 +163,7 @@ def range_str(val):
|
||||
|
||||
|
||||
def example_extract_docstring(filepath):
|
||||
file = open(filepath, 'r')
|
||||
file = open(filepath, "r", encoding="utf-8")
|
||||
line = file.readline()
|
||||
line_no = 0
|
||||
text = []
|
||||
@@ -362,7 +362,7 @@ def pymodule2sphinx(BASEPATH, module_name, module, title):
|
||||
if module_all:
|
||||
module_dir = module_all
|
||||
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
|
||||
fw = file.write
|
||||
|
||||
@@ -518,7 +518,7 @@ def pycontext2sphinx(BASEPATH):
|
||||
# Only use once. very irregular
|
||||
|
||||
filepath = os.path.join(BASEPATH, "bpy.context.rst")
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
fw("Context Access (bpy.context)\n")
|
||||
fw("============================\n\n")
|
||||
@@ -706,7 +706,7 @@ def pyrna2sphinx(BASEPATH):
|
||||
# return
|
||||
|
||||
filepath = os.path.join(BASEPATH, "bpy.types.%s.rst" % struct.identifier)
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
|
||||
base_id = getattr(struct.base, "identifier", "")
|
||||
@@ -920,7 +920,7 @@ def pyrna2sphinx(BASEPATH):
|
||||
|
||||
def fake_bpy_type(class_value, class_name, descr_str, use_subclasses=True):
|
||||
filepath = os.path.join(BASEPATH, "bpy.types.%s.rst" % class_name)
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
|
||||
write_title(fw, class_name, "=")
|
||||
@@ -971,7 +971,7 @@ def pyrna2sphinx(BASEPATH):
|
||||
|
||||
for op_module_name, ops_mod in op_modules.items():
|
||||
filepath = os.path.join(BASEPATH, "bpy.ops.%s.rst" % op_module_name)
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
|
||||
title = "%s Operators" % op_module_name.replace("_", " ").title()
|
||||
@@ -1025,7 +1025,7 @@ def rna2sphinx(BASEPATH):
|
||||
|
||||
# conf.py - empty for now
|
||||
filepath = os.path.join(BASEPATH, "conf.py")
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
|
||||
version_string = ".".join(str(v) for v in bpy.app.version)
|
||||
@@ -1061,7 +1061,7 @@ def rna2sphinx(BASEPATH):
|
||||
|
||||
# main page needed for sphinx (index.html)
|
||||
filepath = os.path.join(BASEPATH, "contents.rst")
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
|
||||
fw("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
|
||||
@@ -1179,7 +1179,7 @@ def rna2sphinx(BASEPATH):
|
||||
# internal modules
|
||||
if "bpy.ops" not in EXCLUDE_MODULES:
|
||||
filepath = os.path.join(BASEPATH, "bpy.ops.rst")
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
fw("Operators (bpy.ops)\n")
|
||||
fw("===================\n\n")
|
||||
@@ -1191,7 +1191,7 @@ def rna2sphinx(BASEPATH):
|
||||
|
||||
if "bpy.types" not in EXCLUDE_MODULES:
|
||||
filepath = os.path.join(BASEPATH, "bpy.types.rst")
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
fw("Types (bpy.types)\n")
|
||||
fw("=================\n\n")
|
||||
@@ -1204,7 +1204,7 @@ def rna2sphinx(BASEPATH):
|
||||
# not actually a module, only write this file so we
|
||||
# can reference in the TOC
|
||||
filepath = os.path.join(BASEPATH, "bpy.data.rst")
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
fw("Data Access (bpy.data)\n")
|
||||
fw("======================\n\n")
|
||||
@@ -1298,7 +1298,7 @@ def rna2sphinx(BASEPATH):
|
||||
|
||||
if 0:
|
||||
filepath = os.path.join(BASEPATH, "bpy.rst")
|
||||
file = open(filepath, "w")
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
|
||||
fw("\n")
|
||||
|
||||
9
extern/recastnavigation/CMakeLists.txt
vendored
9
extern/recastnavigation/CMakeLists.txt
vendored
@@ -53,18 +53,19 @@ set(SRC
|
||||
Detour/Include/DetourTileNavMeshBuilder.h
|
||||
|
||||
Recast/Source/Recast.cpp
|
||||
Recast/Source/RecastAlloc.cpp
|
||||
Recast/Source/RecastArea.cpp
|
||||
Recast/Source/RecastContour.cpp
|
||||
Recast/Source/RecastFilter.cpp
|
||||
Recast/Source/RecastLog.cpp
|
||||
Recast/Source/RecastLayers.cpp
|
||||
Recast/Source/RecastMesh.cpp
|
||||
Recast/Source/RecastMeshDetail.cpp
|
||||
Recast/Source/RecastRasterization.cpp
|
||||
Recast/Source/RecastRegion.cpp
|
||||
Recast/Source/RecastTimer.cpp
|
||||
|
||||
Recast/Include/Recast.h
|
||||
Recast/Include/RecastLog.h
|
||||
Recast/Include/RecastTimer.h
|
||||
Recast/Include/RecastAlloc.h
|
||||
Recast/Include/RecastAssert.h
|
||||
)
|
||||
|
||||
blender_add_lib(extern_recastnavigation "${SRC}" "${INC}" "${INC_SYS}")
|
||||
|
||||
1269
extern/recastnavigation/Recast/Include/Recast.h
vendored
1269
extern/recastnavigation/Recast/Include/Recast.h
vendored
File diff suppressed because it is too large
Load Diff
122
extern/recastnavigation/Recast/Include/RecastAlloc.h
vendored
Normal file
122
extern/recastnavigation/Recast/Include/RecastAlloc.h
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef RECASTALLOC_H
|
||||
#define RECASTALLOC_H
|
||||
|
||||
/// Provides hint values to the memory allocator on how long the
|
||||
/// memory is expected to be used.
|
||||
enum rcAllocHint
|
||||
{
|
||||
RC_ALLOC_PERM, ///< Memory will persist after a function call.
|
||||
RC_ALLOC_TEMP ///< Memory used temporarily within a function.
|
||||
};
|
||||
|
||||
/// A memory allocation function.
|
||||
// @param[in] size The size, in bytes of memory, to allocate.
|
||||
// @param[in] rcAllocHint A hint to the allocator on how long the memory is expected to be in use.
|
||||
// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed.
|
||||
/// @see rcAllocSetCustom
|
||||
typedef void* (rcAllocFunc)(int size, rcAllocHint hint);
|
||||
|
||||
/// A memory deallocation function.
|
||||
/// @see rcAllocSetCustom
|
||||
// @param[in] ptr
|
||||
typedef void (rcFreeFunc)(void* ptr);
|
||||
|
||||
/// Sets the base custom allocation functions to be used by Recast.
|
||||
/// @param[in] allocFunc The memory allocation function to be used by #rcAlloc
|
||||
/// @param[in] freeFunc The memory de-allocation function to be used by #rcFree
|
||||
void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc);
|
||||
|
||||
/// Allocates a memory block.
|
||||
/// @param[in] size The size, in bytes of memory, to allocate.
|
||||
/// @param[in] hint A hint to the allocator on how long the memory is expected to be in use.
|
||||
/// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed.
|
||||
void* rcAlloc(int size, rcAllocHint hint);
|
||||
|
||||
/// Deallocates a memory block.
|
||||
/// @param[in] ptr A pointer to a memory block previously allocated using #rcAlloc.
|
||||
void rcFree(void* ptr);
|
||||
|
||||
|
||||
/// A simple dynamic array of integers.
|
||||
class rcIntArray
|
||||
{
|
||||
int* m_data;
|
||||
int m_size, m_cap;
|
||||
inline rcIntArray(const rcIntArray&);
|
||||
inline rcIntArray& operator=(const rcIntArray&);
|
||||
public:
|
||||
|
||||
/// Constructs an instance with an initial array size of zero.
|
||||
inline rcIntArray() : m_data(0), m_size(0), m_cap(0) {}
|
||||
|
||||
/// Constructs an instance initialized to the specified size.
|
||||
/// @param[in] n The initial size of the integer array.
|
||||
inline rcIntArray(int n) : m_data(0), m_size(0), m_cap(0) { resize(n); }
|
||||
inline ~rcIntArray() { rcFree(m_data); }
|
||||
|
||||
/// Specifies the new size of the integer array.
|
||||
/// @param[in] n The new size of the integer array.
|
||||
void resize(int n);
|
||||
|
||||
/// Push the specified integer onto the end of the array and increases the size by one.
|
||||
/// @param[in] item The new value.
|
||||
inline void push(int item) { resize(m_size+1); m_data[m_size-1] = item; }
|
||||
|
||||
/// Returns the value at the end of the array and reduces the size by one.
|
||||
/// @return The value at the end of the array.
|
||||
inline int pop() { if (m_size > 0) m_size--; return m_data[m_size]; }
|
||||
|
||||
/// The value at the specified array index.
|
||||
/// @warning Does not provide overflow protection.
|
||||
/// @param[in] i The index of the value.
|
||||
inline const int& operator[](int i) const { return m_data[i]; }
|
||||
|
||||
/// The value at the specified array index.
|
||||
/// @warning Does not provide overflow protection.
|
||||
/// @param[in] i The index of the value.
|
||||
inline int& operator[](int i) { return m_data[i]; }
|
||||
|
||||
/// The current size of the integer array.
|
||||
inline int size() const { return m_size; }
|
||||
};
|
||||
|
||||
/// A simple helper class used to delete an array when it goes out of scope.
|
||||
/// @note This class is rarely if ever used by the end user.
|
||||
template<class T> class rcScopedDelete
|
||||
{
|
||||
T* ptr;
|
||||
inline T* operator=(T* p);
|
||||
public:
|
||||
|
||||
/// Constructs an instance with a null pointer.
|
||||
inline rcScopedDelete() : ptr(0) {}
|
||||
|
||||
/// Constructs an instance with the specified pointer.
|
||||
/// @param[in] p An pointer to an allocated array.
|
||||
inline rcScopedDelete(T* p) : ptr(p) {}
|
||||
inline ~rcScopedDelete() { rcFree(ptr); }
|
||||
|
||||
/// The root array pointer.
|
||||
/// @return The root array pointer.
|
||||
inline operator T*() { return ptr; }
|
||||
};
|
||||
|
||||
#endif
|
||||
33
extern/recastnavigation/Recast/Include/RecastAssert.h
vendored
Normal file
33
extern/recastnavigation/Recast/Include/RecastAssert.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef RECASTASSERT_H
|
||||
#define RECASTASSERT_H
|
||||
|
||||
// Note: This header file's only purpose is to include define assert.
|
||||
// Feel free to change the file and include your own implementation instead.
|
||||
|
||||
#ifdef NDEBUG
|
||||
// From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
|
||||
# define rcAssert(x) do { (void)sizeof(x); } while(__LINE__==-1,false)
|
||||
#else
|
||||
# include <assert.h>
|
||||
# define rcAssert assert
|
||||
#endif
|
||||
|
||||
#endif // RECASTASSERT_H
|
||||
335
extern/recastnavigation/Recast/Source/Recast.cpp
vendored
335
extern/recastnavigation/Recast/Source/Recast.cpp
vendored
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -22,35 +22,178 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastLog.h"
|
||||
#include "RecastTimer.h"
|
||||
#include "RecastAlloc.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
|
||||
void rcIntArray::resize(int n)
|
||||
float rcSqrt(float x)
|
||||
{
|
||||
if (n > m_cap)
|
||||
{
|
||||
if (!m_cap) m_cap = 8;
|
||||
while (m_cap < n) m_cap *= 2;
|
||||
int* newData = new int[m_cap];
|
||||
if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(int));
|
||||
delete [] m_data;
|
||||
m_data = newData;
|
||||
return sqrtf(x);
|
||||
}
|
||||
m_size = n;
|
||||
|
||||
/// @class rcContext
|
||||
/// @par
|
||||
///
|
||||
/// This class does not provide logging or timer functionality on its
|
||||
/// own. Both must be provided by a concrete implementation
|
||||
/// by overriding the protected member functions. Also, this class does not
|
||||
/// provide an interface for extracting log messages. (Only adding them.)
|
||||
/// So concrete implementations must provide one.
|
||||
///
|
||||
/// If no logging or timers are required, just pass an instance of this
|
||||
/// class through the Recast build process.
|
||||
///
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// Example:
|
||||
/// @code
|
||||
/// // Where ctx is an instance of rcContext and filepath is a char array.
|
||||
/// ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not load '%s'", filepath);
|
||||
/// @endcode
|
||||
void rcContext::log(const rcLogCategory category, const char* format, ...)
|
||||
{
|
||||
if (!m_logEnabled)
|
||||
return;
|
||||
static const int MSG_SIZE = 512;
|
||||
char msg[MSG_SIZE];
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int len = vsnprintf(msg, MSG_SIZE, format, ap);
|
||||
if (len >= MSG_SIZE)
|
||||
{
|
||||
len = MSG_SIZE-1;
|
||||
msg[MSG_SIZE-1] = '\0';
|
||||
}
|
||||
va_end(ap);
|
||||
doLog(category, msg, len);
|
||||
}
|
||||
|
||||
rcHeightfield* rcAllocHeightfield()
|
||||
{
|
||||
rcHeightfield* hf = (rcHeightfield*)rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM);
|
||||
memset(hf, 0, sizeof(rcHeightfield));
|
||||
return hf;
|
||||
}
|
||||
|
||||
void rcFreeHeightField(rcHeightfield* hf)
|
||||
{
|
||||
if (!hf) return;
|
||||
// Delete span array.
|
||||
rcFree(hf->spans);
|
||||
// Delete span pools.
|
||||
while (hf->pools)
|
||||
{
|
||||
rcSpanPool* next = hf->pools->next;
|
||||
rcFree(hf->pools);
|
||||
hf->pools = next;
|
||||
}
|
||||
rcFree(hf);
|
||||
}
|
||||
|
||||
rcCompactHeightfield* rcAllocCompactHeightfield()
|
||||
{
|
||||
rcCompactHeightfield* chf = (rcCompactHeightfield*)rcAlloc(sizeof(rcCompactHeightfield), RC_ALLOC_PERM);
|
||||
memset(chf, 0, sizeof(rcCompactHeightfield));
|
||||
return chf;
|
||||
}
|
||||
|
||||
void rcFreeCompactHeightfield(rcCompactHeightfield* chf)
|
||||
{
|
||||
if (!chf) return;
|
||||
rcFree(chf->cells);
|
||||
rcFree(chf->spans);
|
||||
rcFree(chf->dist);
|
||||
rcFree(chf->areas);
|
||||
rcFree(chf);
|
||||
}
|
||||
|
||||
|
||||
rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet()
|
||||
{
|
||||
rcHeightfieldLayerSet* lset = (rcHeightfieldLayerSet*)rcAlloc(sizeof(rcHeightfieldLayerSet), RC_ALLOC_PERM);
|
||||
memset(lset, 0, sizeof(rcHeightfieldLayerSet));
|
||||
return lset;
|
||||
}
|
||||
|
||||
void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset)
|
||||
{
|
||||
if (!lset) return;
|
||||
for (int i = 0; i < lset->nlayers; ++i)
|
||||
{
|
||||
rcFree(lset->layers[i].heights);
|
||||
rcFree(lset->layers[i].areas);
|
||||
rcFree(lset->layers[i].cons);
|
||||
}
|
||||
rcFree(lset->layers);
|
||||
rcFree(lset);
|
||||
}
|
||||
|
||||
|
||||
rcContourSet* rcAllocContourSet()
|
||||
{
|
||||
rcContourSet* cset = (rcContourSet*)rcAlloc(sizeof(rcContourSet), RC_ALLOC_PERM);
|
||||
memset(cset, 0, sizeof(rcContourSet));
|
||||
return cset;
|
||||
}
|
||||
|
||||
void rcFreeContourSet(rcContourSet* cset)
|
||||
{
|
||||
if (!cset) return;
|
||||
for (int i = 0; i < cset->nconts; ++i)
|
||||
{
|
||||
rcFree(cset->conts[i].verts);
|
||||
rcFree(cset->conts[i].rverts);
|
||||
}
|
||||
rcFree(cset->conts);
|
||||
rcFree(cset);
|
||||
}
|
||||
|
||||
rcPolyMesh* rcAllocPolyMesh()
|
||||
{
|
||||
rcPolyMesh* pmesh = (rcPolyMesh*)rcAlloc(sizeof(rcPolyMesh), RC_ALLOC_PERM);
|
||||
memset(pmesh, 0, sizeof(rcPolyMesh));
|
||||
return pmesh;
|
||||
}
|
||||
|
||||
void rcFreePolyMesh(rcPolyMesh* pmesh)
|
||||
{
|
||||
if (!pmesh) return;
|
||||
rcFree(pmesh->verts);
|
||||
rcFree(pmesh->polys);
|
||||
rcFree(pmesh->regs);
|
||||
rcFree(pmesh->flags);
|
||||
rcFree(pmesh->areas);
|
||||
rcFree(pmesh);
|
||||
}
|
||||
|
||||
rcPolyMeshDetail* rcAllocPolyMeshDetail()
|
||||
{
|
||||
rcPolyMeshDetail* dmesh = (rcPolyMeshDetail*)rcAlloc(sizeof(rcPolyMeshDetail), RC_ALLOC_PERM);
|
||||
memset(dmesh, 0, sizeof(rcPolyMeshDetail));
|
||||
return dmesh;
|
||||
}
|
||||
|
||||
void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh)
|
||||
{
|
||||
if (!dmesh) return;
|
||||
rcFree(dmesh->meshes);
|
||||
rcFree(dmesh->verts);
|
||||
rcFree(dmesh->tris);
|
||||
rcFree(dmesh);
|
||||
}
|
||||
|
||||
void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax)
|
||||
{
|
||||
// Calculate bounding box.
|
||||
vcopy(bmin, verts);
|
||||
vcopy(bmax, verts);
|
||||
rcVcopy(bmin, verts);
|
||||
rcVcopy(bmax, verts);
|
||||
for (int i = 1; i < nv; ++i)
|
||||
{
|
||||
const float* v = &verts[i*3];
|
||||
vmin(bmin, v);
|
||||
vmax(bmax, v);
|
||||
rcVmin(bmin, v);
|
||||
rcVmax(bmax, v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,17 +203,25 @@ void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int*
|
||||
*h = (int)((bmax[2] - bmin[2])/cs+0.5f);
|
||||
}
|
||||
|
||||
bool rcCreateHeightfield(rcHeightfield& hf, int width, int height,
|
||||
/// @par
|
||||
///
|
||||
/// See the #rcConfig documentation for more information on the configuration parameters.
|
||||
///
|
||||
/// @see rcAllocHeightfield, rcHeightfield
|
||||
bool rcCreateHeightfield(rcContext* /*ctx*/, rcHeightfield& hf, int width, int height,
|
||||
const float* bmin, const float* bmax,
|
||||
float cs, float ch)
|
||||
{
|
||||
// TODO: VC complains about unref formal variable, figure out a way to handle this better.
|
||||
// rcAssert(ctx);
|
||||
|
||||
hf.width = width;
|
||||
hf.height = height;
|
||||
hf.spans = new rcSpan*[hf.width*hf.height];
|
||||
vcopy(hf.bmin, bmin);
|
||||
vcopy(hf.bmax, bmax);
|
||||
rcVcopy(hf.bmin, bmin);
|
||||
rcVcopy(hf.bmax, bmax);
|
||||
hf.cs = cs;
|
||||
hf.ch = ch;
|
||||
hf.spans = (rcSpan**)rcAlloc(sizeof(rcSpan*)*hf.width*hf.height, RC_ALLOC_PERM);
|
||||
if (!hf.spans)
|
||||
return false;
|
||||
memset(hf.spans, 0, sizeof(rcSpan*)*hf.width*hf.height);
|
||||
@@ -80,18 +231,29 @@ bool rcCreateHeightfield(rcHeightfield& hf, int width, int height,
|
||||
static void calcTriNormal(const float* v0, const float* v1, const float* v2, float* norm)
|
||||
{
|
||||
float e0[3], e1[3];
|
||||
vsub(e0, v1, v0);
|
||||
vsub(e1, v2, v0);
|
||||
vcross(norm, e0, e1);
|
||||
vnormalize(norm);
|
||||
rcVsub(e0, v1, v0);
|
||||
rcVsub(e1, v2, v0);
|
||||
rcVcross(norm, e0, e1);
|
||||
rcVnormalize(norm);
|
||||
}
|
||||
|
||||
void rcMarkWalkableTriangles(const float walkableSlopeAngle,
|
||||
const float* verts, int nv,
|
||||
/// @par
|
||||
///
|
||||
/// Only sets the aread id's for the walkable triangles. Does not alter the
|
||||
/// area id's for unwalkable triangles.
|
||||
///
|
||||
/// See the #rcConfig documentation for more information on the configuration parameters.
|
||||
///
|
||||
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
|
||||
void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
|
||||
const float* verts, int /*nv*/,
|
||||
const int* tris, int nt,
|
||||
unsigned char* flags)
|
||||
unsigned char* areas)
|
||||
{
|
||||
const float walkableThr = cosf(walkableSlopeAngle/180.0f*(float)M_PI);
|
||||
// TODO: VC complains about unref formal variable, figure out a way to handle this better.
|
||||
// rcAssert(ctx);
|
||||
|
||||
const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI);
|
||||
|
||||
float norm[3];
|
||||
|
||||
@@ -101,12 +263,45 @@ void rcMarkWalkableTriangles(const float walkableSlopeAngle,
|
||||
calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
|
||||
// Check if the face is walkable.
|
||||
if (norm[1] > walkableThr)
|
||||
flags[i] |= RC_WALKABLE;
|
||||
areas[i] = RC_WALKABLE_AREA;
|
||||
}
|
||||
}
|
||||
|
||||
static int getSpanCount(unsigned char flags, rcHeightfield& hf)
|
||||
/// @par
|
||||
///
|
||||
/// Only sets the aread id's for the unwalkable triangles. Does not alter the
|
||||
/// area id's for walkable triangles.
|
||||
///
|
||||
/// See the #rcConfig documentation for more information on the configuration parameters.
|
||||
///
|
||||
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
|
||||
void rcClearUnwalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
|
||||
const float* verts, int /*nv*/,
|
||||
const int* tris, int nt,
|
||||
unsigned char* areas)
|
||||
{
|
||||
// TODO: VC complains about unref formal variable, figure out a way to handle this better.
|
||||
// rcAssert(ctx);
|
||||
|
||||
const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI);
|
||||
|
||||
float norm[3];
|
||||
|
||||
for (int i = 0; i < nt; ++i)
|
||||
{
|
||||
const int* tri = &tris[i*3];
|
||||
calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
|
||||
// Check if the face is walkable.
|
||||
if (norm[1] <= walkableThr)
|
||||
areas[i] = RC_NULL_AREA;
|
||||
}
|
||||
}
|
||||
|
||||
int rcGetHeightFieldSpanCount(rcContext* /*ctx*/, rcHeightfield& hf)
|
||||
{
|
||||
// TODO: VC complains about unref formal variable, figure out a way to handle this better.
|
||||
// rcAssert(ctx);
|
||||
|
||||
const int w = hf.width;
|
||||
const int h = hf.height;
|
||||
int spanCount = 0;
|
||||
@@ -116,7 +311,7 @@ static int getSpanCount(unsigned char flags, rcHeightfield& hf)
|
||||
{
|
||||
for (rcSpan* s = hf.spans[x + y*w]; s; s = s->next)
|
||||
{
|
||||
if (s->flags == flags)
|
||||
if (s->area != RC_NULL_AREA)
|
||||
spanCount++;
|
||||
}
|
||||
}
|
||||
@@ -124,21 +319,25 @@ static int getSpanCount(unsigned char flags, rcHeightfield& hf)
|
||||
return spanCount;
|
||||
}
|
||||
|
||||
inline void setCon(rcCompactSpan& s, int dir, int i)
|
||||
/// @par
|
||||
///
|
||||
/// This is just the beginning of the process of fully building a compact heightfield.
|
||||
/// Various filters may be applied applied, then the distance field and regions built.
|
||||
/// E.g: #rcBuildDistanceField and #rcBuildRegions
|
||||
///
|
||||
/// See the #rcConfig documentation for more information on the configuration parameters.
|
||||
///
|
||||
/// @see rcAllocCompactHeightfield, rcHeightfield, rcCompactHeightfield, rcConfig
|
||||
bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
|
||||
rcHeightfield& hf, rcCompactHeightfield& chf)
|
||||
{
|
||||
s.con &= ~(0xf << (dir*4));
|
||||
s.con |= (i&0xf) << (dir*4);
|
||||
}
|
||||
rcAssert(ctx);
|
||||
|
||||
bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb,
|
||||
unsigned char flags, rcHeightfield& hf,
|
||||
rcCompactHeightfield& chf)
|
||||
{
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
ctx->startTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD);
|
||||
|
||||
const int w = hf.width;
|
||||
const int h = hf.height;
|
||||
const int spanCount = getSpanCount(flags, hf);
|
||||
const int spanCount = rcGetHeightFieldSpanCount(ctx, hf);
|
||||
|
||||
// Fill in header.
|
||||
chf.width = w;
|
||||
@@ -147,27 +346,32 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb
|
||||
chf.walkableHeight = walkableHeight;
|
||||
chf.walkableClimb = walkableClimb;
|
||||
chf.maxRegions = 0;
|
||||
vcopy(chf.bmin, hf.bmin);
|
||||
vcopy(chf.bmax, hf.bmax);
|
||||
rcVcopy(chf.bmin, hf.bmin);
|
||||
rcVcopy(chf.bmax, hf.bmax);
|
||||
chf.bmax[1] += walkableHeight*hf.ch;
|
||||
chf.cs = hf.cs;
|
||||
chf.ch = hf.ch;
|
||||
chf.cells = new rcCompactCell[w*h];
|
||||
chf.cells = (rcCompactCell*)rcAlloc(sizeof(rcCompactCell)*w*h, RC_ALLOC_PERM);
|
||||
if (!chf.cells)
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (%d)", w*h);
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (%d)", w*h);
|
||||
return false;
|
||||
}
|
||||
memset(chf.cells, 0, sizeof(rcCompactCell)*w*h);
|
||||
chf.spans = new rcCompactSpan[spanCount];
|
||||
chf.spans = (rcCompactSpan*)rcAlloc(sizeof(rcCompactSpan)*spanCount, RC_ALLOC_PERM);
|
||||
if (!chf.spans)
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (%d)", spanCount);
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (%d)", spanCount);
|
||||
return false;
|
||||
}
|
||||
memset(chf.spans, 0, sizeof(rcCompactSpan)*spanCount);
|
||||
chf.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*spanCount, RC_ALLOC_PERM);
|
||||
if (!chf.areas)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.areas' (%d)", spanCount);
|
||||
return false;
|
||||
}
|
||||
memset(chf.areas, RC_NULL_AREA, sizeof(unsigned char)*spanCount);
|
||||
|
||||
const int MAX_HEIGHT = 0xffff;
|
||||
|
||||
@@ -185,12 +389,13 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb
|
||||
c.count = 0;
|
||||
while (s)
|
||||
{
|
||||
if (s->flags == flags)
|
||||
if (s->area != RC_NULL_AREA)
|
||||
{
|
||||
const int bot = (int)s->smax;
|
||||
const int top = s->next ? (int)s->next->smin : MAX_HEIGHT;
|
||||
chf.spans[idx].y = (unsigned short)rcClamp(bot, 0, 0xffff);
|
||||
chf.spans[idx].h = (unsigned char)rcClamp(top - bot, 0, 0xff);
|
||||
chf.areas[idx] = s->area;
|
||||
idx++;
|
||||
c.count++;
|
||||
}
|
||||
@@ -200,6 +405,8 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb
|
||||
}
|
||||
|
||||
// Find neighbour connections.
|
||||
const int MAX_LAYERS = RC_NOT_CONNECTED-1;
|
||||
int tooHighNeighbour = 0;
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
@@ -208,14 +415,16 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
rcCompactSpan& s = chf.spans[i];
|
||||
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
setCon(s, dir, 0xf);
|
||||
rcSetCon(s, dir, RC_NOT_CONNECTED);
|
||||
const int nx = x + rcGetDirOffsetX(dir);
|
||||
const int ny = y + rcGetDirOffsetY(dir);
|
||||
// First check that the neighbour cell is in bounds.
|
||||
if (nx < 0 || ny < 0 || nx >= w || ny >= h)
|
||||
continue;
|
||||
|
||||
// Iterate over all neighbour spans and check if any of the is
|
||||
// accessible from current cell.
|
||||
const rcCompactCell& nc = chf.cells[nx+ny*w];
|
||||
@@ -230,23 +439,34 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb
|
||||
if ((top - bot) >= walkableHeight && rcAbs((int)ns.y - (int)s.y) <= walkableClimb)
|
||||
{
|
||||
// Mark direction as walkable.
|
||||
setCon(s, dir, k - (int)nc.index);
|
||||
const int idx = k - (int)nc.index;
|
||||
if (idx < 0 || idx > MAX_LAYERS)
|
||||
{
|
||||
tooHighNeighbour = rcMax(tooHighNeighbour, idx);
|
||||
continue;
|
||||
}
|
||||
rcSetCon(s, dir, idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
if (tooHighNeighbour > MAX_LAYERS)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heightfield has too many layers %d (max: %d)",
|
||||
tooHighNeighbour, MAX_LAYERS);
|
||||
}
|
||||
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->buildCompact += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
ctx->stopTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
static int getHeightfieldMemoryUsage(const rcHeightfield& hf)
|
||||
{
|
||||
int size = 0;
|
||||
@@ -270,3 +490,4 @@ static int getCompactHeightFieldMemoryusage(const rcCompactHeightfield& chf)
|
||||
size += sizeof(rcCompactCell) * chf.width * chf.height;
|
||||
return size;
|
||||
}
|
||||
*/
|
||||
88
extern/recastnavigation/Recast/Source/RecastAlloc.cpp
vendored
Normal file
88
extern/recastnavigation/Recast/Source/RecastAlloc.cpp
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "RecastAlloc.h"
|
||||
|
||||
static void *rcAllocDefault(int size, rcAllocHint)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void rcFreeDefault(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static rcAllocFunc* sRecastAllocFunc = rcAllocDefault;
|
||||
static rcFreeFunc* sRecastFreeFunc = rcFreeDefault;
|
||||
|
||||
/// @see rcAlloc, rcFree
|
||||
void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc)
|
||||
{
|
||||
sRecastAllocFunc = allocFunc ? allocFunc : rcAllocDefault;
|
||||
sRecastFreeFunc = freeFunc ? freeFunc : rcFreeDefault;
|
||||
}
|
||||
|
||||
/// @see rcAllocSetCustom
|
||||
void* rcAlloc(int size, rcAllocHint hint)
|
||||
{
|
||||
return sRecastAllocFunc(size, hint);
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// @warning This function leaves the value of @p ptr unchanged. So it still
|
||||
/// points to the same (now invalid) location, and not to null.
|
||||
///
|
||||
/// @see rcAllocSetCustom
|
||||
void rcFree(void* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
sRecastFreeFunc(ptr);
|
||||
}
|
||||
|
||||
/// @class rcIntArray
|
||||
///
|
||||
/// While it is possible to pre-allocate a specific array size during
|
||||
/// construction or by using the #resize method, certain methods will
|
||||
/// automatically resize the array as needed.
|
||||
///
|
||||
/// @warning The array memory is not initialized to zero when the size is
|
||||
/// manually set during construction or when using #resize.
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// Using this method ensures the array is at least large enough to hold
|
||||
/// the specified number of elements. This can improve performance by
|
||||
/// avoiding auto-resizing during use.
|
||||
void rcIntArray::resize(int n)
|
||||
{
|
||||
if (n > m_cap)
|
||||
{
|
||||
if (!m_cap) m_cap = n;
|
||||
while (m_cap < n) m_cap *= 2;
|
||||
int* newData = (int*)rcAlloc(m_cap*sizeof(int), RC_ALLOC_TEMP);
|
||||
if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(int));
|
||||
rcFree(m_data);
|
||||
m_data = newData;
|
||||
}
|
||||
m_size = n;
|
||||
}
|
||||
|
||||
524
extern/recastnavigation/Recast/Source/RecastArea.cpp
vendored
Normal file
524
extern/recastnavigation/Recast/Source/RecastArea.cpp
vendored
Normal file
@@ -0,0 +1,524 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <float.h>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastAlloc.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// Basically, any spans that are closer to a boundary or obstruction than the specified radius
|
||||
/// are marked as unwalkable.
|
||||
///
|
||||
/// This method is usually called immediately after the heightfield has been built.
|
||||
///
|
||||
/// @see rcCompactHeightfield, rcBuildCompactHeightfield, rcConfig::walkableRadius
|
||||
bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
const int w = chf.width;
|
||||
const int h = chf.height;
|
||||
|
||||
ctx->startTimer(RC_TIMER_ERODE_AREA);
|
||||
|
||||
unsigned char* dist = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
|
||||
if (!dist)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "erodeWalkableArea: Out of memory 'dist' (%d).", chf.spanCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Init distance.
|
||||
memset(dist, 0xff, sizeof(unsigned char)*chf.spanCount);
|
||||
|
||||
// Mark boundary cells.
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
if (chf.areas[i] == RC_NULL_AREA)
|
||||
{
|
||||
dist[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
int nc = 0;
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int nx = x + rcGetDirOffsetX(dir);
|
||||
const int ny = y + rcGetDirOffsetY(dir);
|
||||
const int ni = (int)chf.cells[nx+ny*w].index + rcGetCon(s, dir);
|
||||
if (chf.areas[ni] != RC_NULL_AREA)
|
||||
{
|
||||
nc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// At least one missing neighbour.
|
||||
if (nc != 4)
|
||||
dist[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char nd;
|
||||
|
||||
// Pass 1
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
|
||||
if (rcGetCon(s, 0) != RC_NOT_CONNECTED)
|
||||
{
|
||||
// (-1,0)
|
||||
const int ax = x + rcGetDirOffsetX(0);
|
||||
const int ay = y + rcGetDirOffsetY(0);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
|
||||
// (-1,-1)
|
||||
if (rcGetCon(as, 3) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int aax = ax + rcGetDirOffsetX(3);
|
||||
const int aay = ay + rcGetDirOffsetY(3);
|
||||
const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 3);
|
||||
nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
}
|
||||
}
|
||||
if (rcGetCon(s, 3) != RC_NOT_CONNECTED)
|
||||
{
|
||||
// (0,-1)
|
||||
const int ax = x + rcGetDirOffsetX(3);
|
||||
const int ay = y + rcGetDirOffsetY(3);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
|
||||
// (1,-1)
|
||||
if (rcGetCon(as, 2) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int aax = ax + rcGetDirOffsetX(2);
|
||||
const int aay = ay + rcGetDirOffsetY(2);
|
||||
const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 2);
|
||||
nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 2
|
||||
for (int y = h-1; y >= 0; --y)
|
||||
{
|
||||
for (int x = w-1; x >= 0; --x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
|
||||
if (rcGetCon(s, 2) != RC_NOT_CONNECTED)
|
||||
{
|
||||
// (1,0)
|
||||
const int ax = x + rcGetDirOffsetX(2);
|
||||
const int ay = y + rcGetDirOffsetY(2);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 2);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
|
||||
// (1,1)
|
||||
if (rcGetCon(as, 1) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int aax = ax + rcGetDirOffsetX(1);
|
||||
const int aay = ay + rcGetDirOffsetY(1);
|
||||
const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 1);
|
||||
nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
}
|
||||
}
|
||||
if (rcGetCon(s, 1) != RC_NOT_CONNECTED)
|
||||
{
|
||||
// (0,1)
|
||||
const int ax = x + rcGetDirOffsetX(1);
|
||||
const int ay = y + rcGetDirOffsetY(1);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 1);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
|
||||
// (-1,1)
|
||||
if (rcGetCon(as, 0) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int aax = ax + rcGetDirOffsetX(0);
|
||||
const int aay = ay + rcGetDirOffsetY(0);
|
||||
const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 0);
|
||||
nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned char thr = (unsigned char)(radius*2);
|
||||
for (int i = 0; i < chf.spanCount; ++i)
|
||||
if (dist[i] < thr)
|
||||
chf.areas[i] = RC_NULL_AREA;
|
||||
|
||||
rcFree(dist);
|
||||
|
||||
ctx->stopTimer(RC_TIMER_ERODE_AREA);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void insertSort(unsigned char* a, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 1; i < n; i++)
|
||||
{
|
||||
const unsigned char value = a[i];
|
||||
for (j = i - 1; j >= 0 && a[j] > value; j--)
|
||||
a[j+1] = a[j];
|
||||
a[j+1] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// This filter is usually applied after applying area id's using functions
|
||||
/// such as #rcMarkBoxArea, #rcMarkConvexPolyArea, and #rcMarkCylinderArea.
|
||||
///
|
||||
/// @see rcCompactHeightfield
|
||||
bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
const int w = chf.width;
|
||||
const int h = chf.height;
|
||||
|
||||
ctx->startTimer(RC_TIMER_MEDIAN_AREA);
|
||||
|
||||
unsigned char* areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
|
||||
if (!areas)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "medianFilterWalkableArea: Out of memory 'areas' (%d).", chf.spanCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Init distance.
|
||||
memset(areas, 0xff, sizeof(unsigned char)*chf.spanCount);
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (chf.areas[i] == RC_NULL_AREA)
|
||||
{
|
||||
areas[i] = chf.areas[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned char nei[9];
|
||||
for (int j = 0; j < 9; ++j)
|
||||
nei[j] = chf.areas[i];
|
||||
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dir);
|
||||
const int ay = y + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
||||
if (chf.areas[ai] != RC_NULL_AREA)
|
||||
nei[dir*2+0] = chf.areas[ai];
|
||||
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
const int dir2 = (dir+1) & 0x3;
|
||||
if (rcGetCon(as, dir2) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax2 = ax + rcGetDirOffsetX(dir2);
|
||||
const int ay2 = ay + rcGetDirOffsetY(dir2);
|
||||
const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2);
|
||||
if (chf.areas[ai2] != RC_NULL_AREA)
|
||||
nei[dir*2+1] = chf.areas[ai2];
|
||||
}
|
||||
}
|
||||
}
|
||||
insertSort(nei, 9);
|
||||
areas[i] = nei[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(chf.areas, areas, sizeof(unsigned char)*chf.spanCount);
|
||||
|
||||
rcFree(areas);
|
||||
|
||||
ctx->stopTimer(RC_TIMER_MEDIAN_AREA);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// The value of spacial parameters are in world units.
|
||||
///
|
||||
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
|
||||
void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId,
|
||||
rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_MARK_BOX_AREA);
|
||||
|
||||
int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
|
||||
int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
|
||||
int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
|
||||
int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
|
||||
int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
|
||||
int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
|
||||
|
||||
if (maxx < 0) return;
|
||||
if (minx >= chf.width) return;
|
||||
if (maxz < 0) return;
|
||||
if (minz >= chf.height) return;
|
||||
|
||||
if (minx < 0) minx = 0;
|
||||
if (maxx >= chf.width) maxx = chf.width-1;
|
||||
if (minz < 0) minz = 0;
|
||||
if (maxz >= chf.height) maxz = chf.height-1;
|
||||
|
||||
for (int z = minz; z <= maxz; ++z)
|
||||
{
|
||||
for (int x = minx; x <= maxx; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+z*chf.width];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
rcCompactSpan& s = chf.spans[i];
|
||||
if ((int)s.y >= miny && (int)s.y <= maxy)
|
||||
{
|
||||
if (chf.areas[i] != RC_NULL_AREA)
|
||||
chf.areas[i] = areaId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_MARK_BOX_AREA);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int pointInPoly(int nvert, const float* verts, const float* p)
|
||||
{
|
||||
int i, j, c = 0;
|
||||
for (i = 0, j = nvert-1; i < nvert; j = i++)
|
||||
{
|
||||
const float* vi = &verts[i*3];
|
||||
const float* vj = &verts[j*3];
|
||||
if (((vi[2] > p[2]) != (vj[2] > p[2])) &&
|
||||
(p[0] < (vj[0]-vi[0]) * (p[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) )
|
||||
c = !c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// The value of spacial parameters are in world units.
|
||||
///
|
||||
/// The y-values of the polygon vertices are ignored. So the polygon is effectively
|
||||
/// projected onto the xz-plane at @p hmin, then extruded to @p hmax.
|
||||
///
|
||||
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
|
||||
void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
||||
const float hmin, const float hmax, unsigned char areaId,
|
||||
rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
|
||||
|
||||
float bmin[3], bmax[3];
|
||||
rcVcopy(bmin, verts);
|
||||
rcVcopy(bmax, verts);
|
||||
for (int i = 1; i < nverts; ++i)
|
||||
{
|
||||
rcVmin(bmin, &verts[i*3]);
|
||||
rcVmax(bmax, &verts[i*3]);
|
||||
}
|
||||
bmin[1] = hmin;
|
||||
bmax[1] = hmax;
|
||||
|
||||
int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
|
||||
int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
|
||||
int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
|
||||
int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
|
||||
int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
|
||||
int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
|
||||
|
||||
if (maxx < 0) return;
|
||||
if (minx >= chf.width) return;
|
||||
if (maxz < 0) return;
|
||||
if (minz >= chf.height) return;
|
||||
|
||||
if (minx < 0) minx = 0;
|
||||
if (maxx >= chf.width) maxx = chf.width-1;
|
||||
if (minz < 0) minz = 0;
|
||||
if (maxz >= chf.height) maxz = chf.height-1;
|
||||
|
||||
|
||||
// TODO: Optimize.
|
||||
for (int z = minz; z <= maxz; ++z)
|
||||
{
|
||||
for (int x = minx; x <= maxx; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+z*chf.width];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
rcCompactSpan& s = chf.spans[i];
|
||||
if (chf.areas[i] == RC_NULL_AREA)
|
||||
continue;
|
||||
if ((int)s.y >= miny && (int)s.y <= maxy)
|
||||
{
|
||||
float p[3];
|
||||
p[0] = chf.bmin[0] + (x+0.5f)*chf.cs;
|
||||
p[1] = 0;
|
||||
p[2] = chf.bmin[2] + (z+0.5f)*chf.cs;
|
||||
|
||||
if (pointInPoly(nverts, verts, p))
|
||||
{
|
||||
chf.areas[i] = areaId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// The value of spacial parameters are in world units.
|
||||
///
|
||||
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
|
||||
void rcMarkCylinderArea(rcContext* ctx, const float* pos,
|
||||
const float r, const float h, unsigned char areaId,
|
||||
rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_MARK_CYLINDER_AREA);
|
||||
|
||||
float bmin[3], bmax[3];
|
||||
bmin[0] = pos[0] - r;
|
||||
bmin[1] = pos[1];
|
||||
bmin[2] = pos[2] - r;
|
||||
bmax[0] = pos[0] + r;
|
||||
bmax[1] = pos[1] + h;
|
||||
bmax[2] = pos[2] + r;
|
||||
const float r2 = r*r;
|
||||
|
||||
int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
|
||||
int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
|
||||
int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
|
||||
int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
|
||||
int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
|
||||
int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
|
||||
|
||||
if (maxx < 0) return;
|
||||
if (minx >= chf.width) return;
|
||||
if (maxz < 0) return;
|
||||
if (minz >= chf.height) return;
|
||||
|
||||
if (minx < 0) minx = 0;
|
||||
if (maxx >= chf.width) maxx = chf.width-1;
|
||||
if (minz < 0) minz = 0;
|
||||
if (maxz >= chf.height) maxz = chf.height-1;
|
||||
|
||||
|
||||
for (int z = minz; z <= maxz; ++z)
|
||||
{
|
||||
for (int x = minx; x <= maxx; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+z*chf.width];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
rcCompactSpan& s = chf.spans[i];
|
||||
|
||||
if (chf.areas[i] == RC_NULL_AREA)
|
||||
continue;
|
||||
|
||||
if ((int)s.y >= miny && (int)s.y <= maxy)
|
||||
{
|
||||
const float sx = chf.bmin[0] + (x+0.5f)*chf.cs;
|
||||
const float sz = chf.bmin[2] + (z+0.5f)*chf.cs;
|
||||
const float dx = sx - pos[0];
|
||||
const float dz = sz - pos[2];
|
||||
|
||||
if (dx*dx + dz*dz < r2)
|
||||
{
|
||||
chf.areas[i] = areaId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_MARK_CYLINDER_AREA);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -21,8 +21,8 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastLog.h"
|
||||
#include "RecastTimer.h"
|
||||
#include "RecastAlloc.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
|
||||
static int getCornerHeight(int x, int y, int i, int dir,
|
||||
@@ -33,44 +33,46 @@ static int getCornerHeight(int x, int y, int i, int dir,
|
||||
int ch = (int)s.y;
|
||||
int dirp = (dir+1) & 0x3;
|
||||
|
||||
unsigned short regs[4] = {0,0,0,0};
|
||||
unsigned int regs[4] = {0,0,0,0};
|
||||
|
||||
regs[0] = s.reg;
|
||||
// Combine region and area codes in order to prevent
|
||||
// border vertices which are in between two areas to be removed.
|
||||
regs[0] = chf.spans[i].reg | (chf.areas[i] << 16);
|
||||
|
||||
if (rcGetCon(s, dir) != 0xf)
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dir);
|
||||
const int ay = y + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
ch = rcMax(ch, (int)as.y);
|
||||
regs[1] = as.reg;
|
||||
if (rcGetCon(as, dirp) != 0xf)
|
||||
regs[1] = chf.spans[ai].reg | (chf.areas[ai] << 16);
|
||||
if (rcGetCon(as, dirp) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax2 = ax + rcGetDirOffsetX(dirp);
|
||||
const int ay2 = ay + rcGetDirOffsetY(dirp);
|
||||
const int ai2 = (int)chf.cells[ax2+ay2*chf.width].index + rcGetCon(as, dirp);
|
||||
const rcCompactSpan& as2 = chf.spans[ai2];
|
||||
ch = rcMax(ch, (int)as2.y);
|
||||
regs[2] = as2.reg;
|
||||
regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
|
||||
}
|
||||
}
|
||||
if (rcGetCon(s, dirp) != 0xf)
|
||||
if (rcGetCon(s, dirp) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dirp);
|
||||
const int ay = y + rcGetDirOffsetY(dirp);
|
||||
const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dirp);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
ch = rcMax(ch, (int)as.y);
|
||||
regs[3] = as.reg;
|
||||
if (rcGetCon(as, dir) != 0xf)
|
||||
regs[3] = chf.spans[ai].reg | (chf.areas[ai] << 16);
|
||||
if (rcGetCon(as, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax2 = ax + rcGetDirOffsetX(dir);
|
||||
const int ay2 = ay + rcGetDirOffsetY(dir);
|
||||
const int ai2 = (int)chf.cells[ax2+ay2*chf.width].index + rcGetCon(as, dir);
|
||||
const rcCompactSpan& as2 = chf.spans[ai2];
|
||||
ch = rcMax(ch, (int)as2.y);
|
||||
regs[2] = as2.reg;
|
||||
regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,8 +88,9 @@ static int getCornerHeight(int x, int y, int i, int dir,
|
||||
// followed by two interior cells and none of the regions are out of bounds.
|
||||
const bool twoSameExts = (regs[a] & regs[b] & RC_BORDER_REG) != 0 && regs[a] == regs[b];
|
||||
const bool twoInts = ((regs[c] | regs[d]) & RC_BORDER_REG) == 0;
|
||||
const bool intsSameArea = (regs[c]>>16) == (regs[d]>>16);
|
||||
const bool noZeros = regs[a] != 0 && regs[b] != 0 && regs[c] != 0 && regs[d] != 0;
|
||||
if (twoSameExts && twoInts && noZeros)
|
||||
if (twoSameExts && twoInts && intsSameArea && noZeros)
|
||||
{
|
||||
isBorderVertex = true;
|
||||
break;
|
||||
@@ -109,6 +112,8 @@ static void walkContour(int x, int y, int i,
|
||||
unsigned char startDir = dir;
|
||||
int starti = i;
|
||||
|
||||
const unsigned char area = chf.areas[i];
|
||||
|
||||
int iter = 0;
|
||||
while (++iter < 40000)
|
||||
{
|
||||
@@ -116,6 +121,7 @@ static void walkContour(int x, int y, int i,
|
||||
{
|
||||
// Choose the edge corner
|
||||
bool isBorderVertex = false;
|
||||
bool isAreaBorder = false;
|
||||
int px = x;
|
||||
int py = getCornerHeight(x, y, i, dir, chf, isBorderVertex);
|
||||
int pz = y;
|
||||
@@ -127,16 +133,19 @@ static void walkContour(int x, int y, int i,
|
||||
}
|
||||
int r = 0;
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (rcGetCon(s, dir) != 0xf)
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dir);
|
||||
const int ay = y + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
r = (int)as.reg;
|
||||
r = (int)chf.spans[ai].reg;
|
||||
if (area != chf.areas[ai])
|
||||
isAreaBorder = true;
|
||||
}
|
||||
if (isBorderVertex)
|
||||
r |= RC_BORDER_VERTEX;
|
||||
if (isAreaBorder)
|
||||
r |= RC_AREA_BORDER;
|
||||
points.push(px);
|
||||
points.push(py);
|
||||
points.push(pz);
|
||||
@@ -151,7 +160,7 @@ static void walkContour(int x, int y, int i,
|
||||
const int nx = x + rcGetDirOffsetX(dir);
|
||||
const int ny = y + rcGetDirOffsetY(dir);
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (rcGetCon(s, dir) != 0xf)
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const rcCompactCell& nc = chf.cells[nx+ny*chf.width];
|
||||
ni = (int)nc.index + rcGetCon(s, dir);
|
||||
@@ -174,9 +183,9 @@ static void walkContour(int x, int y, int i,
|
||||
}
|
||||
}
|
||||
|
||||
static float distancePtSeg(int x, int y, int z,
|
||||
int px, int py, int pz,
|
||||
int qx, int qy, int qz)
|
||||
static float distancePtSeg(const int x, const int z,
|
||||
const int px, const int pz,
|
||||
const int qx, const int qz)
|
||||
{
|
||||
/* float pqx = (float)(qx - px);
|
||||
float pqy = (float)(qy - py);
|
||||
@@ -218,20 +227,40 @@ static float distancePtSeg(int x, int y, int z,
|
||||
return dx*dx + dz*dz;
|
||||
}
|
||||
|
||||
static void simplifyContour(rcIntArray& points, rcIntArray& simplified, float maxError, int maxEdgeLen)
|
||||
static void simplifyContour(rcIntArray& points, rcIntArray& simplified,
|
||||
const float maxError, const int maxEdgeLen, const int buildFlags)
|
||||
{
|
||||
// Add initial points.
|
||||
bool noConnections = true;
|
||||
bool hasConnections = false;
|
||||
for (int i = 0; i < points.size(); i += 4)
|
||||
{
|
||||
if ((points[i+3] & 0xffff) != 0)
|
||||
if ((points[i+3] & RC_CONTOUR_REG_MASK) != 0)
|
||||
{
|
||||
noConnections = false;
|
||||
hasConnections = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (noConnections)
|
||||
if (hasConnections)
|
||||
{
|
||||
// The contour has some portals to other regions.
|
||||
// Add a new point to every location where the region changes.
|
||||
for (int i = 0, ni = points.size()/4; i < ni; ++i)
|
||||
{
|
||||
int ii = (i+1) % ni;
|
||||
const bool differentRegs = (points[i*4+3] & RC_CONTOUR_REG_MASK) != (points[ii*4+3] & RC_CONTOUR_REG_MASK);
|
||||
const bool areaBorders = (points[i*4+3] & RC_AREA_BORDER) != (points[ii*4+3] & RC_AREA_BORDER);
|
||||
if (differentRegs || areaBorders)
|
||||
{
|
||||
simplified.push(points[i*4+0]);
|
||||
simplified.push(points[i*4+1]);
|
||||
simplified.push(points[i*4+2]);
|
||||
simplified.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (simplified.size() == 0)
|
||||
{
|
||||
// If there is no connections at all,
|
||||
// create some initial points for the simplification process.
|
||||
@@ -256,7 +285,7 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, float ma
|
||||
llz = z;
|
||||
lli = i/4;
|
||||
}
|
||||
if (x >= urx || (x == urx && z > urz))
|
||||
if (x > urx || (x == urx && z > urz))
|
||||
{
|
||||
urx = x;
|
||||
ury = y;
|
||||
@@ -274,22 +303,6 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, float ma
|
||||
simplified.push(urz);
|
||||
simplified.push(uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The contour has some portals to other regions.
|
||||
// Add a new point to every location where the region changes.
|
||||
for (int i = 0, ni = points.size()/4; i < ni; ++i)
|
||||
{
|
||||
int ii = (i+1) % ni;
|
||||
if ((points[i*4+3] & 0xffff) != (points[ii*4+3] & 0xffff))
|
||||
{
|
||||
simplified.push(points[i*4+0]);
|
||||
simplified.push(points[i*4+1]);
|
||||
simplified.push(points[i*4+2]);
|
||||
simplified.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add points until all raw points are within
|
||||
// error tolerance to the simplified shape.
|
||||
@@ -298,34 +311,48 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, float ma
|
||||
{
|
||||
int ii = (i+1) % (simplified.size()/4);
|
||||
|
||||
int ax = simplified[i*4+0];
|
||||
int ay = simplified[i*4+1];
|
||||
int az = simplified[i*4+2];
|
||||
int ai = simplified[i*4+3];
|
||||
const int ax = simplified[i*4+0];
|
||||
const int az = simplified[i*4+2];
|
||||
const int ai = simplified[i*4+3];
|
||||
|
||||
int bx = simplified[ii*4+0];
|
||||
int by = simplified[ii*4+1];
|
||||
int bz = simplified[ii*4+2];
|
||||
int bi = simplified[ii*4+3];
|
||||
const int bx = simplified[ii*4+0];
|
||||
const int bz = simplified[ii*4+2];
|
||||
const int bi = simplified[ii*4+3];
|
||||
|
||||
// Find maximum deviation from the segment.
|
||||
float maxd = 0;
|
||||
int maxi = -1;
|
||||
int ci = (ai+1) % pn;
|
||||
int ci, cinc, endi;
|
||||
|
||||
// Tesselate only outer edges.
|
||||
if ((points[ci*4+3] & 0xffff) == 0)
|
||||
// Traverse the segment in lexilogical order so that the
|
||||
// max deviation is calculated similarly when traversing
|
||||
// opposite segments.
|
||||
if (bx > ax || (bx == ax && bz > az))
|
||||
{
|
||||
while (ci != bi)
|
||||
cinc = 1;
|
||||
ci = (ai+cinc) % pn;
|
||||
endi = bi;
|
||||
}
|
||||
else
|
||||
{
|
||||
float d = distancePtSeg(points[ci*4+0], points[ci*4+1]/4, points[ci*4+2],
|
||||
ax, ay/4, az, bx, by/4, bz);
|
||||
cinc = pn-1;
|
||||
ci = (bi+cinc) % pn;
|
||||
endi = ai;
|
||||
}
|
||||
|
||||
// Tessellate only outer edges or edges between areas.
|
||||
if ((points[ci*4+3] & RC_CONTOUR_REG_MASK) == 0 ||
|
||||
(points[ci*4+3] & RC_AREA_BORDER))
|
||||
{
|
||||
while (ci != endi)
|
||||
{
|
||||
float d = distancePtSeg(points[ci*4+0], points[ci*4+2], ax, az, bx, bz);
|
||||
if (d > maxd)
|
||||
{
|
||||
maxd = d;
|
||||
maxi = ci;
|
||||
}
|
||||
ci = (ci+1) % pn;
|
||||
ci = (ci+cinc) % pn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +363,7 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, float ma
|
||||
{
|
||||
// Add space for the new point.
|
||||
simplified.resize(simplified.size()+4);
|
||||
int n = simplified.size()/4;
|
||||
const int n = simplified.size()/4;
|
||||
for (int j = n-1; j > i; --j)
|
||||
{
|
||||
simplified[j*4+0] = simplified[(j-1)*4+0];
|
||||
@@ -357,34 +384,53 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, float ma
|
||||
}
|
||||
|
||||
// Split too long edges.
|
||||
if (maxEdgeLen > 0)
|
||||
if (maxEdgeLen > 0 && (buildFlags & (RC_CONTOUR_TESS_WALL_EDGES|RC_CONTOUR_TESS_AREA_EDGES)) != 0)
|
||||
{
|
||||
for (int i = 0; i < simplified.size()/4; )
|
||||
{
|
||||
int ii = (i+1) % (simplified.size()/4);
|
||||
const int ii = (i+1) % (simplified.size()/4);
|
||||
|
||||
int ax = simplified[i*4+0];
|
||||
int az = simplified[i*4+2];
|
||||
int ai = simplified[i*4+3];
|
||||
const int ax = simplified[i*4+0];
|
||||
const int az = simplified[i*4+2];
|
||||
const int ai = simplified[i*4+3];
|
||||
|
||||
int bx = simplified[ii*4+0];
|
||||
int bz = simplified[ii*4+2];
|
||||
int bi = simplified[ii*4+3];
|
||||
const int bx = simplified[ii*4+0];
|
||||
const int bz = simplified[ii*4+2];
|
||||
const int bi = simplified[ii*4+3];
|
||||
|
||||
// Find maximum deviation from the segment.
|
||||
int maxi = -1;
|
||||
int ci = (ai+1) % pn;
|
||||
|
||||
// Tesselate only outer edges.
|
||||
if ((points[ci*4+3] & 0xffff) == 0)
|
||||
// Tessellate only outer edges or edges between areas.
|
||||
bool tess = false;
|
||||
// Wall edges.
|
||||
if ((buildFlags & RC_CONTOUR_TESS_WALL_EDGES) && (points[ci*4+3] & RC_CONTOUR_REG_MASK) == 0)
|
||||
tess = true;
|
||||
// Edges between areas.
|
||||
if ((buildFlags & RC_CONTOUR_TESS_AREA_EDGES) && (points[ci*4+3] & RC_AREA_BORDER))
|
||||
tess = true;
|
||||
|
||||
if (tess)
|
||||
{
|
||||
int dx = bx - ax;
|
||||
int dz = bz - az;
|
||||
if (dx*dx + dz*dz > maxEdgeLen*maxEdgeLen)
|
||||
{
|
||||
int n = bi < ai ? (bi+pn - ai) : (bi - ai);
|
||||
// Round based on the segments in lexilogical order so that the
|
||||
// max tesselation is consistent regardles in which direction
|
||||
// segments are traversed.
|
||||
if (bx > ax || (bx == ax && bz > az))
|
||||
{
|
||||
const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
|
||||
maxi = (ai + n/2) % pn;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
|
||||
maxi = (ai + (n+1)/2) % pn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the max deviation is larger than accepted error,
|
||||
@@ -393,7 +439,7 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, float ma
|
||||
{
|
||||
// Add space for the new point.
|
||||
simplified.resize(simplified.size()+4);
|
||||
int n = simplified.size()/4;
|
||||
const int n = simplified.size()/4;
|
||||
for (int j = n-1; j > i; --j)
|
||||
{
|
||||
simplified[j*4+0] = simplified[(j-1)*4+0];
|
||||
@@ -420,7 +466,7 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, float ma
|
||||
// and the neighbour region is take from the next raw point.
|
||||
const int ai = (simplified[i*4+3]+1) % pn;
|
||||
const int bi = simplified[i*4+3];
|
||||
simplified[i*4+3] = (points[ai*4+3] & 0xffff) | (points[bi*4+3] & RC_BORDER_VERTEX);
|
||||
simplified[i*4+3] = (points[ai*4+3] & RC_CONTOUR_REG_MASK) | (points[bi*4+3] & RC_BORDER_VERTEX);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -446,7 +492,7 @@ static void removeDegenerateSegments(rcIntArray& simplified)
|
||||
simplified[j*4+2] = simplified[(j+1)*4+2];
|
||||
simplified[j*4+3] = simplified[(j+1)*4+3];
|
||||
}
|
||||
simplified.pop();
|
||||
simplified.resize(simplified.size()-4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -463,17 +509,31 @@ static int calcAreaOfPolygon2D(const int* verts, const int nverts)
|
||||
return (area+1) / 2;
|
||||
}
|
||||
|
||||
inline bool ileft(const int* a, const int* b, const int* c)
|
||||
{
|
||||
return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]) <= 0;
|
||||
}
|
||||
|
||||
static void getClosestIndices(const int* vertsa, const int nvertsa,
|
||||
const int* vertsb, const int nvertsb,
|
||||
int& ia, int& ib)
|
||||
{
|
||||
int closestDist = 0xfffffff;
|
||||
ia = -1, ib = -1;
|
||||
for (int i = 0; i < nvertsa; ++i)
|
||||
{
|
||||
const int in = (i+1) % nvertsa;
|
||||
const int ip = (i+nvertsa-1) % nvertsa;
|
||||
const int* va = &vertsa[i*4];
|
||||
const int* van = &vertsa[in*4];
|
||||
const int* vap = &vertsa[ip*4];
|
||||
|
||||
for (int j = 0; j < nvertsb; ++j)
|
||||
{
|
||||
const int* vb = &vertsb[j*4];
|
||||
// vb must be "infront" of va.
|
||||
if (ileft(vap,va,vb) && ileft(va,van,vb))
|
||||
{
|
||||
const int dx = vb[0] - va[0];
|
||||
const int dz = vb[2] - va[2];
|
||||
const int d = dx*dx + dz*dz;
|
||||
@@ -486,11 +546,12 @@ static void getClosestIndices(const int* vertsa, const int nvertsa,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib)
|
||||
{
|
||||
const int maxVerts = ca.nverts + cb.nverts + 2;
|
||||
int* verts = new int[maxVerts*4];
|
||||
int* verts = (int*)rcAlloc(sizeof(int)*maxVerts*4, RC_ALLOC_PERM);
|
||||
if (!verts)
|
||||
return false;
|
||||
|
||||
@@ -520,47 +581,73 @@ static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib)
|
||||
nv++;
|
||||
}
|
||||
|
||||
delete [] ca.verts;
|
||||
rcFree(ca.verts);
|
||||
ca.verts = verts;
|
||||
ca.nverts = nv;
|
||||
|
||||
delete [] cb.verts;
|
||||
rcFree(cb.verts);
|
||||
cb.verts = 0;
|
||||
cb.nverts = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
/// @par
|
||||
///
|
||||
/// The raw contours will match the region outlines exactly. The @p maxError and @p maxEdgeLen
|
||||
/// parameters control how closely the simplified contours will match the raw contours.
|
||||
///
|
||||
/// Simplified contours are generated such that the vertices for portals between areas match up.
|
||||
/// (They are considered mandatory vertices.)
|
||||
///
|
||||
/// Setting @p maxEdgeLength to zero will disabled the edge length feature.
|
||||
///
|
||||
/// See the #rcConfig documentation for more information on the configuration parameters.
|
||||
///
|
||||
/// @see rcAllocContourSet, rcCompactHeightfield, rcContourSet, rcConfig
|
||||
bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
const float maxError, const int maxEdgeLen,
|
||||
rcContourSet& cset)
|
||||
rcContourSet& cset, const int buildFlags)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
const int w = chf.width;
|
||||
const int h = chf.height;
|
||||
const int borderSize = chf.borderSize;
|
||||
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
ctx->startTimer(RC_TIMER_BUILD_CONTOURS);
|
||||
|
||||
vcopy(cset.bmin, chf.bmin);
|
||||
vcopy(cset.bmax, chf.bmax);
|
||||
rcVcopy(cset.bmin, chf.bmin);
|
||||
rcVcopy(cset.bmax, chf.bmax);
|
||||
if (borderSize > 0)
|
||||
{
|
||||
// If the heightfield was build with bordersize, remove the offset.
|
||||
const float pad = borderSize*chf.cs;
|
||||
cset.bmin[0] += pad;
|
||||
cset.bmin[2] += pad;
|
||||
cset.bmax[0] -= pad;
|
||||
cset.bmax[2] -= pad;
|
||||
}
|
||||
cset.cs = chf.cs;
|
||||
cset.ch = chf.ch;
|
||||
cset.width = chf.width - chf.borderSize*2;
|
||||
cset.height = chf.height - chf.borderSize*2;
|
||||
cset.borderSize = chf.borderSize;
|
||||
|
||||
const int maxContours = chf.maxRegions*2;
|
||||
cset.conts = new rcContour[maxContours];
|
||||
int maxContours = rcMax((int)chf.maxRegions, 8);
|
||||
cset.conts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM);
|
||||
if (!cset.conts)
|
||||
return false;
|
||||
cset.nconts = 0;
|
||||
|
||||
unsigned char* flags = new unsigned char[chf.spanCount];
|
||||
rcScopedDelete<unsigned char> flags = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
|
||||
if (!flags)
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'flags'.");
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'flags' (%d).", chf.spanCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
rcTimeVal traceStartTime = rcGetPerformanceTimer();
|
||||
|
||||
ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
|
||||
|
||||
// Mark boundaries.
|
||||
for (int y = 0; y < h; ++y)
|
||||
@@ -572,7 +659,7 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
{
|
||||
unsigned char res = 0;
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (!s.reg || (s.reg & RC_BORDER_REG))
|
||||
if (!chf.spans[i].reg || (chf.spans[i].reg & RC_BORDER_REG))
|
||||
{
|
||||
flags[i] = 0;
|
||||
continue;
|
||||
@@ -580,15 +667,14 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
unsigned short r = 0;
|
||||
if (rcGetCon(s, dir) != 0xf)
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dir);
|
||||
const int ay = y + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
r = as.reg;
|
||||
r = chf.spans[ai].reg;
|
||||
}
|
||||
if (r == s.reg)
|
||||
if (r == chf.spans[i].reg)
|
||||
res |= (1 << dir);
|
||||
}
|
||||
flags[i] = res ^ 0xf; // Inverse, mark non connected edges.
|
||||
@@ -596,9 +682,7 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
}
|
||||
}
|
||||
|
||||
rcTimeVal traceEndTime = rcGetPerformanceTimer();
|
||||
|
||||
rcTimeVal simplifyStartTime = rcGetPerformanceTimer();
|
||||
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
|
||||
|
||||
rcIntArray verts(256);
|
||||
rcIntArray simplified(64);
|
||||
@@ -615,15 +699,23 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
flags[i] = 0;
|
||||
continue;
|
||||
}
|
||||
unsigned short reg = chf.spans[i].reg;
|
||||
const unsigned short reg = chf.spans[i].reg;
|
||||
if (!reg || (reg & RC_BORDER_REG))
|
||||
continue;
|
||||
const unsigned char area = chf.areas[i];
|
||||
|
||||
verts.resize(0);
|
||||
simplified.resize(0);
|
||||
|
||||
ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
|
||||
walkContour(x, y, i, chf, flags, verts);
|
||||
simplifyContour(verts, simplified, maxError, maxEdgeLen);
|
||||
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
|
||||
|
||||
ctx->startTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
|
||||
simplifyContour(verts, simplified, maxError, maxEdgeLen, buildFlags);
|
||||
removeDegenerateSegments(simplified);
|
||||
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
|
||||
|
||||
|
||||
// Store region->contour remap info.
|
||||
// Create contour.
|
||||
@@ -631,20 +723,63 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
{
|
||||
if (cset.nconts >= maxContours)
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "rcBuildContours: Too many contours %d, max %d.", cset.nconts, maxContours);
|
||||
return false;
|
||||
// Allocate more contours.
|
||||
// This can happen when there are tiny holes in the heightfield.
|
||||
const int oldMax = maxContours;
|
||||
maxContours *= 2;
|
||||
rcContour* newConts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM);
|
||||
for (int j = 0; j < cset.nconts; ++j)
|
||||
{
|
||||
newConts[j] = cset.conts[j];
|
||||
// Reset source pointers to prevent data deletion.
|
||||
cset.conts[j].verts = 0;
|
||||
cset.conts[j].rverts = 0;
|
||||
}
|
||||
rcFree(cset.conts);
|
||||
cset.conts = newConts;
|
||||
|
||||
ctx->log(RC_LOG_WARNING, "rcBuildContours: Expanding max contours from %d to %d.", oldMax, maxContours);
|
||||
}
|
||||
|
||||
rcContour* cont = &cset.conts[cset.nconts++];
|
||||
|
||||
cont->nverts = simplified.size()/4;
|
||||
cont->verts = new int[cont->nverts*4];
|
||||
cont->verts = (int*)rcAlloc(sizeof(int)*cont->nverts*4, RC_ALLOC_PERM);
|
||||
if (!cont->verts)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'verts' (%d).", cont->nverts);
|
||||
return false;
|
||||
}
|
||||
memcpy(cont->verts, &simplified[0], sizeof(int)*cont->nverts*4);
|
||||
if (borderSize > 0)
|
||||
{
|
||||
// If the heightfield was build with bordersize, remove the offset.
|
||||
for (int i = 0; i < cont->nverts; ++i)
|
||||
{
|
||||
int* v = &cont->verts[i*4];
|
||||
v[0] -= borderSize;
|
||||
v[2] -= borderSize;
|
||||
}
|
||||
}
|
||||
|
||||
cont->nrverts = verts.size()/4;
|
||||
cont->rverts = new int[cont->nrverts*4];
|
||||
cont->rverts = (int*)rcAlloc(sizeof(int)*cont->nrverts*4, RC_ALLOC_PERM);
|
||||
if (!cont->rverts)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'rverts' (%d).", cont->nrverts);
|
||||
return false;
|
||||
}
|
||||
memcpy(cont->rverts, &verts[0], sizeof(int)*cont->nrverts*4);
|
||||
if (borderSize > 0)
|
||||
{
|
||||
// If the heightfield was build with bordersize, remove the offset.
|
||||
for (int i = 0; i < cont->nrverts; ++i)
|
||||
{
|
||||
int* v = &cont->rverts[i*4];
|
||||
v[0] -= borderSize;
|
||||
v[2] -= borderSize;
|
||||
}
|
||||
}
|
||||
|
||||
/* cont->cx = cont->cy = cont->cz = 0;
|
||||
for (int i = 0; i < cont->nverts; ++i)
|
||||
@@ -658,13 +793,14 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
cont->cz /= cont->nverts;*/
|
||||
|
||||
cont->reg = reg;
|
||||
cont->area = area;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check and merge droppings.
|
||||
// Sometimes the previous algorithms can fail and create several countours
|
||||
// Sometimes the previous algorithms can fail and create several contours
|
||||
// per area. This pass will try to merge the holes into the main region.
|
||||
for (int i = 0; i < cset.nconts; ++i)
|
||||
{
|
||||
@@ -689,44 +825,29 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
}
|
||||
if (mergeIdx == -1)
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_WARNING, "rcBuildContours: Could not find merge target for bad contour %d.", i);
|
||||
ctx->log(RC_LOG_WARNING, "rcBuildContours: Could not find merge target for bad contour %d.", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
rcContour& mcont = cset.conts[mergeIdx];
|
||||
// Merge by closest points.
|
||||
int ia, ib;
|
||||
int ia = 0, ib = 0;
|
||||
getClosestIndices(mcont.verts, mcont.nverts, cont.verts, cont.nverts, ia, ib);
|
||||
if (ia == -1 || ib == -1)
|
||||
{
|
||||
ctx->log(RC_LOG_WARNING, "rcBuildContours: Failed to find merge points for %d and %d.", i, mergeIdx);
|
||||
continue;
|
||||
}
|
||||
if (!mergeContours(mcont, cont, ia, ib))
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_WARNING, "rcBuildContours: Failed to merge contours %d and %d.", i, mergeIdx);
|
||||
ctx->log(RC_LOG_WARNING, "rcBuildContours: Failed to merge contours %d and %d.", i, mergeIdx);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete [] flags;
|
||||
|
||||
rcTimeVal simplifyEndTime = rcGetPerformanceTimer();
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
// if (rcGetLog())
|
||||
// {
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Create contours: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, " - boundary: %.3f ms", rcGetDeltaTimeUsec(boundaryStartTime, boundaryEndTime)/1000.0f);
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, " - contour: %.3f ms", rcGetDeltaTimeUsec(contourStartTime, contourEndTime)/1000.0f);
|
||||
// }
|
||||
|
||||
if (rcGetBuildTimes())
|
||||
{
|
||||
rcGetBuildTimes()->buildContours += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
rcGetBuildTimes()->buildContoursTrace += rcGetDeltaTimeUsec(traceStartTime, traceEndTime);
|
||||
rcGetBuildTimes()->buildContoursSimplify += rcGetDeltaTimeUsec(simplifyStartTime, simplifyEndTime);
|
||||
}
|
||||
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -20,15 +20,73 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastLog.h"
|
||||
#include "RecastTimer.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// Allows the formation of walkable regions that will flow over low lying
|
||||
/// objects such as curbs, and up structures such as stairways.
|
||||
///
|
||||
/// Two neighboring spans are walkable if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) < waklableClimb</tt>
|
||||
///
|
||||
/// @warning Will override the effect of #rcFilterLedgeSpans. So if both filters are used, call
|
||||
/// #rcFilterLedgeSpans after calling this filter.
|
||||
///
|
||||
/// @see rcHeightfield, rcConfig
|
||||
void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
void rcFilterLedgeSpans(const int walkableHeight,
|
||||
const int walkableClimb,
|
||||
ctx->startTimer(RC_TIMER_FILTER_LOW_OBSTACLES);
|
||||
|
||||
const int w = solid.width;
|
||||
const int h = solid.height;
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
rcSpan* ps = 0;
|
||||
bool previousWalkable = false;
|
||||
unsigned char previousArea = RC_NULL_AREA;
|
||||
|
||||
for (rcSpan* s = solid.spans[x + y*w]; s; ps = s, s = s->next)
|
||||
{
|
||||
const bool walkable = s->area != RC_NULL_AREA;
|
||||
// If current span is not walkable, but there is walkable
|
||||
// span just below it, mark the span above it walkable too.
|
||||
if (!walkable && previousWalkable)
|
||||
{
|
||||
if (rcAbs((int)s->smax - (int)ps->smax) <= walkableClimb)
|
||||
s->area = previousArea;
|
||||
}
|
||||
// Copy walkable flag so that it cannot propagate
|
||||
// past multiple non-walkable objects.
|
||||
previousWalkable = walkable;
|
||||
previousArea = s->area;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_FILTER_LOW_OBSTACLES);
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// A ledge is a span with one or more neighbors whose maximum is further away than @p walkableClimb
|
||||
/// from the current span's maximum.
|
||||
/// This method removes the impact of the overestimation of conservative voxelization
|
||||
/// so the resulting mesh will not have regions hanging in the air over ledges.
|
||||
///
|
||||
/// A span is a ledge if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) > walkableClimb</tt>
|
||||
///
|
||||
/// @see rcHeightfield, rcConfig
|
||||
void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb,
|
||||
rcHeightfield& solid)
|
||||
{
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_FILTER_BORDER);
|
||||
|
||||
const int w = solid.width;
|
||||
const int h = solid.height;
|
||||
@@ -42,15 +100,19 @@ void rcFilterLedgeSpans(const int walkableHeight,
|
||||
for (rcSpan* s = solid.spans[x + y*w]; s; s = s->next)
|
||||
{
|
||||
// Skip non walkable spans.
|
||||
if ((s->flags & RC_WALKABLE) == 0)
|
||||
if (s->area == RC_NULL_AREA)
|
||||
continue;
|
||||
|
||||
const int bot = (int)s->smax;
|
||||
const int top = s->next ? (int)s->next->smin : MAX_HEIGHT;
|
||||
const int bot = (int)(s->smax);
|
||||
const int top = s->next ? (int)(s->next->smin) : MAX_HEIGHT;
|
||||
|
||||
// Find neighbours minimum height.
|
||||
int minh = MAX_HEIGHT;
|
||||
|
||||
// Min and max height of accessible neighbours.
|
||||
int asmin = s->smax;
|
||||
int asmax = s->smax;
|
||||
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
int dx = x + rcGetDirOffsetX(dir);
|
||||
@@ -77,30 +139,49 @@ void rcFilterLedgeSpans(const int walkableHeight,
|
||||
ntop = ns->next ? (int)ns->next->smin : MAX_HEIGHT;
|
||||
// Skip neightbour if the gap between the spans is too small.
|
||||
if (rcMin(top,ntop) - rcMax(bot,nbot) > walkableHeight)
|
||||
{
|
||||
minh = rcMin(minh, nbot - bot);
|
||||
|
||||
// Find min/max accessible neighbour height.
|
||||
if (rcAbs(nbot - bot) <= walkableClimb)
|
||||
{
|
||||
if (nbot < asmin) asmin = nbot;
|
||||
if (nbot > asmax) asmax = nbot;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The current span is close to a ledge if the drop to any
|
||||
// neighbour span is less than the walkableClimb.
|
||||
if (minh < -walkableClimb)
|
||||
s->flags &= ~RC_WALKABLE;
|
||||
s->area = RC_NULL_AREA;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
// if (rcGetLog())
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Filter border: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->filterBorder += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
}
|
||||
|
||||
void rcFilterWalkableLowHeightSpans(int walkableHeight,
|
||||
rcHeightfield& solid)
|
||||
// If the difference between all neighbours is too large,
|
||||
// we are at steep slope, mark the span as ledge.
|
||||
if ((asmax - asmin) > walkableClimb)
|
||||
{
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
s->area = RC_NULL_AREA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_FILTER_BORDER);
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// For this filter, the clearance above the span is the distance from the span's
|
||||
/// maximum to the next higher span's minimum. (Same grid column.)
|
||||
///
|
||||
/// @see rcHeightfield, rcConfig
|
||||
void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_FILTER_WALKABLE);
|
||||
|
||||
const int w = solid.width;
|
||||
const int h = solid.height;
|
||||
@@ -114,136 +195,13 @@ void rcFilterWalkableLowHeightSpans(int walkableHeight,
|
||||
{
|
||||
for (rcSpan* s = solid.spans[x + y*w]; s; s = s->next)
|
||||
{
|
||||
const int bot = (int)s->smax;
|
||||
const int top = s->next ? (int)s->next->smin : MAX_HEIGHT;
|
||||
const int bot = (int)(s->smax);
|
||||
const int top = s->next ? (int)(s->next->smin) : MAX_HEIGHT;
|
||||
if ((top - bot) <= walkableHeight)
|
||||
s->flags &= ~RC_WALKABLE;
|
||||
s->area = RC_NULL_AREA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
// if (rcGetLog())
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Filter walkable: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->filterWalkable += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
}
|
||||
|
||||
|
||||
struct rcReachableSeed
|
||||
{
|
||||
inline void set(int ix, int iy, rcSpan* is)
|
||||
{
|
||||
x = (unsigned short)ix;
|
||||
y = (unsigned short)iy;
|
||||
s = is;
|
||||
}
|
||||
unsigned short x, y;
|
||||
rcSpan* s;
|
||||
};
|
||||
|
||||
bool rcMarkReachableSpans(const int walkableHeight,
|
||||
const int walkableClimb,
|
||||
rcHeightfield& solid)
|
||||
{
|
||||
const int w = solid.width;
|
||||
const int h = solid.height;
|
||||
const int MAX_HEIGHT = 0xffff;
|
||||
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
|
||||
// Build navigable space.
|
||||
const int MAX_SEEDS = w*h;
|
||||
rcReachableSeed* stack = new rcReachableSeed[MAX_SEEDS];
|
||||
if (!stack)
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "rcMarkReachableSpans: Out of memory 'stack' (%d).", MAX_SEEDS);
|
||||
return false;
|
||||
}
|
||||
int stackSize = 0;
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
rcSpan* topSpan = solid.spans[x + y*w];
|
||||
if (!topSpan)
|
||||
continue;
|
||||
while (topSpan->next)
|
||||
topSpan = topSpan->next;
|
||||
|
||||
// If the span is not walkable, skip it.
|
||||
if ((topSpan->flags & RC_WALKABLE) == 0)
|
||||
continue;
|
||||
// If the span has been visited already, skip it.
|
||||
if (topSpan->flags & RC_REACHABLE)
|
||||
continue;
|
||||
|
||||
// Start flood fill.
|
||||
topSpan->flags |= RC_REACHABLE;
|
||||
stackSize = 0;
|
||||
stack[stackSize].set(x, y, topSpan);
|
||||
stackSize++;
|
||||
|
||||
while (stackSize)
|
||||
{
|
||||
// Pop a seed from the stack.
|
||||
stackSize--;
|
||||
rcReachableSeed cur = stack[stackSize];
|
||||
|
||||
const int bot = (int)cur.s->smax;
|
||||
const int top = cur.s->next ? (int)cur.s->next->smin : MAX_HEIGHT;
|
||||
|
||||
// Visit neighbours in all 4 directions.
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
int dx = (int)cur.x + rcGetDirOffsetX(dir);
|
||||
int dy = (int)cur.y + rcGetDirOffsetY(dir);
|
||||
// Skip neighbour which are out of bounds.
|
||||
if (dx < 0 || dy < 0 || dx >= w || dy >= h)
|
||||
continue;
|
||||
for (rcSpan* ns = solid.spans[dx + dy*w]; ns; ns = ns->next)
|
||||
{
|
||||
// Skip neighbour if it is not walkable.
|
||||
if ((ns->flags & RC_WALKABLE) == 0)
|
||||
continue;
|
||||
// Skip the neighbour if it has been visited already.
|
||||
if (ns->flags & RC_REACHABLE)
|
||||
continue;
|
||||
|
||||
const int nbot = (int)ns->smax;
|
||||
const int ntop = ns->next ? (int)ns->next->smin : MAX_HEIGHT;
|
||||
// Skip neightbour if the gap between the spans is too small.
|
||||
if (rcMin(top,ntop) - rcMax(bot,nbot) < walkableHeight)
|
||||
continue;
|
||||
// Skip neightbour if the climb height to the neighbour is too high.
|
||||
if (rcAbs(nbot - bot) >= walkableClimb)
|
||||
continue;
|
||||
|
||||
// This neighbour has not been visited yet.
|
||||
// Mark it as reachable and add it to the seed stack.
|
||||
ns->flags |= RC_REACHABLE;
|
||||
if (stackSize < MAX_SEEDS)
|
||||
{
|
||||
stack[stackSize].set(dx, dy, ns);
|
||||
stackSize++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete [] stack;
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
// if (rcGetLog())
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Mark reachable: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->filterMarkReachable += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
|
||||
return true;
|
||||
ctx->stopTimer(RC_TIMER_FILTER_WALKABLE);
|
||||
}
|
||||
|
||||
620
extern/recastnavigation/Recast/Source/RecastLayers.cpp
vendored
Normal file
620
extern/recastnavigation/Recast/Source/RecastLayers.cpp
vendored
Normal file
@@ -0,0 +1,620 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <float.h>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastAlloc.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
|
||||
static const int RC_MAX_LAYERS = RC_NOT_CONNECTED;
|
||||
static const int RC_MAX_NEIS = 16;
|
||||
|
||||
struct rcLayerRegion
|
||||
{
|
||||
unsigned char layers[RC_MAX_LAYERS];
|
||||
unsigned char neis[RC_MAX_NEIS];
|
||||
unsigned short ymin, ymax;
|
||||
unsigned char layerId; // Layer ID
|
||||
unsigned char nlayers; // Layer count
|
||||
unsigned char nneis; // Neighbour count
|
||||
unsigned char base; // Flag indicating if the region is hte base of merged regions.
|
||||
};
|
||||
|
||||
|
||||
static void addUnique(unsigned char* a, unsigned char& an, unsigned char v)
|
||||
{
|
||||
const int n = (int)an;
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (a[i] == v)
|
||||
return;
|
||||
a[an] = v;
|
||||
an++;
|
||||
}
|
||||
|
||||
static bool contains(const unsigned char* a, const unsigned char an, const unsigned char v)
|
||||
{
|
||||
const int n = (int)an;
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (a[i] == v)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool overlapRange(const unsigned short amin, const unsigned short amax,
|
||||
const unsigned short bmin, const unsigned short bmax)
|
||||
{
|
||||
return (amin > bmax || amax < bmin) ? false : true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct rcLayerSweepSpan
|
||||
{
|
||||
unsigned short ns; // number samples
|
||||
unsigned char id; // region id
|
||||
unsigned char nei; // neighbour id
|
||||
};
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// See the #rcConfig documentation for more information on the configuration parameters.
|
||||
///
|
||||
/// @see rcAllocHeightfieldLayerSet, rcCompactHeightfield, rcHeightfieldLayerSet, rcConfig
|
||||
bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
const int borderSize, const int walkableHeight,
|
||||
rcHeightfieldLayerSet& lset)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_BUILD_LAYERS);
|
||||
|
||||
const int w = chf.width;
|
||||
const int h = chf.height;
|
||||
|
||||
rcScopedDelete<unsigned char> srcReg = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
|
||||
if (!srcReg)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'srcReg' (%d).", chf.spanCount);
|
||||
return false;
|
||||
}
|
||||
memset(srcReg,0xff,sizeof(unsigned char)*chf.spanCount);
|
||||
|
||||
const int nsweeps = chf.width;
|
||||
rcScopedDelete<rcLayerSweepSpan> sweeps = (rcLayerSweepSpan*)rcAlloc(sizeof(rcLayerSweepSpan)*nsweeps, RC_ALLOC_TEMP);
|
||||
if (!sweeps)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'sweeps' (%d).", nsweeps);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Partition walkable area into monotone regions.
|
||||
int prevCount[256];
|
||||
unsigned char regId = 0;
|
||||
|
||||
for (int y = borderSize; y < h-borderSize; ++y)
|
||||
{
|
||||
memset(prevCount,0,sizeof(int)*regId);
|
||||
unsigned char sweepId = 0;
|
||||
|
||||
for (int x = borderSize; x < w-borderSize; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (chf.areas[i] == RC_NULL_AREA) continue;
|
||||
|
||||
unsigned char sid = 0xff;
|
||||
|
||||
// -x
|
||||
if (rcGetCon(s, 0) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(0);
|
||||
const int ay = y + rcGetDirOffsetY(0);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0);
|
||||
if (chf.areas[ai] != RC_NULL_AREA && srcReg[ai] != 0xff)
|
||||
sid = srcReg[ai];
|
||||
}
|
||||
|
||||
if (sid == 0xff)
|
||||
{
|
||||
sid = sweepId++;
|
||||
sweeps[sid].nei = 0xff;
|
||||
sweeps[sid].ns = 0;
|
||||
}
|
||||
|
||||
// -y
|
||||
if (rcGetCon(s,3) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(3);
|
||||
const int ay = y + rcGetDirOffsetY(3);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3);
|
||||
const unsigned char nr = srcReg[ai];
|
||||
if (nr != 0xff)
|
||||
{
|
||||
// Set neighbour when first valid neighbour is encoutered.
|
||||
if (sweeps[sid].ns == 0)
|
||||
sweeps[sid].nei = nr;
|
||||
|
||||
if (sweeps[sid].nei == nr)
|
||||
{
|
||||
// Update existing neighbour
|
||||
sweeps[sid].ns++;
|
||||
prevCount[nr]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is hit if there is nore than one neighbour.
|
||||
// Invalidate the neighbour.
|
||||
sweeps[sid].nei = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
srcReg[i] = sid;
|
||||
}
|
||||
}
|
||||
|
||||
// Create unique ID.
|
||||
for (int i = 0; i < sweepId; ++i)
|
||||
{
|
||||
// If the neighbour is set and there is only one continuous connection to it,
|
||||
// the sweep will be merged with the previous one, else new region is created.
|
||||
if (sweeps[i].nei != 0xff && prevCount[sweeps[i].nei] == (int)sweeps[i].ns)
|
||||
{
|
||||
sweeps[i].id = sweeps[i].nei;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (regId == 255)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Region ID overflow.");
|
||||
return false;
|
||||
}
|
||||
sweeps[i].id = regId++;
|
||||
}
|
||||
}
|
||||
|
||||
// Remap local sweep ids to region ids.
|
||||
for (int x = borderSize; x < w-borderSize; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
if (srcReg[i] != 0xff)
|
||||
srcReg[i] = sweeps[srcReg[i]].id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate and init layer regions.
|
||||
const int nregs = (int)regId;
|
||||
rcScopedDelete<rcLayerRegion> regs = (rcLayerRegion*)rcAlloc(sizeof(rcLayerRegion)*nregs, RC_ALLOC_TEMP);
|
||||
if (!regs)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'regs' (%d).", nregs);
|
||||
return false;
|
||||
}
|
||||
memset(regs, 0, sizeof(rcLayerRegion)*nregs);
|
||||
for (int i = 0; i < nregs; ++i)
|
||||
{
|
||||
regs[i].layerId = 0xff;
|
||||
regs[i].ymin = 0xffff;
|
||||
regs[i].ymax = 0;
|
||||
}
|
||||
|
||||
// Find region neighbours and overlapping regions.
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
|
||||
unsigned char lregs[RC_MAX_LAYERS];
|
||||
int nlregs = 0;
|
||||
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
const unsigned char ri = srcReg[i];
|
||||
if (ri == 0xff) continue;
|
||||
|
||||
regs[ri].ymin = rcMin(regs[ri].ymin, s.y);
|
||||
regs[ri].ymax = rcMax(regs[ri].ymax, s.y);
|
||||
|
||||
// Collect all region layers.
|
||||
if (nlregs < RC_MAX_LAYERS)
|
||||
lregs[nlregs++] = ri;
|
||||
|
||||
// Update neighbours
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dir);
|
||||
const int ay = y + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
||||
const unsigned char rai = srcReg[ai];
|
||||
if (rai != 0xff && rai != ri)
|
||||
addUnique(regs[ri].neis, regs[ri].nneis, rai);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Update overlapping regions.
|
||||
for (int i = 0; i < nlregs-1; ++i)
|
||||
{
|
||||
for (int j = i+1; j < nlregs; ++j)
|
||||
{
|
||||
if (lregs[i] != lregs[j])
|
||||
{
|
||||
rcLayerRegion& ri = regs[lregs[i]];
|
||||
rcLayerRegion& rj = regs[lregs[j]];
|
||||
addUnique(ri.layers, ri.nlayers, lregs[j]);
|
||||
addUnique(rj.layers, rj.nlayers, lregs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Create 2D layers from regions.
|
||||
unsigned char layerId = 0;
|
||||
|
||||
static const int MAX_STACK = 64;
|
||||
unsigned char stack[MAX_STACK];
|
||||
int nstack = 0;
|
||||
|
||||
for (int i = 0; i < nregs; ++i)
|
||||
{
|
||||
rcLayerRegion& root = regs[i];
|
||||
// Skip alreadu visited.
|
||||
if (root.layerId != 0xff)
|
||||
continue;
|
||||
|
||||
// Start search.
|
||||
root.layerId = layerId;
|
||||
root.base = 1;
|
||||
|
||||
nstack = 0;
|
||||
stack[nstack++] = (unsigned char)i;
|
||||
|
||||
while (nstack)
|
||||
{
|
||||
// Pop front
|
||||
rcLayerRegion& reg = regs[stack[0]];
|
||||
nstack--;
|
||||
for (int j = 0; j < nstack; ++j)
|
||||
stack[j] = stack[j+1];
|
||||
|
||||
const int nneis = (int)reg.nneis;
|
||||
for (int j = 0; j < nneis; ++j)
|
||||
{
|
||||
const unsigned char nei = reg.neis[j];
|
||||
rcLayerRegion& regn = regs[nei];
|
||||
// Skip already visited.
|
||||
if (regn.layerId != 0xff)
|
||||
continue;
|
||||
// Skip if the neighbour is overlapping root region.
|
||||
if (contains(root.layers, root.nlayers, nei))
|
||||
continue;
|
||||
// Skip if the height range would become too large.
|
||||
const int ymin = rcMin(root.ymin, regn.ymin);
|
||||
const int ymax = rcMin(root.ymax, regn.ymax);
|
||||
if ((ymax - ymin) >= 255)
|
||||
continue;
|
||||
|
||||
if (nstack < MAX_STACK)
|
||||
{
|
||||
// Deepen
|
||||
stack[nstack++] = (unsigned char)nei;
|
||||
|
||||
// Mark layer id
|
||||
regn.layerId = layerId;
|
||||
// Merge current layers to root.
|
||||
for (int k = 0; k < regn.nlayers; ++k)
|
||||
addUnique(root.layers, root.nlayers, regn.layers[k]);
|
||||
root.ymin = rcMin(root.ymin, regn.ymin);
|
||||
root.ymax = rcMax(root.ymax, regn.ymax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layerId++;
|
||||
}
|
||||
|
||||
// Merge non-overlapping regions that are close in height.
|
||||
const unsigned short mergeHeight = (unsigned short)walkableHeight * 4;
|
||||
|
||||
for (int i = 0; i < nregs; ++i)
|
||||
{
|
||||
rcLayerRegion& ri = regs[i];
|
||||
if (!ri.base) continue;
|
||||
|
||||
unsigned char newId = ri.layerId;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned char oldId = 0xff;
|
||||
|
||||
for (int j = 0; j < nregs; ++j)
|
||||
{
|
||||
if (i == j) continue;
|
||||
rcLayerRegion& rj = regs[j];
|
||||
if (!rj.base) continue;
|
||||
|
||||
// Skip if teh regions are not close to each other.
|
||||
if (!overlapRange(ri.ymin,ri.ymax+mergeHeight, rj.ymin,rj.ymax+mergeHeight))
|
||||
continue;
|
||||
// Skip if the height range would become too large.
|
||||
const int ymin = rcMin(ri.ymin, rj.ymin);
|
||||
const int ymax = rcMin(ri.ymax, rj.ymax);
|
||||
if ((ymax - ymin) >= 255)
|
||||
continue;
|
||||
|
||||
// Make sure that there is no overlap when mergin 'ri' and 'rj'.
|
||||
bool overlap = false;
|
||||
// Iterate over all regions which have the same layerId as 'rj'
|
||||
for (int k = 0; k < nregs; ++k)
|
||||
{
|
||||
if (regs[k].layerId != rj.layerId)
|
||||
continue;
|
||||
// Check if region 'k' is overlapping region 'ri'
|
||||
// Index to 'regs' is the same as region id.
|
||||
if (contains(ri.layers,ri.nlayers, (unsigned char)k))
|
||||
{
|
||||
overlap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Cannot merge of regions overlap.
|
||||
if (overlap)
|
||||
continue;
|
||||
|
||||
// Can merge i and j.
|
||||
oldId = rj.layerId;
|
||||
break;
|
||||
}
|
||||
|
||||
// Could not find anything to merge with, stop.
|
||||
if (oldId == 0xff)
|
||||
break;
|
||||
|
||||
// Merge
|
||||
for (int j = 0; j < nregs; ++j)
|
||||
{
|
||||
rcLayerRegion& rj = regs[j];
|
||||
if (rj.layerId == oldId)
|
||||
{
|
||||
rj.base = 0;
|
||||
// Remap layerIds.
|
||||
rj.layerId = newId;
|
||||
// Add overlaid layers from 'rj' to 'ri'.
|
||||
for (int k = 0; k < rj.nlayers; ++k)
|
||||
addUnique(ri.layers, ri.nlayers, rj.layers[k]);
|
||||
// Update heigh bounds.
|
||||
ri.ymin = rcMin(ri.ymin, rj.ymin);
|
||||
ri.ymax = rcMax(ri.ymax, rj.ymax);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compact layerIds
|
||||
unsigned char remap[256];
|
||||
memset(remap, 0, 256);
|
||||
|
||||
// Find number of unique layers.
|
||||
layerId = 0;
|
||||
for (int i = 0; i < nregs; ++i)
|
||||
remap[regs[i].layerId] = 1;
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
if (remap[i])
|
||||
remap[i] = layerId++;
|
||||
else
|
||||
remap[i] = 0xff;
|
||||
}
|
||||
// Remap ids.
|
||||
for (int i = 0; i < nregs; ++i)
|
||||
regs[i].layerId = remap[regs[i].layerId];
|
||||
|
||||
// No layers, return empty.
|
||||
if (layerId == 0)
|
||||
{
|
||||
ctx->stopTimer(RC_TIMER_BUILD_LAYERS);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create layers.
|
||||
rcAssert(lset.layers == 0);
|
||||
|
||||
const int lw = w - borderSize*2;
|
||||
const int lh = h - borderSize*2;
|
||||
|
||||
// Build contracted bbox for layers.
|
||||
float bmin[3], bmax[3];
|
||||
rcVcopy(bmin, chf.bmin);
|
||||
rcVcopy(bmax, chf.bmax);
|
||||
bmin[0] += borderSize*chf.cs;
|
||||
bmin[2] += borderSize*chf.cs;
|
||||
bmax[0] -= borderSize*chf.cs;
|
||||
bmax[2] -= borderSize*chf.cs;
|
||||
|
||||
lset.nlayers = (int)layerId;
|
||||
|
||||
lset.layers = (rcHeightfieldLayer*)rcAlloc(sizeof(rcHeightfieldLayer)*lset.nlayers, RC_ALLOC_PERM);
|
||||
if (!lset.layers)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'layers' (%d).", lset.nlayers);
|
||||
return false;
|
||||
}
|
||||
memset(lset.layers, 0, sizeof(rcHeightfieldLayer)*lset.nlayers);
|
||||
|
||||
|
||||
// Store layers.
|
||||
for (int i = 0; i < lset.nlayers; ++i)
|
||||
{
|
||||
unsigned char curId = (unsigned char)i;
|
||||
|
||||
// Allocate memory for the current layer.
|
||||
rcHeightfieldLayer* layer = &lset.layers[i];
|
||||
memset(layer, 0, sizeof(rcHeightfieldLayer));
|
||||
|
||||
const int gridSize = sizeof(unsigned char)*lw*lh;
|
||||
|
||||
layer->heights = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM);
|
||||
if (!layer->heights)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'heights' (%d).", gridSize);
|
||||
return false;
|
||||
}
|
||||
memset(layer->heights, 0xff, gridSize);
|
||||
|
||||
layer->areas = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM);
|
||||
if (!layer->areas)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'areas' (%d).", gridSize);
|
||||
return false;
|
||||
}
|
||||
memset(layer->areas, 0, gridSize);
|
||||
|
||||
layer->cons = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM);
|
||||
if (!layer->cons)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'cons' (%d).", gridSize);
|
||||
return false;
|
||||
}
|
||||
memset(layer->cons, 0, gridSize);
|
||||
|
||||
// Find layer height bounds.
|
||||
int hmin = 0, hmax = 0;
|
||||
for (int j = 0; j < nregs; ++j)
|
||||
{
|
||||
if (regs[j].base && regs[j].layerId == curId)
|
||||
{
|
||||
hmin = (int)regs[j].ymin;
|
||||
hmax = (int)regs[j].ymax;
|
||||
}
|
||||
}
|
||||
|
||||
layer->width = lw;
|
||||
layer->height = lh;
|
||||
layer->cs = chf.cs;
|
||||
layer->ch = chf.ch;
|
||||
|
||||
// Adjust the bbox to fit the heighfield.
|
||||
rcVcopy(layer->bmin, bmin);
|
||||
rcVcopy(layer->bmax, bmax);
|
||||
layer->bmin[1] = bmin[1] + hmin*chf.ch;
|
||||
layer->bmax[1] = bmin[1] + hmax*chf.ch;
|
||||
layer->hmin = hmin;
|
||||
layer->hmax = hmax;
|
||||
|
||||
// Update usable data region.
|
||||
layer->minx = layer->width;
|
||||
layer->maxx = 0;
|
||||
layer->miny = layer->height;
|
||||
layer->maxy = 0;
|
||||
|
||||
// Copy height and area from compact heighfield.
|
||||
for (int y = 0; y < lh; ++y)
|
||||
{
|
||||
for (int x = 0; x < lw; ++x)
|
||||
{
|
||||
const int cx = borderSize+x;
|
||||
const int cy = borderSize+y;
|
||||
const rcCompactCell& c = chf.cells[cx+cy*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
// Skip unassigned regions.
|
||||
if (srcReg[i] == 0xff)
|
||||
continue;
|
||||
// Skip of does nto belong to current layer.
|
||||
unsigned char lid = regs[srcReg[i]].layerId;
|
||||
if (lid != curId)
|
||||
continue;
|
||||
|
||||
// Update data bounds.
|
||||
layer->minx = rcMin(layer->minx, x);
|
||||
layer->maxx = rcMax(layer->maxx, x);
|
||||
layer->miny = rcMin(layer->miny, y);
|
||||
layer->maxy = rcMax(layer->maxy, y);
|
||||
|
||||
// Store height and area type.
|
||||
const int idx = x+y*lw;
|
||||
layer->heights[idx] = (unsigned char)(s.y - hmin);
|
||||
layer->areas[idx] = chf.areas[i];
|
||||
|
||||
// Check connection.
|
||||
unsigned char portal = 0;
|
||||
unsigned char con = 0;
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = cx + rcGetDirOffsetX(dir);
|
||||
const int ay = cy + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
||||
unsigned char alid = srcReg[ai] != 0xff ? regs[srcReg[ai]].layerId : 0xff;
|
||||
// Portal mask
|
||||
if (chf.areas[ai] != RC_NULL_AREA && lid != alid)
|
||||
{
|
||||
portal |= (unsigned char)(1<<dir);
|
||||
// Update height so that it matches on both sides of the portal.
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
if (as.y > hmin)
|
||||
layer->heights[idx] = rcMax(layer->heights[idx], (unsigned char)(as.y - hmin));
|
||||
}
|
||||
// Valid connection mask
|
||||
if (chf.areas[ai] != RC_NULL_AREA && lid == alid)
|
||||
{
|
||||
const int nx = ax - borderSize;
|
||||
const int ny = ay - borderSize;
|
||||
if (nx >= 0 && ny >= 0 && nx < lw && ny < lh)
|
||||
con |= (unsigned char)(1<<dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layer->cons[idx] = (portal << 4) | con;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (layer->minx > layer->maxx)
|
||||
layer->minx = layer->maxx = 0;
|
||||
if (layer->miny > layer->maxy)
|
||||
layer->miny = layer->maxy = 0;
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_BUILD_LAYERS);
|
||||
|
||||
return true;
|
||||
}
|
||||
675
extern/recastnavigation/Recast/Source/RecastMesh.cpp
vendored
675
extern/recastnavigation/Recast/Source/RecastMesh.cpp
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -20,8 +20,8 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastTimer.h"
|
||||
#include "RecastLog.h"
|
||||
#include "RecastAlloc.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
inline bool overlapBounds(const float* amin, const float* amax, const float* bmin, const float* bmax)
|
||||
{
|
||||
@@ -48,8 +48,7 @@ static rcSpan* allocSpan(rcHeightfield& hf)
|
||||
{
|
||||
// Create new page.
|
||||
// Allocate memory for the new pool.
|
||||
const int size = (sizeof(rcSpanPool)-sizeof(rcSpan)) + sizeof(rcSpan)*RC_SPANS_PER_POOL;
|
||||
rcSpanPool* pool = reinterpret_cast<rcSpanPool*>(new unsigned char[size]);
|
||||
rcSpanPool* pool = (rcSpanPool*)rcAlloc(sizeof(rcSpanPool), RC_ALLOC_PERM);
|
||||
if (!pool) return 0;
|
||||
pool->next = 0;
|
||||
// Add the pool into the list of pools.
|
||||
@@ -83,16 +82,17 @@ static void freeSpan(rcHeightfield& hf, rcSpan* ptr)
|
||||
hf.freelist = ptr;
|
||||
}
|
||||
|
||||
static void addSpan(rcHeightfield& hf, int x, int y,
|
||||
unsigned short smin, unsigned short smax,
|
||||
unsigned short flags)
|
||||
static void addSpan(rcHeightfield& hf, const int x, const int y,
|
||||
const unsigned short smin, const unsigned short smax,
|
||||
const unsigned char area, const int flagMergeThr)
|
||||
{
|
||||
|
||||
int idx = x + y*hf.width;
|
||||
|
||||
rcSpan* s = allocSpan(hf);
|
||||
s->smin = smin;
|
||||
s->smax = smax;
|
||||
s->flags = flags;
|
||||
s->area = area;
|
||||
s->next = 0;
|
||||
|
||||
// Empty cell, add he first span.
|
||||
@@ -127,9 +127,8 @@ static void addSpan(rcHeightfield& hf, int x, int y,
|
||||
s->smax = cur->smax;
|
||||
|
||||
// Merge flags.
|
||||
// if (s->smax == cur->smax)
|
||||
if (rcAbs((int)s->smax - (int)cur->smax) <= 1)
|
||||
s->flags |= cur->flags;
|
||||
if (rcAbs((int)s->smax - (int)cur->smax) <= flagMergeThr)
|
||||
s->area = rcMax(s->area, cur->area);
|
||||
|
||||
// Remove current span.
|
||||
rcSpan* next = cur->next;
|
||||
@@ -155,6 +154,21 @@ static void addSpan(rcHeightfield& hf, int x, int y,
|
||||
}
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// The span addition can be set to favor flags. If the span is merged to
|
||||
/// another span and the new @p smax is within @p flagMergeThr units
|
||||
/// from the existing span, the span flags are merged.
|
||||
///
|
||||
/// @see rcHeightfield, rcSpan.
|
||||
void rcAddSpan(rcContext* /*ctx*/, rcHeightfield& hf, const int x, const int y,
|
||||
const unsigned short smin, const unsigned short smax,
|
||||
const unsigned char area, const int flagMergeThr)
|
||||
{
|
||||
// rcAssert(ctx);
|
||||
addSpan(hf, x,y, smin, smax, area, flagMergeThr);
|
||||
}
|
||||
|
||||
static int clipPoly(const float* in, int n, float* out, float pnx, float pnz, float pd)
|
||||
{
|
||||
float d[12];
|
||||
@@ -186,9 +200,10 @@ static int clipPoly(const float* in, int n, float* out, float pnx, float pnz, fl
|
||||
}
|
||||
|
||||
static void rasterizeTri(const float* v0, const float* v1, const float* v2,
|
||||
unsigned char flags, rcHeightfield& hf,
|
||||
const unsigned char area, rcHeightfield& hf,
|
||||
const float* bmin, const float* bmax,
|
||||
const float cs, const float ics, const float ich)
|
||||
const float cs, const float ics, const float ich,
|
||||
const int flagMergeThr)
|
||||
{
|
||||
const int w = hf.width;
|
||||
const int h = hf.height;
|
||||
@@ -196,12 +211,12 @@ static void rasterizeTri(const float* v0, const float* v1, const float* v2,
|
||||
const float by = bmax[1] - bmin[1];
|
||||
|
||||
// Calculate the bounding box of the triangle.
|
||||
vcopy(tmin, v0);
|
||||
vcopy(tmax, v0);
|
||||
vmin(tmin, v1);
|
||||
vmin(tmin, v2);
|
||||
vmax(tmax, v1);
|
||||
vmax(tmax, v2);
|
||||
rcVcopy(tmin, v0);
|
||||
rcVcopy(tmax, v0);
|
||||
rcVmin(tmin, v1);
|
||||
rcVmin(tmin, v2);
|
||||
rcVmax(tmax, v1);
|
||||
rcVmax(tmax, v2);
|
||||
|
||||
// If the triangle does not touch the bbox of the heightfield, skip the triagle.
|
||||
if (!overlapBounds(bmin, bmax, tmin, tmax))
|
||||
@@ -223,9 +238,9 @@ static void rasterizeTri(const float* v0, const float* v1, const float* v2,
|
||||
for (int y = y0; y <= y1; ++y)
|
||||
{
|
||||
// Clip polygon to row.
|
||||
vcopy(&in[0], v0);
|
||||
vcopy(&in[1*3], v1);
|
||||
vcopy(&in[2*3], v2);
|
||||
rcVcopy(&in[0], v0);
|
||||
rcVcopy(&in[1*3], v1);
|
||||
rcVcopy(&in[2*3], v2);
|
||||
int nvrow = 3;
|
||||
const float cz = bmin[2] + y*cs;
|
||||
nvrow = clipPoly(in, nvrow, out, 0, 1, -cz);
|
||||
@@ -256,38 +271,50 @@ static void rasterizeTri(const float* v0, const float* v1, const float* v2,
|
||||
if (smax < 0.0f) continue;
|
||||
if (smin > by) continue;
|
||||
// Clamp the span to the heightfield bbox.
|
||||
if (smin < 0.0f) smin = bmin[1];
|
||||
if (smax > by) smax = bmax[1];
|
||||
if (smin < 0.0f) smin = 0;
|
||||
if (smax > by) smax = by;
|
||||
|
||||
// Snap the span to the heightfield height grid.
|
||||
unsigned short ismin = (unsigned short)rcClamp((int)floorf(smin * ich), 0, 0x7fff);
|
||||
unsigned short ismax = (unsigned short)rcClamp((int)ceilf(smax * ich), 0, 0x7fff);
|
||||
unsigned short ismin = (unsigned short)rcClamp((int)floorf(smin * ich), 0, RC_SPAN_MAX_HEIGHT);
|
||||
unsigned short ismax = (unsigned short)rcClamp((int)ceilf(smax * ich), (int)ismin+1, RC_SPAN_MAX_HEIGHT);
|
||||
|
||||
addSpan(hf, x, y, ismin, ismax, flags);
|
||||
addSpan(hf, x, y, ismin, ismax, area, flagMergeThr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rcRasterizeTriangle(const float* v0, const float* v1, const float* v2,
|
||||
unsigned char flags, rcHeightfield& solid)
|
||||
/// @par
|
||||
///
|
||||
/// No spans will be added if the triangle does not overlap the heightfield grid.
|
||||
///
|
||||
/// @see rcHeightfield
|
||||
void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2,
|
||||
const unsigned char area, rcHeightfield& solid,
|
||||
const int flagMergeThr)
|
||||
{
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
|
||||
const float ics = 1.0f/solid.cs;
|
||||
const float ich = 1.0f/solid.ch;
|
||||
rasterizeTri(v0, v1, v2, flags, solid, solid.bmin, solid.bmax, solid.cs, ics, ich);
|
||||
rasterizeTri(v0, v1, v2, area, solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->rasterizeTriangles += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
}
|
||||
|
||||
void rcRasterizeTriangles(const float* verts, int nv,
|
||||
const int* tris, const unsigned char* flags, int nt,
|
||||
rcHeightfield& solid)
|
||||
/// @par
|
||||
///
|
||||
/// Spans will only be added for triangles that overlap the heightfield grid.
|
||||
///
|
||||
/// @see rcHeightfield
|
||||
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
|
||||
const int* tris, const unsigned char* areas, const int nt,
|
||||
rcHeightfield& solid, const int flagMergeThr)
|
||||
{
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
|
||||
const float ics = 1.0f/solid.cs;
|
||||
const float ich = 1.0f/solid.ch;
|
||||
@@ -298,11 +325,63 @@ void rcRasterizeTriangles(const float* verts, int nv,
|
||||
const float* v1 = &verts[tris[i*3+1]*3];
|
||||
const float* v2 = &verts[tris[i*3+2]*3];
|
||||
// Rasterize.
|
||||
rasterizeTri(v0, v1, v2, flags[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich);
|
||||
rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
|
||||
}
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->rasterizeTriangles += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// Spans will only be added for triangles that overlap the heightfield grid.
|
||||
///
|
||||
/// @see rcHeightfield
|
||||
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
|
||||
const unsigned short* tris, const unsigned char* areas, const int nt,
|
||||
rcHeightfield& solid, const int flagMergeThr)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
|
||||
const float ics = 1.0f/solid.cs;
|
||||
const float ich = 1.0f/solid.ch;
|
||||
// Rasterize triangles.
|
||||
for (int i = 0; i < nt; ++i)
|
||||
{
|
||||
const float* v0 = &verts[tris[i*3+0]*3];
|
||||
const float* v1 = &verts[tris[i*3+1]*3];
|
||||
const float* v2 = &verts[tris[i*3+2]*3];
|
||||
// Rasterize.
|
||||
rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// Spans will only be added for triangles that overlap the heightfield grid.
|
||||
///
|
||||
/// @see rcHeightfield
|
||||
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt,
|
||||
rcHeightfield& solid, const int flagMergeThr)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
|
||||
const float ics = 1.0f/solid.cs;
|
||||
const float ich = 1.0f/solid.ch;
|
||||
// Rasterize triangles.
|
||||
for (int i = 0; i < nt; ++i)
|
||||
{
|
||||
const float* v0 = &verts[(i*3+0)*3];
|
||||
const float* v1 = &verts[(i*3+1)*3];
|
||||
const float* v2 = &verts[(i*3+2)*3];
|
||||
// Rasterize.
|
||||
rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
362
extern/recastnavigation/recast-capi.cpp
vendored
362
extern/recastnavigation/recast-capi.cpp
vendored
@@ -30,8 +30,370 @@
|
||||
#include <math.h>
|
||||
#include "Recast.h"
|
||||
|
||||
static rcContext *sctx;
|
||||
|
||||
#define INIT_SCTX() \
|
||||
if (sctx == NULL) sctx = new rcContext(false)
|
||||
|
||||
int recast_buildMeshAdjacency(unsigned short* polys, const int npolys,
|
||||
const int nverts, const int vertsPerPoly)
|
||||
{
|
||||
return (int) buildMeshAdjacency(polys, npolys, nverts, vertsPerPoly);
|
||||
}
|
||||
|
||||
void recast_calcBounds(const float *verts, int nv, float *bmin, float *bmax)
|
||||
{
|
||||
rcCalcBounds(verts, nv, bmin, bmax);
|
||||
}
|
||||
|
||||
void recast_calcGridSize(const float *bmin, const float *bmax, float cs, int *w, int *h)
|
||||
{
|
||||
rcCalcGridSize(bmin, bmax, cs, w, h);
|
||||
}
|
||||
|
||||
struct recast_heightfield *recast_newHeightfield(void)
|
||||
{
|
||||
return (struct recast_heightfield *) rcAllocHeightfield();
|
||||
}
|
||||
|
||||
void recast_destroyHeightfield(struct recast_heightfield *heightfield)
|
||||
{
|
||||
rcFreeHeightField((rcHeightfield *) heightfield);
|
||||
}
|
||||
|
||||
int recast_createHeightfield(struct recast_heightfield *hf, int width, int height,
|
||||
const float *bmin, const float* bmax, float cs, float ch)
|
||||
{
|
||||
INIT_SCTX();
|
||||
return rcCreateHeightfield(sctx, *(rcHeightfield *)hf, width, height, bmin, bmax, cs, ch);
|
||||
}
|
||||
|
||||
void recast_markWalkableTriangles(const float walkableSlopeAngle,const float *verts, int nv,
|
||||
const int *tris, int nt, unsigned char *flags)
|
||||
{
|
||||
INIT_SCTX();
|
||||
rcMarkWalkableTriangles(sctx, walkableSlopeAngle, verts, nv, tris, nt, flags);
|
||||
}
|
||||
|
||||
void recast_rasterizeTriangles(const float *verts, int nv, const int *tris,
|
||||
const unsigned char *flags, int nt, struct recast_heightfield *solid)
|
||||
{
|
||||
INIT_SCTX();
|
||||
rcRasterizeTriangles(sctx, verts, nv, tris, flags, nt, *(rcHeightfield *) solid);
|
||||
}
|
||||
|
||||
void recast_filterLedgeSpans(const int walkableHeight, const int walkableClimb,
|
||||
struct recast_heightfield *solid)
|
||||
{
|
||||
INIT_SCTX();
|
||||
rcFilterLedgeSpans(sctx, walkableHeight, walkableClimb, *(rcHeightfield *) solid);
|
||||
}
|
||||
|
||||
void recast_filterWalkableLowHeightSpans(int walkableHeight, struct recast_heightfield *solid)
|
||||
{
|
||||
INIT_SCTX();
|
||||
rcFilterWalkableLowHeightSpans(sctx, walkableHeight, *(rcHeightfield *) solid);
|
||||
}
|
||||
|
||||
void recast_filterLowHangingWalkableObstacles(const int walkableClimb, struct recast_heightfield *solid)
|
||||
{
|
||||
INIT_SCTX();
|
||||
rcFilterLowHangingWalkableObstacles(sctx, walkableClimb, *(rcHeightfield *) solid);
|
||||
}
|
||||
|
||||
struct recast_compactHeightfield *recast_newCompactHeightfield(void)
|
||||
{
|
||||
return (struct recast_compactHeightfield *) rcAllocCompactHeightfield();
|
||||
}
|
||||
|
||||
void recast_destroyCompactHeightfield(struct recast_compactHeightfield *compactHeightfield)
|
||||
{
|
||||
rcFreeCompactHeightfield( (rcCompactHeightfield *) compactHeightfield);
|
||||
}
|
||||
|
||||
int recast_buildCompactHeightfield(const int walkableHeight, const int walkableClimb,
|
||||
struct recast_heightfield *hf, struct recast_compactHeightfield *chf)
|
||||
{
|
||||
INIT_SCTX();
|
||||
return rcBuildCompactHeightfield(sctx, walkableHeight, walkableClimb,
|
||||
*(rcHeightfield *) hf, *(rcCompactHeightfield *) chf);
|
||||
}
|
||||
|
||||
int recast_erodeWalkableArea(int radius, struct recast_compactHeightfield *chf)
|
||||
{
|
||||
INIT_SCTX();
|
||||
return rcErodeWalkableArea(sctx, radius, *(rcCompactHeightfield *) chf);
|
||||
}
|
||||
|
||||
int recast_buildDistanceField(struct recast_compactHeightfield *chf)
|
||||
{
|
||||
INIT_SCTX();
|
||||
return rcBuildDistanceField(sctx, *(rcCompactHeightfield *) chf);
|
||||
}
|
||||
|
||||
int recast_buildRegions(struct recast_compactHeightfield *chf, int borderSize,
|
||||
int minRegionSize, int mergeRegionSize)
|
||||
{
|
||||
INIT_SCTX();
|
||||
return rcBuildRegions(sctx, *(rcCompactHeightfield *) chf, borderSize,
|
||||
minRegionSize, mergeRegionSize);
|
||||
}
|
||||
|
||||
struct recast_contourSet *recast_newContourSet(void)
|
||||
{
|
||||
return (struct recast_contourSet *) rcAllocContourSet();
|
||||
}
|
||||
|
||||
void recast_destroyContourSet(struct recast_contourSet *contourSet)
|
||||
{
|
||||
rcFreeContourSet((rcContourSet *) contourSet);
|
||||
}
|
||||
|
||||
int recast_buildContours(struct recast_compactHeightfield *chf,
|
||||
const float maxError, const int maxEdgeLen, struct recast_contourSet *cset)
|
||||
{
|
||||
INIT_SCTX();
|
||||
return rcBuildContours(sctx, *(rcCompactHeightfield *) chf, maxError, maxEdgeLen, *(rcContourSet *) cset);
|
||||
}
|
||||
|
||||
struct recast_polyMesh *recast_newPolyMesh(void)
|
||||
{
|
||||
return (recast_polyMesh *) rcAllocPolyMesh();
|
||||
}
|
||||
|
||||
void recast_destroyPolyMesh(struct recast_polyMesh *polyMesh)
|
||||
{
|
||||
rcFreePolyMesh((rcPolyMesh *) polyMesh);
|
||||
}
|
||||
|
||||
int recast_buildPolyMesh(struct recast_contourSet *cset, int nvp, struct recast_polyMesh *mesh)
|
||||
{
|
||||
INIT_SCTX();
|
||||
return rcBuildPolyMesh(sctx, *(rcContourSet *) cset, nvp, * (rcPolyMesh *) mesh);
|
||||
}
|
||||
|
||||
unsigned short *recast_polyMeshGetVerts(struct recast_polyMesh *mesh, int *nverts)
|
||||
{
|
||||
rcPolyMesh *pmesh = (rcPolyMesh *)mesh;
|
||||
|
||||
if (nverts)
|
||||
*nverts = pmesh->nverts;
|
||||
|
||||
return pmesh->verts;
|
||||
}
|
||||
|
||||
void recast_polyMeshGetBoundbox(struct recast_polyMesh *mesh, float *bmin, float *bmax)
|
||||
{
|
||||
rcPolyMesh *pmesh = (rcPolyMesh *)mesh;
|
||||
|
||||
if (bmin) {
|
||||
bmin[0] = pmesh->bmin[0];
|
||||
bmin[1] = pmesh->bmin[1];
|
||||
bmin[2] = pmesh->bmin[2];
|
||||
}
|
||||
|
||||
if (bmax) {
|
||||
bmax[0] = pmesh->bmax[0];
|
||||
bmax[1] = pmesh->bmax[1];
|
||||
bmax[2] = pmesh->bmax[2];
|
||||
}
|
||||
}
|
||||
|
||||
void recast_polyMeshGetCell(struct recast_polyMesh *mesh, float *cs, float *ch)
|
||||
{
|
||||
rcPolyMesh *pmesh = (rcPolyMesh *)mesh;
|
||||
|
||||
if (cs)
|
||||
*cs = pmesh->cs;
|
||||
|
||||
if (ch)
|
||||
*ch = pmesh->ch;
|
||||
}
|
||||
|
||||
unsigned short *recast_polyMeshGetPolys(struct recast_polyMesh *mesh, int *npolys, int *nvp)
|
||||
{
|
||||
rcPolyMesh *pmesh = (rcPolyMesh *)mesh;
|
||||
|
||||
if (npolys)
|
||||
*npolys = pmesh->npolys;
|
||||
|
||||
if (nvp)
|
||||
*nvp = pmesh->nvp;
|
||||
|
||||
return pmesh->polys;
|
||||
}
|
||||
|
||||
struct recast_polyMeshDetail *recast_newPolyMeshDetail(void)
|
||||
{
|
||||
return (struct recast_polyMeshDetail *) rcAllocPolyMeshDetail();
|
||||
}
|
||||
|
||||
void recast_destroyPolyMeshDetail(struct recast_polyMeshDetail *polyMeshDetail)
|
||||
{
|
||||
rcFreePolyMeshDetail((rcPolyMeshDetail *) polyMeshDetail);
|
||||
}
|
||||
|
||||
int recast_buildPolyMeshDetail(const struct recast_polyMesh *mesh, const struct recast_compactHeightfield *chf,
|
||||
const float sampleDist, const float sampleMaxError, struct recast_polyMeshDetail *dmesh)
|
||||
{
|
||||
INIT_SCTX();
|
||||
return rcBuildPolyMeshDetail(sctx, *(rcPolyMesh *) mesh, *(rcCompactHeightfield *) chf,
|
||||
sampleDist, sampleMaxError, *(rcPolyMeshDetail *) dmesh);
|
||||
}
|
||||
|
||||
float *recast_polyMeshDetailGetVerts(struct recast_polyMeshDetail *mesh, int *nverts)
|
||||
{
|
||||
rcPolyMeshDetail *dmesh = (rcPolyMeshDetail *)mesh;
|
||||
|
||||
if (nverts)
|
||||
*nverts = dmesh->nverts;
|
||||
|
||||
return dmesh->verts;
|
||||
}
|
||||
|
||||
unsigned char *recast_polyMeshDetailGetTris(struct recast_polyMeshDetail *mesh, int *ntris)
|
||||
{
|
||||
rcPolyMeshDetail *dmesh = (rcPolyMeshDetail *)mesh;
|
||||
|
||||
if (ntris)
|
||||
*ntris = dmesh->ntris;
|
||||
|
||||
return dmesh->tris;
|
||||
}
|
||||
|
||||
unsigned int *recast_polyMeshDetailGetMeshes(struct recast_polyMeshDetail *mesh, int *nmeshes)
|
||||
{
|
||||
rcPolyMeshDetail *dmesh = (rcPolyMeshDetail *)mesh;
|
||||
|
||||
if (nmeshes)
|
||||
*nmeshes = dmesh->nmeshes;
|
||||
|
||||
return dmesh->meshes;
|
||||
}
|
||||
|
||||
// qsort based on FreeBSD source (libkern\qsort.c)
|
||||
typedef int cmp_t(void *, const void *, const void *);
|
||||
static inline char *med3(char *, char *, char *, cmp_t *, void *);
|
||||
static inline void swapfunc(char *, char *, int, int);
|
||||
|
||||
#define min(a, b) (a) < (b) ? a : b
|
||||
#define swapcode(TYPE, parmi, parmj, n) \
|
||||
{ \
|
||||
long i = (n) / sizeof (TYPE); \
|
||||
TYPE *pi = (TYPE *) (parmi); \
|
||||
TYPE *pj = (TYPE *) (parmj); \
|
||||
do { \
|
||||
TYPE t = *pi; \
|
||||
*pi++ = *pj; \
|
||||
*pj++ = t; \
|
||||
} while (--i > 0); \
|
||||
}
|
||||
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
|
||||
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
|
||||
|
||||
static inline void swapfunc(char* a, char* b, int n, int swaptype)
|
||||
{
|
||||
if(swaptype <= 1)
|
||||
swapcode(long, a, b, n)
|
||||
else
|
||||
swapcode(char, a, b, n)
|
||||
}
|
||||
|
||||
#define swap(a, b) \
|
||||
if (swaptype == 0) { \
|
||||
long t = *(long *)(a); \
|
||||
*(long *)(a) = *(long *)(b);\
|
||||
*(long *)(b) = t; \
|
||||
} else \
|
||||
swapfunc(a, b, es, swaptype)
|
||||
|
||||
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
||||
#define CMP(t, x, y) (cmp((t), (x), (y)))
|
||||
|
||||
static inline char * med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk)
|
||||
{
|
||||
return CMP(thunk, a, b) < 0 ?
|
||||
(CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
|
||||
:(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
|
||||
}
|
||||
|
||||
void recast_qsort(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
|
||||
{
|
||||
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
||||
int d, r, swaptype, swap_cnt;
|
||||
|
||||
loop:
|
||||
SWAPINIT(a, es);
|
||||
swap_cnt = 0;
|
||||
if (n < 7) {
|
||||
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
|
||||
for (pl = pm;
|
||||
pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
|
||||
pl -= es)
|
||||
swap(pl, pl - es);
|
||||
return;
|
||||
}
|
||||
pm = (char *)a + (n / 2) * es;
|
||||
if (n > 7) {
|
||||
pl = (char *)a;
|
||||
pn = (char *)a + (n - 1) * es;
|
||||
if (n > 40) {
|
||||
d = (n / 8) * es;
|
||||
pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
|
||||
pm = med3(pm - d, pm, pm + d, cmp, thunk);
|
||||
pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
|
||||
}
|
||||
pm = med3(pl, pm, pn, cmp, thunk);
|
||||
}
|
||||
swap((char *)a, pm);
|
||||
pa = pb = (char *)a + es;
|
||||
|
||||
pc = pd = (char *)a + (n - 1) * es;
|
||||
for (;;) {
|
||||
while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) {
|
||||
if (r == 0) {
|
||||
swap_cnt = 1;
|
||||
swap(pa, pb);
|
||||
pa += es;
|
||||
}
|
||||
pb += es;
|
||||
}
|
||||
while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) {
|
||||
if (r == 0) {
|
||||
swap_cnt = 1;
|
||||
swap(pc, pd);
|
||||
pd -= es;
|
||||
}
|
||||
pc -= es;
|
||||
}
|
||||
if (pb > pc)
|
||||
break;
|
||||
swap(pb, pc);
|
||||
swap_cnt = 1;
|
||||
pb += es;
|
||||
pc -= es;
|
||||
}
|
||||
if (swap_cnt == 0) { /* Switch to insertion sort */
|
||||
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
|
||||
for (pl = pm;
|
||||
pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
|
||||
pl -= es)
|
||||
swap(pl, pl - es);
|
||||
return;
|
||||
}
|
||||
|
||||
pn = (char *)a + n * es;
|
||||
r = min(pa - (char *)a, pb - pa);
|
||||
vecswap((char *)a, pb - r, r);
|
||||
r = min(pd - pc, pn - pd - es);
|
||||
vecswap(pb, pn - r, r);
|
||||
if ((r = pb - pa) > es)
|
||||
recast_qsort(a, r / es, es, thunk, cmp);
|
||||
if ((r = pd - pc) > es) {
|
||||
/* Iterate rather than recurse to save stack space */
|
||||
a = pn - r;
|
||||
n = r / es;
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
98
extern/recastnavigation/recast-capi.h
vendored
98
extern/recastnavigation/recast-capi.h
vendored
@@ -28,13 +28,111 @@
|
||||
#ifndef RECAST_C_API_H
|
||||
#define RECAST_C_API_H
|
||||
|
||||
// for size_t
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct recast_polyMesh;
|
||||
struct recast_polyMeshDetail;
|
||||
struct recast_heightfield;
|
||||
struct recast_compactHeightfield;
|
||||
struct recast_contourSet;
|
||||
|
||||
enum recast_SpanFlags
|
||||
{
|
||||
RECAST_WALKABLE = 0x01,
|
||||
RECAST_REACHABLE = 0x02
|
||||
};
|
||||
|
||||
int recast_buildMeshAdjacency(unsigned short* polys, const int npolys,
|
||||
const int nverts, const int vertsPerPoly);
|
||||
|
||||
void recast_calcBounds(const float *verts, int nv, float *bmin, float *bmax);
|
||||
|
||||
void recast_calcGridSize(const float *bmin, const float *bmax, float cs, int *w, int *h);
|
||||
|
||||
struct recast_heightfield *recast_newHeightfield(void);
|
||||
|
||||
void recast_destroyHeightfield(struct recast_heightfield *heightfield);
|
||||
|
||||
int recast_createHeightfield(struct recast_heightfield *hf, int width, int height,
|
||||
const float *bmin, const float* bmax, float cs, float ch);
|
||||
|
||||
void recast_markWalkableTriangles(const float walkableSlopeAngle,const float *verts, int nv,
|
||||
const int *tris, int nt, unsigned char *flags);
|
||||
|
||||
void recast_rasterizeTriangles(const float *verts, int nv, const int *tris,
|
||||
const unsigned char *flags, int nt, struct recast_heightfield *solid);
|
||||
|
||||
void recast_filterLedgeSpans(const int walkableHeight, const int walkableClimb,
|
||||
struct recast_heightfield *solid);
|
||||
|
||||
void recast_filterWalkableLowHeightSpans(int walkableHeight, struct recast_heightfield *solid);
|
||||
|
||||
void recast_filterLowHangingWalkableObstacles(const int walkableClimb, struct recast_heightfield *solid);
|
||||
|
||||
struct recast_compactHeightfield *recast_newCompactHeightfield(void);
|
||||
|
||||
void recast_destroyCompactHeightfield(struct recast_compactHeightfield *compactHeightfield);
|
||||
|
||||
int recast_buildCompactHeightfield(const int walkableHeight, const int walkableClimb,
|
||||
struct recast_heightfield *hf, struct recast_compactHeightfield *chf);
|
||||
|
||||
int recast_erodeWalkableArea(int radius, struct recast_compactHeightfield *chf);
|
||||
|
||||
int recast_buildDistanceField(struct recast_compactHeightfield *chf);
|
||||
|
||||
int recast_buildRegions(struct recast_compactHeightfield *chf, int borderSize,
|
||||
int minRegionSize, int mergeRegionSize);
|
||||
|
||||
/* Contour set */
|
||||
|
||||
struct recast_contourSet *recast_newContourSet(void);
|
||||
|
||||
void recast_destroyContourSet(struct recast_contourSet *contourSet);
|
||||
|
||||
int recast_buildContours(struct recast_compactHeightfield *chf,
|
||||
const float maxError, const int maxEdgeLen, struct recast_contourSet *cset);
|
||||
|
||||
/* Poly mesh */
|
||||
|
||||
struct recast_polyMesh *recast_newPolyMesh(void);
|
||||
|
||||
void recast_destroyPolyMesh(struct recast_polyMesh *polyMesh);
|
||||
|
||||
int recast_buildPolyMesh(struct recast_contourSet *cset, int nvp, struct recast_polyMesh *mesh);
|
||||
|
||||
unsigned short *recast_polyMeshGetVerts(struct recast_polyMesh *mesh, int *nverts);
|
||||
|
||||
void recast_polyMeshGetBoundbox(struct recast_polyMesh *mesh, float *bmin, float *bmax);
|
||||
|
||||
void recast_polyMeshGetCell(struct recast_polyMesh *mesh, float *cs, float *ch);
|
||||
|
||||
unsigned short *recast_polyMeshGetPolys(struct recast_polyMesh *mesh, int *npolys, int *nvp);
|
||||
|
||||
/* Poly mesh detail */
|
||||
|
||||
struct recast_polyMeshDetail *recast_newPolyMeshDetail(void);
|
||||
|
||||
void recast_destroyPolyMeshDetail(struct recast_polyMeshDetail *polyMeshDetail);
|
||||
|
||||
int recast_buildPolyMeshDetail(const struct recast_polyMesh *mesh, const struct recast_compactHeightfield *chf,
|
||||
const float sampleDist, const float sampleMaxError, struct recast_polyMeshDetail *dmesh);
|
||||
|
||||
float *recast_polyMeshDetailGetVerts(struct recast_polyMeshDetail *mesh, int *nverts);
|
||||
|
||||
unsigned char *recast_polyMeshDetailGetTris(struct recast_polyMeshDetail *mesh, int *ntris);
|
||||
|
||||
unsigned int *recast_polyMeshDetailGetMeshes(struct recast_polyMeshDetail *mesh, int *nmeshes);
|
||||
|
||||
/* utility function: quick sort reentrant */
|
||||
typedef int recast_cmp_t(void *ctx, const void *a, const void *b);
|
||||
|
||||
void recast_qsort(void *a, size_t n, size_t es, void *thunk, recast_cmp_t *cmp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
set(INC
|
||||
.
|
||||
FX
|
||||
SRC
|
||||
intern
|
||||
../ffmpeg
|
||||
)
|
||||
@@ -262,20 +261,6 @@ if(WITH_CODEC_SNDFILE)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_SAMPLERATE)
|
||||
add_definitions(-DWITH_SAMPLERATE)
|
||||
list(APPEND INC_SYS
|
||||
${SAMPLERATE_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND SRC
|
||||
SRC/AUD_SRCResampleFactory.cpp
|
||||
SRC/AUD_SRCResampleReader.cpp
|
||||
|
||||
SRC/AUD_SRCResampleFactory.h
|
||||
SRC/AUD_SRCResampleReader.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_FFTW3 AND FALSE)
|
||||
add_definitions(-DWITH_FFTW3)
|
||||
list(APPEND INC
|
||||
|
||||
@@ -848,6 +848,8 @@ Factory_filter(Factory* self, PyObject* args)
|
||||
{
|
||||
PyObject* py_b;
|
||||
PyObject* py_a = NULL;
|
||||
Py_ssize_t py_a_len;
|
||||
Py_ssize_t py_b_len;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a))
|
||||
return NULL;
|
||||
@@ -858,7 +860,10 @@ Factory_filter(Factory* self, PyObject* args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!PySequence_Size(py_b) || (py_a != NULL && !PySequence_Size(py_a)))
|
||||
py_a_len= py_a ? PySequence_Size(py_a) : 0;
|
||||
py_b_len= PySequence_Size(py_b);
|
||||
|
||||
if(!py_b_len || ((py_a != NULL) && !py_b_len))
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
|
||||
return NULL;
|
||||
@@ -867,30 +872,31 @@ Factory_filter(Factory* self, PyObject* args)
|
||||
std::vector<float> a, b;
|
||||
PyObject* py_value;
|
||||
float value;
|
||||
int result;
|
||||
|
||||
for(int i = 0; i < PySequence_Size(py_b); i++)
|
||||
for(Py_ssize_t i = 0; i < py_b_len; i++)
|
||||
{
|
||||
py_value = PySequence_GetItem(py_b, i);
|
||||
result = PyArg_Parse(py_value, "f:filter", &value);
|
||||
value= (float)PyFloat_AsDouble(py_value);
|
||||
Py_DECREF(py_value);
|
||||
|
||||
if(!result)
|
||||
if (value==-1.0f && PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b.push_back(value);
|
||||
}
|
||||
|
||||
if(py_a)
|
||||
{
|
||||
for(int i = 0; i < PySequence_Size(py_a); i++)
|
||||
for(Py_ssize_t i = 0; i < py_a_len; i++)
|
||||
{
|
||||
py_value = PySequence_GetItem(py_a, i);
|
||||
result = PyArg_Parse(py_value, "f:filter", &value);
|
||||
value= (float)PyFloat_AsDouble(py_value);
|
||||
Py_DECREF(py_value);
|
||||
|
||||
if(!result)
|
||||
if (value==-1.0f && PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a.push_back(value);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
Import ('env')
|
||||
|
||||
sources = env.Glob('intern/*.cpp') + env.Glob('FX/*.cpp') + env.Glob('SRC/*.cpp')
|
||||
incs = '. intern FX SRC ' + env['BF_PTHREADS_INC'] + ' ' + env['BF_LIBSAMPLERATE_INC']
|
||||
sources = env.Glob('intern/*.cpp') + env.Glob('FX/*.cpp')
|
||||
incs = '. intern FX ' + env['BF_PTHREADS_INC']
|
||||
defs = []
|
||||
|
||||
if env['WITH_BF_FFMPEG']:
|
||||
@@ -44,7 +44,4 @@ if env['WITH_BF_PYTHON']:
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
|
||||
incs += ' ' + env['BF_PTHREADS_INC']
|
||||
|
||||
# not optional with scons yet
|
||||
defs.append('WITH_SAMPLERATE')
|
||||
|
||||
env.BlenderLib ('bf_intern_audaspace', sources, Split(incs), defs, libtype=['intern','player'], priority = [25,215] )
|
||||
|
||||
@@ -1094,9 +1094,11 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_pe
|
||||
specs.specs = reader->getSpecs();
|
||||
int len;
|
||||
float samplejump = specs.rate / samples_per_second;
|
||||
float min, max, power;
|
||||
float min, max, power, overallmax;
|
||||
bool eos;
|
||||
|
||||
overallmax = 0;
|
||||
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
len = floor(samplejump * (i+1)) - floor(samplejump * i);
|
||||
@@ -1121,6 +1123,11 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_pe
|
||||
buffer[i * 3 + 1] = max;
|
||||
buffer[i * 3 + 2] = sqrt(power) / len;
|
||||
|
||||
if(overallmax < max)
|
||||
overallmax = max;
|
||||
if(overallmax < -min)
|
||||
overallmax = -min;
|
||||
|
||||
if(eos)
|
||||
{
|
||||
length = i;
|
||||
@@ -1128,6 +1135,14 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_pe
|
||||
}
|
||||
}
|
||||
|
||||
if(overallmax > 1.0f)
|
||||
{
|
||||
for(int i = 0; i < length * 3; i++)
|
||||
{
|
||||
buffer[i] /= overallmax;
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
@@ -131,9 +131,15 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
}
|
||||
|
||||
while(eit != m_factory->m_entries.end())
|
||||
{
|
||||
try
|
||||
{
|
||||
handle = new AUD_SequencerHandle(*eit, m_device);
|
||||
handles.push_front(handle);
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
}
|
||||
eit++;
|
||||
}
|
||||
|
||||
|
||||
@@ -216,7 +216,6 @@ void ntlWorld::finishWorldInit()
|
||||
}
|
||||
long stopTime = getTime();
|
||||
|
||||
mSimulationTime += (*mpSims)[mFirstSim]->getStartTime();
|
||||
debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Time for start-sims:"<< getTimeString(stopTime-startTime) , 1);
|
||||
#ifndef NOGUI
|
||||
guiResetSimulationTimeRange( mSimulationTime );
|
||||
|
||||
@@ -25,6 +25,15 @@
|
||||
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
|
||||
/* check our ffmpeg is new enough, avoids user complaints */
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR < 52) || ((LIBAVFORMAT_VERSION_MAJOR == 52) && (LIBAVFORMAT_VERSION_MINOR <= 64))
|
||||
# error "FFmpeg 0.7 or newer is needed, Upgrade you're FFmpeg or disable it"
|
||||
#endif
|
||||
/* end sanity check */
|
||||
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/rational.h>
|
||||
|
||||
|
||||
@@ -248,9 +248,10 @@ elseif(UNIX)
|
||||
endif()
|
||||
|
||||
elseif(WIN32)
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
|
||||
endif()
|
||||
## Warnings as errors, this is too strict!
|
||||
#if(MSVC)
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
|
||||
#endif()
|
||||
|
||||
list(APPEND INC_SYS
|
||||
${WINTAB_INC}
|
||||
|
||||
@@ -34,7 +34,12 @@ elif window_system in ('linux', 'openbsd3', 'sunos5', 'freebsd7', 'freebsd8', 'f
|
||||
sources.remove('intern' + os.sep + f + 'SDL.cpp')
|
||||
except ValueError:
|
||||
pass
|
||||
defs += ['PREFIX=\\"/usr/local/\\"'] # XXX, make an option
|
||||
## removing because scons does not support system installation
|
||||
## if this is used for blender.org builds it means our distrobution
|
||||
## will find any locally installed blender and double up its script path.
|
||||
## So until this is supported properly as with CMake,
|
||||
## just dont use the PREFIX.
|
||||
# defs += ['PREFIX=\\"/usr/local/\\"'] # XXX, make an option
|
||||
defs += ['WITH_X11_XINPUT'] # XXX, make an option
|
||||
|
||||
elif window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
|
||||
@@ -101,5 +106,10 @@ if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-v
|
||||
|
||||
if window_system in ('win32-vc', 'win64-vc'):
|
||||
env.BlenderLib ('bf_intern_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15]) #, cc_compileflags=env['CCFLAGS'].append('/WX') )
|
||||
|
||||
elif env['WITH_GHOST_COCOA']: # always use Apple-gcc-4.2 for objC language, for gnu-compilers do not support it fully yet
|
||||
env.BlenderLib ('bf_intern_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15], cc_compilerchange='/usr/bin/gcc-4.2', cxx_compilerchange='/usr/bin/g++-4.2' )
|
||||
print "GHOST COCOA WILL BE COMPILED WITH APPLE GCC"
|
||||
|
||||
else:
|
||||
env.BlenderLib ('bf_intern_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] )
|
||||
|
||||
@@ -711,6 +711,10 @@ static void rem_memblock(MemHead *memh)
|
||||
static void MemorY_ErroR(const char *block, const char *error)
|
||||
{
|
||||
print_error("Memoryblock %s: %s\n",block, error);
|
||||
|
||||
#ifdef WITH_ASSERT_ABORT
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *check_memlist(MemHead *memh)
|
||||
|
||||
@@ -166,11 +166,11 @@ typedef struct
|
||||
tbool bOrient;
|
||||
} STSpace;
|
||||
|
||||
int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
|
||||
void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
|
||||
void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
|
||||
int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn);
|
||||
tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[],
|
||||
static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
|
||||
static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
|
||||
static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
|
||||
static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn);
|
||||
static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[],
|
||||
const int iNrActiveGroups, const int piTriListIn[], const float fThresCos,
|
||||
const SMikkTSpaceContext * pContext);
|
||||
|
||||
@@ -216,14 +216,14 @@ static STSpace AvgTSpace(const STSpace * pTS0, const STSpace * pTS1)
|
||||
|
||||
|
||||
|
||||
SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index);
|
||||
SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index);
|
||||
SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index);
|
||||
static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index);
|
||||
static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index);
|
||||
static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index);
|
||||
|
||||
|
||||
// degen triangles
|
||||
void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris);
|
||||
void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn, const int iTotTris);
|
||||
static void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris);
|
||||
static void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn, const int iTotTris);
|
||||
|
||||
|
||||
tbool genTangSpaceDefault(const SMikkTSpaceContext * pContext)
|
||||
@@ -450,11 +450,11 @@ NOINLINE int FindGridCell(const float fMin, const float fMax, const float fVal)
|
||||
return iIndex<g_iCells?iIndex:(g_iCells-1);
|
||||
}
|
||||
|
||||
void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in);
|
||||
void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries);
|
||||
void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
|
||||
static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in);
|
||||
static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries);
|
||||
static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn);
|
||||
|
||||
void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
|
||||
static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
|
||||
{
|
||||
|
||||
// Generate bounding box
|
||||
@@ -579,7 +579,7 @@ void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpa
|
||||
free(piHashOffsets);
|
||||
}
|
||||
|
||||
void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in)
|
||||
static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in)
|
||||
{
|
||||
// make bbox
|
||||
int c=0, l=0, channel=0;
|
||||
@@ -689,7 +689,7 @@ void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikk
|
||||
}
|
||||
}
|
||||
|
||||
void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries)
|
||||
static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries)
|
||||
{
|
||||
// this can be optimized further using a tree structure or more hashing.
|
||||
int e=0;
|
||||
@@ -724,7 +724,7 @@ void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pCont
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
|
||||
static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
|
||||
{
|
||||
int iNumUniqueVerts = 0, t=0, i=0;
|
||||
for(t=0; t<iNrTrianglesIn; t++)
|
||||
@@ -767,7 +767,7 @@ void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikk
|
||||
}
|
||||
}
|
||||
|
||||
int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
|
||||
static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
|
||||
{
|
||||
int iTSpacesOffs = 0, f=0, t=0;
|
||||
int iDstTriIndex = 0;
|
||||
@@ -878,7 +878,7 @@ int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_out[],
|
||||
return iTSpacesOffs;
|
||||
}
|
||||
|
||||
SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index)
|
||||
static SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index)
|
||||
{
|
||||
int iF, iI;
|
||||
SVec3 res; float pos[3];
|
||||
@@ -888,7 +888,7 @@ SVec3 GetPosition(const SMikkTSpaceContext * pContext, const int index)
|
||||
return res;
|
||||
}
|
||||
|
||||
SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index)
|
||||
static SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index)
|
||||
{
|
||||
int iF, iI;
|
||||
SVec3 res; float norm[3];
|
||||
@@ -898,7 +898,7 @@ SVec3 GetNormal(const SMikkTSpaceContext * pContext, const int index)
|
||||
return res;
|
||||
}
|
||||
|
||||
SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index)
|
||||
static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index)
|
||||
{
|
||||
int iF, iI;
|
||||
SVec3 res; float texc[2];
|
||||
@@ -920,8 +920,8 @@ typedef union
|
||||
int array[3];
|
||||
} SEdge;
|
||||
|
||||
void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriListIn[], const int iNrTrianglesIn);
|
||||
void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn);
|
||||
static void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriListIn[], const int iNrTrianglesIn);
|
||||
static void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn);
|
||||
|
||||
// returns the texture area times 2
|
||||
static float CalcTexArea(const SMikkTSpaceContext * pContext, const int indices[])
|
||||
@@ -940,7 +940,7 @@ static float CalcTexArea(const SMikkTSpaceContext * pContext, const int indices[
|
||||
return fSignedAreaSTx2<0 ? (-fSignedAreaSTx2) : fSignedAreaSTx2;
|
||||
}
|
||||
|
||||
void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
|
||||
static void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
|
||||
{
|
||||
int f=0, i=0, t=0;
|
||||
// pTriInfos[f].iFlag is cleared in GenerateInitialVerticesIndexList() which is called before this function.
|
||||
@@ -1062,10 +1062,10 @@ void InitTriInfo(STriInfo pTriInfos[], const int piTriListIn[], const SMikkTSpac
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], const int iMyTriIndex, SGroup * pGroup);
|
||||
void AddTriToGroup(SGroup * pGroup, const int iTriIndex);
|
||||
static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], const int iMyTriIndex, SGroup * pGroup);
|
||||
static void AddTriToGroup(SGroup * pGroup, const int iTriIndex);
|
||||
|
||||
int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn)
|
||||
static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTrianglesBuffer[], const int piTriListIn[], const int iNrTrianglesIn)
|
||||
{
|
||||
const int iNrMaxGroups = iNrTrianglesIn*3;
|
||||
int iNrActiveGroups = 0;
|
||||
@@ -1126,13 +1126,13 @@ int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupTriangle
|
||||
return iNrActiveGroups;
|
||||
}
|
||||
|
||||
void AddTriToGroup(SGroup * pGroup, const int iTriIndex)
|
||||
static void AddTriToGroup(SGroup * pGroup, const int iTriIndex)
|
||||
{
|
||||
pGroup->pFaceIndices[pGroup->iNrFaces] = iTriIndex;
|
||||
++pGroup->iNrFaces;
|
||||
}
|
||||
|
||||
tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[],
|
||||
static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[],
|
||||
const int iMyTriIndex, SGroup * pGroup)
|
||||
{
|
||||
STriInfo * pMyTriInfo = &psTriInfos[iMyTriIndex];
|
||||
@@ -1187,11 +1187,11 @@ tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[],
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2);
|
||||
void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed);
|
||||
STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], const SMikkTSpaceContext * pContext, const int iVertexRepresentitive);
|
||||
static tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2);
|
||||
static void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed);
|
||||
static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], const SMikkTSpaceContext * pContext, const int iVertexRepresentitive);
|
||||
|
||||
tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[],
|
||||
static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[],
|
||||
const int iNrActiveGroups, const int piTriListIn[], const float fThresCos,
|
||||
const SMikkTSpaceContext * pContext)
|
||||
{
|
||||
@@ -1361,7 +1361,7 @@ tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGro
|
||||
return TTRUE;
|
||||
}
|
||||
|
||||
STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[],
|
||||
static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[],
|
||||
const SMikkTSpaceContext * pContext, const int iVertexRepresentitive)
|
||||
{
|
||||
STSpace res;
|
||||
@@ -1435,7 +1435,7 @@ STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[]
|
||||
return res;
|
||||
}
|
||||
|
||||
tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2)
|
||||
static tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2)
|
||||
{
|
||||
tbool bStillSame=TTRUE;
|
||||
int i=0;
|
||||
@@ -1448,7 +1448,7 @@ tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2)
|
||||
return bStillSame;
|
||||
}
|
||||
|
||||
void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed)
|
||||
static void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed)
|
||||
{
|
||||
int iL, iR, n, index, iMid, iTmp;
|
||||
|
||||
@@ -1492,10 +1492,10 @@ void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed);
|
||||
void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[], const int i0_in, const int i1_in);
|
||||
static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed);
|
||||
static void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[], const int i0_in, const int i1_in);
|
||||
|
||||
void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriListIn[], const int iNrTrianglesIn)
|
||||
static void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriListIn[], const int iNrTrianglesIn)
|
||||
{
|
||||
// build array of edges
|
||||
unsigned int uSeed = INTERNAL_RND_SORT_SEED; // could replace with a random seed?
|
||||
@@ -1590,7 +1590,7 @@ void BuildNeighborsFast(STriInfo pTriInfos[], SEdge * pEdges, const int piTriLis
|
||||
}
|
||||
}
|
||||
|
||||
void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn)
|
||||
static void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int iNrTrianglesIn)
|
||||
{
|
||||
int f=0, i=0;
|
||||
for(f=0; f<iNrTrianglesIn; f++)
|
||||
@@ -1639,7 +1639,7 @@ void BuildNeighborsSlow(STriInfo pTriInfos[], const int piTriListIn[], const int
|
||||
}
|
||||
}
|
||||
|
||||
void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed)
|
||||
static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channel, unsigned int uSeed)
|
||||
{
|
||||
unsigned int t;
|
||||
int iL, iR, n, index, iMid;
|
||||
@@ -1696,7 +1696,7 @@ void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int channe
|
||||
}
|
||||
|
||||
// resolve ordering and edge number
|
||||
void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[], const int i0_in, const int i1_in)
|
||||
static void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[], const int i0_in, const int i1_in)
|
||||
{
|
||||
*edgenum_out = -1;
|
||||
|
||||
@@ -1730,7 +1730,7 @@ void GetEdge(int * i0_out, int * i1_out, int * edgenum_out, const int indices[],
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////// Degenerate triangles ////////////////////////////////////
|
||||
|
||||
void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris)
|
||||
static void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrianglesIn, const int iTotTris)
|
||||
{
|
||||
int iNextGoodTriangleSearchIndex=-1;
|
||||
tbool bStillFindingGoodOnes;
|
||||
@@ -1813,7 +1813,7 @@ void DegenPrologue(STriInfo pTriInfos[], int piTriList_out[], const int iNrTrian
|
||||
assert(iNrTrianglesIn == t);
|
||||
}
|
||||
|
||||
void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn, const int iTotTris)
|
||||
static void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriListIn[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn, const int iTotTris)
|
||||
{
|
||||
int t=0, i=0;
|
||||
// deal with degenerate triangles
|
||||
|
||||
@@ -132,7 +132,7 @@ protected:
|
||||
uint32 mixBits( const uint32& u, const uint32& v ) const
|
||||
{ return hiBit(u) | loBits(v); }
|
||||
uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
|
||||
{ return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
|
||||
{ return m ^ (mixBits(s0,s1)>>1) ^ ((~loBit(s1) + 1) & 0x9908b0dfUL); }
|
||||
static uint32 hash( time_t t, clock_t c );
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
release/scripts/modules/rna_prop_ui.py
|
||||
|
||||
release/scripts/startup/bl_operators/animsys_update.py
|
||||
release/scripts/startup/bl_operators/object.py
|
||||
release/scripts/startup/bl_operators/object_align.py
|
||||
release/scripts/startup/bl_operators/object_quick_effects.py
|
||||
|
||||
81
po/README.txt
Normal file
81
po/README.txt
Normal file
@@ -0,0 +1,81 @@
|
||||
Blender translation HOWTO
|
||||
=========================
|
||||
|
||||
I'll try briefly explain how translation works and how to update translation files.
|
||||
|
||||
1. How it works
|
||||
---------------
|
||||
|
||||
This folder contains source files for translation system. This source files have
|
||||
got .po extension and they've got pretty simple syntax:
|
||||
|
||||
msgid "some message id"
|
||||
msgstr "translation for this message"
|
||||
|
||||
This means when string "some message id" is used as operator name, tooltip, menu
|
||||
and so it'll be displayed on the screen as "translation for this message".
|
||||
Pretty simple.
|
||||
|
||||
This source files are pre-compiled into ../relese/bin/.blender/locale/<language>/LC_MESSAGES/blender.mo,
|
||||
so they aren't getting compiled every time Blender is compiling to same some time and prevent
|
||||
failure on systems which doesn't have needed tools for compiling .po files.
|
||||
|
||||
2. How to update translations
|
||||
-----------------------------
|
||||
|
||||
It's also pretty simple. If you can find string you want to translate in <language>.po
|
||||
file as msgid, just write correct msgstr string for it. If msgid is marked as fuzzy,
|
||||
i.e.
|
||||
|
||||
#, fuzzy
|
||||
msgid "some message id"
|
||||
msgstr "translation for this message"
|
||||
|
||||
it means translation used to exist for this message, but message was changed, so translation
|
||||
also have to be updated (it's easier to make new translation based on previos translation).
|
||||
When translation was updated, remove line with '#, fuzzy' and it'll work.
|
||||
|
||||
If there's no message in .po file you want to translate, probably .po file should be updated.
|
||||
Use the following steps for this:
|
||||
- With newly compiled blender run:
|
||||
`blender --background --factory-startup --python update_msg.py`
|
||||
to update messages.txt file (this file contains strings collected
|
||||
automatically from RNA system and python UI scripts)
|
||||
- Run update_pot.py script which will update blender.pot file. This file contains all
|
||||
strings which should be transated.
|
||||
- Run update_po.py script to merge all .po files with blender.pot (so all .po files
|
||||
will contain all msgid-s declared in blender.pot) or update_po.py <language> to
|
||||
update only needed .po file(s) to save time when you're busy with translation.
|
||||
But before ocmmit all .po files better be updated.
|
||||
|
||||
When you've finished with translation, you should re-compile .po file into .mo file.
|
||||
It's also pretty simple: just run update_mo.py script to recompile all languages or
|
||||
just update_mo.py <language> to re-compile only needed language(s).
|
||||
|
||||
NOTE: msgfmt, msgmerge and xgettext tools should be available in your PATH.
|
||||
|
||||
This steps to update template, translation files and compile them can be made in "batch" mode
|
||||
using GNUMakefile:
|
||||
|
||||
make -f GNUMakefile translations
|
||||
|
||||
NOTE: Blender has to be compiled using GNUMakefile first.
|
||||
|
||||
|
||||
3. Note for Windows users
|
||||
-------------------------
|
||||
You can find compiled builds of gettext in the lib folder under "binaries\gettext\" for both windows and win64.
|
||||
In order to run the scripts you will need to replace the location of the GETTEXT_..._EXeCUTABLE.
|
||||
|
||||
For example in update_pot.py:
|
||||
-GETTEXT_XGETTEXT_EXECUTABLE = "xgettext"
|
||||
+GETTEXT_XGETTEXT_EXECUTABLE = "C:\\Blender\\lib\\\windows\\\binaries\\\gettext\\xgettext.exe"
|
||||
|
||||
4. Other scripts
|
||||
----------------
|
||||
|
||||
- check_po.py: this script checks if all messages declared in blender.pot exists in.po files
|
||||
and that no extra messages are declared in .po files
|
||||
- clean_po.py: this script removes all commented messages which aren't required by .pot file anymore.
|
||||
- merge_po.py: this scripts accepts two files as arguments and copies translations from second file
|
||||
into first file.
|
||||
93
po/check_po.py
Executable file
93
po/check_po.py
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# $Id$
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# update the pot file according the POTFILES.in
|
||||
|
||||
import os
|
||||
import sys
|
||||
from codecs import open
|
||||
|
||||
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
FILE_NAME_POT = os.path.join(CURRENT_DIR, "blender.pot")
|
||||
|
||||
|
||||
def read_messages(fname):
|
||||
def stripeol(s):
|
||||
return s.rstrip("\n\r")
|
||||
|
||||
messages = {}
|
||||
reading_message = False
|
||||
message = ""
|
||||
with open(fname, 'r', "utf-8") as handle:
|
||||
while True:
|
||||
line = handle.readline()
|
||||
|
||||
if not line:
|
||||
break
|
||||
|
||||
line = stripeol(line)
|
||||
if line.startswith("msgid"):
|
||||
reading_message = True
|
||||
message = line[7:-1]
|
||||
elif line.startswith("msgstr"):
|
||||
reading_message = False
|
||||
messages[message] = True
|
||||
elif reading_message:
|
||||
message += line[1:-1]
|
||||
return messages
|
||||
|
||||
|
||||
def main():
|
||||
pot_messages = read_messages(FILE_NAME_POT)
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
for lang in sys.argv[1:]:
|
||||
po = os.path.join(CURRENT_DIR, lang + '.po')
|
||||
|
||||
if os.path.exists(po):
|
||||
po_messages = read_messages(po)
|
||||
for msgid in po_messages:
|
||||
if not pot_messages.get(msgid):
|
||||
print('Unneeded message id \'%s\'' % (msgid))
|
||||
|
||||
for msgid in pot_messages:
|
||||
if not po_messages.get(msgid):
|
||||
print('Missed message id \'%s\'' % (msgid))
|
||||
else:
|
||||
for po in os.listdir(CURRENT_DIR):
|
||||
if po.endswith('.po'):
|
||||
print('Processing %s...' % (po))
|
||||
po_messages = read_messages(po)
|
||||
for msgid in po_messages:
|
||||
if not pot_messages.get(msgid):
|
||||
print(' Unneeded message id \'%s\'' % (msgid))
|
||||
|
||||
for msgid in pot_messages:
|
||||
if not po_messages.get(msgid):
|
||||
print(' Missed message id \'%s\'' % (msgid))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n\n *** Running %r *** \n" % __file__)
|
||||
main()
|
||||
190
po/clean_po.py
Executable file
190
po/clean_po.py
Executable file
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# $Id$
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# update the pot file according the POTFILES.in
|
||||
|
||||
import os
|
||||
import sys
|
||||
import collections
|
||||
|
||||
from codecs import open
|
||||
|
||||
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
FILE_NAME_POT = os.path.join(CURRENT_DIR, "blender.pot")
|
||||
|
||||
|
||||
def read_messages(fname):
|
||||
def stripeol(s):
|
||||
return s.rstrip("\n\r")
|
||||
|
||||
last_message = None
|
||||
|
||||
if hasattr(collections, 'OrderedDict'):
|
||||
messages = collections.OrderedDict()
|
||||
commented_messages = collections.OrderedDict()
|
||||
else:
|
||||
messages = {}
|
||||
commented_messages = {}
|
||||
|
||||
reading_message = False
|
||||
reading_translation = False
|
||||
commented = False
|
||||
message = ""
|
||||
translation = ""
|
||||
message_lines = []
|
||||
translation_lines = []
|
||||
comment_lines = []
|
||||
with open(fname, 'r', "utf-8") as handle:
|
||||
while True:
|
||||
line = handle.readline()
|
||||
|
||||
if not line:
|
||||
break
|
||||
|
||||
line = stripeol(line)
|
||||
if line.startswith("msgid") or line.startswith("#~ msgid"):
|
||||
if reading_translation:
|
||||
last_message['translation'] = translation
|
||||
translation_lines = []
|
||||
|
||||
reading_message = True
|
||||
reading_translation = False
|
||||
|
||||
if line.startswith('#~'):
|
||||
message = line[10:-1]
|
||||
commented = True
|
||||
else:
|
||||
message = line[7:-1]
|
||||
commented = False
|
||||
|
||||
message_lines.append(message)
|
||||
elif line.startswith("msgstr") or line.startswith("#~ msgstr"):
|
||||
reading_message = False
|
||||
reading_translation = True
|
||||
last_message = {'comment_lines': comment_lines,
|
||||
'message_lines': message_lines,
|
||||
'translation_lines': translation_lines}
|
||||
|
||||
if commented:
|
||||
translation = line[11:-1]
|
||||
commented_messages[message] = last_message
|
||||
else:
|
||||
translation = line[8:-1]
|
||||
messages[message] = last_message
|
||||
|
||||
message_lines = []
|
||||
comment_lines = []
|
||||
translation_lines.append(translation)
|
||||
elif not line.startswith('"') and not line.startswith('#~ "'):
|
||||
if reading_translation:
|
||||
last_message['translation'] = translation
|
||||
else:
|
||||
comment_lines.append(line)
|
||||
|
||||
reading_message = False
|
||||
reading_translation = False
|
||||
message_lines = []
|
||||
translation_lines = []
|
||||
elif reading_message:
|
||||
if line.startswith('#~ "'):
|
||||
m = line[4:-1]
|
||||
else:
|
||||
m = line[1:-1]
|
||||
|
||||
message += m
|
||||
message_lines.append(m)
|
||||
elif reading_translation:
|
||||
if line.startswith('#~ "'):
|
||||
t = line[4:-1]
|
||||
else:
|
||||
t = line[1:-1]
|
||||
|
||||
translation += t
|
||||
translation_lines.append(t)
|
||||
|
||||
return (messages, commented_messages)
|
||||
|
||||
|
||||
def do_clean(po, pot_messages):
|
||||
po_messages, commented_messages = read_messages(po)
|
||||
|
||||
for msgid in commented_messages:
|
||||
if pot_messages.get(msgid):
|
||||
t = po_messages.get(msgid)
|
||||
if not t:
|
||||
print("Reusing full item from commented "
|
||||
"lines for msgid '%s'" % msgid)
|
||||
po_messages[msgid] = commented_messages[msgid]
|
||||
elif not t['translation']:
|
||||
print("Reusing translation from commented "
|
||||
"lines for msgid '%s'" % msgid)
|
||||
m = commented_messages[msgid]
|
||||
t['translation'] = m['translation']
|
||||
t['translation_lines'] = m['translation_lines']
|
||||
|
||||
with open(po, 'w', 'utf-8') as handle:
|
||||
for msgid in po_messages:
|
||||
item = po_messages[msgid]
|
||||
|
||||
for x in item['comment_lines']:
|
||||
handle.write(x + "\n")
|
||||
|
||||
first = True
|
||||
for x in item['message_lines']:
|
||||
if first:
|
||||
handle.write("msgid \"%s\"\n" % x)
|
||||
else:
|
||||
handle.write("\"%s\"\n" % x)
|
||||
first = False
|
||||
|
||||
first = True
|
||||
for x in item['translation_lines']:
|
||||
if first:
|
||||
handle.write("msgstr \"%s\"\n" % x)
|
||||
else:
|
||||
handle.write("\"%s\"\n" % x)
|
||||
first = False
|
||||
|
||||
handle.write("\n")
|
||||
|
||||
|
||||
def main():
|
||||
pot_messages, commented_messages = read_messages(FILE_NAME_POT)
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
for lang in sys.argv[1:]:
|
||||
po = os.path.join(CURRENT_DIR, lang + '.po')
|
||||
|
||||
if os.path.exists(po):
|
||||
do_clean(po, pot_messages)
|
||||
else:
|
||||
for po in os.listdir(CURRENT_DIR):
|
||||
if po.endswith('.po'):
|
||||
print('Processing %s...' % (po))
|
||||
do_clean(po, pot_messages)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n\n *** Running %r *** \n" % __file__)
|
||||
main()
|
||||
167
po/merge_po.py
Executable file
167
po/merge_po.py
Executable file
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# $Id$
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# update the pot file according the POTFILES.in
|
||||
|
||||
import sys
|
||||
import collections
|
||||
|
||||
from codecs import open
|
||||
|
||||
|
||||
def read_messages(fname):
|
||||
def stripeol(s):
|
||||
return s.rstrip("\n\r")
|
||||
|
||||
last_message = None
|
||||
|
||||
if hasattr(collections, 'OrderedDict'):
|
||||
messages = collections.OrderedDict()
|
||||
commented_messages = collections.OrderedDict()
|
||||
else:
|
||||
messages = {}
|
||||
commented_messages = {}
|
||||
|
||||
reading_message = False
|
||||
reading_translation = False
|
||||
commented = False
|
||||
message = ""
|
||||
translation = ""
|
||||
message_lines = []
|
||||
translation_lines = []
|
||||
comment_lines = []
|
||||
with open(fname, 'r', "utf-8") as handle:
|
||||
while True:
|
||||
line = handle.readline()
|
||||
|
||||
if not line:
|
||||
break
|
||||
|
||||
line = stripeol(line)
|
||||
if line.startswith("msgid") or line.startswith("#~ msgid"):
|
||||
if reading_translation:
|
||||
last_message['translation'] = translation
|
||||
translation_lines = []
|
||||
|
||||
reading_message = True
|
||||
reading_translation = False
|
||||
|
||||
if line.startswith('#~'):
|
||||
message = line[10:-1]
|
||||
commented = True
|
||||
else:
|
||||
message = line[7:-1]
|
||||
commented = False
|
||||
|
||||
message_lines.append(message)
|
||||
elif line.startswith("msgstr") or line.startswith("#~ msgstr"):
|
||||
reading_message = False
|
||||
reading_translation = True
|
||||
last_message = {'comment_lines': comment_lines,
|
||||
'message_lines': message_lines,
|
||||
'translation_lines': translation_lines}
|
||||
|
||||
if commented:
|
||||
translation = line[11:-1]
|
||||
commented_messages[message] = last_message
|
||||
else:
|
||||
translation = line[8:-1]
|
||||
messages[message] = last_message
|
||||
|
||||
message_lines = []
|
||||
comment_lines = []
|
||||
translation_lines.append(translation)
|
||||
elif not line.startswith('"') and not line.startswith('#~ "'):
|
||||
if reading_translation:
|
||||
last_message['translation'] = translation
|
||||
else:
|
||||
comment_lines.append(line)
|
||||
|
||||
reading_message = False
|
||||
reading_translation = False
|
||||
message_lines = []
|
||||
translation_lines = []
|
||||
elif reading_message:
|
||||
if line.startswith('#~ "'):
|
||||
m = line[4:-1]
|
||||
else:
|
||||
m = line[1:-1]
|
||||
|
||||
message += m
|
||||
message_lines.append(m)
|
||||
elif reading_translation:
|
||||
if line.startswith('#~ "'):
|
||||
t = line[4:-1]
|
||||
else:
|
||||
t = line[1:-1]
|
||||
|
||||
translation += t
|
||||
translation_lines.append(t)
|
||||
|
||||
return (messages, commented_messages)
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) == 3:
|
||||
dst_messages, tmp = read_messages(sys.argv[1])
|
||||
from_messages, tmp = read_messages(sys.argv[2])
|
||||
|
||||
for msgid in dst_messages:
|
||||
msg = dst_messages.get(msgid)
|
||||
from_msg = from_messages.get(msgid)
|
||||
|
||||
if from_msg and from_msg['translation']:
|
||||
msg['translation'] = from_msg['translation']
|
||||
msg['translation_lines'] = from_msg['translation_lines']
|
||||
|
||||
with open(sys.argv[1], 'w', 'utf-8') as handle:
|
||||
for msgid in dst_messages:
|
||||
item = dst_messages[msgid]
|
||||
|
||||
for x in item['comment_lines']:
|
||||
handle.write(x + "\n")
|
||||
|
||||
first = True
|
||||
for x in item['message_lines']:
|
||||
if first:
|
||||
handle.write("msgid \"%s\"\n" % x)
|
||||
else:
|
||||
handle.write("\"%s\"\n" % x)
|
||||
first = False
|
||||
|
||||
first = True
|
||||
for x in item['translation_lines']:
|
||||
if first:
|
||||
handle.write("msgstr \"%s\"\n" % x)
|
||||
else:
|
||||
handle.write("\"%s\"\n" % x)
|
||||
first = False
|
||||
|
||||
handle.write("\n")
|
||||
else:
|
||||
print('Usage: %s <destination-po> <source-po>' % (sys.argv[0]))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n\n *** Running %r *** \n" % __file__)
|
||||
main()
|
||||
5433
po/messages.txt
5433
po/messages.txt
File diff suppressed because it is too large
Load Diff
@@ -25,20 +25,21 @@
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
|
||||
CURRENT_DIR = os.path.dirname(__file__)
|
||||
GETTEXT_MSGFMT_EXECUTABLE = "msgfmt"
|
||||
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.join(CURRENT_DIR, "..")))
|
||||
LOCALE_DIR = os.path.join(SOURCE_DIR, "release", "bin", ".blender", "locale")
|
||||
|
||||
DOMAIN = "blender"
|
||||
|
||||
|
||||
def main():
|
||||
for po in os.listdir(CURRENT_DIR):
|
||||
if po.endswith(".po"):
|
||||
lang = po[:-3]
|
||||
def process_po(po):
|
||||
lang = os.path.basename(po)[:-3]
|
||||
|
||||
# show stats
|
||||
cmd = ("msgfmt",
|
||||
cmd = (GETTEXT_MSGFMT_EXECUTABLE,
|
||||
"--statistics",
|
||||
os.path.join(CURRENT_DIR, "%s.po" % lang),
|
||||
"-o",
|
||||
@@ -49,6 +50,19 @@ def main():
|
||||
process = subprocess.Popen(cmd)
|
||||
process.wait()
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) > 1:
|
||||
for lang in sys.argv[1:]:
|
||||
po = os.path.join(CURRENT_DIR, lang + '.po')
|
||||
|
||||
if os.path.exists(po):
|
||||
process_po(po)
|
||||
else:
|
||||
for po in os.listdir(CURRENT_DIR):
|
||||
if po.endswith(".po"):
|
||||
process_po(po)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n\n *** Running %r *** \n" % __file__)
|
||||
main()
|
||||
|
||||
249
po/update_msg.py
249
po/update_msg.py
@@ -17,7 +17,7 @@
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
# <pep8 compliant>
|
||||
# <pep8-80 compliant>
|
||||
|
||||
# Write out messages.txt from blender
|
||||
|
||||
@@ -26,67 +26,190 @@
|
||||
|
||||
import os
|
||||
|
||||
CURRENT_DIR = os.path.dirname(__file__)
|
||||
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.join(CURRENT_DIR, "..")))
|
||||
|
||||
FILE_NAME_MESSAGES = os.path.join(CURRENT_DIR, "messages.txt")
|
||||
COMMENT_PREFIX = "#~ "
|
||||
|
||||
|
||||
def dump_messages_rna(messages):
|
||||
import bpy
|
||||
|
||||
def classBlackList():
|
||||
blacklist_rna_class = [
|
||||
# core classes
|
||||
"Context", "Event", "Function", "UILayout",
|
||||
"BlendData",
|
||||
# registerable classes
|
||||
"Panel", "Menu", "Header", "RenderEngine",
|
||||
"Operator", "OperatorMacro", "Macro",
|
||||
"KeyingSetInfo", "UnknownType",
|
||||
# window classes
|
||||
"WindowManager", "Window"
|
||||
]
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Collect internal operators
|
||||
|
||||
# extend with all internal operators
|
||||
# note that this uses internal api introspection functions
|
||||
# all possible operator names
|
||||
op_names = list(sorted(set(
|
||||
[cls.bl_rna.identifier for cls in
|
||||
bpy.types.OperatorProperties.__subclasses__()] +
|
||||
[cls.bl_rna.identifier for cls in
|
||||
bpy.types.Operator.__subclasses__()] +
|
||||
[cls.bl_rna.identifier for cls in
|
||||
bpy.types.OperatorMacro.__subclasses__()]
|
||||
)))
|
||||
|
||||
get_inatance = __import__("_bpy").ops.get_instance
|
||||
path_resolve = type(bpy.context).__base__.path_resolve
|
||||
for idname in op_names:
|
||||
op = get_inatance(idname)
|
||||
if 'INTERNAL' in path_resolve(op, "bl_options"):
|
||||
blacklist_rna_class.append(idname)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Collect builtin classes we dont need to doc
|
||||
blacklist_rna_class.append("Property")
|
||||
blacklist_rna_class.extend(
|
||||
[cls.__name__ for cls in
|
||||
bpy.types.Property.__subclasses__()])
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Collect classes which are attached to collections, these are api
|
||||
# access only.
|
||||
collection_props = set()
|
||||
for cls_id in dir(bpy.types):
|
||||
cls = getattr(bpy.types, cls_id)
|
||||
for prop in cls.bl_rna.properties:
|
||||
if prop.type == 'COLLECTION':
|
||||
prop_cls = prop.srna
|
||||
if prop_cls is not None:
|
||||
collection_props.add(prop_cls.identifier)
|
||||
blacklist_rna_class.extend(sorted(collection_props))
|
||||
|
||||
return blacklist_rna_class
|
||||
|
||||
blacklist_rna_class = classBlackList()
|
||||
|
||||
def filterRNA(bl_rna):
|
||||
id = bl_rna.identifier
|
||||
if id in blacklist_rna_class:
|
||||
print(" skipping", id)
|
||||
return True
|
||||
return False
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Function definitions
|
||||
|
||||
def walkProperties(properties):
|
||||
def walkProperties(bl_rna):
|
||||
import bpy
|
||||
for prop in properties:
|
||||
messages.add(prop.name)
|
||||
messages.add(prop.description)
|
||||
|
||||
# get our parents properties not to export them multiple times
|
||||
bl_rna_base = bl_rna.base
|
||||
if bl_rna_base:
|
||||
bl_rna_base_props = bl_rna_base.properties.values()
|
||||
else:
|
||||
bl_rna_base_props = ()
|
||||
|
||||
for prop in bl_rna.properties:
|
||||
# only write this property is our parent hasn't got it.
|
||||
if prop in bl_rna_base_props:
|
||||
continue
|
||||
if prop.identifier == "rna_type":
|
||||
continue
|
||||
|
||||
msgsrc = "bpy.types.%s.%s" % (bl_rna.identifier, prop.identifier)
|
||||
if prop.name and prop.name != prop.identifier:
|
||||
messages.setdefault(prop.name, []).append(msgsrc)
|
||||
if prop.description:
|
||||
messages.setdefault(prop.description, []).append(msgsrc)
|
||||
|
||||
if isinstance(prop, bpy.types.EnumProperty):
|
||||
for item in prop.enum_items:
|
||||
messages.add(item.name)
|
||||
messages.add(item.description)
|
||||
msgsrc = "bpy.types.%s.%s, '%s'" % (bl_rna.identifier,
|
||||
prop.identifier,
|
||||
item.identifier,
|
||||
)
|
||||
# Here identifier and name can be the same!
|
||||
if item.name: # and item.name != item.identifier:
|
||||
messages.setdefault(item.name, []).append(msgsrc)
|
||||
if item.description:
|
||||
messages.setdefault(item.description, []).append(msgsrc)
|
||||
|
||||
def walkRNA(bl_rna):
|
||||
|
||||
if filterRNA(bl_rna):
|
||||
return
|
||||
|
||||
msgsrc = "bpy.types.%s" % bl_rna.identifier
|
||||
|
||||
if bl_rna.name and bl_rna.name != bl_rna.identifier:
|
||||
messages.add(bl_rna.name)
|
||||
messages.setdefault(bl_rna.name, []).append(msgsrc)
|
||||
|
||||
if bl_rna.description:
|
||||
messages.add(bl_rna.description)
|
||||
messages.setdefault(bl_rna.description, []).append(msgsrc)
|
||||
|
||||
walkProperties(bl_rna.properties)
|
||||
if hasattr(bl_rna, 'bl_label') and bl_rna.bl_label:
|
||||
messages.setdefault(bl_rna.bl_label, []).append(msgsrc)
|
||||
|
||||
walkProperties(bl_rna)
|
||||
|
||||
def walkClass(cls):
|
||||
walkRNA(cls.bl_rna)
|
||||
|
||||
def walk_keymap_hierarchy(hier):
|
||||
def walk_keymap_hierarchy(hier, msgsrc_prev):
|
||||
for lvl in hier:
|
||||
messages.add(lvl[0])
|
||||
msgsrc = "%s.%s" % (msgsrc_prev, lvl[1])
|
||||
messages.setdefault(lvl[0], []).append(msgsrc)
|
||||
|
||||
if lvl[3]:
|
||||
walk_keymap_hierarchy(lvl[3])
|
||||
walk_keymap_hierarchy(lvl[3], msgsrc)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Dump Messages
|
||||
|
||||
for cls in type(bpy.context).__base__.__subclasses__():
|
||||
def full_class_id(cls):
|
||||
""" gives us 'ID.Lamp.AreaLamp' which is best for sorting.
|
||||
"""
|
||||
cls_id = ""
|
||||
bl_rna = cls.bl_rna
|
||||
while bl_rna:
|
||||
cls_id = "%s.%s" % (bl_rna.identifier, cls_id)
|
||||
bl_rna = bl_rna.base
|
||||
return cls_id
|
||||
|
||||
cls_list = type(bpy.context).__base__.__subclasses__()
|
||||
cls_list.sort(key=full_class_id)
|
||||
for cls in cls_list:
|
||||
walkClass(cls)
|
||||
|
||||
for cls in bpy.types.Space.__subclasses__():
|
||||
cls_list = bpy.types.Space.__subclasses__()
|
||||
cls_list.sort(key=full_class_id)
|
||||
for cls in cls_list:
|
||||
walkClass(cls)
|
||||
|
||||
for cls in bpy.types.Operator.__subclasses__():
|
||||
cls_list = bpy.types.Operator.__subclasses__()
|
||||
cls_list.sort(key=full_class_id)
|
||||
for cls in cls_list:
|
||||
walkClass(cls)
|
||||
|
||||
from bl_ui.space_userpref_keymap import KM_HIERARCHY
|
||||
cls_list = bpy.types.OperatorProperties.__subclasses__()
|
||||
cls_list.sort(key=full_class_id)
|
||||
for cls in cls_list:
|
||||
walkClass(cls)
|
||||
|
||||
walk_keymap_hierarchy(KM_HIERARCHY)
|
||||
cls_list = bpy.types.Menu.__subclasses__()
|
||||
cls_list.sort(key=full_class_id)
|
||||
for cls in cls_list:
|
||||
walkClass(cls)
|
||||
|
||||
from bpy_extras.keyconfig_utils import KM_HIERARCHY
|
||||
|
||||
## XXX. what is this supposed to do, we wrote the file already???
|
||||
#_walkClass(bpy.types.SpaceDopeSheetEditor)
|
||||
walk_keymap_hierarchy(KM_HIERARCHY, "KM_HIERARCHY")
|
||||
|
||||
|
||||
def dump_messages_pytext(messages):
|
||||
@@ -121,26 +244,30 @@ def dump_messages_pytext(messages):
|
||||
# -------------------------------------------------------------------------
|
||||
# Function definitions
|
||||
|
||||
def extract_strings(fp, node_container):
|
||||
def extract_strings(fp_rel, node_container):
|
||||
""" Recursively get strings, needed incase we have "Blah" + "Blah",
|
||||
passed as an argument in that case it wont evaluate to a string.
|
||||
"""
|
||||
|
||||
for node in ast.walk(node_container):
|
||||
if type(node) == ast.Str:
|
||||
eval_str = ast.literal_eval(node)
|
||||
if eval_str:
|
||||
# print("%s:%d: %s" % (fp, node.lineno, eval_str)) # testing
|
||||
messages.add(eval_str)
|
||||
# print("%s:%d: %s" % (fp, node.lineno, eval_str))
|
||||
msgsrc = "%s:%s" % (fp_rel, node.lineno)
|
||||
messages.setdefault(eval_str, []).append(msgsrc)
|
||||
|
||||
def extract_strings_from_file(fn):
|
||||
filedata = open(fn, 'r', encoding="utf8")
|
||||
root_node = ast.parse(filedata.read(), fn, 'exec')
|
||||
def extract_strings_from_file(fp):
|
||||
filedata = open(fp, 'r', encoding="utf8")
|
||||
root_node = ast.parse(filedata.read(), fp, 'exec')
|
||||
filedata.close()
|
||||
|
||||
fp_rel = os.path.relpath(fp, SOURCE_DIR)
|
||||
|
||||
for node in ast.walk(root_node):
|
||||
if type(node) == ast.Call:
|
||||
# print("found function at")
|
||||
# print("%s:%d" % (fn, node.lineno))
|
||||
# print("%s:%d" % (fp, node.lineno))
|
||||
|
||||
# lambda's
|
||||
if type(node.func) == ast.Name:
|
||||
@@ -155,29 +282,60 @@ def dump_messages_pytext(messages):
|
||||
# do nothing if not found
|
||||
for arg_kw, arg_pos in translate_args:
|
||||
if arg_pos < len(node.args):
|
||||
extract_strings(fn, node.args[arg_pos])
|
||||
extract_strings(fp_rel, node.args[arg_pos])
|
||||
else:
|
||||
for kw in node.keywords:
|
||||
if kw.arg == arg_kw:
|
||||
extract_strings(fn, kw.value)
|
||||
extract_strings(fp_rel, kw.value)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Dump Messages
|
||||
|
||||
mod_dir = os.path.join(SOURCE_DIR, "release", "scripts", "startup", "bl_ui")
|
||||
mod_dir = os.path.join(SOURCE_DIR,
|
||||
"release",
|
||||
"scripts",
|
||||
"startup",
|
||||
"bl_ui")
|
||||
|
||||
files = [os.path.join(mod_dir, f)
|
||||
for f in os.listdir(mod_dir)
|
||||
if not f.startswith("_")
|
||||
if f.endswith("py")
|
||||
files = [os.path.join(mod_dir, fn)
|
||||
for fn in sorted(os.listdir(mod_dir))
|
||||
if not fn.startswith("_")
|
||||
if fn.endswith("py")
|
||||
]
|
||||
|
||||
for fn in files:
|
||||
extract_strings_from_file(fn)
|
||||
for fp in files:
|
||||
extract_strings_from_file(fp)
|
||||
|
||||
|
||||
def dump_messages():
|
||||
messages = {""}
|
||||
|
||||
def filter_message(msg):
|
||||
|
||||
# check for strings like ": %d"
|
||||
msg_test = msg
|
||||
for ignore in ("%d", "%s", "%r", # string formatting
|
||||
"*", ".", "(", ")", "-", "/", "\\", "+", ":", "#", "%"
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"x", # used on its own eg: 100x200
|
||||
"X", "Y", "Z", # used alone. no need to include
|
||||
):
|
||||
msg_test = msg_test.replace(ignore, "")
|
||||
msg_test = msg_test.strip()
|
||||
if not msg_test:
|
||||
# print("Skipping: '%s'" % msg)
|
||||
return True
|
||||
|
||||
# we could filter out different strings here
|
||||
|
||||
return False
|
||||
|
||||
if 1:
|
||||
import collections
|
||||
messages = collections.OrderedDict()
|
||||
else:
|
||||
messages = {}
|
||||
|
||||
messages[""] = []
|
||||
|
||||
# get strings from RNA
|
||||
dump_messages_rna(messages)
|
||||
@@ -185,10 +343,21 @@ def dump_messages():
|
||||
# get strings from UI layout definitions text="..." args
|
||||
dump_messages_pytext(messages)
|
||||
|
||||
messages.remove("")
|
||||
del messages[""]
|
||||
|
||||
message_file = open(FILE_NAME_MESSAGES, 'w', encoding="utf8")
|
||||
message_file.writelines("\n".join(sorted(messages)))
|
||||
# message_file.writelines("\n".join(sorted(messages)))
|
||||
|
||||
for key, value in messages.items():
|
||||
|
||||
# filter out junk values
|
||||
if filter_message(key):
|
||||
continue
|
||||
|
||||
for msgsrc in value:
|
||||
message_file.write("%s%s\n" % (COMMENT_PREFIX, msgsrc))
|
||||
message_file.write("%s\n" % key)
|
||||
|
||||
message_file.close()
|
||||
|
||||
print("Written %d messages to: %r" % (len(messages), FILE_NAME_MESSAGES))
|
||||
|
||||
@@ -25,19 +25,20 @@
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
|
||||
CURRENT_DIR = os.path.dirname(__file__)
|
||||
GETTEXT_MSGMERGE_EXECUTABLE = "msgmerge"
|
||||
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
DOMAIN = "blender"
|
||||
|
||||
|
||||
def main():
|
||||
for po in os.listdir(CURRENT_DIR):
|
||||
if po.endswith(".po"):
|
||||
lang = po[:-3]
|
||||
def process_po(po):
|
||||
lang = os.path.basename(po)[:-3]
|
||||
|
||||
# update po file
|
||||
cmd = ("msgmerge",
|
||||
cmd = (GETTEXT_MSGMERGE_EXECUTABLE,
|
||||
"--update",
|
||||
"--backup=none",
|
||||
"--lang=%s" % lang,
|
||||
os.path.join(CURRENT_DIR, "%s.po" % lang),
|
||||
os.path.join(CURRENT_DIR, "%s.pot" % DOMAIN),
|
||||
@@ -48,6 +49,19 @@ def main():
|
||||
process.wait()
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) > 1:
|
||||
for lang in sys.argv[1:]:
|
||||
po = os.path.join(CURRENT_DIR, lang + '.po')
|
||||
|
||||
if os.path.exists(po):
|
||||
process_po(po)
|
||||
else:
|
||||
for po in os.listdir(CURRENT_DIR):
|
||||
if po.endswith(".po"):
|
||||
process_po(po)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("\n\n *** Running %r *** \n" % __file__)
|
||||
main()
|
||||
|
||||
@@ -25,11 +25,13 @@
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
from codecs import open
|
||||
|
||||
GETTEXT_XGETTEXT_EXECUTABLE = "xgettext"
|
||||
CURRENT_DIR = os.path.dirname(__file__)
|
||||
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.join(CURRENT_DIR, "..")))
|
||||
DOMAIN = "blender"
|
||||
COMMENT_PREFIX = "#~ " # from update_msg.py
|
||||
|
||||
FILE_NAME_POT = os.path.join(CURRENT_DIR, "blender.pot")
|
||||
FILE_NAME_MESSAGES = os.path.join(CURRENT_DIR, "messages.txt")
|
||||
@@ -55,7 +57,7 @@ def main():
|
||||
pot_messages = {}
|
||||
reading_message = False
|
||||
message = ""
|
||||
with open(FILE_NAME_POT, 'r') as handle:
|
||||
with open(FILE_NAME_POT, 'r', "utf-8") as handle:
|
||||
while True:
|
||||
line = handle.readline()
|
||||
|
||||
@@ -73,8 +75,9 @@ def main():
|
||||
message += line[1:-1]
|
||||
|
||||
# add messages collected automatically from RNA
|
||||
with open(FILE_NAME_POT, "a") as pot_handle:
|
||||
with open(FILE_NAME_MESSAGES, 'r') as handle:
|
||||
with open(FILE_NAME_POT, "a", "utf-8") as pot_handle:
|
||||
with open(FILE_NAME_MESSAGES, 'r', "utf-8") as handle:
|
||||
msgsrc_ls = []
|
||||
while True:
|
||||
line = handle.readline()
|
||||
|
||||
@@ -82,13 +85,21 @@ def main():
|
||||
break
|
||||
|
||||
line = stripeol(line)
|
||||
|
||||
# COMMENT_PREFIX
|
||||
if line.startswith(COMMENT_PREFIX):
|
||||
msgsrc_ls.append(line[len(COMMENT_PREFIX):].strip())
|
||||
else:
|
||||
line = line.replace("\\", "\\\\")
|
||||
line = line.replace("\"", "\\\"")
|
||||
line = line.replace("\t", "\\t")
|
||||
|
||||
if not pot_messages.get(line):
|
||||
pot_handle.write("\n#: Automatically collected from RNA\n")
|
||||
pot_handle.write("msgid \"%s\"\n" % (line))
|
||||
pot_handle.write("msgstr \"\"\n")
|
||||
for msgsrc in msgsrc_ls:
|
||||
pot_handle.write("#: %s\n" % msgsrc)
|
||||
pot_handle.write("msgid \"%s\"\n" % line)
|
||||
pot_handle.write("msgstr \"\"\n\n")
|
||||
msgsrc_ls[:] = []
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
English:en_US
|
||||
Japanese:ja_JP
|
||||
Dutch:nl_NL
|
||||
Italian:it_IT
|
||||
German:de_DE
|
||||
Finnish:fi_FI
|
||||
Swedish:sv_SE
|
||||
French:fr_FR
|
||||
Spanish:es_ES
|
||||
Catalan:ca_ES
|
||||
Czech:cs_CZ
|
||||
Brazilian Portuguese:pt_BR
|
||||
Simplified Chinese:zh_CN
|
||||
Traditional Chinese:zh_TW
|
||||
Russian:ru_RU
|
||||
Croatian:hr_HR
|
||||
Serbian:sr_RS
|
||||
Ukrainian:uk_UA
|
||||
Polish:pl_PL
|
||||
Romanian:ro_RO
|
||||
Arabic:ar_SA
|
||||
Bulgarian:bg_BG
|
||||
Greek:el_GR
|
||||
Korean:ko_KR
|
||||
Binary file not shown.
@@ -27,6 +27,7 @@ op_poll = ops_module.poll
|
||||
op_call = ops_module.call
|
||||
op_as_string = ops_module.as_string
|
||||
op_get_rna = ops_module.get_rna
|
||||
op_get_instance = ops_module.get_instance
|
||||
|
||||
|
||||
class BPyOps(object):
|
||||
@@ -184,11 +185,13 @@ class BPyOpsSubModOp(object):
|
||||
return ret
|
||||
|
||||
def get_rna(self):
|
||||
'''
|
||||
currently only used for 'bl_rna'
|
||||
'''
|
||||
"""Internal function for introspection"""
|
||||
return op_get_rna(self.idname())
|
||||
|
||||
def get_instance(self):
|
||||
"""Internal function for introspection"""
|
||||
return op_get_instance(self.idname())
|
||||
|
||||
def __repr__(self): # useful display, repr(op)
|
||||
import bpy
|
||||
idname = self.idname()
|
||||
|
||||
@@ -27,6 +27,7 @@ __all__ = (
|
||||
"object_utils",
|
||||
"io_utils",
|
||||
"image_utils",
|
||||
"keyconfig_utils",
|
||||
"mesh_utils",
|
||||
"view3d_utils",
|
||||
)
|
||||
|
||||
@@ -115,7 +115,6 @@ def bake_action(frame_start,
|
||||
|
||||
return info
|
||||
|
||||
|
||||
def obj_frame_info(obj):
|
||||
info = {}
|
||||
# parent = obj.parent
|
||||
@@ -183,7 +182,8 @@ def bake_action(frame_start,
|
||||
pbone.constraints.remove(pbone.constraints[0])
|
||||
|
||||
for f in frame_range:
|
||||
matrix = pose_info[(f - frame_start) // frame_step][name]["matrix_key"]
|
||||
f_step = (f - frame_start) // frame_step
|
||||
matrix = pose_info[f_step][name]["matrix_key"]
|
||||
|
||||
# pbone.location = matrix.to_translation()
|
||||
# pbone.rotation_quaternion = matrix.to_quaternion()
|
||||
|
||||
305
release/scripts/modules/bpy_extras/keyconfig_utils.py
Normal file
305
release/scripts/modules/bpy_extras/keyconfig_utils.py
Normal file
@@ -0,0 +1,305 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
KM_HIERARCHY = [
|
||||
('Window', 'EMPTY', 'WINDOW', []), # file save, window change, exit
|
||||
('Screen', 'EMPTY', 'WINDOW', [ # full screen, undo, screenshot
|
||||
('Screen Editing', 'EMPTY', 'WINDOW', []), # resizing, action corners
|
||||
]),
|
||||
|
||||
('View2D', 'EMPTY', 'WINDOW', []), # view 2d navigation (per region)
|
||||
('View2D Buttons List', 'EMPTY', 'WINDOW', []), # view 2d with buttons navigation
|
||||
('Header', 'EMPTY', 'WINDOW', []), # header stuff (per region)
|
||||
('Grease Pencil', 'EMPTY', 'WINDOW', []), # grease pencil stuff (per region)
|
||||
|
||||
('3D View', 'VIEW_3D', 'WINDOW', [ # view 3d navigation and generic stuff (select, transform)
|
||||
('Object Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Mesh', 'EMPTY', 'WINDOW', []),
|
||||
('Curve', 'EMPTY', 'WINDOW', []),
|
||||
('Armature', 'EMPTY', 'WINDOW', []),
|
||||
('Metaball', 'EMPTY', 'WINDOW', []),
|
||||
('Lattice', 'EMPTY', 'WINDOW', []),
|
||||
('Font', 'EMPTY', 'WINDOW', []),
|
||||
|
||||
('Pose', 'EMPTY', 'WINDOW', []),
|
||||
|
||||
('Vertex Paint', 'EMPTY', 'WINDOW', []),
|
||||
('Weight Paint', 'EMPTY', 'WINDOW', []),
|
||||
('Face Mask', 'EMPTY', 'WINDOW', []),
|
||||
('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
|
||||
('Sculpt', 'EMPTY', 'WINDOW', []),
|
||||
|
||||
('Armature Sketch', 'EMPTY', 'WINDOW', []),
|
||||
('Particle', 'EMPTY', 'WINDOW', []),
|
||||
|
||||
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
|
||||
|
||||
('3D View Generic', 'VIEW_3D', 'WINDOW', []) # toolbar and properties
|
||||
]),
|
||||
|
||||
('Frames', 'EMPTY', 'WINDOW', []), # frame navigation (per region)
|
||||
('Markers', 'EMPTY', 'WINDOW', []), # markers (per region)
|
||||
('Animation', 'EMPTY', 'WINDOW', []), # frame change on click, preview range (per region)
|
||||
('Animation Channels', 'EMPTY', 'WINDOW', []),
|
||||
('Graph Editor', 'GRAPH_EDITOR', 'WINDOW', [
|
||||
('Graph Editor Generic', 'GRAPH_EDITOR', 'WINDOW', [])
|
||||
]),
|
||||
('Dopesheet', 'DOPESHEET_EDITOR', 'WINDOW', []),
|
||||
('NLA Editor', 'NLA_EDITOR', 'WINDOW', [
|
||||
('NLA Channels', 'NLA_EDITOR', 'WINDOW', []),
|
||||
('NLA Generic', 'NLA_EDITOR', 'WINDOW', [])
|
||||
]),
|
||||
|
||||
('Image', 'IMAGE_EDITOR', 'WINDOW', [
|
||||
('UV Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image
|
||||
('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
|
||||
('Image Generic', 'IMAGE_EDITOR', 'WINDOW', [])
|
||||
]),
|
||||
|
||||
('Timeline', 'TIMELINE', 'WINDOW', []),
|
||||
('Outliner', 'OUTLINER', 'WINDOW', []),
|
||||
|
||||
('Node Editor', 'NODE_EDITOR', 'WINDOW', [
|
||||
('Node Generic', 'NODE_EDITOR', 'WINDOW', [])
|
||||
]),
|
||||
('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', []),
|
||||
('Logic Editor', 'LOGIC_EDITOR', 'WINDOW', []),
|
||||
|
||||
('File Browser', 'FILE_BROWSER', 'WINDOW', [
|
||||
('File Browser Main', 'FILE_BROWSER', 'WINDOW', []),
|
||||
('File Browser Buttons', 'FILE_BROWSER', 'WINDOW', [])
|
||||
]),
|
||||
|
||||
('Property Editor', 'PROPERTIES', 'WINDOW', []), # align context menu
|
||||
|
||||
('Script', 'SCRIPTS_WINDOW', 'WINDOW', []),
|
||||
('Text', 'TEXT_EDITOR', 'WINDOW', []),
|
||||
('Console', 'CONSOLE', 'WINDOW', []),
|
||||
|
||||
('View3D Gesture Circle', 'EMPTY', 'WINDOW', []),
|
||||
('Gesture Border', 'EMPTY', 'WINDOW', []),
|
||||
('Standard Modal Map', 'EMPTY', 'WINDOW', []),
|
||||
('Transform Modal Map', 'EMPTY', 'WINDOW', []),
|
||||
('View3D Fly Modal', 'EMPTY', 'WINDOW', []),
|
||||
('View3D Rotate Modal', 'EMPTY', 'WINDOW', []),
|
||||
('View3D Move Modal', 'EMPTY', 'WINDOW', []),
|
||||
('View3D Zoom Modal', 'EMPTY', 'WINDOW', []),
|
||||
]
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Utility functions
|
||||
|
||||
def km_exists_in(km, export_keymaps):
|
||||
for km2, kc in export_keymaps:
|
||||
if km2.name == km.name:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def keyconfig_merge(kc1, kc2):
|
||||
""" note: kc1 takes priority over kc2
|
||||
"""
|
||||
merged_keymaps = [(km, kc1) for km in kc1.keymaps]
|
||||
if kc1 != kc2:
|
||||
merged_keymaps.extend((km, kc2) for km in kc2.keymaps if not km_exists_in(km, merged_keymaps))
|
||||
|
||||
return merged_keymaps
|
||||
|
||||
|
||||
def _export_properties(prefix, properties, lines=None):
|
||||
from bpy.types import OperatorProperties
|
||||
|
||||
if lines is None:
|
||||
lines = []
|
||||
|
||||
def string_value(value):
|
||||
if isinstance(value, str) or isinstance(value, bool) or isinstance(value, float) or isinstance(value, int):
|
||||
result = repr(value)
|
||||
elif getattr(value, '__len__', False):
|
||||
return repr(list(value))
|
||||
else:
|
||||
print("Export key configuration: can't write ", value)
|
||||
|
||||
return result
|
||||
|
||||
for pname in properties.bl_rna.properties.keys():
|
||||
if pname != "rna_type" and not properties.is_property_hidden(pname):
|
||||
value = getattr(properties, pname)
|
||||
if isinstance(value, OperatorProperties):
|
||||
_export_properties(prefix + "." + pname, value, lines)
|
||||
elif properties.is_property_set(pname):
|
||||
value = string_value(value)
|
||||
if value != "":
|
||||
lines.append("%s.%s = %s\n" % (prefix, pname, value))
|
||||
return lines
|
||||
|
||||
|
||||
def keyconfig_export(wm, kc, filepath):
|
||||
|
||||
f = open(filepath, "w")
|
||||
|
||||
f.write("import bpy\n")
|
||||
f.write("import os\n\n")
|
||||
f.write("wm = bpy.context.window_manager\n")
|
||||
f.write("kc = wm.keyconfigs.new(os.path.splitext(os.path.basename(__file__))[0])\n\n") # keymap must be created by caller
|
||||
|
||||
# Generate a list of keymaps to export:
|
||||
#
|
||||
# First add all user_modified keymaps (found in keyconfigs.user.keymaps list),
|
||||
# then add all remaining keymaps from the currently active custom keyconfig.
|
||||
#
|
||||
# This will create a final list of keymaps that can be used as a 'diff' against
|
||||
# the default blender keyconfig, recreating the current setup from a fresh blender
|
||||
# without needing to export keymaps which haven't been edited.
|
||||
|
||||
class FakeKeyConfig():
|
||||
keymaps = []
|
||||
edited_kc = FakeKeyConfig()
|
||||
for km in wm.keyconfigs.user.keymaps:
|
||||
if km.is_user_modified:
|
||||
edited_kc.keymaps.append(km)
|
||||
# merge edited keymaps with non-default keyconfig, if it exists
|
||||
if kc != wm.keyconfigs.default:
|
||||
export_keymaps = keyconfig_merge(edited_kc, kc)
|
||||
else:
|
||||
export_keymaps = keyconfig_merge(edited_kc, edited_kc)
|
||||
|
||||
for km, kc_x in export_keymaps:
|
||||
|
||||
km = km.active()
|
||||
|
||||
f.write("# Map %s\n" % km.name)
|
||||
f.write("km = kc.keymaps.new('%s', space_type='%s', region_type='%s', modal=%s)\n\n" % (km.name, km.space_type, km.region_type, km.is_modal))
|
||||
for kmi in km.keymap_items:
|
||||
if km.is_modal:
|
||||
f.write("kmi = km.keymap_items.new_modal('%s', '%s', '%s'" % (kmi.propvalue, kmi.type, kmi.value))
|
||||
else:
|
||||
f.write("kmi = km.keymap_items.new('%s', '%s', '%s'" % (kmi.idname, kmi.type, kmi.value))
|
||||
if kmi.any:
|
||||
f.write(", any=True")
|
||||
else:
|
||||
if kmi.shift:
|
||||
f.write(", shift=True")
|
||||
if kmi.ctrl:
|
||||
f.write(", ctrl=True")
|
||||
if kmi.alt:
|
||||
f.write(", alt=True")
|
||||
if kmi.oskey:
|
||||
f.write(", oskey=True")
|
||||
if kmi.key_modifier and kmi.key_modifier != 'NONE':
|
||||
f.write(", key_modifier='%s'" % kmi.key_modifier)
|
||||
f.write(")\n")
|
||||
|
||||
props = kmi.properties
|
||||
|
||||
if props is not None:
|
||||
f.write("".join(_export_properties("kmi.properties", props)))
|
||||
|
||||
f.write("\n")
|
||||
|
||||
f.close()
|
||||
|
||||
|
||||
def keyconfig_test(kc):
|
||||
|
||||
def testEntry(kc, entry, src=None, parent=None):
|
||||
result = False
|
||||
|
||||
def kmistr(kmi):
|
||||
if km.is_modal:
|
||||
s = ["kmi = km.keymap_items.new_modal(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)]
|
||||
else:
|
||||
s = ["kmi = km.keymap_items.new(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value)]
|
||||
|
||||
if kmi.any:
|
||||
s.append(", any=True")
|
||||
else:
|
||||
if kmi.shift:
|
||||
s.append(", shift=True")
|
||||
if kmi.ctrl:
|
||||
s.append(", ctrl=True")
|
||||
if kmi.alt:
|
||||
s.append(", alt=True")
|
||||
if kmi.oskey:
|
||||
s.append(", oskey=True")
|
||||
if kmi.key_modifier and kmi.key_modifier != 'NONE':
|
||||
s.append(", key_modifier=\'%s\'" % kmi.key_modifier)
|
||||
|
||||
s.append(")\n")
|
||||
|
||||
props = kmi.properties
|
||||
|
||||
if props is not None:
|
||||
_export_properties("kmi.properties", props, s)
|
||||
|
||||
return "".join(s).strip()
|
||||
|
||||
idname, spaceid, regionid, children = entry
|
||||
|
||||
km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid)
|
||||
|
||||
if km:
|
||||
km = km.active()
|
||||
|
||||
if src:
|
||||
for item in km.keymap_items:
|
||||
if src.compare(item):
|
||||
print("===========")
|
||||
print(parent.name)
|
||||
print(kmistr(src))
|
||||
print(km.name)
|
||||
print(kmistr(item))
|
||||
result = True
|
||||
|
||||
for child in children:
|
||||
if testEntry(kc, child, src, parent):
|
||||
result = True
|
||||
else:
|
||||
for i in range(len(km.keymap_items)):
|
||||
src = km.keymap_items[i]
|
||||
|
||||
for child in children:
|
||||
if testEntry(kc, child, src, km):
|
||||
result = True
|
||||
|
||||
for j in range(len(km.keymap_items) - i - 1):
|
||||
item = km.keymap_items[j + i + 1]
|
||||
if src.compare(item):
|
||||
print("===========")
|
||||
print(km.name)
|
||||
print(kmistr(src))
|
||||
print(kmistr(item))
|
||||
result = True
|
||||
|
||||
for child in children:
|
||||
if testEntry(kc, child):
|
||||
result = True
|
||||
|
||||
return result
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Function body
|
||||
|
||||
result = False
|
||||
for entry in KM_HIERARCHY:
|
||||
if testEntry(kc, entry):
|
||||
result = True
|
||||
return result
|
||||
@@ -37,12 +37,14 @@ class ConsoleExec(Operator):
|
||||
if execute:
|
||||
return execute(context)
|
||||
else:
|
||||
print("Error: bpy.ops.console.execute_" + sc.language + " - not found")
|
||||
print("Error: bpy.ops.console.execute_%s - not found" %
|
||||
sc.language)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class ConsoleAutocomplete(Operator):
|
||||
'''Evaluate the namespace up until the cursor and give a list of options or complete the name if there is only one'''
|
||||
"""Evaluate the namespace up until the cursor and give a list of """ \
|
||||
"""options or complete the name if there is only one"""
|
||||
bl_idname = "console.autocomplete"
|
||||
bl_label = "Console Autocomplete"
|
||||
|
||||
@@ -54,7 +56,8 @@ class ConsoleAutocomplete(Operator):
|
||||
if autocomplete:
|
||||
return autocomplete(context)
|
||||
else:
|
||||
print("Error: bpy.ops.console.autocomplete_" + sc.language + " - not found")
|
||||
print("Error: bpy.ops.console.autocomplete_%s - not found" %
|
||||
sc.language)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@@ -76,7 +79,8 @@ class ConsoleBanner(Operator):
|
||||
if banner:
|
||||
return banner(context)
|
||||
else:
|
||||
print("Error: bpy.ops.console.banner_" + sc.language + " - not found")
|
||||
print("Error: bpy.ops.console.banner_%s - not found" %
|
||||
sc.language)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@@ -103,4 +107,3 @@ class ConsoleLanguage(Operator):
|
||||
remove_duplicates=True)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ def align_objects(align_x,
|
||||
|
||||
for obj, bb_world in objs:
|
||||
|
||||
if bb_quality:
|
||||
if bb_quality and obj.type == 'MESH':
|
||||
GBB = GlobalBB_HQ(obj)
|
||||
else:
|
||||
GBB = GlobalBB_LQ(bb_world)
|
||||
@@ -204,7 +204,7 @@ def align_objects(align_x,
|
||||
matrix_world = obj.matrix_world.copy()
|
||||
bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
|
||||
|
||||
if bb_quality:
|
||||
if bb_quality and obj.type == 'MESH':
|
||||
GBB = GlobalBB_HQ(obj)
|
||||
else:
|
||||
GBB = GlobalBB_LQ(bb_world)
|
||||
|
||||
@@ -462,10 +462,10 @@ class QuickFluid(Operator):
|
||||
|
||||
if self.style == 'INFLOW':
|
||||
mod.settings.type = 'INFLOW'
|
||||
mod.settings.inflow_velocity = self.initial_velocity.copy()
|
||||
mod.settings.inflow_velocity = self.initial_velocity
|
||||
else:
|
||||
mod.settings.type = 'FLUID'
|
||||
mod.settings.initial_velocity = self.initial_velocity.copy()
|
||||
mod.settings.initial_velocity = self.initial_velocity
|
||||
|
||||
obj.hide_render = not self.show_flows
|
||||
if not self.show_flows:
|
||||
|
||||
@@ -136,7 +136,8 @@ class PlayRenderedAnim(Operator):
|
||||
del process
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
opts = ["-a", "-f", str(rd.fps), str(rd.fps_base), file]
|
||||
opts = ["-a", "-f", str(rd.fps), str(rd.fps_base),
|
||||
"-j", str(scene.frame_step), file]
|
||||
cmd.extend(opts)
|
||||
elif preset == 'DJV':
|
||||
opts = [file, "-playback_speed", "%d" % int(rd.fps / rd.fps_base)]
|
||||
@@ -166,9 +167,8 @@ class PlayRenderedAnim(Operator):
|
||||
print("Executing command:\n %r" % " ".join(cmd))
|
||||
|
||||
try:
|
||||
process = subprocess.Popen(cmd)
|
||||
subprocess.Popen(cmd)
|
||||
except Exception as e:
|
||||
import traceback
|
||||
self.report({'ERROR'},
|
||||
"Couldn't run external animation player with command "
|
||||
"%r\n%s" % (" ".join(cmd), str(e)))
|
||||
|
||||
@@ -36,7 +36,10 @@ class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator):
|
||||
# totvert = mesh.total_vert_sel
|
||||
|
||||
if select_mode[2] and totface == 1:
|
||||
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', TRANSFORM_OT_translate={"constraint_orientation": 'NORMAL', "constraint_axis": (False, False, True)})
|
||||
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN',
|
||||
TRANSFORM_OT_translate={
|
||||
"constraint_orientation": 'NORMAL',
|
||||
"constraint_axis": (False, False, True)})
|
||||
elif select_mode[2] and totface > 1:
|
||||
bpy.ops.mesh.extrude_faces_move('INVOKE_REGION_WIN')
|
||||
elif select_mode[1] and totedge >= 1:
|
||||
@@ -44,7 +47,8 @@ class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator):
|
||||
else:
|
||||
bpy.ops.mesh.extrude_vertices_move('INVOKE_REGION_WIN')
|
||||
|
||||
# ignore return from operators above because they are 'RUNNING_MODAL', and cause this one not to be freed. [#24671]
|
||||
# ignore return from operators above because they are 'RUNNING_MODAL',
|
||||
# and cause this one not to be freed. [#24671]
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
@@ -64,13 +68,20 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
|
||||
# totvert = mesh.total_vert_sel
|
||||
|
||||
if totface >= 1:
|
||||
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', TRANSFORM_OT_translate={"constraint_orientation": 'NORMAL', "constraint_axis": (False, False, True)})
|
||||
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN',
|
||||
TRANSFORM_OT_translate={
|
||||
"constraint_orientation": 'NORMAL',
|
||||
"constraint_axis": (False, False, True)})
|
||||
elif totedge == 1:
|
||||
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', TRANSFORM_OT_translate={"constraint_orientation": 'NORMAL', "constraint_axis": (True, True, False)})
|
||||
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN',
|
||||
TRANSFORM_OT_translate={
|
||||
"constraint_orientation": 'NORMAL',
|
||||
"constraint_axis": (True, True, False)})
|
||||
else:
|
||||
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN')
|
||||
|
||||
# ignore return from operators above because they are 'RUNNING_MODAL', and cause this one not to be freed. [#24671]
|
||||
# ignore return from operators above because they are 'RUNNING_MODAL',
|
||||
# and cause this one not to be freed. [#24671]
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
|
||||
@@ -1186,109 +1186,18 @@ class WM_OT_keyconfig_test(Operator):
|
||||
bl_idname = "wm.keyconfig_test"
|
||||
bl_label = "Test Key Configuration for Conflicts"
|
||||
|
||||
def testEntry(self, kc, entry, src=None, parent=None):
|
||||
result = False
|
||||
|
||||
def kmistr(kmi):
|
||||
if km.is_modal:
|
||||
s = ["kmi = km.keymap_items.new_modal(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)]
|
||||
else:
|
||||
s = ["kmi = km.keymap_items.new(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value)]
|
||||
|
||||
if kmi.any:
|
||||
s.append(", any=True")
|
||||
else:
|
||||
if kmi.shift:
|
||||
s.append(", shift=True")
|
||||
if kmi.ctrl:
|
||||
s.append(", ctrl=True")
|
||||
if kmi.alt:
|
||||
s.append(", alt=True")
|
||||
if kmi.oskey:
|
||||
s.append(", oskey=True")
|
||||
if kmi.key_modifier and kmi.key_modifier != 'NONE':
|
||||
s.append(", key_modifier=\'%s\'" % kmi.key_modifier)
|
||||
|
||||
s.append(")\n")
|
||||
|
||||
props = kmi.properties
|
||||
|
||||
if props is not None:
|
||||
export_properties("kmi.properties", props, s)
|
||||
|
||||
return "".join(s).strip()
|
||||
|
||||
idname, spaceid, regionid, children = entry
|
||||
|
||||
km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid)
|
||||
|
||||
if km:
|
||||
km = km.active()
|
||||
|
||||
if src:
|
||||
for item in km.keymap_items:
|
||||
if src.compare(item):
|
||||
print("===========")
|
||||
print(parent.name)
|
||||
print(kmistr(src))
|
||||
print(km.name)
|
||||
print(kmistr(item))
|
||||
result = True
|
||||
|
||||
for child in children:
|
||||
if self.testEntry(kc, child, src, parent):
|
||||
result = True
|
||||
else:
|
||||
for i in range(len(km.keymap_items)):
|
||||
src = km.keymap_items[i]
|
||||
|
||||
for child in children:
|
||||
if self.testEntry(kc, child, src, km):
|
||||
result = True
|
||||
|
||||
for j in range(len(km.keymap_items) - i - 1):
|
||||
item = km.keymap_items[j + i + 1]
|
||||
if src.compare(item):
|
||||
print("===========")
|
||||
print(km.name)
|
||||
print(kmistr(src))
|
||||
print(kmistr(item))
|
||||
result = True
|
||||
|
||||
for child in children:
|
||||
if self.testEntry(kc, child):
|
||||
result = True
|
||||
|
||||
return result
|
||||
|
||||
def testConfig(self, kc):
|
||||
result = False
|
||||
for entry in KM_HIERARCHY:
|
||||
if self.testEntry(kc, entry):
|
||||
result = True
|
||||
return result
|
||||
|
||||
def execute(self, context):
|
||||
from bpy_extras import keyconfig_utils
|
||||
|
||||
wm = context.window_manager
|
||||
kc = wm.keyconfigs.default
|
||||
|
||||
if self.testConfig(kc):
|
||||
if keyconfig_utils.keyconfig_test(kc):
|
||||
print("CONFLICT")
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
def _string_value(value):
|
||||
if isinstance(value, str) or isinstance(value, bool) or isinstance(value, float) or isinstance(value, int):
|
||||
result = repr(value)
|
||||
elif getattr(value, '__len__', False):
|
||||
return repr(list(value))
|
||||
else:
|
||||
print("Export key configuration: can't write ", value)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class WM_OT_keyconfig_import(Operator):
|
||||
"Import key configuration from a python script"
|
||||
bl_idname = "wm.keyconfig_import"
|
||||
@@ -1321,6 +1230,7 @@ class WM_OT_keyconfig_import(Operator):
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
import os
|
||||
from os.path import basename
|
||||
import shutil
|
||||
|
||||
@@ -1382,79 +1292,20 @@ class WM_OT_keyconfig_export(Operator):
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
from bpy_extras import keyconfig_utils
|
||||
|
||||
if not self.filepath:
|
||||
raise Exception("Filepath not set")
|
||||
|
||||
if not self.filepath.endswith('.py'):
|
||||
self.filepath += '.py'
|
||||
|
||||
f = open(self.filepath, "w")
|
||||
if not f:
|
||||
raise Exception("Could not open file")
|
||||
|
||||
wm = context.window_manager
|
||||
kc = wm.keyconfigs.active
|
||||
|
||||
f.write("import bpy\n")
|
||||
f.write("import os\n\n")
|
||||
f.write("wm = bpy.context.window_manager\n")
|
||||
f.write("kc = wm.keyconfigs.new(os.path.splitext(os.path.basename(__file__))[0])\n\n") # keymap must be created by caller
|
||||
|
||||
# Generate a list of keymaps to export:
|
||||
#
|
||||
# First add all user_modified keymaps (found in keyconfigs.user.keymaps list),
|
||||
# then add all remaining keymaps from the currently active custom keyconfig.
|
||||
#
|
||||
# This will create a final list of keymaps that can be used as a 'diff' against
|
||||
# the default blender keyconfig, recreating the current setup from a fresh blender
|
||||
# without needing to export keymaps which haven't been edited.
|
||||
|
||||
class FakeKeyConfig():
|
||||
keymaps = []
|
||||
edited_kc = FakeKeyConfig()
|
||||
for km in wm.keyconfigs.user.keymaps:
|
||||
if km.is_user_modified:
|
||||
edited_kc.keymaps.append(km)
|
||||
# merge edited keymaps with non-default keyconfig, if it exists
|
||||
if kc != wm.keyconfigs.default:
|
||||
export_keymaps = _merge_keymaps(edited_kc, kc)
|
||||
else:
|
||||
export_keymaps = _merge_keymaps(edited_kc, edited_kc)
|
||||
|
||||
for km, kc_x in export_keymaps:
|
||||
|
||||
km = km.active()
|
||||
|
||||
f.write("# Map %s\n" % km.name)
|
||||
f.write("km = kc.keymaps.new('%s', space_type='%s', region_type='%s', modal=%s)\n\n" % (km.name, km.space_type, km.region_type, km.is_modal))
|
||||
for kmi in km.keymap_items:
|
||||
if km.is_modal:
|
||||
f.write("kmi = km.keymap_items.new_modal('%s', '%s', '%s'" % (kmi.propvalue, kmi.type, kmi.value))
|
||||
else:
|
||||
f.write("kmi = km.keymap_items.new('%s', '%s', '%s'" % (kmi.idname, kmi.type, kmi.value))
|
||||
if kmi.any:
|
||||
f.write(", any=True")
|
||||
else:
|
||||
if kmi.shift:
|
||||
f.write(", shift=True")
|
||||
if kmi.ctrl:
|
||||
f.write(", ctrl=True")
|
||||
if kmi.alt:
|
||||
f.write(", alt=True")
|
||||
if kmi.oskey:
|
||||
f.write(", oskey=True")
|
||||
if kmi.key_modifier and kmi.key_modifier != 'NONE':
|
||||
f.write(", key_modifier='%s'" % kmi.key_modifier)
|
||||
f.write(")\n")
|
||||
|
||||
props = kmi.properties
|
||||
|
||||
if props is not None:
|
||||
f.write("".join(export_properties("kmi.properties", props)))
|
||||
|
||||
f.write("\n")
|
||||
|
||||
f.close()
|
||||
keyconfig_utils.keyconfig_export(wm,
|
||||
wm.keyconfigs.active,
|
||||
self.filepath,
|
||||
)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@@ -1683,6 +1534,7 @@ class WM_OT_addon_install(Operator):
|
||||
|
||||
@staticmethod
|
||||
def _module_remove(path_addons, module):
|
||||
import os
|
||||
module = os.path.splitext(module)[0]
|
||||
for f in os.listdir(path_addons):
|
||||
f_base = os.path.splitext(f)[0]
|
||||
@@ -1699,6 +1551,7 @@ class WM_OT_addon_install(Operator):
|
||||
import traceback
|
||||
import zipfile
|
||||
import shutil
|
||||
import os
|
||||
|
||||
pyfile = self.filepath
|
||||
|
||||
@@ -1824,6 +1677,7 @@ class WM_OT_addon_remove(Operator):
|
||||
|
||||
@staticmethod
|
||||
def path_from_addon(module):
|
||||
import os
|
||||
import addon_utils
|
||||
|
||||
for mod in addon_utils.modules(addon_utils.addons_fake_modules):
|
||||
@@ -1838,6 +1692,7 @@ class WM_OT_addon_remove(Operator):
|
||||
|
||||
def execute(self, context):
|
||||
import addon_utils
|
||||
import os
|
||||
|
||||
path, isdir = WM_OT_addon_remove.path_from_addon(self.module)
|
||||
if path is None:
|
||||
|
||||
@@ -72,7 +72,7 @@ class DATA_PT_skeleton(ArmatureButtonsPanel, Panel):
|
||||
flow.prop(arm, "use_deform_preserve_volume", text="Quaternion")
|
||||
|
||||
if context.scene.render.engine == "BLENDER_GAME":
|
||||
layout.row().prop(arm, "vert_deformer", expand=True)
|
||||
layout.row().prop(arm, "deform_method", expand=True)
|
||||
|
||||
|
||||
class DATA_PT_display(ArmatureButtonsPanel, Panel):
|
||||
|
||||
@@ -379,10 +379,6 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
col.label(text="Mirror Object:")
|
||||
col.prop(md, "mirror_object", text="")
|
||||
|
||||
def NAVMESH(self, layout, ob, md):
|
||||
layout.operator("object.assign_navpolygon")
|
||||
layout.operator("object.assign_new_navpolygon")
|
||||
|
||||
def MULTIRES(self, layout, ob, md):
|
||||
layout.row().prop(md, "subdivision_type", expand=True)
|
||||
|
||||
|
||||
@@ -47,8 +47,9 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
|
||||
layout.prop(game, "physics_type")
|
||||
layout.separator()
|
||||
|
||||
#if game.physics_type == 'DYNAMIC':
|
||||
if game.physics_type in {'DYNAMIC', 'RIGID_BODY'}:
|
||||
physics_type = game.physics_type
|
||||
|
||||
if physics_type in {'DYNAMIC', 'RIGID_BODY'}:
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
@@ -108,7 +109,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
|
||||
col.prop(game, "lock_rotation_y", text="Y")
|
||||
col.prop(game, "lock_rotation_z", text="Z")
|
||||
|
||||
elif game.physics_type == 'SOFT_BODY':
|
||||
elif physics_type == 'SOFT_BODY':
|
||||
col = layout.column()
|
||||
col.prop(game, "use_actor")
|
||||
col.prop(game, "use_ghost")
|
||||
@@ -143,7 +144,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
|
||||
sub.active = (soft.use_cluster_rigid_to_softbody or soft.use_cluster_soft_to_softbody)
|
||||
sub.prop(soft, "cluster_iterations", text="Iterations")
|
||||
|
||||
elif game.physics_type == 'STATIC':
|
||||
elif physics_type == 'STATIC':
|
||||
col = layout.column()
|
||||
col.prop(game, "use_actor")
|
||||
col.prop(game, "use_ghost")
|
||||
@@ -164,9 +165,18 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
|
||||
subsub.active = game.use_anisotropic_friction
|
||||
subsub.prop(game, "friction_coefficients", text="", slider=True)
|
||||
|
||||
elif game.physics_type in {'SENSOR', 'INVISIBLE', 'NO_COLLISION', 'OCCLUDE'}:
|
||||
elif physics_type in {'SENSOR', 'INVISIBLE', 'NO_COLLISION', 'OCCLUDE'}:
|
||||
layout.prop(ob, "hide_render", text="Invisible")
|
||||
|
||||
elif physics_type == 'NAVMESH':
|
||||
layout.operator("mesh.navmesh_face_copy")
|
||||
layout.operator("mesh.navmesh_face_add")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("mesh.navmesh_reset")
|
||||
layout.operator("mesh.navmesh_clear")
|
||||
|
||||
|
||||
class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel):
|
||||
bl_label = "Collision Bounds"
|
||||
@@ -204,19 +214,19 @@ class PHYSICS_PT_game_obstacles(PhysicsButtonsPanel, Panel):
|
||||
def poll(cls, context):
|
||||
game = context.object.game
|
||||
rd = context.scene.render
|
||||
return (game.physics_type in ('DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC')) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
return (game.physics_type in {'DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC'}) and (rd.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
def draw_header(self, context):
|
||||
game = context.active_object.game
|
||||
|
||||
self.layout.prop(game, "create_obstacle", text="")
|
||||
self.layout.prop(game, "use_obstacle_create", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
game = context.active_object.game
|
||||
|
||||
layout.active = game.create_obstacle
|
||||
layout.active = game.use_obstacle_create
|
||||
|
||||
row = layout.row()
|
||||
row.prop(game, "obstacle_radius", text="Radius")
|
||||
@@ -412,7 +422,7 @@ class SCENE_PT_game_navmesh(SceneButtonsPanel, bpy.types.Panel):
|
||||
|
||||
rd = context.scene.game_settings.recast_data
|
||||
|
||||
layout.operator("object.create_navmesh", text='Build navigation mesh')
|
||||
layout.operator("mesh.navmesh_make", text='Build navigation mesh')
|
||||
|
||||
col = layout.column()
|
||||
col.label(text="Rasterization:")
|
||||
@@ -429,8 +439,8 @@ class SCENE_PT_game_navmesh(SceneButtonsPanel, bpy.types.Panel):
|
||||
col.prop(rd, "agent_radius", text="Radius")
|
||||
|
||||
col = split.column()
|
||||
col.prop(rd, "max_slope")
|
||||
col.prop(rd, "max_climb")
|
||||
col.prop(rd, "slope_max")
|
||||
col.prop(rd, "climb_max")
|
||||
|
||||
col = layout.column()
|
||||
col.label(text="Region:")
|
||||
|
||||
@@ -625,7 +625,7 @@ class MATERIAL_PT_game_settings(MaterialButtonsPanel, bpy.types.Panel):
|
||||
game = context.material.game_settings # dont use node material
|
||||
|
||||
row = layout.row()
|
||||
row.prop(game, "back_culling")
|
||||
row.prop(game, "use_backface_culling")
|
||||
row.prop(game, "invisible")
|
||||
row.prop(game, "text")
|
||||
|
||||
|
||||
@@ -476,7 +476,12 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
|
||||
col.label(text="Integration:")
|
||||
col.prop(part, "integrator", text="")
|
||||
col.prop(part, "timestep")
|
||||
col.prop(part, "subframes")
|
||||
sub = col.row()
|
||||
if part.adaptive_subframes:
|
||||
sub.prop(part, "courant_target", text="Threshold")
|
||||
else:
|
||||
sub.prop(part, "subframes")
|
||||
sub.prop(part, "adaptive_subframes", text="")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(part, "use_size_deflect")
|
||||
@@ -983,7 +988,7 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, Panel):
|
||||
col.label(text="Color:")
|
||||
col.prop(part, "draw_color", text="")
|
||||
sub = col.row()
|
||||
sub.active = part.draw_color in ('VELOCITY', 'ACCELERATION')
|
||||
sub.active = (part.draw_color in {'VELOCITY', 'ACCELERATION'})
|
||||
sub.prop(part, "color_maximum", text="Max")
|
||||
|
||||
if (path):
|
||||
|
||||
@@ -360,7 +360,7 @@ class INFO_MT_help(Menu):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("wm.url_open", text="Manual", icon='HELP').url = 'http://wiki.blender.org/index.php/Doc:Manual'
|
||||
layout.operator("wm.url_open", text="Release Log", icon='URL').url = 'http://www.blender.org/development/release-logs/blender-259/'
|
||||
layout.operator("wm.url_open", text="Release Log", icon='URL').url = 'http://www.blender.org/development/release-logs/blender-260/'
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ class SEQUENCER_MT_select(Menu):
|
||||
layout.operator("sequencer.select_handles", text="Left Handle").side = 'LEFT'
|
||||
layout.operator("sequencer.select_handles", text="Right Handle").side = 'RIGHT'
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("object.select_grouped", "type", text="Grouped")
|
||||
layout.operator("sequencer.select_linked")
|
||||
layout.operator("sequencer.select_all_toggle")
|
||||
layout.operator("sequencer.select_inverse")
|
||||
@@ -546,7 +547,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
|
||||
'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
|
||||
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
|
||||
'PLUGIN',
|
||||
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
|
||||
'WIPE', 'GLOW', 'TRANSFORM',
|
||||
'MULTICAM', 'SPEED', 'ADJUSTMENT'}
|
||||
|
||||
def draw(self, context):
|
||||
@@ -584,7 +585,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
|
||||
col = split.column()
|
||||
col.prop(strip, "filepath", text="")
|
||||
col.prop(strip, "mpeg_preseek", text="MPEG Preseek")
|
||||
col.prop(strip, "streamindex", text="Stream Index")
|
||||
col.prop(strip, "stream_index", text="Stream Index")
|
||||
|
||||
# TODO, sound???
|
||||
# end drawing filename
|
||||
|
||||
@@ -66,9 +66,11 @@ class TEXT_HT_header(Header):
|
||||
row = layout.row()
|
||||
if text.filepath:
|
||||
if text.is_dirty:
|
||||
row.label(text="File" + ": *%r " % text.filepath + "(unsaved)")
|
||||
row.label(text="File" + ": *%r " %
|
||||
text.filepath + "(unsaved)")
|
||||
else:
|
||||
row.label(text="File" + ": %r" % text.filepath)
|
||||
row.label(text="File" + ": %r" %
|
||||
text.filepath)
|
||||
else:
|
||||
row.label(text="Text: External"
|
||||
if text.library
|
||||
|
||||
@@ -22,8 +22,6 @@ from bpy.types import Header, Menu, Panel
|
||||
import os
|
||||
import addon_utils
|
||||
|
||||
from bpy.props import StringProperty, BoolProperty, EnumProperty
|
||||
|
||||
|
||||
def ui_items_general(col, context):
|
||||
""" General UI Theme Settings (User Interface)
|
||||
|
||||
@@ -19,110 +19,6 @@
|
||||
# <pep8 compliant>
|
||||
import bpy
|
||||
from bpy.types import Menu, OperatorProperties
|
||||
import os
|
||||
|
||||
|
||||
KM_HIERARCHY = [
|
||||
('Window', 'EMPTY', 'WINDOW', []), # file save, window change, exit
|
||||
('Screen', 'EMPTY', 'WINDOW', [ # full screen, undo, screenshot
|
||||
('Screen Editing', 'EMPTY', 'WINDOW', []), # resizing, action corners
|
||||
]),
|
||||
|
||||
('View2D', 'EMPTY', 'WINDOW', []), # view 2d navigation (per region)
|
||||
('View2D Buttons List', 'EMPTY', 'WINDOW', []), # view 2d with buttons navigation
|
||||
('Header', 'EMPTY', 'WINDOW', []), # header stuff (per region)
|
||||
('Grease Pencil', 'EMPTY', 'WINDOW', []), # grease pencil stuff (per region)
|
||||
|
||||
('3D View', 'VIEW_3D', 'WINDOW', [ # view 3d navigation and generic stuff (select, transform)
|
||||
('Object Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Mesh', 'EMPTY', 'WINDOW', []),
|
||||
('Curve', 'EMPTY', 'WINDOW', []),
|
||||
('Armature', 'EMPTY', 'WINDOW', []),
|
||||
('Metaball', 'EMPTY', 'WINDOW', []),
|
||||
('Lattice', 'EMPTY', 'WINDOW', []),
|
||||
('Font', 'EMPTY', 'WINDOW', []),
|
||||
|
||||
('Pose', 'EMPTY', 'WINDOW', []),
|
||||
|
||||
('Vertex Paint', 'EMPTY', 'WINDOW', []),
|
||||
('Weight Paint', 'EMPTY', 'WINDOW', []),
|
||||
('Face Mask', 'EMPTY', 'WINDOW', []),
|
||||
('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
|
||||
('Sculpt', 'EMPTY', 'WINDOW', []),
|
||||
|
||||
('Armature Sketch', 'EMPTY', 'WINDOW', []),
|
||||
('Particle', 'EMPTY', 'WINDOW', []),
|
||||
|
||||
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
|
||||
|
||||
('3D View Generic', 'VIEW_3D', 'WINDOW', []) # toolbar and properties
|
||||
]),
|
||||
|
||||
('Frames', 'EMPTY', 'WINDOW', []), # frame navigation (per region)
|
||||
('Markers', 'EMPTY', 'WINDOW', []), # markers (per region)
|
||||
('Animation', 'EMPTY', 'WINDOW', []), # frame change on click, preview range (per region)
|
||||
('Animation Channels', 'EMPTY', 'WINDOW', []),
|
||||
('Graph Editor', 'GRAPH_EDITOR', 'WINDOW', [
|
||||
('Graph Editor Generic', 'GRAPH_EDITOR', 'WINDOW', [])
|
||||
]),
|
||||
('Dopesheet', 'DOPESHEET_EDITOR', 'WINDOW', []),
|
||||
('NLA Editor', 'NLA_EDITOR', 'WINDOW', [
|
||||
('NLA Channels', 'NLA_EDITOR', 'WINDOW', []),
|
||||
('NLA Generic', 'NLA_EDITOR', 'WINDOW', [])
|
||||
]),
|
||||
|
||||
('Image', 'IMAGE_EDITOR', 'WINDOW', [
|
||||
('UV Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image
|
||||
('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
|
||||
('Image Generic', 'IMAGE_EDITOR', 'WINDOW', [])
|
||||
]),
|
||||
|
||||
('Timeline', 'TIMELINE', 'WINDOW', []),
|
||||
('Outliner', 'OUTLINER', 'WINDOW', []),
|
||||
|
||||
('Node Editor', 'NODE_EDITOR', 'WINDOW', [
|
||||
('Node Generic', 'NODE_EDITOR', 'WINDOW', [])
|
||||
]),
|
||||
('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', []),
|
||||
('Logic Editor', 'LOGIC_EDITOR', 'WINDOW', []),
|
||||
|
||||
('File Browser', 'FILE_BROWSER', 'WINDOW', [
|
||||
('File Browser Main', 'FILE_BROWSER', 'WINDOW', []),
|
||||
('File Browser Buttons', 'FILE_BROWSER', 'WINDOW', [])
|
||||
]),
|
||||
|
||||
('Property Editor', 'PROPERTIES', 'WINDOW', []), # align context menu
|
||||
|
||||
('Script', 'SCRIPTS_WINDOW', 'WINDOW', []),
|
||||
('Text', 'TEXT_EDITOR', 'WINDOW', []),
|
||||
('Console', 'CONSOLE', 'WINDOW', []),
|
||||
|
||||
('View3D Gesture Circle', 'EMPTY', 'WINDOW', []),
|
||||
('Gesture Border', 'EMPTY', 'WINDOW', []),
|
||||
('Standard Modal Map', 'EMPTY', 'WINDOW', []),
|
||||
('Transform Modal Map', 'EMPTY', 'WINDOW', []),
|
||||
('View3D Fly Modal', 'EMPTY', 'WINDOW', []),
|
||||
('View3D Rotate Modal', 'EMPTY', 'WINDOW', []),
|
||||
('View3D Move Modal', 'EMPTY', 'WINDOW', []),
|
||||
('View3D Zoom Modal', 'EMPTY', 'WINDOW', []),
|
||||
]
|
||||
|
||||
|
||||
def _km_exists_in(km, export_keymaps):
|
||||
for km2, kc in export_keymaps:
|
||||
if km2.name == km.name:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _merge_keymaps(kc1, kc2):
|
||||
""" note: kc1 takes priority over kc2
|
||||
"""
|
||||
merged_keymaps = [(km, kc1) for km in kc1.keymaps]
|
||||
if kc1 != kc2:
|
||||
merged_keymaps.extend((km, kc2) for km in kc2.keymaps if not _km_exists_in(km, merged_keymaps))
|
||||
|
||||
return merged_keymaps
|
||||
|
||||
|
||||
class USERPREF_MT_keyconfigs(Menu):
|
||||
@@ -225,19 +121,6 @@ class InputKeyMapPanel:
|
||||
for entry in children:
|
||||
self.draw_entry(display_keymaps, entry, col, level + 1)
|
||||
|
||||
@staticmethod
|
||||
def draw_kmi_properties(box, properties, title=None):
|
||||
box.separator()
|
||||
if title:
|
||||
box.label(text=title)
|
||||
flow = box.column_flow(columns=2)
|
||||
for pname, value in properties.bl_rna.properties.items():
|
||||
if pname != "rna_type" and not properties.is_property_hidden(pname):
|
||||
if isinstance(value, OperatorProperties):
|
||||
InputKeyMapPanel.draw_kmi_properties(box, value, title=pname)
|
||||
else:
|
||||
flow.prop(properties, pname)
|
||||
|
||||
def draw_kmi(self, display_keymaps, kc, km, kmi, layout, level):
|
||||
map_type = kmi.map_type
|
||||
|
||||
@@ -322,9 +205,7 @@ class InputKeyMapPanel:
|
||||
subrow.prop(kmi, "key_modifier", text="", event=True)
|
||||
|
||||
# Operator properties
|
||||
props = kmi.properties
|
||||
if props is not None:
|
||||
InputKeyMapPanel.draw_kmi_properties(box, props)
|
||||
box.template_keymap_item_properties(kmi)
|
||||
|
||||
# Modal key maps attached to this operator
|
||||
if not km.is_modal:
|
||||
@@ -363,10 +244,13 @@ class InputKeyMapPanel:
|
||||
subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
|
||||
|
||||
def draw_hierarchy(self, display_keymaps, layout):
|
||||
for entry in KM_HIERARCHY:
|
||||
from bpy_extras import keyconfig_utils
|
||||
for entry in keyconfig_utils.KM_HIERARCHY:
|
||||
self.draw_entry(display_keymaps, entry, layout)
|
||||
|
||||
def draw_keymaps(self, context, layout):
|
||||
from bpy_extras import keyconfig_utils
|
||||
|
||||
wm = context.window_manager
|
||||
kc = wm.keyconfigs.user
|
||||
|
||||
@@ -393,7 +277,7 @@ class InputKeyMapPanel:
|
||||
|
||||
col.separator()
|
||||
|
||||
display_keymaps = _merge_keymaps(kc, kc)
|
||||
display_keymaps = keyconfig_utils.keyconfig_merge(kc, kc)
|
||||
if context.space_data.filter_text != "":
|
||||
filter_text = context.space_data.filter_text.lower()
|
||||
self.draw_filtered(display_keymaps, filter_text, col)
|
||||
@@ -401,20 +285,5 @@ class InputKeyMapPanel:
|
||||
self.draw_hierarchy(display_keymaps, col)
|
||||
|
||||
|
||||
def export_properties(prefix, properties, lines=None):
|
||||
if lines is None:
|
||||
lines = []
|
||||
|
||||
for pname in properties.bl_rna.properties.keys():
|
||||
if pname != "rna_type" and not properties.is_property_hidden(pname):
|
||||
value = getattr(properties, pname)
|
||||
if isinstance(value, OperatorProperties):
|
||||
export_properties(prefix + "." + pname, value, lines)
|
||||
elif properties.is_property_set(pname):
|
||||
value = _string_value(value)
|
||||
if value != "":
|
||||
lines.append("%s.%s = %s\n" % (prefix, pname, value))
|
||||
return lines
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
bpy.utils.register_module(__name__)
|
||||
|
||||
@@ -721,11 +721,14 @@ class VIEW3D_MT_object(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("VIEW3D_MT_object_quick_effects")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("VIEW3D_MT_object_game")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("object.join_uvs")
|
||||
layout.operator("object.join")
|
||||
|
||||
layout.separator()
|
||||
@@ -879,8 +882,8 @@ class VIEW3D_MT_object_parent(Menu):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("object.parent_set", text="Set")
|
||||
layout.operator("object.parent_clear", text="Clear")
|
||||
layout.operator_menu_enum("object.parent_set", "type", text="Set")
|
||||
layout.operator_menu_enum("object.parent_clear", "type", text="Clear")
|
||||
|
||||
|
||||
class VIEW3D_MT_object_track(Menu):
|
||||
@@ -889,8 +892,8 @@ class VIEW3D_MT_object_track(Menu):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("object.track_set", text="Set")
|
||||
layout.operator("object.track_clear", text="Clear")
|
||||
layout.operator_menu_enum("object.track_set", "type", text="Set")
|
||||
layout.operator_menu_enum("object.track_clear", "type", text="Clear")
|
||||
|
||||
|
||||
class VIEW3D_MT_object_group(Menu):
|
||||
@@ -919,6 +922,18 @@ class VIEW3D_MT_object_constraints(Menu):
|
||||
layout.operator("object.constraints_clear")
|
||||
|
||||
|
||||
class VIEW3D_MT_object_quick_effects(Menu):
|
||||
bl_label = "Quick Effects"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("object.quick_fur")
|
||||
layout.operator("object.quick_explode")
|
||||
layout.operator("object.quick_smoke")
|
||||
layout.operator("object.quick_fluid")
|
||||
|
||||
|
||||
class VIEW3D_MT_object_showhide(Menu):
|
||||
bl_label = "Show/Hide"
|
||||
|
||||
@@ -968,6 +983,7 @@ class VIEW3D_MT_make_links(Menu):
|
||||
|
||||
layout.operator_enum("object.make_links_data", "type") # inline
|
||||
|
||||
layout.operator("object.join_uvs") # stupid place to add this!
|
||||
|
||||
class VIEW3D_MT_object_game(Menu):
|
||||
bl_label = "Game"
|
||||
|
||||
@@ -353,14 +353,26 @@ class BUILTIN_KSI_WholeCharacter(KeyingSetInfo):
|
||||
|
||||
# custom properties
|
||||
def doCustomProps(ksi, ks, bone):
|
||||
|
||||
prop_type_compat = {bpy.types.BooleanProperty,
|
||||
bpy.types.IntProperty,
|
||||
bpy.types.FloatProperty}
|
||||
|
||||
# go over all custom properties for bone
|
||||
for prop, val in bone.items():
|
||||
for prop in bone.keys():
|
||||
# ignore special "_RNA_UI" used for UI editing
|
||||
if prop == "_RNA_UI":
|
||||
continue
|
||||
|
||||
# for now, just add all of 'em
|
||||
ksi.addProp(ks, bone, '["%s"]' % (prop))
|
||||
prop_rna = type(bone).bl_rna.properties.get(prop, None)
|
||||
if prop_rna is None:
|
||||
prop_path = '["%s"]' % prop
|
||||
if bone.path_resolve(prop_path, False).rna_type in prop_type_compat:
|
||||
ksi.addProp(ks, bone, prop_path)
|
||||
elif prop_rna.is_animatable:
|
||||
ksi.addProp(ks, bone, prop)
|
||||
|
||||
|
||||
###############################
|
||||
|
||||
|
||||
@@ -12,22 +12,18 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p class="title"><b>Blender 2.59</b></p>
|
||||
<p class="title"><b>Blender 2.60</b></p>
|
||||
<p><br></p>
|
||||
<p class="header"><b>About</b></p>
|
||||
<p class="body">Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X, Windows, Solaris and FreeBSD and has a large world-wide community.</p>
|
||||
<p class="body">Blender can be used freely for any purpose, including commercial use and distribution. It's free and open-source software, released under the GNU GPL licence. The entire source code is available on our website.</p>
|
||||
<p class="body">For more information, visit <a href="http://www.blender.org">blender.org</a>.</p>
|
||||
<p><br></p>
|
||||
<p class="header"><b>2.59</b></p>
|
||||
<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.59. This release is the third official stable release of the Blender 2.5 series, and represents the culmination of many years of redesign and development work. <a href="http://www.blender.org/development/release-logs/blender-259/">More information about this release</a>.</p>
|
||||
<p class="body">What to Expect:</p>
|
||||
<p class="body"> • Big improvements - This is our most exciting version to date, already a significant improvement in many ways over 2.49</p>
|
||||
<p class="body"> • Missing/Incomplete Features - Although most of it is there, not all functionality from pre-2.5 versions has been restored yet. Some functionality may be re-implemented a different way.</p>
|
||||
<p class="body"> • Changes - If you're used to the old Blenders, Blender 2.5 may seem quite different at first, but it won't be long before it grows on you even more than before.</p>
|
||||
<p class="header"><b>2.60</b></p>
|
||||
<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.60. This release is the first official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features again.<a href="http://www.blender.org/development/release-logs/blender-260/">More information about this release</a>.</p>
|
||||
<p><br></p>
|
||||
<p class="header"><b>Bugs</b></p>
|
||||
<p class="body">Although Blender 2.59 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender 2.59. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
|
||||
<p class="body">Although Blender 2.60 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
|
||||
<p><br></p>
|
||||
<p class="header"><b>Package Contents</b></p>
|
||||
<p class="body">The downloaded Blender package includes:</p>
|
||||
@@ -43,7 +39,7 @@
|
||||
<p class="body"><b>Installing Add-ons (all systems)</b> Add-ons can be installed from the user preferences addons section, download an addon as a .py or .zip file, then press the "Install Add-on" button and select the file to install it.</p>
|
||||
<p><br></p>
|
||||
<p class="header"><b>Getting Started</b></p>
|
||||
<p class="body">When opening Blender, you’ll see large 3D view in the center, a Toolbar on the left, a Properties area on the right and a Timeline at the bottom.</p>
|
||||
<p class="body">When opening Blender, you’ll see large 3D view in the center, a Toolbar on the left, a Properties area and an Outliner area on the right and a Timeline at the bottom.</p>
|
||||
<p class="body">Orbit around in the 3D view by holding the middle mouse button and dragging. Alternatively, hold the alt key and drag the left mouse button. Additionally, hold Shift to pan the view and Ctrl to zoom.</p>
|
||||
<p class="body">Select objects using the right mouse button. With the object selected, perform actions by clicking any of the tool buttons on the left, or make changes to its properties by altering any of the setting on the right.</p>
|
||||
<p class="body">For more information on how to use Blender, <a href="http://www.blender.org/education-help/">watch tutorials</a> or <a href="http://wiki.blender.org/index.php/Doc:Manual">read the manual</a>.</p>
|
||||
@@ -51,7 +47,7 @@
|
||||
<p class="header"><b>Links</b></p>
|
||||
<p class="body">Users:</p>
|
||||
<p class="body"> General information <a href="http://www.blender.org">www.blender.org</a> <br>
|
||||
Full release log <a href="http://www.blender.org/development/release-logs/blender-259/">www.blender.org/development/release-logs/blender-259/</a><br>
|
||||
Full release log <a href="http://www.blender.org/development/release-logs/blender-260/">www.blender.org/development/release-logs/blender-260/</a><br>
|
||||
Tutorials <a href="http://www.blender.org/education-help/">www.blender.org/education-help/</a> <br>
|
||||
Manual <a href="http://wiki.blender.org/index.php/Doc:Manual">wiki.blender.org/index.php/Doc:Manual</a><br>
|
||||
User Forum <a href="http://www.blenderartists.org">www.blenderartists.org</a><br>
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
|
||||
/* implementation */
|
||||
|
||||
void *avi_converter_from_avi_rgb (AviMovie *movie, int stream, unsigned char *buffer, int *size) {
|
||||
void *avi_converter_from_avi_rgb (AviMovie *movie, int stream, unsigned char *buffer, int *size)
|
||||
{
|
||||
int x, y,i, rowstride;
|
||||
unsigned char *buf;
|
||||
AviBitmapInfoHeader *bi;
|
||||
@@ -116,7 +117,8 @@ void *avi_converter_from_avi_rgb (AviMovie *movie, int stream, unsigned char *bu
|
||||
}
|
||||
}
|
||||
|
||||
void *avi_converter_to_avi_rgb (AviMovie *movie, int stream, unsigned char *buffer, int *size) {
|
||||
void *avi_converter_to_avi_rgb (AviMovie *movie, int stream, unsigned char *buffer, int *size)
|
||||
{
|
||||
int y, x, i, rowstride;
|
||||
unsigned char *buf;
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
AviError AVI_set_compress_option (AviMovie *movie, int option_type, int stream, AviOption option, void *opt_data) {
|
||||
int i;
|
||||
int useconds;
|
||||
|
||||
(void)stream; /* unused */
|
||||
|
||||
@@ -100,8 +101,9 @@ AviError AVI_set_compress_option (AviMovie *movie, int option_type, int stream,
|
||||
break;
|
||||
|
||||
case AVI_OPTION_FRAMERATE:
|
||||
if (1000000/(*((double *) opt_data)))
|
||||
movie->header->MicroSecPerFrame = 1000000/(*((double *) opt_data));
|
||||
useconds = (int)(1000000/(*((double *) opt_data)));
|
||||
if (useconds)
|
||||
movie->header->MicroSecPerFrame = useconds;
|
||||
|
||||
for (i=0; i < movie->header->Streams; i++) {
|
||||
if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user