svn merge ^/trunk/blender -r40644:40720
This commit is contained in:
commit
8695bedda2
@ -488,17 +488,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)
|
||||
|
@ -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
|
||||
|
@ -277,7 +277,7 @@ 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'):
|
||||
|
@ -213,6 +213,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,13 +234,6 @@ 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})
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -161,7 +161,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 = []
|
||||
@ -360,7 +360,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
|
||||
|
||||
@ -510,7 +510,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")
|
||||
@ -698,7 +698,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", "")
|
||||
@ -912,7 +912,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, "=")
|
||||
@ -963,7 +963,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()
|
||||
@ -1017,7 +1017,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)
|
||||
@ -1053,7 +1053,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")
|
||||
@ -1169,7 +1169,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")
|
||||
@ -1181,7 +1181,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")
|
||||
@ -1194,7 +1194,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")
|
||||
@ -1284,7 +1284,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}")
|
||||
|
1275
extern/recastnavigation/Recast/Include/Recast.h
vendored
1275
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
|
337
extern/recastnavigation/Recast/Source/Recast.cpp
vendored
337
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)
|
||||
return sqrtf(x);
|
||||
}
|
||||
|
||||
/// @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)
|
||||
{
|
||||
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;
|
||||
len = MSG_SIZE-1;
|
||||
msg[MSG_SIZE-1] = '\0';
|
||||
}
|
||||
m_size = n;
|
||||
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);
|
||||
}
|
||||
|
||||
bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb,
|
||||
unsigned char flags, rcHeightfield& hf,
|
||||
rcCompactHeightfield& chf)
|
||||
{
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
rcAssert(ctx);
|
||||
|
||||
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 (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->buildCompact += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
if (tooHighNeighbour > MAX_LAYERS)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heightfield has too many layers %d (max: %d)",
|
||||
tooHighNeighbour, MAX_LAYERS);
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
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 ax = simplified[i*4+0];
|
||||
const int az = simplified[i*4+2];
|
||||
const int ai = simplified[i*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
|
||||
{
|
||||
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+1]/4, points[ci*4+2],
|
||||
ax, ay/4, az, bx, by/4, bz);
|
||||
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,33 +384,52 @@ 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];
|
||||
|
||||
int bx = simplified[ii*4+0];
|
||||
int bz = simplified[ii*4+2];
|
||||
int bi = simplified[ii*4+3];
|
||||
const int ax = simplified[i*4+0];
|
||||
const int az = simplified[i*4+2];
|
||||
const int ai = simplified[i*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;
|
||||
|
||||
// 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;
|
||||
|
||||
// Tesselate only outer edges.
|
||||
if ((points[ci*4+3] & 0xffff) == 0)
|
||||
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);
|
||||
maxi = (ai + n/2) % pn;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,25 +509,40 @@ 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];
|
||||
const int dx = vb[0] - va[0];
|
||||
const int dz = vb[2] - va[2];
|
||||
const int d = dx*dx + dz*dz;
|
||||
if (d < closestDist)
|
||||
// vb must be "infront" of va.
|
||||
if (ileft(vap,va,vb) && ileft(va,van,vb))
|
||||
{
|
||||
ia = i;
|
||||
ib = j;
|
||||
closestDist = d;
|
||||
const int dx = vb[0] - va[0];
|
||||
const int dz = vb[2] - va[2];
|
||||
const int d = dx*dx + dz*dz;
|
||||
if (d < closestDist)
|
||||
{
|
||||
ia = i;
|
||||
ib = j;
|
||||
closestDist = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -490,7 +551,7 @@ 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,36 +699,87 @@ 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.
|
||||
if (simplified.size()/4 >= 3)
|
||||
{
|
||||
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;
|
||||
|
||||
// If the difference between all neighbours is too large,
|
||||
// we are at steep slope, mark the span as ledge.
|
||||
if ((asmax - asmin) > walkableClimb)
|
||||
{
|
||||
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);
|
||||
ctx->stopTimer(RC_TIMER_FILTER_BORDER);
|
||||
}
|
||||
|
||||
void rcFilterWalkableLowHeightSpans(int walkableHeight,
|
||||
rcHeightfield& solid)
|
||||
/// @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)
|
||||
{
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
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;
|
||||
}
|
713
extern/recastnavigation/Recast/Source/RecastMesh.cpp
vendored
713
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
211
extern/recastnavigation/recast-capi.cpp
vendored
211
extern/recastnavigation/recast-capi.cpp
vendored
@ -30,6 +30,11 @@
|
||||
#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)
|
||||
{
|
||||
@ -48,109 +53,123 @@ void recast_calcGridSize(const float *bmin, const float *bmax, float cs, int *w,
|
||||
|
||||
struct recast_heightfield *recast_newHeightfield(void)
|
||||
{
|
||||
return (struct recast_heightfield *) (new rcHeightfield);
|
||||
return (struct recast_heightfield *) rcAllocHeightfield();
|
||||
}
|
||||
|
||||
void recast_destroyHeightfield(struct recast_heightfield *heightfield)
|
||||
{
|
||||
delete (rcHeightfield *) 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)
|
||||
{
|
||||
return rcCreateHeightfield(*(rcHeightfield *)hf, width, height, bmin, bmax, cs, 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)
|
||||
{
|
||||
rcMarkWalkableTriangles(walkableSlopeAngle, verts, nv, tris, nt, 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)
|
||||
{
|
||||
rcRasterizeTriangles(verts, nv, tris, flags, nt, *(rcHeightfield *) 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)
|
||||
{
|
||||
rcFilterLedgeSpans(walkableHeight, walkableClimb, *(rcHeightfield *) solid);
|
||||
INIT_SCTX();
|
||||
rcFilterLedgeSpans(sctx, walkableHeight, walkableClimb, *(rcHeightfield *) solid);
|
||||
}
|
||||
|
||||
void recast_filterWalkableLowHeightSpans(int walkableHeight, struct recast_heightfield *solid)
|
||||
{
|
||||
rcFilterWalkableLowHeightSpans(walkableHeight, *(rcHeightfield *) 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 *) (new rcCompactHeightfield);
|
||||
return (struct recast_compactHeightfield *) rcAllocCompactHeightfield();
|
||||
}
|
||||
|
||||
void recast_destroyCompactHeightfield(struct recast_compactHeightfield *compactHeightfield)
|
||||
{
|
||||
delete (rcCompactHeightfield *) compactHeightfield;
|
||||
rcFreeCompactHeightfield( (rcCompactHeightfield *) compactHeightfield);
|
||||
}
|
||||
|
||||
int recast_buildCompactHeightfield(const int walkableHeight, const int walkableClimb,
|
||||
unsigned char flags, struct recast_heightfield *hf, struct recast_compactHeightfield *chf)
|
||||
struct recast_heightfield *hf, struct recast_compactHeightfield *chf)
|
||||
{
|
||||
int rcFlags = 0;
|
||||
INIT_SCTX();
|
||||
return rcBuildCompactHeightfield(sctx, walkableHeight, walkableClimb,
|
||||
*(rcHeightfield *) hf, *(rcCompactHeightfield *) chf);
|
||||
}
|
||||
|
||||
if(flags & RECAST_WALKABLE)
|
||||
rcFlags |= RC_WALKABLE;
|
||||
|
||||
if(flags & RECAST_REACHABLE)
|
||||
rcFlags |= RC_REACHABLE;
|
||||
|
||||
return rcBuildCompactHeightfield(walkableHeight, walkableClimb, rcFlags,
|
||||
*(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)
|
||||
{
|
||||
return rcBuildDistanceField(*(rcCompactHeightfield *) chf);
|
||||
INIT_SCTX();
|
||||
return rcBuildDistanceField(sctx, *(rcCompactHeightfield *) chf);
|
||||
}
|
||||
|
||||
int recast_buildRegions(struct recast_compactHeightfield *chf, int walkableRadius, int borderSize,
|
||||
int recast_buildRegions(struct recast_compactHeightfield *chf, int borderSize,
|
||||
int minRegionSize, int mergeRegionSize)
|
||||
{
|
||||
return rcBuildRegions(*(rcCompactHeightfield *) chf, walkableRadius, borderSize,
|
||||
INIT_SCTX();
|
||||
return rcBuildRegions(sctx, *(rcCompactHeightfield *) chf, borderSize,
|
||||
minRegionSize, mergeRegionSize);
|
||||
}
|
||||
|
||||
struct recast_contourSet *recast_newContourSet(void)
|
||||
{
|
||||
return (struct recast_contourSet *) (new rcContourSet);
|
||||
return (struct recast_contourSet *) rcAllocContourSet();
|
||||
}
|
||||
|
||||
void recast_destroyContourSet(struct recast_contourSet *contourSet)
|
||||
{
|
||||
delete (rcContourSet *) contourSet;
|
||||
rcFreeContourSet((rcContourSet *) contourSet);
|
||||
}
|
||||
|
||||
int recast_buildContours(struct recast_compactHeightfield *chf,
|
||||
const float maxError, const int maxEdgeLen, struct recast_contourSet *cset)
|
||||
{
|
||||
return rcBuildContours(*(rcCompactHeightfield *) chf, maxError, maxEdgeLen, *(rcContourSet *) cset);
|
||||
INIT_SCTX();
|
||||
return rcBuildContours(sctx, *(rcCompactHeightfield *) chf, maxError, maxEdgeLen, *(rcContourSet *) cset);
|
||||
}
|
||||
|
||||
struct recast_polyMesh *recast_newPolyMesh(void)
|
||||
{
|
||||
return (recast_polyMesh *) (new rcPolyMesh);
|
||||
return (recast_polyMesh *) rcAllocPolyMesh();
|
||||
}
|
||||
|
||||
void recast_destroyPolyMesh(struct recast_polyMesh *polyMesh)
|
||||
{
|
||||
delete (rcPolyMesh *) polyMesh;
|
||||
rcFreePolyMesh((rcPolyMesh *) polyMesh);
|
||||
}
|
||||
|
||||
int recast_buildPolyMesh(struct recast_contourSet *cset, int nvp, struct recast_polyMesh *mesh)
|
||||
{
|
||||
return rcBuildPolyMesh(*(rcContourSet *) cset, nvp, * (rcPolyMesh *) mesh);
|
||||
INIT_SCTX();
|
||||
return rcBuildPolyMesh(sctx, *(rcContourSet *) cset, nvp, * (rcPolyMesh *) mesh);
|
||||
}
|
||||
|
||||
unsigned short *recast_polyMeshGetVerts(struct recast_polyMesh *mesh, int *nverts)
|
||||
@ -206,18 +225,19 @@ unsigned short *recast_polyMeshGetPolys(struct recast_polyMesh *mesh, int *npoly
|
||||
|
||||
struct recast_polyMeshDetail *recast_newPolyMeshDetail(void)
|
||||
{
|
||||
return (struct recast_polyMeshDetail *) (new rcPolyMeshDetail);
|
||||
return (struct recast_polyMeshDetail *) rcAllocPolyMeshDetail();
|
||||
}
|
||||
|
||||
void recast_destroyPolyMeshDetail(struct recast_polyMeshDetail *polyMeshDetail)
|
||||
{
|
||||
delete (rcPolyMeshDetail *) 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)
|
||||
{
|
||||
return rcBuildPolyMeshDetail(*(rcPolyMesh *) mesh, *(rcCompactHeightfield *) chf,
|
||||
INIT_SCTX();
|
||||
return rcBuildPolyMeshDetail(sctx, *(rcPolyMesh *) mesh, *(rcCompactHeightfield *) chf,
|
||||
sampleDist, sampleMaxError, *(rcPolyMeshDetail *) dmesh);
|
||||
}
|
||||
|
||||
@ -241,7 +261,7 @@ unsigned char *recast_polyMeshDetailGetTris(struct recast_polyMeshDetail *mesh,
|
||||
return dmesh->tris;
|
||||
}
|
||||
|
||||
unsigned short *recast_polyMeshDetailGetMeshes(struct recast_polyMeshDetail *mesh, int *nmeshes)
|
||||
unsigned int *recast_polyMeshDetailGetMeshes(struct recast_polyMeshDetail *mesh, int *nmeshes)
|
||||
{
|
||||
rcPolyMeshDetail *dmesh = (rcPolyMeshDetail *)mesh;
|
||||
|
||||
@ -250,3 +270,130 @@ unsigned short *recast_polyMeshDetailGetMeshes(struct recast_polyMeshDetail *mes
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
18
extern/recastnavigation/recast-capi.h
vendored
18
extern/recastnavigation/recast-capi.h
vendored
@ -28,6 +28,9 @@
|
||||
#ifndef RECAST_C_API_H
|
||||
#define RECAST_C_API_H
|
||||
|
||||
// for size_t
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -69,16 +72,20 @@ void recast_filterLedgeSpans(const int walkableHeight, const int walkableClimb,
|
||||
|
||||
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,
|
||||
unsigned char flags, struct recast_heightfield *hf, struct recast_compactHeightfield *chf);
|
||||
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 walkableRadius, int borderSize,
|
||||
int recast_buildRegions(struct recast_compactHeightfield *chf, int borderSize,
|
||||
int minRegionSize, int mergeRegionSize);
|
||||
|
||||
/* Contour set */
|
||||
@ -119,7 +126,12 @@ float *recast_polyMeshDetailGetVerts(struct recast_polyMeshDetail *mesh, int *nv
|
||||
|
||||
unsigned char *recast_polyMeshDetailGetTris(struct recast_polyMeshDetail *mesh, int *ntris);
|
||||
|
||||
unsigned short *recast_polyMeshDetailGetMeshes(struct recast_polyMeshDetail *mesh, int *nmeshes);
|
||||
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
|
||||
}
|
||||
|
@ -132,8 +132,14 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
|
||||
while(eit != m_factory->m_entries.end())
|
||||
{
|
||||
handle = new AUD_SequencerHandle(*eit, m_device);
|
||||
handles.push_front(handle);
|
||||
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 );
|
||||
|
@ -102,8 +102,8 @@ 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['OURPLATFORM'] == 'darwin' and env['CC'].endswith('4.6.1'): # compile ghost always with apple-gcc to keep objectiveC compatibility
|
||||
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/gcc-4.2' ) #, cc_compileflags=env['CXXFLAGS'].append('-fobjc-exceptions')
|
||||
elif env['OURPLATFORM'] == 'darwin': # 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/gcc-4.2' )
|
||||
print "GHOST COCOA WILL BE COMPILED WITH APPLE GCC"
|
||||
|
||||
else:
|
||||
|
@ -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()
|
168
po/merge_po.py
Executable file
168
po/merge_po.py
Executable file
@ -0,0 +1,168 @@
|
||||
#!/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
|
||||
|
||||
|
||||
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,29 +25,43 @@
|
||||
|
||||
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]
|
||||
# show stats
|
||||
cmd = ("msgfmt",
|
||||
"--statistics",
|
||||
os.path.join(CURRENT_DIR, "%s.po" % lang),
|
||||
"-o",
|
||||
os.path.join(LOCALE_DIR, lang, "LC_MESSAGES", "%s.mo" % DOMAIN),
|
||||
)
|
||||
def process_po(po):
|
||||
lang = os.path.basename(po)[:-3]
|
||||
|
||||
print(" ".join(cmd))
|
||||
process = subprocess.Popen(cmd)
|
||||
process.wait()
|
||||
# show stats
|
||||
cmd = (GETTEXT_MSGFMT_EXECUTABLE,
|
||||
"--statistics",
|
||||
os.path.join(CURRENT_DIR, "%s.po" % lang),
|
||||
"-o",
|
||||
os.path.join(LOCALE_DIR, lang, "LC_MESSAGES", "%s.mo" % DOMAIN),
|
||||
)
|
||||
|
||||
print(" ".join(cmd))
|
||||
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__)
|
||||
|
174
po/update_msg.py
174
po/update_msg.py
@ -26,10 +26,11 @@
|
||||
|
||||
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):
|
||||
@ -38,55 +39,102 @@ def dump_messages_rna(messages):
|
||||
# -------------------------------------------------------------------------
|
||||
# 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)
|
||||
messages.setdefault(prop.name, []).append(msgsrc)
|
||||
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,
|
||||
)
|
||||
messages.setdefault(item.name, []).append(msgsrc)
|
||||
messages.setdefault(item.description, []).append(msgsrc)
|
||||
|
||||
def walkRNA(bl_rna):
|
||||
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)
|
||||
|
||||
cls_list = bpy.types.OperatorProperties.__subclasses__()
|
||||
cls_list.sort(key=full_class_id)
|
||||
for cls in cls_list:
|
||||
walkClass(cls)
|
||||
|
||||
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
|
||||
|
||||
walk_keymap_hierarchy(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 +169,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 +207,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 +268,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,27 +25,41 @@
|
||||
|
||||
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 process_po(po):
|
||||
lang = os.path.basename(po)[:-3]
|
||||
|
||||
# update po file
|
||||
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),
|
||||
)
|
||||
|
||||
print(" ".join(cmd))
|
||||
process = subprocess.Popen(cmd)
|
||||
process.wait()
|
||||
|
||||
|
||||
def main():
|
||||
for po in os.listdir(CURRENT_DIR):
|
||||
if po.endswith(".po"):
|
||||
lang = po[:-3]
|
||||
if len(sys.argv) > 1:
|
||||
for lang in sys.argv[1:]:
|
||||
po = os.path.join(CURRENT_DIR, lang + '.po')
|
||||
|
||||
# update po file
|
||||
cmd = ("msgmerge",
|
||||
"--update",
|
||||
"--lang=%s" % lang,
|
||||
os.path.join(CURRENT_DIR, "%s.po" % lang),
|
||||
os.path.join(CURRENT_DIR, "%s.pot" % DOMAIN),
|
||||
)
|
||||
|
||||
print(" ".join(cmd))
|
||||
process = subprocess.Popen(cmd)
|
||||
process.wait()
|
||||
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__":
|
||||
|
@ -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)
|
||||
line = line.replace("\\", "\\\\")
|
||||
line = line.replace("\"", "\\\"")
|
||||
|
||||
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")
|
||||
# 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):
|
||||
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__":
|
||||
|
Binary file not shown.
@ -136,7 +136,7 @@ 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)]
|
||||
|
@ -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")
|
||||
@ -407,7 +408,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
|
||||
return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
|
||||
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
|
||||
'PLUGIN',
|
||||
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
|
||||
'WIPE', 'GLOW', 'TRANSFORM', 'SPEED',
|
||||
'MULTICAM', 'ADJUSTMENT'}
|
||||
|
||||
def draw(self, context):
|
||||
|
@ -44,7 +44,7 @@ extern "C" {
|
||||
* and keep comment above the defines.
|
||||
* Use STRINGIFY() rather than defining with quotes */
|
||||
#define BLENDER_VERSION 259
|
||||
#define BLENDER_SUBVERSION 3
|
||||
#define BLENDER_SUBVERSION 4
|
||||
|
||||
#define BLENDER_MINVERSION 250
|
||||
#define BLENDER_MINSUBVERSION 0
|
||||
|
@ -231,7 +231,7 @@ short fcurve_is_keyframable(struct FCurve *fcu);
|
||||
/* -------- Curve Sanity -------- */
|
||||
|
||||
void calchandles_fcurve(struct FCurve *fcu);
|
||||
void testhandles_fcurve(struct FCurve *fcu);
|
||||
void testhandles_fcurve(struct FCurve *fcu, const short use_handle);
|
||||
void sort_time_fcurve(struct FCurve *fcu);
|
||||
short test_time_fcurve(struct FCurve *fcu);
|
||||
|
||||
|
@ -146,6 +146,11 @@ void object_camera_matrix(
|
||||
float winmat[][4], struct rctf *viewplane, float *clipsta, float *clipend, float *lens, float *ycor,
|
||||
float *viewdx, float *viewdy);
|
||||
|
||||
void camera_view_frame_ex(struct Scene *scene, struct Camera *camera, float drawsize, const short do_clip, const float scale[3],
|
||||
float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3]);
|
||||
|
||||
void camera_view_frame(struct Scene *scene, struct Camera *camera, float r_vec[4][3]);
|
||||
|
||||
void object_relink(struct Object *ob);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -742,7 +742,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
|
||||
MDeformVert *dvert = NULL;
|
||||
Cloth *clothObj = NULL;
|
||||
int numverts;
|
||||
float goalfac = 0;
|
||||
/* float goalfac = 0; */ /* UNUSED */
|
||||
ClothVertex *verts = NULL;
|
||||
|
||||
if (!clmd || !dm) return;
|
||||
@ -765,7 +765,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
|
||||
if (( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_mass-1)) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ))
|
||||
{
|
||||
verts->goal = dvert->dw [j].weight;
|
||||
goalfac= 1.0f;
|
||||
/* goalfac= 1.0f; */ /* UNUSED */
|
||||
|
||||
/*
|
||||
// Kicking goal factor to simplify things...who uses that anyway?
|
||||
|
@ -2365,7 +2365,7 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl
|
||||
{
|
||||
Cloth *cloth= clmd->clothObject;
|
||||
BVHTree *cloth_bvh= cloth->bvhtree;
|
||||
unsigned int i=0, numfaces = 0, numverts = 0, k, l, j;
|
||||
unsigned int i=0, /* numfaces = 0, */ /* UNUSED */ numverts = 0, k, l, j;
|
||||
int rounds = 0; // result counts applied collisions; ic is for debug output;
|
||||
ClothVertex *verts = NULL;
|
||||
int ret = 0, ret2 = 0;
|
||||
@ -2376,7 +2376,7 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl
|
||||
return 0;
|
||||
|
||||
verts = cloth->verts;
|
||||
numfaces = cloth->numfaces;
|
||||
/* numfaces = cloth->numfaces; */ /* UNUSED */
|
||||
numverts = cloth->numverts;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -2478,7 +2478,7 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl
|
||||
// collisions = 1;
|
||||
verts = cloth->verts; // needed for openMP
|
||||
|
||||
numfaces = cloth->numfaces;
|
||||
/* numfaces = cloth->numfaces; */ /* UNUSED */
|
||||
numverts = cloth->numverts;
|
||||
|
||||
verts = cloth->verts;
|
||||
|
@ -361,72 +361,70 @@ void curvemap_sethandle(CurveMap *cuma, int type)
|
||||
static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *next, int UNUSED(mode))
|
||||
{
|
||||
float *p1,*p2,*p3,pt[3];
|
||||
float dx1,dy1, dx,dy, vx,vy, len,len1,len2;
|
||||
|
||||
if(bezt->h1==0 && bezt->h2==0) return;
|
||||
float len,len_a, len_b;
|
||||
float dvec_a[2], dvec_b[2];
|
||||
|
||||
if(bezt->h1==0 && bezt->h2==0) {
|
||||
return;
|
||||
}
|
||||
|
||||
p2= bezt->vec[1];
|
||||
|
||||
if(prev==NULL) {
|
||||
p3= next->vec[1];
|
||||
pt[0]= 2*p2[0]- p3[0];
|
||||
pt[1]= 2*p2[1]- p3[1];
|
||||
pt[0]= 2.0f*p2[0] - p3[0];
|
||||
pt[1]= 2.0f*p2[1] - p3[1];
|
||||
p1= pt;
|
||||
}
|
||||
else p1= prev->vec[1];
|
||||
else {
|
||||
p1= prev->vec[1];
|
||||
}
|
||||
|
||||
if(next==NULL) {
|
||||
p1= prev->vec[1];
|
||||
pt[0]= 2*p2[0]- p1[0];
|
||||
pt[1]= 2*p2[1]- p1[1];
|
||||
pt[0]= 2.0f*p2[0] - p1[0];
|
||||
pt[1]= 2.0f*p2[1] - p1[1];
|
||||
p3= pt;
|
||||
}
|
||||
else p3= next->vec[1];
|
||||
|
||||
dx= p2[0]- p1[0];
|
||||
dy= p2[1]- p1[1];
|
||||
else {
|
||||
p3= next->vec[1];
|
||||
}
|
||||
|
||||
len1= (float)sqrt(dx*dx+dy*dy);
|
||||
|
||||
dx1= p3[0]- p2[0];
|
||||
dy1= p3[1]- p2[1];
|
||||
sub_v2_v2v2(dvec_a, p2, p1);
|
||||
sub_v2_v2v2(dvec_b, p3, p2);
|
||||
|
||||
len2= (float)sqrt(dx1*dx1+dy1*dy1);
|
||||
|
||||
if(len1==0.0f) len1=1.0f;
|
||||
if(len2==0.0f) len2=1.0f;
|
||||
|
||||
if(bezt->h1==HD_AUTO || bezt->h2==HD_AUTO) { /* auto */
|
||||
vx= dx1/len2 + dx/len1;
|
||||
vy= dy1/len2 + dy/len1;
|
||||
|
||||
len= 2.5614f*(float)sqrt(vx*vx + vy*vy);
|
||||
len_a= len_v2(dvec_a);
|
||||
len_b= len_v2(dvec_b);
|
||||
|
||||
if(len_a==0.0f) len_a=1.0f;
|
||||
if(len_b==0.0f) len_b=1.0f;
|
||||
|
||||
if(bezt->h1==HD_AUTO || bezt->h2==HD_AUTO) { /* auto */
|
||||
float tvec[2];
|
||||
tvec[0]= dvec_b[0]/len_b + dvec_a[0]/len_a;
|
||||
tvec[1]= dvec_b[1]/len_b + dvec_a[1]/len_a;
|
||||
|
||||
len= len_v2(tvec) * 2.5614f;
|
||||
if(len!=0.0f) {
|
||||
|
||||
if(bezt->h1==HD_AUTO) {
|
||||
len1/=len;
|
||||
*(p2-3)= *p2-vx*len1;
|
||||
*(p2-2)= *(p2+1)-vy*len1;
|
||||
len_a/=len;
|
||||
madd_v2_v2v2fl(p2-3, p2, tvec, -len_a);
|
||||
}
|
||||
if(bezt->h2==HD_AUTO) {
|
||||
len2/=len;
|
||||
*(p2+3)= *p2+vx*len2;
|
||||
*(p2+4)= *(p2+1)+vy*len2;
|
||||
len_b/=len;
|
||||
madd_v2_v2v2fl(p2+3, p2, tvec, len_b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bezt->h1==HD_VECT) { /* vector */
|
||||
dx/=3.0f;
|
||||
dy/=3.0f;
|
||||
*(p2-3)= *p2-dx;
|
||||
*(p2-2)= *(p2+1)-dy;
|
||||
mul_v2_fl(dvec_a, 1.0f/3.0f);
|
||||
sub_v2_v2v2(p2-3, p2, dvec_a);
|
||||
}
|
||||
if(bezt->h2==HD_VECT) {
|
||||
dx1/=3.0f;
|
||||
dy1/=3.0f;
|
||||
*(p2+3)= *p2+dx1;
|
||||
*(p2+4)= *(p2+1)+dy1;
|
||||
mul_v2_fl(dvec_b, 1.0f/3.0f);
|
||||
sub_v2_v2v2(p2+3, p2, dvec_b);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2458,72 +2458,77 @@ void makeBevelList(Object *ob)
|
||||
void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
|
||||
{
|
||||
float *p1,*p2,*p3, pt[3];
|
||||
float dx1,dy1,dz1,dx,dy,dz,vx,vy,vz,len,len1,len2;
|
||||
float dvec_a[3], dvec_b[3];
|
||||
float len, len_a, len_b;
|
||||
const float eps= 1e-5;
|
||||
|
||||
if(bezt->h1==0 && bezt->h2==0) return;
|
||||
if(bezt->h1==0 && bezt->h2==0) {
|
||||
return;
|
||||
}
|
||||
|
||||
p2= bezt->vec[1];
|
||||
|
||||
if(prev==NULL) {
|
||||
p3= next->vec[1];
|
||||
pt[0]= 2*p2[0]- p3[0];
|
||||
pt[1]= 2*p2[1]- p3[1];
|
||||
pt[2]= 2*p2[2]- p3[2];
|
||||
pt[0]= 2.0f*p2[0] - p3[0];
|
||||
pt[1]= 2.0f*p2[1] - p3[1];
|
||||
pt[2]= 2.0f*p2[2] - p3[2];
|
||||
p1= pt;
|
||||
}
|
||||
else p1= prev->vec[1];
|
||||
else {
|
||||
p1= prev->vec[1];
|
||||
}
|
||||
|
||||
if(next==NULL) {
|
||||
pt[0]= 2*p2[0]- p1[0];
|
||||
pt[1]= 2*p2[1]- p1[1];
|
||||
pt[2]= 2*p2[2]- p1[2];
|
||||
pt[0]= 2.0f*p2[0] - p1[0];
|
||||
pt[1]= 2.0f*p2[1] - p1[1];
|
||||
pt[2]= 2.0f*p2[2] - p1[2];
|
||||
p3= pt;
|
||||
}
|
||||
else p3= next->vec[1];
|
||||
else {
|
||||
p3= next->vec[1];
|
||||
}
|
||||
|
||||
dx= p2[0]- p1[0];
|
||||
dy= p2[1]- p1[1];
|
||||
dz= p2[2]- p1[2];
|
||||
|
||||
if(mode) len1= dx;
|
||||
else len1= (float)sqrt(dx*dx+dy*dy+dz*dz);
|
||||
|
||||
dx1= p3[0]- p2[0];
|
||||
dy1= p3[1]- p2[1];
|
||||
dz1= p3[2]- p2[2];
|
||||
|
||||
if(mode) len2= dx1;
|
||||
else len2= (float)sqrt(dx1*dx1+dy1*dy1+dz1*dz1);
|
||||
sub_v3_v3v3(dvec_a, p2, p1);
|
||||
sub_v3_v3v3(dvec_b, p3, p2);
|
||||
|
||||
if(len1==0.0f) len1=1.0f;
|
||||
if(len2==0.0f) len2=1.0f;
|
||||
if (mode != 0) {
|
||||
len_a= dvec_a[0];
|
||||
len_b= dvec_b[0];
|
||||
}
|
||||
else {
|
||||
len_a= len_v3(dvec_a);
|
||||
len_b= len_v3(dvec_b);
|
||||
}
|
||||
|
||||
if(len_a==0.0f) len_a=1.0f;
|
||||
if(len_b==0.0f) len_b=1.0f;
|
||||
|
||||
|
||||
if(ELEM(bezt->h1,HD_AUTO,HD_AUTO_ANIM) || ELEM(bezt->h2,HD_AUTO,HD_AUTO_ANIM)) { /* auto */
|
||||
vx= dx1/len2 + dx/len1;
|
||||
vy= dy1/len2 + dy/len1;
|
||||
vz= dz1/len2 + dz/len1;
|
||||
len= 2.5614f*(float)sqrt(vx*vx + vy*vy + vz*vz);
|
||||
float tvec[3];
|
||||
tvec[0]= dvec_b[0]/len_b + dvec_a[0]/len_a;
|
||||
tvec[1]= dvec_b[1]/len_b + dvec_a[1]/len_a;
|
||||
tvec[2]= dvec_b[2]/len_b + dvec_a[2]/len_a;
|
||||
len= len_v3(tvec) * 2.5614f;
|
||||
|
||||
if(len!=0.0f) {
|
||||
int leftviolate=0, rightviolate=0; /* for mode==2 */
|
||||
|
||||
if(len1>5.0f*len2) len1= 5.0f*len2;
|
||||
if(len2>5.0f*len1) len2= 5.0f*len1;
|
||||
if(len_a>5.0f*len_b) len_a= 5.0f*len_b;
|
||||
if(len_b>5.0f*len_a) len_b= 5.0f*len_a;
|
||||
|
||||
if(ELEM(bezt->h1,HD_AUTO,HD_AUTO_ANIM)) {
|
||||
len1/=len;
|
||||
*(p2-3)= *p2-vx*len1;
|
||||
*(p2-2)= *(p2+1)-vy*len1;
|
||||
*(p2-1)= *(p2+2)-vz*len1;
|
||||
len_a/=len;
|
||||
madd_v3_v3v3fl(p2-3, p2, tvec, -len_a);
|
||||
|
||||
if((bezt->h1==HD_AUTO_ANIM) && next && prev) { // keep horizontal if extrema
|
||||
if((bezt->h1==HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
|
||||
float ydiff1= prev->vec[1][1] - bezt->vec[1][1];
|
||||
float ydiff2= next->vec[1][1] - bezt->vec[1][1];
|
||||
if( (ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f) ) {
|
||||
bezt->vec[0][1]= bezt->vec[1][1];
|
||||
}
|
||||
else { // handles should not be beyond y coord of two others
|
||||
else { /* handles should not be beyond y coord of two others */
|
||||
if(ydiff1 <= 0.0f) {
|
||||
if(prev->vec[1][1] > bezt->vec[0][1]) {
|
||||
bezt->vec[0][1]= prev->vec[1][1];
|
||||
@ -2540,18 +2545,16 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
|
||||
}
|
||||
}
|
||||
if(ELEM(bezt->h2,HD_AUTO,HD_AUTO_ANIM)) {
|
||||
len2/=len;
|
||||
*(p2+3)= *p2+vx*len2;
|
||||
*(p2+4)= *(p2+1)+vy*len2;
|
||||
*(p2+5)= *(p2+2)+vz*len2;
|
||||
len_b/=len;
|
||||
madd_v3_v3v3fl(p2+3, p2, tvec, len_b);
|
||||
|
||||
if((bezt->h2==HD_AUTO_ANIM) && next && prev) { // keep horizontal if extrema
|
||||
if((bezt->h2==HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
|
||||
float ydiff1= prev->vec[1][1] - bezt->vec[1][1];
|
||||
float ydiff2= next->vec[1][1] - bezt->vec[1][1];
|
||||
if( (ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f) ) {
|
||||
bezt->vec[2][1]= bezt->vec[1][1];
|
||||
}
|
||||
else { // handles should not be beyond y coord of two others
|
||||
else { /* andles should not be beyond y coord of two others */
|
||||
if(ydiff1 <= 0.0f) {
|
||||
if(next->vec[1][1] < bezt->vec[2][1]) {
|
||||
bezt->vec[2][1]= next->vec[1][1];
|
||||
@ -2567,25 +2570,25 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(leftviolate || rightviolate) { /* align left handle */
|
||||
if(leftviolate || rightviolate) { /* align left handle */
|
||||
float h1[3], h2[3];
|
||||
float dot;
|
||||
|
||||
sub_v3_v3v3(h1, p2-3, p2);
|
||||
sub_v3_v3v3(h2, p2, p2+3);
|
||||
len1= normalize_v3(h1);
|
||||
len2= normalize_v3(h2);
|
||||
|
||||
vz= dot_v3v3(h1, h2);
|
||||
len_a= normalize_v3(h1);
|
||||
len_b= normalize_v3(h2);
|
||||
|
||||
dot= dot_v3v3(h1, h2);
|
||||
|
||||
if(leftviolate) {
|
||||
*(p2+3)= *(p2) - vz*len2*h1[0];
|
||||
*(p2+4)= *(p2+1) - vz*len2*h1[1];
|
||||
*(p2+5)= *(p2+2) - vz*len2*h1[2];
|
||||
mul_v3_fl(h1, dot * len_b);
|
||||
sub_v3_v3v3(p2+3, p2, h1);
|
||||
}
|
||||
else {
|
||||
*(p2-3)= *(p2) + vz*len1*h2[0];
|
||||
*(p2-2)= *(p2+1) + vz*len1*h2[1];
|
||||
*(p2-1)= *(p2+2) + vz*len1*h2[2];
|
||||
mul_v3_fl(h2, dot * len_a);
|
||||
add_v3_v3v3(p2-3, p2, h2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2593,60 +2596,52 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
|
||||
}
|
||||
|
||||
if(bezt->h1==HD_VECT) { /* vector */
|
||||
dx/=3.0f;
|
||||
dy/=3.0f;
|
||||
dz/=3.0f;
|
||||
*(p2-3)= *p2-dx;
|
||||
*(p2-2)= *(p2+1)-dy;
|
||||
*(p2-1)= *(p2+2)-dz;
|
||||
mul_v3_fl(dvec_a, 1.0f/3.0f);
|
||||
sub_v3_v3v3(p2-3, p2, dvec_a);
|
||||
}
|
||||
if(bezt->h2==HD_VECT) {
|
||||
dx1/=3.0f;
|
||||
dy1/=3.0f;
|
||||
dz1/=3.0f;
|
||||
*(p2+3)= *p2+dx1;
|
||||
*(p2+4)= *(p2+1)+dy1;
|
||||
*(p2+5)= *(p2+2)+dz1;
|
||||
mul_v3_fl(dvec_b, 1.0f/3.0f);
|
||||
sub_v3_v3v3(p2+3, p2, dvec_b);
|
||||
}
|
||||
|
||||
len2= len_v3v3(p2, p2+3);
|
||||
len1= len_v3v3(p2, p2-3);
|
||||
if(len1==0.0f) len1= 1.0f;
|
||||
if(len2==0.0f) len2= 1.0f;
|
||||
len_b= len_v3v3(p2, p2+3);
|
||||
len_a= len_v3v3(p2, p2-3);
|
||||
if(len_a==0.0f) len_a= 1.0f;
|
||||
if(len_b==0.0f) len_b= 1.0f;
|
||||
|
||||
if(bezt->f1 & SELECT) { /* order of calculation */
|
||||
if(bezt->h2==HD_ALIGN) { /* aligned */
|
||||
if(len1>eps) {
|
||||
len= len2/len1;
|
||||
p2[3]= p2[0]+len*(p2[0]-p2[-3]);
|
||||
p2[4]= p2[1]+len*(p2[1]-p2[-2]);
|
||||
p2[5]= p2[2]+len*(p2[2]-p2[-1]);
|
||||
if(bezt->h2==HD_ALIGN) { /* aligned */
|
||||
if(len_a>eps) {
|
||||
len= len_b/len_a;
|
||||
p2[3]= p2[0]+len*(p2[0] - p2[-3]);
|
||||
p2[4]= p2[1]+len*(p2[1] - p2[-2]);
|
||||
p2[5]= p2[2]+len*(p2[2] - p2[-1]);
|
||||
}
|
||||
}
|
||||
if(bezt->h1==HD_ALIGN) {
|
||||
if(len2>eps) {
|
||||
len= len1/len2;
|
||||
p2[-3]= p2[0]+len*(p2[0]-p2[3]);
|
||||
p2[-2]= p2[1]+len*(p2[1]-p2[4]);
|
||||
p2[-1]= p2[2]+len*(p2[2]-p2[5]);
|
||||
if(len_b>eps) {
|
||||
len= len_a/len_b;
|
||||
p2[-3]= p2[0]+len*(p2[0] - p2[3]);
|
||||
p2[-2]= p2[1]+len*(p2[1] - p2[4]);
|
||||
p2[-1]= p2[2]+len*(p2[2] - p2[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(bezt->h1==HD_ALIGN) {
|
||||
if(len2>eps) {
|
||||
len= len1/len2;
|
||||
p2[-3]= p2[0]+len*(p2[0]-p2[3]);
|
||||
p2[-2]= p2[1]+len*(p2[1]-p2[4]);
|
||||
p2[-1]= p2[2]+len*(p2[2]-p2[5]);
|
||||
if(len_b>eps) {
|
||||
len= len_a/len_b;
|
||||
p2[-3]= p2[0]+len*(p2[0] - p2[3]);
|
||||
p2[-2]= p2[1]+len*(p2[1] - p2[4]);
|
||||
p2[-1]= p2[2]+len*(p2[2] - p2[5]);
|
||||
}
|
||||
}
|
||||
if(bezt->h2==HD_ALIGN) { /* aligned */
|
||||
if(len1>eps) {
|
||||
len= len2/len1;
|
||||
p2[3]= p2[0]+len*(p2[0]-p2[-3]);
|
||||
p2[4]= p2[1]+len*(p2[1]-p2[-2]);
|
||||
p2[5]= p2[2]+len*(p2[2]-p2[-1]);
|
||||
if(len_a>eps) {
|
||||
len= len_b/len_a;
|
||||
p2[3]= p2[0]+len*(p2[0] - p2[-3]);
|
||||
p2[4]= p2[1]+len*(p2[1] - p2[-2]);
|
||||
p2[5]= p2[2]+len*(p2[2] - p2[-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -818,7 +818,7 @@ void calchandles_fcurve (FCurve *fcu)
|
||||
* -> Vector handles: become 'nothing' when (one half selected AND other not)
|
||||
* - PHASE 2: recalculate handles
|
||||
*/
|
||||
void testhandles_fcurve (FCurve *fcu)
|
||||
void testhandles_fcurve (FCurve *fcu, const short use_handle)
|
||||
{
|
||||
BezTriple *bezt;
|
||||
unsigned int a;
|
||||
@ -834,9 +834,16 @@ void testhandles_fcurve (FCurve *fcu)
|
||||
/* flag is initialised as selection status
|
||||
* of beztriple control-points (labelled 0,1,2)
|
||||
*/
|
||||
if (bezt->f1 & SELECT) flag |= (1<<0); // == 1
|
||||
if (bezt->f2 & SELECT) flag |= (1<<1); // == 2
|
||||
if (bezt->f3 & SELECT) flag |= (1<<2); // == 4
|
||||
if(use_handle == FALSE) {
|
||||
if(flag & 2) {
|
||||
flag |= (1<<0) | (1<<2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (bezt->f1 & SELECT) flag |= (1<<0); // == 1
|
||||
if (bezt->f3 & SELECT) flag |= (1<<2); // == 4
|
||||
}
|
||||
|
||||
/* one or two handles selected only */
|
||||
if (ELEM(flag, 0, 7)==0) {
|
||||
|
@ -913,7 +913,7 @@ static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z
|
||||
{
|
||||
// Solves for unknown X in equation AX=B
|
||||
unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100;
|
||||
float conjgrad_epsilon=0.0001f, conjgrad_lasterror=0;
|
||||
float conjgrad_epsilon=0.0001f /* , conjgrad_lasterror=0 */ /* UNUSED */;
|
||||
lfVector *q, *d, *tmp, *r;
|
||||
float s, starget, a, s_prev;
|
||||
unsigned int numverts = lA[0].vcount;
|
||||
@ -964,7 +964,7 @@ static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z
|
||||
|
||||
conjgrad_loopcount++;
|
||||
}
|
||||
conjgrad_lasterror = s;
|
||||
/* conjgrad_lasterror = s; */ /* UNUSED */
|
||||
|
||||
del_lfvector(q);
|
||||
del_lfvector(d);
|
||||
@ -1777,7 +1777,7 @@ int cloth_calc_helper_forces(Object *UNUSED(ob), ClothModifierData * clmd, float
|
||||
steps = 55;
|
||||
for (i=0; i<steps; i++) {
|
||||
for (node=cloth->springs; node; node=node->next) {
|
||||
ClothVertex *cv1, *cv2;
|
||||
/* ClothVertex *cv1, *cv2; */ /* UNUSED */
|
||||
int v1, v2;
|
||||
float len, c, l, vec[3];
|
||||
|
||||
@ -1786,8 +1786,8 @@ int cloth_calc_helper_forces(Object *UNUSED(ob), ClothModifierData * clmd, float
|
||||
continue;
|
||||
|
||||
v1 = spring->ij; v2 = spring->kl;
|
||||
cv1 = cloth->verts + v1;
|
||||
cv2 = cloth->verts + v2;
|
||||
/* cv1 = cloth->verts + v1; */ /* UNUSED */
|
||||
/* cv2 = cloth->verts + v2; */ /* UNUSED */
|
||||
len = len_v3v3(cos[v1], cos[v2]);
|
||||
|
||||
sub_v3_v3v3(vec, cos[v1], cos[v2]);
|
||||
|
@ -1177,7 +1177,7 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp)
|
||||
int nvert = (mface->v4)? 4: 3;
|
||||
int newtotdisp = multires_grid_tot[newlvl]*nvert;
|
||||
int x, y, S;
|
||||
float (*disps)[3], (*out)[3], u, v;
|
||||
float (*disps)[3], (*out)[3], u = 0.0f, v = 0.0f; /* Quite gcc barking. */
|
||||
|
||||
disps = BLI_cellalloc_calloc(sizeof(float) * 3 * newtotdisp, "multires disps");
|
||||
|
||||
|
@ -328,14 +328,10 @@ struct SortContext
|
||||
const int* trisToFacesMap;
|
||||
};
|
||||
|
||||
/* XXX: not thread-safe, but it's called only from modifiers stack
|
||||
which isn't threaded. Anyway, better to avoid this in the future */
|
||||
static struct SortContext *_qsort_context;
|
||||
|
||||
static int compareByData(const void * a, const void * b)
|
||||
static int compareByData(void *ctx, const void * a, const void * b)
|
||||
{
|
||||
return ( _qsort_context->recastData[_qsort_context->trisToFacesMap[*(int*)a]] -
|
||||
_qsort_context->recastData[_qsort_context->trisToFacesMap[*(int*)b]] );
|
||||
return (((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)a]] -
|
||||
((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)b]] );
|
||||
}
|
||||
|
||||
int buildNavMeshData(const int nverts, const float* verts,
|
||||
@ -367,8 +363,7 @@ int buildNavMeshData(const int nverts, const float* verts,
|
||||
trisMapping[i]=i;
|
||||
context.recastData = recastData;
|
||||
context.trisToFacesMap = trisToFacesMap;
|
||||
_qsort_context = &context;
|
||||
qsort(trisMapping, ntris, sizeof(int), compareByData);
|
||||
recast_qsort(trisMapping, ntris, sizeof(int), &context, compareByData);
|
||||
|
||||
//search first valid triangle - triangle of convex polygon
|
||||
validTriStart = -1;
|
||||
|
@ -3067,6 +3067,82 @@ void object_camera_matrix(
|
||||
|
||||
}
|
||||
|
||||
void camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, const short do_clip, const float scale[3],
|
||||
float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3])
|
||||
{
|
||||
float aspx, aspy;
|
||||
float facx, facy;
|
||||
float depth;
|
||||
|
||||
/* aspect correcton */
|
||||
if (scene) {
|
||||
aspx= (float) scene->r.xsch*scene->r.xasp;
|
||||
aspy= (float) scene->r.ysch*scene->r.yasp;
|
||||
|
||||
if(aspx < aspy) {
|
||||
r_asp[0]= aspx / aspy;
|
||||
r_asp[1]= 1.0;
|
||||
}
|
||||
else {
|
||||
r_asp[0]= 1.0;
|
||||
r_asp[1]= aspy / aspx;
|
||||
}
|
||||
}
|
||||
else {
|
||||
aspx= 1.0f;
|
||||
aspy= 1.0f;
|
||||
r_asp[0]= 1.0f;
|
||||
r_asp[1]= 1.0f;
|
||||
}
|
||||
|
||||
if(camera->type==CAM_ORTHO) {
|
||||
facx= 0.5f * camera->ortho_scale * r_asp[0] * scale[0];
|
||||
facy= 0.5f * camera->ortho_scale * r_asp[1] * scale[1];
|
||||
r_shift[0]= camera->shiftx * camera->ortho_scale * scale[0];
|
||||
r_shift[1]= camera->shifty * camera->ortho_scale * scale[1];
|
||||
depth= do_clip ? -((camera->clipsta * scale[2]) + 0.1f) : - drawsize * camera->ortho_scale * scale[2];
|
||||
|
||||
*r_drawsize= 0.5f * camera->ortho_scale;
|
||||
}
|
||||
else {
|
||||
/* that way it's always visible - clipsta+0.1 */
|
||||
float fac;
|
||||
*r_drawsize= drawsize / ((scale[0] + scale[1] + scale[2]) / 3.0f);
|
||||
|
||||
if(do_clip) {
|
||||
/* fixed depth, variable size (avoids exceeding clipping range) */
|
||||
depth = -(camera->clipsta + 0.1f);
|
||||
fac = depth / (camera->lens/-16.0f * scale[2]);
|
||||
}
|
||||
else {
|
||||
/* fixed size, variable depth (stays a reasonable size in the 3D view) */
|
||||
depth= *r_drawsize * camera->lens/-16.0f * scale[2];
|
||||
fac= *r_drawsize;
|
||||
}
|
||||
|
||||
facx= fac * r_asp[0] * scale[0];
|
||||
facy= fac * r_asp[1] * scale[1];
|
||||
r_shift[0]= camera->shiftx*fac*2 * scale[0];
|
||||
r_shift[1]= camera->shifty*fac*2 * scale[1];
|
||||
}
|
||||
|
||||
r_vec[0][0]= r_shift[0] + facx; r_vec[0][1]= r_shift[1] + facy; r_vec[0][2]= depth;
|
||||
r_vec[1][0]= r_shift[0] + facx; r_vec[1][1]= r_shift[1] - facy; r_vec[1][2]= depth;
|
||||
r_vec[2][0]= r_shift[0] - facx; r_vec[2][1]= r_shift[1] - facy; r_vec[2][2]= depth;
|
||||
r_vec[3][0]= r_shift[0] - facx; r_vec[3][1]= r_shift[1] + facy; r_vec[3][2]= depth;
|
||||
}
|
||||
|
||||
void camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3])
|
||||
{
|
||||
float dummy_asp[2];
|
||||
float dummy_shift[2];
|
||||
float dummy_drawsize;
|
||||
const float dummy_scale[3]= {1.0f, 1.0f, 1.0f};
|
||||
|
||||
camera_view_frame_ex(scene, camera, FALSE, 1.0, dummy_scale,
|
||||
dummy_asp, dummy_shift, &dummy_drawsize, r_vec);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int pc_findindex(ListBase *listbase, int index)
|
||||
{
|
||||
|
@ -526,7 +526,7 @@ Scene *add_scene(const char *name)
|
||||
sce->gm.recastData.agentradius = 0.6f;
|
||||
sce->gm.recastData.edgemaxlen = 12.0f;
|
||||
sce->gm.recastData.edgemaxerror = 1.3f;
|
||||
sce->gm.recastData.regionminsize = 50.f;
|
||||
sce->gm.recastData.regionminsize = 8.f;
|
||||
sce->gm.recastData.regionmergesize = 20.f;
|
||||
sce->gm.recastData.vertsperpoly = 6;
|
||||
sce->gm.recastData.detailsampledist = 6.0f;
|
||||
|
@ -1744,12 +1744,12 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
|
||||
GHash *hash;
|
||||
GHashIterator *ihash;
|
||||
float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], dv1[3],ve[3],avel[3]={0.0,0.0,0.0},
|
||||
vv1[3], vv2[3], vv3[3], vv4[3], coledge[3]={0.0f, 0.0f, 0.0f}, mindistedge = 1000.0f,
|
||||
outerforceaccu[3],innerforceaccu[3],
|
||||
facedist,n_mag,force_mag_norm,minx,miny,minz,maxx,maxy,maxz,
|
||||
innerfacethickness = -0.5f, outerfacethickness = 0.2f,
|
||||
ee = 5.0f, ff = 0.1f, fa=1;
|
||||
int a, deflected=0, cavel=0,ci=0;
|
||||
vv1[3], vv2[3], vv3[3], vv4[3], coledge[3]={0.0f, 0.0f, 0.0f}, mindistedge = 1000.0f,
|
||||
outerforceaccu[3], innerforceaccu[3],
|
||||
facedist, /* n_mag, */ /* UNUSED */ force_mag_norm, minx, miny, minz, maxx, maxy, maxz,
|
||||
innerfacethickness = -0.5f, outerfacethickness = 0.2f,
|
||||
ee = 5.0f, ff = 0.1f, fa=1;
|
||||
int a, deflected=0, cavel=0, ci=0;
|
||||
/* init */
|
||||
*intrusion = 0.0f;
|
||||
hash = vertexowner->soft->scratch->colliderhash;
|
||||
@ -1869,7 +1869,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
|
||||
VECSUB(dv1,opco,nv2); /* abuse dv1 to have vertex in question at *origin* of triangle */
|
||||
|
||||
cross_v3_v3v3(d_nvect, edge2, edge1);
|
||||
n_mag = normalize_v3(d_nvect);
|
||||
/* n_mag = */ /* UNUSED */ normalize_v3(d_nvect);
|
||||
facedist = dot_v3v3(dv1,d_nvect);
|
||||
// so rules are
|
||||
//
|
||||
@ -1906,7 +1906,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
|
||||
VECSUB(dv1,opco,nv4); /* abuse dv1 to have vertex in question at *origin* of triangle */
|
||||
|
||||
cross_v3_v3v3(d_nvect, edge2, edge1);
|
||||
n_mag = normalize_v3(d_nvect);
|
||||
/* n_mag = */ /* UNUSED */ normalize_v3(d_nvect);
|
||||
facedist = dot_v3v3(dv1,d_nvect);
|
||||
|
||||
if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
|
||||
|
@ -640,7 +640,11 @@ void default_mtex(MTex *mtex)
|
||||
mtex->size[1]= 1.0;
|
||||
mtex->size[2]= 1.0;
|
||||
mtex->tex= NULL;
|
||||
mtex->texflag= MTEX_3TAP_BUMP | MTEX_BUMP_OBJECTSPACE;
|
||||
|
||||
/* MTEX_BUMP_FLIPPED is temporary before 2.61 release to prevent flipping normals
|
||||
when creating file in 2.60, opening it in 2.59, saving and opening in 2.60 again */
|
||||
mtex->texflag= MTEX_3TAP_BUMP | MTEX_BUMP_OBJECTSPACE | MTEX_BUMP_FLIPPED;
|
||||
|
||||
mtex->colormodel= 0;
|
||||
mtex->r= 1.0;
|
||||
mtex->g= 0.0;
|
||||
|
@ -7124,7 +7124,7 @@ void convert_tface_mt(FileData *fd, Main *main)
|
||||
G.main = main;
|
||||
|
||||
if(!(do_version_tface(main, 1))) {
|
||||
BKE_report(fd->reports, RPT_ERROR, "Texface conversion problem. Error in console");
|
||||
BKE_report(fd->reports, RPT_WARNING, "Texface conversion problem. Error in console");
|
||||
}
|
||||
|
||||
//XXX hack, material.c uses G.main allover the place, instead of main
|
||||
@ -12129,9 +12129,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
/* put compatibility code here until next subversion bump */
|
||||
|
||||
{
|
||||
if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 4)){
|
||||
{
|
||||
/* Adaptive time step for particle systems */
|
||||
ParticleSettings *part;
|
||||
@ -12140,45 +12138,72 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
part->time_flag &= ~PART_TIME_AUTOSF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//set defaults for obstacle avoidance, recast data
|
||||
{
|
||||
Scene *sce;
|
||||
for(sce = main->scene.first; sce; sce = sce->id.next)
|
||||
{
|
||||
if (sce->gm.levelHeight == 0.f)
|
||||
sce->gm.levelHeight = 2.f;
|
||||
/* set defaults for obstacle avoidance, recast data */
|
||||
Scene *sce;
|
||||
for(sce = main->scene.first; sce; sce = sce->id.next)
|
||||
{
|
||||
if (sce->gm.levelHeight == 0.f)
|
||||
sce->gm.levelHeight = 2.f;
|
||||
|
||||
if(sce->gm.recastData.cellsize == 0.0f)
|
||||
sce->gm.recastData.cellsize = 0.3f;
|
||||
if(sce->gm.recastData.cellheight == 0.0f)
|
||||
sce->gm.recastData.cellheight = 0.2f;
|
||||
if(sce->gm.recastData.agentmaxslope == 0.0f)
|
||||
sce->gm.recastData.agentmaxslope = (float)M_PI/4;
|
||||
if(sce->gm.recastData.agentmaxclimb == 0.0f)
|
||||
sce->gm.recastData.agentmaxclimb = 0.9f;
|
||||
if(sce->gm.recastData.agentheight == 0.0f)
|
||||
sce->gm.recastData.agentheight = 2.0f;
|
||||
if(sce->gm.recastData.agentradius == 0.0f)
|
||||
sce->gm.recastData.agentradius = 0.6f;
|
||||
if(sce->gm.recastData.edgemaxlen == 0.0f)
|
||||
sce->gm.recastData.edgemaxlen = 12.0f;
|
||||
if(sce->gm.recastData.edgemaxerror == 0.0f)
|
||||
sce->gm.recastData.edgemaxerror = 1.3f;
|
||||
if(sce->gm.recastData.regionminsize == 0.0f)
|
||||
sce->gm.recastData.regionminsize = 8.f;
|
||||
if(sce->gm.recastData.regionmergesize == 0.0f)
|
||||
sce->gm.recastData.regionmergesize = 20.f;
|
||||
if(sce->gm.recastData.vertsperpoly<3)
|
||||
sce->gm.recastData.vertsperpoly = 6;
|
||||
if(sce->gm.recastData.detailsampledist == 0.0f)
|
||||
sce->gm.recastData.detailsampledist = 6.0f;
|
||||
if(sce->gm.recastData.detailsamplemaxerror == 0.0f)
|
||||
sce->gm.recastData.detailsamplemaxerror = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* flip normals */
|
||||
Material *ma= main->mat.first;
|
||||
while(ma) {
|
||||
int a;
|
||||
for(a= 0; a<MAX_MTEX; a++) {
|
||||
MTex *mtex= ma->mtex[a];
|
||||
|
||||
if(mtex) {
|
||||
if((mtex->texflag&MTEX_BUMP_FLIPPED)==0) {
|
||||
if((mtex->mapto&MAP_NORM) && mtex->texflag&(MTEX_COMPAT_BUMP|MTEX_3TAP_BUMP|MTEX_5TAP_BUMP)) {
|
||||
mtex->norfac= -mtex->norfac;
|
||||
mtex->texflag|= MTEX_BUMP_FLIPPED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ma= ma->id.next;
|
||||
}
|
||||
}
|
||||
|
||||
if(sce->gm.recastData.cellsize == 0.0f)
|
||||
sce->gm.recastData.cellsize = 0.3f;
|
||||
if(sce->gm.recastData.cellheight == 0.0f)
|
||||
sce->gm.recastData.cellheight = 0.2f;
|
||||
if(sce->gm.recastData.agentmaxslope == 0.0f)
|
||||
sce->gm.recastData.agentmaxslope = (float)M_PI/4;
|
||||
if(sce->gm.recastData.agentmaxclimb == 0.0f)
|
||||
sce->gm.recastData.agentmaxclimb = 0.9f;
|
||||
if(sce->gm.recastData.agentheight == 0.0f)
|
||||
sce->gm.recastData.agentheight = 2.0f;
|
||||
if(sce->gm.recastData.agentradius == 0.0f)
|
||||
sce->gm.recastData.agentradius = 0.6f;
|
||||
if(sce->gm.recastData.edgemaxlen == 0.0f)
|
||||
sce->gm.recastData.edgemaxlen = 12.0f;
|
||||
if(sce->gm.recastData.edgemaxerror == 0.0f)
|
||||
sce->gm.recastData.edgemaxerror = 1.3f;
|
||||
if(sce->gm.recastData.regionminsize == 0.0f)
|
||||
sce->gm.recastData.regionminsize = 50.f;
|
||||
if(sce->gm.recastData.regionmergesize == 0.0f)
|
||||
sce->gm.recastData.regionmergesize = 20.f;
|
||||
if(sce->gm.recastData.vertsperpoly<3)
|
||||
sce->gm.recastData.vertsperpoly = 6;
|
||||
if(sce->gm.recastData.detailsampledist == 0.0f)
|
||||
sce->gm.recastData.detailsampledist = 6.0f;
|
||||
if(sce->gm.recastData.detailsamplemaxerror == 0.0f)
|
||||
sce->gm.recastData.detailsamplemaxerror = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* put compatibility code here until next subversion bump */
|
||||
{
|
||||
}
|
||||
|
||||
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
||||
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
|
||||
|
||||
|
@ -343,6 +343,13 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
|
||||
* channel can be kept around). No need to clear channels-flag in order to
|
||||
* keep expander channels with no sub-data out, as those cases should get
|
||||
* dealt with by the recursive detection idiom in place.
|
||||
*
|
||||
* Implementation Note:
|
||||
* YES the _doSubChannels variable is NOT read anywhere. BUT, this is NOT an excuse
|
||||
* to go steamrolling the logic into a single-line expression as from experience,
|
||||
* those are notoriously difficult to read + debug when extending later on. The code
|
||||
* below is purposefully laid out so that each case noted above corresponds clearly to
|
||||
* one case below.
|
||||
*/
|
||||
#define BEGIN_ANIMFILTER_SUBCHANNELS(expanded_check) \
|
||||
{ \
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "BKE_fcurve.h"
|
||||
@ -386,6 +387,9 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
/* when not in graph view, don't use handles */
|
||||
SpaceIpo *sipo= (ac->spacetype == SPACE_IPO) ? (SpaceIpo *)ac->sl : NULL;
|
||||
const short use_handle = sipo ? !(sipo->flag & SIPO_NOHANDLES) : FALSE;
|
||||
|
||||
/* filter animation data */
|
||||
filter= ANIMFILTER_DATA_VISIBLE;
|
||||
@ -397,7 +401,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
|
||||
|
||||
/* make sure keyframes in F-Curve are all in order, and handles are in valid positions */
|
||||
sort_time_fcurve(fcu);
|
||||
testhandles_fcurve(fcu);
|
||||
testhandles_fcurve(fcu, use_handle);
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
|
@ -787,6 +787,7 @@ void UI_buttons_operatortypes(void);
|
||||
|
||||
/* Helpers for Operators */
|
||||
void uiContextActiveProperty(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index);
|
||||
void uiContextActivePropertyHandle(struct bContext *C);
|
||||
void uiContextAnimUpdate(const struct bContext *C);
|
||||
void uiFileBrowseContextProperty(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
|
||||
void uiIDContextProperty(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
|
||||
|
@ -678,6 +678,11 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut
|
||||
SWAP(void *, oldbut->func_argN, but->func_argN)
|
||||
}
|
||||
|
||||
/* copy hardmin for list rows to prevent 'sticking' highlight to mouse position
|
||||
when scrolling without moving mouse (see [#28432]) */
|
||||
if(ELEM(oldbut->type, ROW, LISTROW))
|
||||
oldbut->hardmax= but->hardmax;
|
||||
|
||||
ui_but_update_linklines(block, oldbut, but);
|
||||
|
||||
BLI_remlink(&block->buttons, but);
|
||||
@ -746,7 +751,7 @@ static int ui_but_is_rna_undo(uiBut *but)
|
||||
* unforseen conciquences, so best check for ID's we _know_ are not
|
||||
* handled by undo - campbell */
|
||||
ID *id= but->rnapoin.id.data;
|
||||
if(ELEM(GS(id->name), ID_SCR, ID_WM)) {
|
||||
if(ID_CHECK_UNDO(id) == FALSE) {
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
@ -2467,7 +2472,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
|
||||
but->pointype= type & BUTPOIN;
|
||||
but->bit= type & BIT;
|
||||
but->bitnr= type & 31;
|
||||
but->icon = 0;
|
||||
but->icon = ICON_NONE;
|
||||
but->iconadd=0;
|
||||
|
||||
but->retval= retval;
|
||||
|
@ -466,6 +466,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
|
||||
{
|
||||
#ifdef WITH_HEADLESS
|
||||
(void)rect;
|
||||
(void)but;
|
||||
#else
|
||||
ImBuf *ibuf= (ImBuf *)but->poin;
|
||||
//GLint scissor[4];
|
||||
|
@ -5089,19 +5089,16 @@ void ui_button_active_free(const bContext *C, uiBut *but)
|
||||
}
|
||||
}
|
||||
|
||||
/* helper function for insert keyframe, reset to default, etc operators */
|
||||
void uiContextActiveProperty(const bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index)
|
||||
static uiBut *ui_context_rna_button_active(const bContext *C)
|
||||
{
|
||||
ARegion *ar= CTX_wm_region(C);
|
||||
uiBut *rnabut= NULL;
|
||||
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
*prop= NULL;
|
||||
*index= 0;
|
||||
ARegion *ar= CTX_wm_region(C);
|
||||
|
||||
while(ar) {
|
||||
uiBlock *block;
|
||||
uiBut *but, *activebut= NULL;
|
||||
|
||||
|
||||
/* find active button */
|
||||
for(block=ar->uiblocks.first; block; block=block->next) {
|
||||
for(but=block->buttons.first; but; but= but->next) {
|
||||
@ -5115,24 +5112,53 @@ void uiContextActiveProperty(const bContext *C, struct PointerRNA *ptr, struct P
|
||||
if(activebut && activebut->rnapoin.data) {
|
||||
uiHandleButtonData *data= activebut->active;
|
||||
|
||||
/* found RNA button */
|
||||
*ptr= activebut->rnapoin;
|
||||
*prop= activebut->rnaprop;
|
||||
*index= activebut->rnaindex;
|
||||
rnabut= activebut;
|
||||
|
||||
/* recurse into opened menu, like colorpicker case */
|
||||
if(data && data->menu && (ar != data->menu->region)) {
|
||||
ar = data->menu->region;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
return rnabut;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* no active button */
|
||||
return;
|
||||
return rnabut;
|
||||
}
|
||||
}
|
||||
|
||||
return rnabut;
|
||||
}
|
||||
|
||||
/* helper function for insert keyframe, reset to default, etc operators */
|
||||
void uiContextActiveProperty(const bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index)
|
||||
{
|
||||
uiBut *activebut= ui_context_rna_button_active(C);
|
||||
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
|
||||
if(activebut && activebut->rnapoin.data) {
|
||||
*ptr= activebut->rnapoin;
|
||||
*prop= activebut->rnaprop;
|
||||
*index= activebut->rnaindex;
|
||||
}
|
||||
else {
|
||||
*prop= NULL;
|
||||
*index= 0;
|
||||
}
|
||||
}
|
||||
|
||||
void uiContextActivePropertyHandle(bContext *C)
|
||||
{
|
||||
uiBut *activebut= ui_context_rna_button_active(C);
|
||||
if(activebut) {
|
||||
/* TODO, look into a better way to handle the button change
|
||||
* currently this is mainly so reset defaults works for the
|
||||
* operator redo panel - campbell */
|
||||
uiBlock *block= activebut->block;
|
||||
block->handle_func(C, block->handle_func_arg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* helper function for insert keyframe, reset to default, etc operators */
|
||||
|
@ -1018,9 +1018,9 @@ static void ui_id_icon_render(bContext *C, ID *id, int big)
|
||||
{
|
||||
/* create the rect if necessary */
|
||||
|
||||
icon_set_image(C, id, pi, 0); /* icon size */
|
||||
icon_set_image(C, id, pi, ICON_SIZE_ICON); /* icon size */
|
||||
if (big)
|
||||
icon_set_image(C, id, pi, 1); /* bigger preview size */
|
||||
icon_set_image(C, id, pi, ICON_SIZE_PREVIEW); /* bigger preview size */
|
||||
|
||||
pi->changed[0] = 0;
|
||||
}
|
||||
@ -1030,7 +1030,7 @@ static void ui_id_icon_render(bContext *C, ID *id, int big)
|
||||
static void ui_id_brush_render(bContext *C, ID *id)
|
||||
{
|
||||
PreviewImage *pi = BKE_previewimg_get(id);
|
||||
int i;
|
||||
enum eIconSizes i;
|
||||
|
||||
if(!pi)
|
||||
return;
|
||||
|
@ -295,10 +295,28 @@ static int reset_default_button_exec(bContext *C, wmOperator *op)
|
||||
if(RNA_property_reset(&ptr, prop, (all)? -1: index)) {
|
||||
/* perform updates required for this property */
|
||||
RNA_property_update(C, &ptr, prop);
|
||||
|
||||
/* as if we pressed the button */
|
||||
uiContextActivePropertyHandle(C);
|
||||
|
||||
success= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Since we dont want to undo _all_ edits to settings, eg window
|
||||
* edits on the screen or on operator settings.
|
||||
* it might be better to move undo's inline - campbell */
|
||||
if(success) {
|
||||
ID *id= ptr.id.data;
|
||||
if(id && ID_CHECK_UNDO(id)) {
|
||||
/* do nothing, go ahead with undo */
|
||||
}
|
||||
else {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
/* end hack */
|
||||
|
||||
return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
@ -314,7 +332,7 @@ static void UI_OT_reset_default_button(wmOperatorType *ot)
|
||||
ot->exec= reset_default_button_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
ot->flag= OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
|
||||
|
@ -415,7 +415,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
|
||||
BLI_snprintf(str, sizeof(str), "%d", id->us);
|
||||
|
||||
but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X + ((id->us < 10) ? 0:10), UI_UNIT_Y, NULL, 0, 0, 0, 0,
|
||||
UI_translate_do_tooltip(_("Displays number of users of this data. Click to make a single-user copy")));
|
||||
UI_translate_do_tooltip(_("Display number of users of this data (click to make a single-user copy)")));
|
||||
|
||||
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
|
||||
if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib) || !editable)
|
||||
|
@ -174,7 +174,7 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
|
||||
struct recast_compactHeightfield* chf;
|
||||
struct recast_contourSet *cset;
|
||||
int width, height, walkableHeight, walkableClimb, walkableRadius;
|
||||
int minRegionSize, mergeRegionSize, maxEdgeLen;
|
||||
int minRegionArea, mergeRegionArea, maxEdgeLen;
|
||||
float detailSampleDist, detailSampleMaxError;
|
||||
|
||||
recast_calcBounds(verts, nverts, bmin, bmax);
|
||||
@ -183,8 +183,8 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
|
||||
walkableHeight= (int)ceilf(recastParams->agentheight/ recastParams->cellheight);
|
||||
walkableClimb= (int)floorf(recastParams->agentmaxclimb / recastParams->cellheight);
|
||||
walkableRadius= (int)ceilf(recastParams->agentradius / recastParams->cellsize);
|
||||
minRegionSize= (int)(recastParams->regionminsize * recastParams->regionminsize);
|
||||
mergeRegionSize= (int)(recastParams->regionmergesize * recastParams->regionmergesize);
|
||||
minRegionArea= (int)(recastParams->regionminsize * recastParams->regionminsize);
|
||||
mergeRegionArea= (int)(recastParams->regionmergesize * recastParams->regionmergesize);
|
||||
maxEdgeLen= (int)(recastParams->edgemaxlen/recastParams->cellsize);
|
||||
detailSampleDist= recastParams->detailsampledist< 0.9f ? 0 :
|
||||
recastParams->cellsize * recastParams->detailsampledist;
|
||||
@ -212,13 +212,14 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
|
||||
MEM_freeN(triflags);
|
||||
|
||||
/* ** Step 3: Filter walkables surfaces ** */
|
||||
recast_filterLowHangingWalkableObstacles(walkableClimb, solid);
|
||||
recast_filterLedgeSpans(walkableHeight, walkableClimb, solid);
|
||||
recast_filterWalkableLowHeightSpans(walkableHeight, solid);
|
||||
|
||||
/* ** Step 4: Partition walkable surface to simple regions ** */
|
||||
|
||||
chf= recast_newCompactHeightfield();
|
||||
if(!recast_buildCompactHeightfield(walkableHeight, walkableClimb, RECAST_WALKABLE, solid, chf)) {
|
||||
if(!recast_buildCompactHeightfield(walkableHeight, walkableClimb, solid, chf)) {
|
||||
recast_destroyHeightfield(solid);
|
||||
recast_destroyCompactHeightfield(chf);
|
||||
|
||||
@ -226,6 +227,13 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
|
||||
}
|
||||
|
||||
recast_destroyHeightfield(solid);
|
||||
solid = NULL;
|
||||
|
||||
if (!recast_erodeWalkableArea(walkableRadius, chf)) {
|
||||
recast_destroyCompactHeightfield(chf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prepare for region partitioning, by calculating distance field along the walkable surface */
|
||||
if(!recast_buildDistanceField(chf)) {
|
||||
@ -235,7 +243,7 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
|
||||
}
|
||||
|
||||
/* Partition the walkable surface into simple regions without holes */
|
||||
if(!recast_buildRegions(chf, walkableRadius, 0, minRegionSize, mergeRegionSize)) {
|
||||
if(!recast_buildRegions(chf, 0, minRegionArea, mergeRegionArea)) {
|
||||
recast_destroyCompactHeightfield(chf);
|
||||
|
||||
return 0;
|
||||
@ -293,7 +301,8 @@ static Object* createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
|
||||
Object* obedit;
|
||||
int createob= base==NULL;
|
||||
int nverts, nmeshes, nvp;
|
||||
unsigned short *verts, *meshes, *polys;
|
||||
unsigned short *verts, *polys;
|
||||
unsigned int *meshes;
|
||||
float bmin[3], cs, ch, *dverts;
|
||||
unsigned char *tris;
|
||||
ModifierData *md;
|
||||
@ -348,7 +357,7 @@ static Object* createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
|
||||
|
||||
for(i= 0; i<nmeshes; i++) {
|
||||
int uniquevbase= em->totvert;
|
||||
unsigned short vbase= meshes[4*i+0];
|
||||
unsigned int vbase= meshes[4*i+0];
|
||||
unsigned short ndv= meshes[4*i+1];
|
||||
unsigned short tribase= meshes[4*i+2];
|
||||
unsigned short trinum= meshes[4*i+3];
|
||||
|
@ -1145,7 +1145,7 @@ static int fluid_bake_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)
|
||||
{
|
||||
/* only one bake job at a time */
|
||||
if(WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C)))
|
||||
return 0;
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
if(!fluidsimBake(C, op->reports, CTX_data_active_object(C), TRUE))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
@ -233,7 +233,8 @@ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max, cons
|
||||
|
||||
/* get data to filter, from Action or Dopesheet */
|
||||
// XXX: what is sel doing here?!
|
||||
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
||||
// Commented it, was breaking things (eg. the "auto preview range" tool).
|
||||
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_SEL *//*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
/* set large values to try to override */
|
||||
|
@ -245,13 +245,15 @@ static short get_active_fcurve_keyframe_edit(FCurve *fcu, BezTriple **bezt, BezT
|
||||
}
|
||||
|
||||
/* update callback for active keyframe properties - base updates stuff */
|
||||
static void graphedit_activekey_update_cb(bContext *UNUSED(C), void *fcu_ptr, void *UNUSED(bezt_ptr))
|
||||
static void graphedit_activekey_update_cb(bContext *C, void *fcu_ptr, void *UNUSED(bezt_ptr))
|
||||
{
|
||||
SpaceIpo *sipo= CTX_wm_space_graph(C);
|
||||
const short use_handle = !(sipo->flag & SIPO_NOHANDLES);
|
||||
FCurve *fcu = (FCurve *)fcu_ptr;
|
||||
|
||||
/* make sure F-Curve and its handles are still valid after this editing */
|
||||
sort_time_fcurve(fcu);
|
||||
testhandles_fcurve(fcu);
|
||||
testhandles_fcurve(fcu, use_handle);
|
||||
}
|
||||
|
||||
/* update callback for active keyframe properties - handle-editing wrapper */
|
||||
|
@ -182,6 +182,10 @@ static void outliner_main_area_listener(ARegion *ar, wmNotifier *wmn)
|
||||
case ND_NLA_ACTCHANGE:
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
case ND_ANIMCHAN:
|
||||
if(wmn->action==NA_SELECTED)
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ void SEQUENCER_OT_select_handles(struct wmOperatorType *ot);
|
||||
void SEQUENCER_OT_select_active_side(struct wmOperatorType *ot);
|
||||
void SEQUENCER_OT_select_border(struct wmOperatorType *ot);
|
||||
void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot);
|
||||
|
||||
void SEQUENCER_OT_select_grouped(struct wmOperatorType *ot);
|
||||
|
||||
/* sequencer_select.c */
|
||||
void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot);
|
||||
|
@ -103,7 +103,8 @@ void sequencer_operatortypes(void)
|
||||
WM_operatortype_append(SEQUENCER_OT_select_handles);
|
||||
WM_operatortype_append(SEQUENCER_OT_select_active_side);
|
||||
WM_operatortype_append(SEQUENCER_OT_select_border);
|
||||
|
||||
WM_operatortype_append(SEQUENCER_OT_select_grouped);
|
||||
|
||||
/* sequencer_add.c */
|
||||
WM_operatortype_append(SEQUENCER_OT_scene_strip_add);
|
||||
WM_operatortype_append(SEQUENCER_OT_movie_strip_add);
|
||||
@ -165,7 +166,7 @@ void sequencer_keymap(wmKeyConfig *keyconf)
|
||||
|
||||
WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_toggle", TABKEY, KM_PRESS, 0, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_make", GKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_make", GKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_separate", GKEY, KM_PRESS, KM_ALT, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
|
||||
@ -247,6 +248,8 @@ void sequencer_keymap(wmKeyConfig *keyconf)
|
||||
|
||||
WM_keymap_add_item(keymap, "SEQUENCER_OT_select_border", BKEY, KM_PRESS, 0, 0);
|
||||
|
||||
WM_keymap_add_item(keymap, "SEQUENCER_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
WM_keymap_add_menu(keymap, "SEQUENCER_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
WM_keymap_add_menu(keymap, "SEQUENCER_MT_change", CKEY, KM_PRESS, 0, 0);
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_sequencer.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
@ -882,3 +883,270 @@ void SEQUENCER_OT_select_border(wmOperatorType *ot)
|
||||
/* rna */
|
||||
WM_operator_properties_gesture_border(ot, FALSE);
|
||||
}
|
||||
|
||||
/* ****** Selected Grouped ****** */
|
||||
|
||||
static EnumPropertyItem sequencer_prop_select_grouped_types[] = {
|
||||
{1, "TYPE", 0, "Type", "Shared strip type"},
|
||||
{2, "TYPE_BASIC", 0, "Global Type", "All strips of same basic type (Graphical or Sound)"},
|
||||
{3, "TYPE_EFFECT", 0, "Effect Type",
|
||||
"Shared strip effect type (if active strip is not an effect one, select all non-effect strips)"},
|
||||
{4, "DATA", 0, "Data", "Shared data (scene, image, sound, etc.)"},
|
||||
{5, "EFFECT", 0, "Effect", "Shared effects"},
|
||||
{6, "EFFECT_LINK", 0, "Effect/Linked",
|
||||
"Other strips affected by the active one (sharing some time, and below or effect-assigned)"},
|
||||
{7, "OVERLAP", 0, "Overlap", "Overlapping time"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
#define SEQ_IS_SOUND(_seq) ((_seq->type & SEQ_SOUND) && !(_seq->type & SEQ_EFFECT))
|
||||
|
||||
#define SEQ_IS_EFFECT(_seq) (_seq->type & SEQ_EFFECT)
|
||||
|
||||
#define SEQ_USE_DATA(_seq) (_seq->type == SEQ_SCENE || SEQ_HAS_PATH(_seq))
|
||||
|
||||
static short select_grouped_type(Editing *ed, Sequence *actseq)
|
||||
{
|
||||
Sequence *seq;
|
||||
short changed = FALSE;
|
||||
|
||||
SEQP_BEGIN(ed, seq) {
|
||||
if (seq->type == actseq->type) {
|
||||
seq->flag |= SELECT;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
SEQ_END;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static short select_grouped_type_basic(Editing *ed, Sequence *actseq)
|
||||
{
|
||||
Sequence *seq;
|
||||
short changed = FALSE;
|
||||
short is_sound = SEQ_IS_SOUND(actseq);
|
||||
|
||||
SEQP_BEGIN(ed, seq) {
|
||||
if (is_sound ? SEQ_IS_SOUND(seq) : !SEQ_IS_SOUND(seq)) {
|
||||
seq->flag |= SELECT;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
SEQ_END;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static short select_grouped_type_effect(Editing *ed, Sequence *actseq)
|
||||
{
|
||||
Sequence *seq;
|
||||
short changed = FALSE;
|
||||
short is_effect = SEQ_IS_EFFECT(actseq);
|
||||
|
||||
SEQP_BEGIN(ed, seq) {
|
||||
if (is_effect ? SEQ_IS_EFFECT(seq) : !SEQ_IS_EFFECT(seq)) {
|
||||
seq->flag |= SELECT;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
SEQ_END;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static short select_grouped_data(Editing *ed, Sequence *actseq)
|
||||
{
|
||||
Sequence *seq;
|
||||
short changed = FALSE;
|
||||
Scene *sce = actseq->scene;
|
||||
char *dir = actseq->strip ? actseq->strip->dir : NULL;
|
||||
|
||||
if (!SEQ_USE_DATA(actseq))
|
||||
return changed;
|
||||
|
||||
if (SEQ_HAS_PATH(actseq) && dir) {
|
||||
SEQP_BEGIN(ed, seq) {
|
||||
if (SEQ_HAS_PATH(seq) && seq->strip && strcmp(seq->strip->dir, dir) == 0) {
|
||||
seq->flag |= SELECT;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
SEQ_END;
|
||||
}
|
||||
else {
|
||||
SEQP_BEGIN(ed, seq) {
|
||||
if (seq->type == SEQ_SCENE && seq->scene == sce) {
|
||||
seq->flag |= SELECT;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
SEQ_END;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static short select_grouped_effect(Editing *ed, Sequence *actseq)
|
||||
{
|
||||
Sequence *seq;
|
||||
short changed = FALSE;
|
||||
short effects[SEQ_EFFECT_MAX+1];
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= SEQ_EFFECT_MAX; i++)
|
||||
effects[i] = FALSE;
|
||||
|
||||
SEQP_BEGIN(ed, seq) {
|
||||
if (ELEM3(actseq, seq->seq1, seq->seq2, seq->seq3)) {
|
||||
effects[seq->type] = TRUE;
|
||||
}
|
||||
}
|
||||
SEQ_END;
|
||||
|
||||
SEQP_BEGIN(ed, seq) {
|
||||
if (effects[seq->type]) {
|
||||
if(seq->seq1) seq->seq1->flag |= SELECT;
|
||||
if(seq->seq2) seq->seq2->flag |= SELECT;
|
||||
if(seq->seq3) seq->seq3->flag |= SELECT;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
SEQ_END;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static short select_grouped_time_overlap(Editing *ed, Sequence *actseq)
|
||||
{
|
||||
Sequence *seq;
|
||||
short changed = FALSE;
|
||||
|
||||
SEQP_BEGIN(ed, seq) {
|
||||
if (!((seq->startdisp >= actseq->enddisp) || (seq->enddisp < actseq->startdisp))) {
|
||||
seq->flag |= SELECT;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
SEQ_END;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static short select_grouped_effect_link(Editing *ed, Sequence *actseq)
|
||||
{
|
||||
Sequence *seq = NULL;
|
||||
short changed = FALSE;
|
||||
short is_audio = ((actseq->type == SEQ_META) || SEQ_IS_SOUND(actseq));
|
||||
int startdisp = actseq->startdisp;
|
||||
int enddisp = actseq->enddisp;
|
||||
int machine = actseq->machine;
|
||||
SeqIterator iter;
|
||||
|
||||
SEQP_BEGIN(ed, seq) {
|
||||
seq->tmp= NULL;
|
||||
}
|
||||
SEQ_END;
|
||||
|
||||
seq->tmp= SET_INT_IN_POINTER(TRUE);
|
||||
|
||||
for(seq_begin(ed, &iter, 1); iter.valid; seq_next(&iter)) {
|
||||
seq = iter.seq;
|
||||
|
||||
/* Ignore all seqs already selected! */
|
||||
/* Ignore all seqs not sharing some time with active one. */
|
||||
/* Ignore all seqs of incompatible types (audio vs video). */
|
||||
if ((seq->flag & SELECT) || (seq->startdisp >= enddisp) || (seq->enddisp < startdisp)
|
||||
|| (!is_audio && SEQ_IS_SOUND(seq))
|
||||
|| (is_audio && !((seq->type == SEQ_META) || SEQ_IS_SOUND(seq))))
|
||||
continue;
|
||||
|
||||
/* If the seq is an effect one, we need extra cheking! */
|
||||
if (SEQ_IS_EFFECT(seq) && ((seq->seq1 && seq->seq1->tmp) ||
|
||||
(seq->seq2 && seq->seq2->tmp) ||
|
||||
(seq->seq3 && seq->seq3->tmp)))
|
||||
{
|
||||
if (startdisp > seq->startdisp) startdisp = seq->startdisp;
|
||||
if (enddisp < seq->enddisp) enddisp = seq->enddisp;
|
||||
if (machine < seq->machine) machine = seq->machine;
|
||||
|
||||
seq->tmp= SET_INT_IN_POINTER(TRUE);
|
||||
|
||||
seq->flag |= SELECT;
|
||||
changed = TRUE;
|
||||
|
||||
/* Unfortunately, we must restart checks from the begining. */
|
||||
seq_end(&iter);
|
||||
seq_begin(ed, &iter, 1);
|
||||
}
|
||||
|
||||
/* Video strips bellow active one, or any strip for audio (order do no matters here!). */
|
||||
else if (seq->machine < machine || is_audio) {
|
||||
seq->flag |= SELECT;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
seq_end(&iter);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = seq_give_editing(scene, 0);
|
||||
Sequence *seq, *actseq = seq_active_get(scene);
|
||||
int type = RNA_enum_get(op->ptr, "type");
|
||||
short changed = 0, extend;
|
||||
|
||||
extend = RNA_boolean_get(op->ptr, "extend");
|
||||
|
||||
if (actseq == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "No Active Sequence!");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (extend == 0) {
|
||||
SEQP_BEGIN(ed, seq) {
|
||||
seq->flag &= ~SELECT;
|
||||
changed = TRUE;
|
||||
}
|
||||
SEQ_END;
|
||||
}
|
||||
|
||||
if(type==1) changed |= select_grouped_type(ed, actseq);
|
||||
else if(type==2) changed |= select_grouped_type_basic(ed, actseq);
|
||||
else if(type==3) changed |= select_grouped_type_effect(ed, actseq);
|
||||
else if(type==4) changed |= select_grouped_data(ed, actseq);
|
||||
else if(type==5) changed |= select_grouped_effect(ed, actseq);
|
||||
else if(type==6) changed |= select_grouped_effect_link(ed, actseq);
|
||||
else if(type==7) changed |= select_grouped_time_overlap(ed, actseq);
|
||||
|
||||
if (changed) {
|
||||
WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER|NA_SELECTED, scene);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void SEQUENCER_OT_select_grouped(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Select Grouped";
|
||||
ot->description = "Select all strips grouped by various properties";
|
||||
ot->idname = "SEQUENCER_OT_select_grouped";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = WM_menu_invoke;
|
||||
ot->exec = sequencer_select_grouped_exec;
|
||||
ot->poll = sequencer_edit_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
|
||||
ot->prop = RNA_def_enum(ot->srna, "type", sequencer_prop_select_grouped_types, 0, "Type", "");
|
||||
}
|
||||
|
||||
|
@ -1373,15 +1373,12 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob
|
||||
{
|
||||
/* a standing up pyramid with (0,0,0) as top */
|
||||
Camera *cam;
|
||||
float vec[8][4], facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
|
||||
float tvec[3];
|
||||
float vec[4][3], asp[2], shift[2], scale[3];
|
||||
int i;
|
||||
float drawsize;
|
||||
const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
|
||||
|
||||
const float scax= 1.0f / len_v3(ob->obmat[0]);
|
||||
const float scay= 1.0f / len_v3(ob->obmat[1]);
|
||||
const float scaz= 1.0f / len_v3(ob->obmat[2]);
|
||||
|
||||
#ifdef VIEW3D_CAMERA_BORDER_HACK
|
||||
if(is_view && !(G.f & G_PICKSEL)) {
|
||||
glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
|
||||
@ -1391,82 +1388,43 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob
|
||||
#endif
|
||||
|
||||
cam= ob->data;
|
||||
aspx= (float) scene->r.xsch*scene->r.xasp;
|
||||
aspy= (float) scene->r.ysch*scene->r.yasp;
|
||||
|
||||
if(aspx < aspy) {
|
||||
caspx= aspx / aspy;
|
||||
caspy= 1.0;
|
||||
}
|
||||
else {
|
||||
caspx= 1.0;
|
||||
caspy= aspy / aspx;
|
||||
}
|
||||
|
||||
scale[0]= 1.0f / len_v3(ob->obmat[0]);
|
||||
scale[1]= 1.0f / len_v3(ob->obmat[1]);
|
||||
scale[2]= 1.0f / len_v3(ob->obmat[2]);
|
||||
|
||||
camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
|
||||
asp, shift, &drawsize, vec);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
if(cam->type==CAM_ORTHO) {
|
||||
facx= 0.5f * cam->ortho_scale * caspx * scax;
|
||||
facy= 0.5f * cam->ortho_scale * caspy * scay;
|
||||
shx= cam->shiftx * cam->ortho_scale * scax;
|
||||
shy= cam->shifty * cam->ortho_scale * scay;
|
||||
depth= is_view ? -((cam->clipsta * scaz) + 0.1f) : - cam->drawsize * cam->ortho_scale * scaz;
|
||||
|
||||
drawsize= 0.5f * cam->ortho_scale;
|
||||
}
|
||||
else {
|
||||
/* that way it's always visible - clipsta+0.1 */
|
||||
float fac;
|
||||
drawsize= cam->drawsize / ((scax + scay + scaz) / 3.0f);
|
||||
|
||||
if(is_view) {
|
||||
/* fixed depth, variable size (avoids exceeding clipping range) */
|
||||
depth = -(cam->clipsta + 0.1f);
|
||||
fac = depth / (cam->lens/-16.0f * scaz);
|
||||
}
|
||||
else {
|
||||
/* fixed size, variable depth (stays a reasonable size in the 3D view) */
|
||||
depth= drawsize * cam->lens/-16.0f * scaz;
|
||||
fac= drawsize;
|
||||
}
|
||||
|
||||
facx= fac * caspx * scax;
|
||||
facy= fac * caspy * scay;
|
||||
shx= cam->shiftx*fac*2 * scax;
|
||||
shy= cam->shifty*fac*2 * scay;
|
||||
}
|
||||
|
||||
vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.0;
|
||||
vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
|
||||
vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
|
||||
vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
|
||||
vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
|
||||
|
||||
/* camera frame */
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3fv(vec[1]);
|
||||
glVertex3fv(vec[2]);
|
||||
glVertex3fv(vec[3]);
|
||||
glVertex3fv(vec[4]);
|
||||
glVertex3fv(vec[0]);
|
||||
glVertex3fv(vec[1]);
|
||||
glVertex3fv(vec[2]);
|
||||
glVertex3fv(vec[3]);
|
||||
glEnd();
|
||||
|
||||
if(is_view)
|
||||
return;
|
||||
|
||||
zero_v3(tvec);
|
||||
|
||||
/* center point to camera frame */
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3fv(vec[2]);
|
||||
glVertex3fv(vec[0]);
|
||||
glVertex3fv(vec[1]);
|
||||
glVertex3fv(vec[4]);
|
||||
glVertex3fv(vec[0]);
|
||||
glVertex3fv(vec[3]);
|
||||
glVertex3fv(vec[1]);
|
||||
glVertex3fv(tvec);
|
||||
glVertex3fv(vec[0]);
|
||||
glVertex3fv(vec[3]);
|
||||
glVertex3fv(tvec);
|
||||
glVertex3fv(vec[2]);
|
||||
glEnd();
|
||||
|
||||
|
||||
/* arrow on top */
|
||||
vec[0][2]= depth;
|
||||
tvec[2]= vec[1][2]; /* copy the depth */
|
||||
|
||||
|
||||
/* draw an outline arrow for inactive cameras and filled
|
||||
@ -1477,16 +1435,16 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob
|
||||
else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
|
||||
else break;
|
||||
|
||||
vec[0][0]= shx + ((-0.7f * drawsize) * scax);
|
||||
vec[0][1]= shy + ((drawsize * (caspy + 0.1f)) * scay);
|
||||
glVertex3fv(vec[0]); /* left */
|
||||
tvec[0]= shift[0] + ((-0.7f * drawsize) * scale[0]);
|
||||
tvec[1]= shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
|
||||
glVertex3fv(tvec); /* left */
|
||||
|
||||
vec[0][0]= shx + ((0.7f * drawsize) * scax);
|
||||
glVertex3fv(vec[0]); /* right */
|
||||
tvec[0]= shift[0] + ((0.7f * drawsize) * scale[0]);
|
||||
glVertex3fv(tvec); /* right */
|
||||
|
||||
vec[0][0]= shx;
|
||||
vec[0][1]= shy + ((1.1f * drawsize * (caspy + 0.7f)) * scay);
|
||||
glVertex3fv(vec[0]); /* top */
|
||||
tvec[0]= shift[0];
|
||||
tvec[1]= shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
|
||||
glVertex3fv(tvec); /* top */
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ typedef struct {
|
||||
float ob_scale[3]; // need temp space due to linked values
|
||||
float ob_dims[3];
|
||||
short link_scale;
|
||||
float ve_median[6];
|
||||
float ve_median[7];
|
||||
int curdef;
|
||||
float *defweightp;
|
||||
} TransformProperties;
|
||||
@ -139,11 +139,11 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
|
||||
uiBlock *block= (layout)? uiLayoutAbsoluteBlock(layout): NULL;
|
||||
MDeformVert *dvert=NULL;
|
||||
TransformProperties *tfp;
|
||||
float median[6], ve_median[6];
|
||||
float median[7], ve_median[7];
|
||||
int tot, totw, totweight, totedge, totradius;
|
||||
char defstr[320];
|
||||
|
||||
median[0]= median[1]= median[2]= median[3]= median[4]= median[5]= 0.0;
|
||||
|
||||
median[0]= median[1]= median[2]= median[3]= median[4]= median[5]= median[6]= 0.0;
|
||||
tot= totw= totweight= totedge= totradius= 0;
|
||||
defstr[0]= 0;
|
||||
|
||||
@ -170,10 +170,14 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
|
||||
|
||||
BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
||||
if(BM_TestHFlag(eed, BM_SELECT)) {
|
||||
float *f = bm_get_cd_float(&bm->edata, eed->head.data, CD_CREASE);
|
||||
float *f;
|
||||
|
||||
totedge++;
|
||||
f = bm_get_cd_float(&bm->edata, eed->head.data, CD_CREASE);
|
||||
median[3]+= f ? *f : 0.0f;
|
||||
|
||||
f = bm_get_cd_float(&bm->edata, eed->head.data, CD_BWEIGHT);
|
||||
median[6]+= f ? *f : 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,7 +288,10 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
|
||||
median[0] /= (float)tot;
|
||||
median[1] /= (float)tot;
|
||||
median[2] /= (float)tot;
|
||||
if(totedge) median[3] /= (float)totedge;
|
||||
if (totedge) {
|
||||
median[3] /= (float)totedge;
|
||||
median[6] /= (float)totedge;
|
||||
}
|
||||
else if(totw) median[3] /= (float)totw;
|
||||
if(totweight) median[4] /= (float)totweight;
|
||||
if(totradius) median[5] /= (float)totradius;
|
||||
@ -299,78 +306,82 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
if(tot==1) {
|
||||
uiDefBut(block, LABEL, 0, "Vertex:", 0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
|
||||
uiDefBut(block, LABEL, 0, "Vertex:", 0, 150, 200, 20, NULL, 0, 0, 0, 0, "");
|
||||
uiBlockBeginAlign(block);
|
||||
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, 130, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
|
||||
uiButSetUnitType(but, PROP_UNIT_LENGTH);
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:", 0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:", 0, 110, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
|
||||
uiButSetUnitType(but, PROP_UNIT_LENGTH);
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:", 0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:", 0, 90, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
|
||||
uiButSetUnitType(but, PROP_UNIT_LENGTH);
|
||||
|
||||
if(totw==1) {
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, "");
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, 70, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, "");
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
|
||||
uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
|
||||
uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
|
||||
uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
|
||||
uiBlockEndAlign(block);
|
||||
if(totweight)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, "");
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, "");
|
||||
if(totradius)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, "Radius of curve CPs");
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 20, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, "Radius of curve CPs");
|
||||
}
|
||||
else {
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 65, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
|
||||
uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 65, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
|
||||
uiBlockEndAlign(block);
|
||||
if(totweight)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 40, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "");
|
||||
if(totradius)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 40, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
|
||||
}
|
||||
}
|
||||
else {
|
||||
uiDefBut(block, LABEL, 0, "Median:", 0, 150, 200, 20, NULL, 0, 0, 0, 0, "");
|
||||
uiBlockBeginAlign(block);
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, 130, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
|
||||
uiButSetUnitType(but, PROP_UNIT_LENGTH);
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:", 0, 110, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
|
||||
uiButSetUnitType(but, PROP_UNIT_LENGTH);
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:", 0, 90, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
|
||||
uiButSetUnitType(but, PROP_UNIT_LENGTH);
|
||||
if(totw==tot) {
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, 70, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, "");
|
||||
uiBlockEndAlign(block);
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
|
||||
uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
|
||||
uiBlockEndAlign(block);
|
||||
if(totweight)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "");
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal");
|
||||
if(totradius)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 20, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
|
||||
}
|
||||
}
|
||||
else {
|
||||
uiDefBut(block, LABEL, 0, "Median:", 0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
|
||||
uiBlockBeginAlign(block);
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
|
||||
uiButSetUnitType(but, PROP_UNIT_LENGTH);
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:", 0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
|
||||
uiButSetUnitType(but, PROP_UNIT_LENGTH);
|
||||
but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:", 0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
|
||||
uiButSetUnitType(but, PROP_UNIT_LENGTH);
|
||||
if(totw==tot) {
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, "");
|
||||
uiBlockEndAlign(block);
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
|
||||
uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
|
||||
uiBlockEndAlign(block);
|
||||
if(totweight)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal");
|
||||
if(totradius)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
else {
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
|
||||
uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
|
||||
uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 65, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
|
||||
uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 65, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
|
||||
uiBlockEndAlign(block);
|
||||
if(totweight)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, "Weight is used for SoftBody Goal");
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 40, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, "Weight is used for SoftBody Goal");
|
||||
if(totradius)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, "Radius of curve CPs");
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:", 0, 20, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, "Radius of curve CPs");
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
}
|
||||
|
||||
if(totedge==1)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease:", 0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, "");
|
||||
else if(totedge>1)
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Mean Crease:", 0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, "");
|
||||
|
||||
|
||||
if(totedge==1){
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease:", 0, 40, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, "");
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Bevel Weight:", 0, 20, 200, 20, &(tfp->ve_median[6]), 0.0, 1.0, 1, 3, "");
|
||||
}
|
||||
else if(totedge>1){
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Mean Crease:", 0, 40, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, "");
|
||||
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Mean Bevel Weight:", 0, 20, 200, 20, &(tfp->ve_median[6]), 0.0, 1.0, 1, 3, "");
|
||||
}
|
||||
|
||||
}
|
||||
else { // apply
|
||||
memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median));
|
||||
@ -384,6 +395,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
|
||||
median[3]= ve_median[3]-median[3];
|
||||
median[4]= ve_median[4]-median[4];
|
||||
median[5]= ve_median[5]-median[5];
|
||||
median[6]= ve_median[6]-median[6];
|
||||
|
||||
if(ob->type==OB_MESH) {
|
||||
Mesh *me= ob->data;
|
||||
@ -458,7 +470,54 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (median[6] != 0.0f) {
|
||||
#if 0 // BMESH_TODO
|
||||
EditEdge *eed;
|
||||
const float fixed_bweight= (ve_median[6] <= 0.0f ? 0.0f : (ve_median[6] >= 1.0f ? 1.0f : FLT_MAX));
|
||||
|
||||
if(fixed_bweight != FLT_MAX) {
|
||||
/* simple case */
|
||||
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if(eed->f & SELECT) {
|
||||
eed->bweight= fixed_bweight;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* scale crease to target median */
|
||||
float median_new= ve_median[6];
|
||||
float median_orig= ve_median[6] - median[6]; /* previous median value */
|
||||
|
||||
/* incase of floating point error */
|
||||
CLAMP(median_orig, 0.0f, 1.0f);
|
||||
CLAMP(median_new, 0.0f, 1.0f);
|
||||
|
||||
if(median_new < median_orig) {
|
||||
/* scale down */
|
||||
const float sca= median_new / median_orig;
|
||||
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if(eed->f & SELECT) {
|
||||
eed->bweight *= sca;
|
||||
CLAMP(eed->bweight, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* scale up */
|
||||
const float sca= (1.0f - median_new) / (1.0f - median_orig);
|
||||
|
||||
for(eed= em->edges.first; eed; eed= eed->next) {
|
||||
if(eed->f & SELECT) {
|
||||
eed->bweight = 1.0f - ((1.0f - eed->bweight) * sca);
|
||||
CLAMP(eed->bweight, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // BMESH_TODO
|
||||
}
|
||||
EDBM_RecalcNormals(em);
|
||||
}
|
||||
else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
|
||||
|
@ -2322,6 +2322,12 @@ void flushTransNodes(TransInfo *t)
|
||||
}
|
||||
|
||||
/* *** SEQUENCE EDITOR *** */
|
||||
|
||||
/* commented _only_ because the meta may have animaion data which
|
||||
* needs moving too [#28158] */
|
||||
|
||||
#define SEQ_TX_NESTED_METAS
|
||||
|
||||
void flushTransSeq(TransInfo *t)
|
||||
{
|
||||
ListBase *seqbasep= seq_give_editing(t->scene, FALSE)->seqbasep; /* Editing null check already done */
|
||||
@ -2347,9 +2353,13 @@ void flushTransSeq(TransInfo *t)
|
||||
|
||||
switch (tdsq->sel_flag) {
|
||||
case SELECT:
|
||||
#ifdef SEQ_TX_NESTED_METAS
|
||||
if ((seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */
|
||||
seq->start= new_frame - tdsq->start_offset;
|
||||
#else
|
||||
if (seq->type != SEQ_META && (seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */
|
||||
seq->start= new_frame - tdsq->start_offset;
|
||||
|
||||
#endif
|
||||
if (seq->depth==0) {
|
||||
seq->machine= (int)floor(td2d->loc[1] + 0.5f);
|
||||
CLAMP(seq->machine, 1, MAXSEQ);
|
||||
@ -2404,7 +2414,7 @@ void flushTransSeq(TransInfo *t)
|
||||
seq_prev= seq;
|
||||
}
|
||||
|
||||
if (t->mode == TFM_TIME_TRANSLATE) { /* originally TFM_TIME_EXTEND, transform changes */
|
||||
if (t->mode == TFM_SEQ_SLIDE) { /* originally TFM_TIME_EXTEND, transform changes */
|
||||
/* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
|
||||
seq= seqbasep->first;
|
||||
|
||||
@ -2906,7 +2916,7 @@ static void posttrans_gpd_clean (bGPdata *gpd)
|
||||
/* Called during special_aftertrans_update to make sure selected keyframes replace
|
||||
* any other keyframes which may reside on that frame (that is not selected).
|
||||
*/
|
||||
static void posttrans_fcurve_clean (FCurve *fcu)
|
||||
static void posttrans_fcurve_clean (FCurve *fcu, const short use_handle)
|
||||
{
|
||||
float *selcache; /* cache for frame numbers of selected frames (fcu->totvert*sizeof(float)) */
|
||||
int len, index, i; /* number of frames in cache, item index */
|
||||
@ -2955,7 +2965,7 @@ static void posttrans_fcurve_clean (FCurve *fcu)
|
||||
}
|
||||
}
|
||||
|
||||
testhandles_fcurve(fcu);
|
||||
testhandles_fcurve(fcu, use_handle);
|
||||
}
|
||||
|
||||
/* free cache */
|
||||
@ -2986,11 +2996,11 @@ static void posttrans_action_clean (bAnimContext *ac, bAction *act)
|
||||
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
||||
posttrans_fcurve_clean(ale->key_data);
|
||||
posttrans_fcurve_clean(ale->key_data, FALSE); /* only use handles in graph editor */
|
||||
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
||||
}
|
||||
else
|
||||
posttrans_fcurve_clean(ale->key_data);
|
||||
posttrans_fcurve_clean(ale->key_data, FALSE); /* only use handles in graph editor */
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
@ -3011,12 +3021,11 @@ static int count_fcurve_keys(FCurve *fcu, char side, float cfra)
|
||||
/* only include points that occur on the right side of cfra */
|
||||
for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
|
||||
if (bezt->f2 & SELECT) {
|
||||
/* fully select the other two keys */
|
||||
bezt->f1 |= SELECT;
|
||||
bezt->f3 |= SELECT;
|
||||
|
||||
if (FrameOnMouseSide(side, bezt->vec[1][0], cfra))
|
||||
/* no need to adjust the handle selection since they are assumed
|
||||
* selected (like graph editor with SIPO_NOHANDLES) */
|
||||
if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3441,9 +3450,9 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
|
||||
/* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse */
|
||||
for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
|
||||
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
|
||||
const char sel1= use_handle ? bezt->f1 & SELECT : 0;
|
||||
const char sel2= bezt->f2 & SELECT;
|
||||
const char sel3= use_handle ? bezt->f3 & SELECT : 0;
|
||||
const char sel1= use_handle ? bezt->f1 & SELECT : sel2;
|
||||
const char sel3= use_handle ? bezt->f3 & SELECT : sel2;
|
||||
|
||||
if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) {
|
||||
/* for 'normal' pivots - just include anything that is selected.
|
||||
@ -3534,9 +3543,9 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
|
||||
/* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */
|
||||
for (i=0, bezt= fcu->bezt; i < fcu->totvert; i++, bezt++) {
|
||||
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
|
||||
const char sel1= use_handle ? bezt->f1 & SELECT : 0;
|
||||
const char sel2= bezt->f2 & SELECT;
|
||||
const char sel3= use_handle ? bezt->f3 & SELECT : 0;
|
||||
const char sel1= use_handle ? bezt->f1 & SELECT : sel2;
|
||||
const char sel3= use_handle ? bezt->f3 & SELECT : sel2;
|
||||
|
||||
TransDataCurveHandleFlags *hdata = NULL;
|
||||
/* short h1=1, h2=1; */ /* UNUSED */
|
||||
@ -3596,7 +3605,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
|
||||
}
|
||||
|
||||
/* Sets handles based on the selection */
|
||||
testhandles_fcurve(fcu);
|
||||
testhandles_fcurve(fcu, use_handle);
|
||||
}
|
||||
|
||||
/* cleanup temp list */
|
||||
@ -3800,7 +3809,7 @@ void remake_graph_transdata (TransInfo *t, ListBase *anim_data)
|
||||
sort_time_fcurve(fcu);
|
||||
|
||||
/* make sure handles are all set correctly */
|
||||
testhandles_fcurve(fcu);
|
||||
testhandles_fcurve(fcu, use_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3958,6 +3967,11 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count
|
||||
else {
|
||||
/* Nested, different rules apply */
|
||||
|
||||
#ifdef SEQ_TX_NESTED_METAS
|
||||
*flag= (seq->flag | SELECT) & ~(SEQ_LEFTSEL|SEQ_RIGHTSEL);
|
||||
*count= 1; /* ignore the selection for nested */
|
||||
*recursive = (seq->type == SEQ_META );
|
||||
#else
|
||||
if (seq->type == SEQ_META) {
|
||||
/* Meta's can only directly be moved between channels since they
|
||||
* dont have their start and length set directly (children affect that)
|
||||
@ -3972,6 +3986,7 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count
|
||||
*count= 1; /* ignore the selection for nested */
|
||||
*recursive = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4947,11 +4962,11 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
|
||||
{
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1);
|
||||
posttrans_fcurve_clean(fcu);
|
||||
posttrans_fcurve_clean(fcu, FALSE); /* only use handles in graph editor */
|
||||
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1);
|
||||
}
|
||||
else
|
||||
posttrans_fcurve_clean(fcu);
|
||||
posttrans_fcurve_clean(fcu, FALSE); /* only use handles in graph editor */
|
||||
}
|
||||
}
|
||||
|
||||
@ -5031,6 +5046,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
|
||||
else if (t->spacetype == SPACE_IPO) {
|
||||
SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
|
||||
bAnimContext ac;
|
||||
const short use_handle = !(sipo->flag & SIPO_NOHANDLES);
|
||||
|
||||
/* initialise relevant anim-context 'context' data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
@ -5059,11 +5075,11 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
|
||||
{
|
||||
if (adt) {
|
||||
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
|
||||
posttrans_fcurve_clean(fcu);
|
||||
posttrans_fcurve_clean(fcu, use_handle);
|
||||
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
|
||||
}
|
||||
else
|
||||
posttrans_fcurve_clean(fcu);
|
||||
posttrans_fcurve_clean(fcu, use_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -903,7 +903,7 @@ static void do_material_tex(GPUShadeInput *shi)
|
||||
/*char *lastuvname = NULL;*/ /*UNUSED*/
|
||||
float one = 1.0f, norfac, ofs[3];
|
||||
int tex_nr, rgbnor, talpha;
|
||||
int init_done = 0, iBumpSpacePrev;
|
||||
int init_done = 0, iBumpSpacePrev = 0; /* Not necessary, quiting gcc warning. */
|
||||
GPUNodeLink *vNorg, *vNacc, *fPrevMagnitude;
|
||||
int iFirstTimeNMap=1;
|
||||
int found_deriv_map = 0;
|
||||
@ -1101,7 +1101,12 @@ static void do_material_tex(GPUShadeInput *shi)
|
||||
|
||||
if( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
|
||||
hScale = hScaleTex;
|
||||
norfac = hScale * mtex->norfac;
|
||||
|
||||
// The negate on norfac is done because the
|
||||
// normal in the renderer points inward which corresponds
|
||||
// to inverting the bump map. Should this ever change
|
||||
// this negate must be removed.
|
||||
norfac = -hScale * mtex->norfac;
|
||||
tnorfac = GPU_uniform(&norfac);
|
||||
|
||||
if(GPU_link_changed(stencil))
|
||||
|
@ -900,8 +900,8 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position,
|
||||
long long st_time;
|
||||
struct anim_index * tc_index = 0;
|
||||
AVStream * v_st;
|
||||
int new_frame_index;
|
||||
int old_frame_index;
|
||||
int new_frame_index = 0; /* To quite gcc barking... */
|
||||
int old_frame_index = 0; /* To quite gcc barking... */
|
||||
|
||||
if (anim == 0) return (0);
|
||||
|
||||
|
@ -125,7 +125,7 @@ typedef struct Library {
|
||||
|
||||
enum eIconSizes {
|
||||
ICON_SIZE_ICON,
|
||||
ICON_SIZE_PREVIEW,
|
||||
ICON_SIZE_PREVIEW
|
||||
};
|
||||
#define NUM_ICON_SIZES (ICON_SIZE_PREVIEW + 1)
|
||||
|
||||
@ -204,6 +204,8 @@ typedef struct PreviewImage {
|
||||
|
||||
#define ID_REAL_USERS(id) (((ID *)id)->us - ((((ID *)id)->flag & LIB_FAKEUSER) ? 1:0))
|
||||
|
||||
#define ID_CHECK_UNDO(id) ((GS((id)->name) != ID_SCR) && (GS((id)->name) != ID_WM))
|
||||
|
||||
#ifdef GS
|
||||
#undef GS
|
||||
#endif
|
||||
|
@ -466,6 +466,7 @@ typedef struct TexMapping {
|
||||
#define MTEX_5TAP_BUMP 512
|
||||
#define MTEX_BUMP_OBJECTSPACE 1024
|
||||
#define MTEX_BUMP_TEXTURESPACE 2048
|
||||
#define MTEX_BUMP_FLIPPED 4096 /* temp flag for 2.59/2.60 */
|
||||
|
||||
/* blendtype */
|
||||
#define MTEX_BLEND 0
|
||||
|
@ -295,6 +295,7 @@ typedef struct wmKeyConfig {
|
||||
|
||||
/* wmKeyConfig.flag */
|
||||
#define KEYCONF_USER (1 << 1)
|
||||
#define KEYCONF_INIT_DEFAULT (1 << 2)
|
||||
|
||||
/* this one is the operator itself, stored in files for macros etc */
|
||||
/* operator + operatortype should be able to redo entirely, but for different contextes */
|
||||
|
@ -95,6 +95,7 @@ set(APISRC
|
||||
rna_actuator_api.c
|
||||
rna_animation_api.c
|
||||
rna_armature_api.c
|
||||
rna_camera_api.c
|
||||
rna_controller_api.c
|
||||
rna_fcurve_api.c
|
||||
rna_image_api.c
|
||||
|
@ -2432,7 +2432,7 @@ static RNAProcessItem PROCESS_ITEMS[]= {
|
||||
{"rna_armature.c", "rna_armature_api.c", RNA_def_armature},
|
||||
{"rna_boid.c", NULL, RNA_def_boid},
|
||||
{"rna_brush.c", NULL, RNA_def_brush},
|
||||
{"rna_camera.c", NULL, RNA_def_camera},
|
||||
{"rna_camera.c", "rna_camera_api.c", RNA_def_camera},
|
||||
{"rna_cloth.c", NULL, RNA_def_cloth},
|
||||
{"rna_color.c", NULL, RNA_def_color},
|
||||
{"rna_constraint.c", NULL, RNA_def_constraint},
|
||||
|
@ -752,7 +752,7 @@ static void rna_def_armature_bones(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
RNA_def_property_struct_type(prop, "Bone");
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "act_bone");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Active Bone", "Armatures active bone");
|
||||
RNA_def_property_ui_text(prop, "Active Bone", "Armature's active bone");
|
||||
RNA_def_property_pointer_funcs(prop, NULL, "rna_Armature_act_bone_set", NULL, NULL);
|
||||
|
||||
/* todo, redraw */
|
||||
|
@ -554,7 +554,7 @@ static void rna_def_boid_settings(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "range", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0, 100.0);
|
||||
RNA_def_property_ui_text(prop, "Range", "The maximum distance from which a boid can attack");
|
||||
RNA_def_property_ui_text(prop, "Range", "Maximum distance from which a boid can attack");
|
||||
RNA_def_property_update(prop, 0, "rna_Boids_reset");
|
||||
|
||||
/* physical properties */
|
||||
|
@ -209,6 +209,9 @@ void RNA_def_camera(BlenderRNA *brna)
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "DOF Object", "Use this object to define the depth of field focal point");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL);
|
||||
|
||||
/* Camera API */
|
||||
RNA_api_camera(srna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
88
source/blender/makesrna/intern/rna_camera_api.c
Normal file
88
source/blender/makesrna/intern/rna_camera_api.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* $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.
|
||||
*
|
||||
* Contributor(s): Campbell Barton
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/makesrna/intern/rna_camera_api.c
|
||||
* \ingroup RNA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
void rna_camera_view_frame(struct Camera *camera, struct Scene *scene,
|
||||
float vec1_r[3], float vec2_r[3], float vec3_r[3], float vec4_r[3])
|
||||
{
|
||||
float vec[4][3];
|
||||
|
||||
camera_view_frame(scene, camera, vec);
|
||||
|
||||
copy_v3_v3(vec1_r, vec[0]);
|
||||
copy_v3_v3(vec2_r, vec[1]);
|
||||
copy_v3_v3(vec3_r, vec[2]);
|
||||
copy_v3_v3(vec4_r, vec[3]);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void RNA_api_camera(StructRNA *srna)
|
||||
{
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
func= RNA_def_function(srna, "view_frame", "rna_camera_view_frame");
|
||||
RNA_def_function_ui_description(func, "Return 4 points for the cameras frame (before object transformation)");
|
||||
|
||||
RNA_def_pointer(func, "scene", "Scene", "", "Scene to use for aspect calculation, when omitted 1:1 aspect is used");
|
||||
|
||||
/* return location and normal */
|
||||
parm= RNA_def_float_vector(func, "result_1", 3, NULL, -FLT_MAX, FLT_MAX, "Result", NULL, -1e4, 1e4);
|
||||
RNA_def_property_flag(parm, PROP_THICK_WRAP);
|
||||
RNA_def_function_output(func, parm);
|
||||
|
||||
parm= RNA_def_float_vector(func, "result_2", 3, NULL, -FLT_MAX, FLT_MAX, "Result", NULL, -1e4, 1e4);
|
||||
RNA_def_property_flag(parm, PROP_THICK_WRAP);
|
||||
RNA_def_function_output(func, parm);
|
||||
|
||||
parm= RNA_def_float_vector(func, "result_3", 3, NULL, -FLT_MAX, FLT_MAX, "Result", NULL, -1e4, 1e4);
|
||||
RNA_def_property_flag(parm, PROP_THICK_WRAP);
|
||||
RNA_def_function_output(func, parm);
|
||||
|
||||
parm= RNA_def_float_vector(func, "result_4", 3, NULL, -FLT_MAX, FLT_MAX, "Result", NULL, -1e4, 1e4);
|
||||
RNA_def_property_flag(parm, PROP_THICK_WRAP);
|
||||
RNA_def_function_output(func, parm);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -234,6 +234,7 @@ char *rna_TextureSlot_path(struct PointerRNA *ptr);
|
||||
void RNA_api_action(StructRNA *srna);
|
||||
void RNA_api_armature_edit_bone(StructRNA *srna);
|
||||
void RNA_api_bone(StructRNA *srna);
|
||||
void RNA_api_camera(StructRNA *srna);
|
||||
void RNA_api_drivers(StructRNA *srna);
|
||||
void RNA_api_image(struct StructRNA *srna);
|
||||
void RNA_api_operator(struct StructRNA *srna);
|
||||
|
@ -670,7 +670,7 @@ void RNA_def_main_materials(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
RNA_def_property_srna(cprop, "BlendDataMaterials");
|
||||
srna= RNA_def_struct(brna, "BlendDataMaterials", NULL);
|
||||
RNA_def_struct_sdna(srna, "Main");
|
||||
RNA_def_struct_ui_text(srna, "Main Material", "Collection of materials");
|
||||
RNA_def_struct_ui_text(srna, "Main Materials", "Collection of materials");
|
||||
|
||||
func= RNA_def_function(srna, "new", "rna_Main_materials_new");
|
||||
RNA_def_function_ui_description(func, "Add a new material to the main database");
|
||||
@ -949,7 +949,7 @@ void RNA_def_main_metaballs(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
RNA_def_property_srna(cprop, "BlendDataMetaBalls");
|
||||
srna= RNA_def_struct(brna, "BlendDataMetaBalls", NULL);
|
||||
RNA_def_struct_sdna(srna, "Main");
|
||||
RNA_def_struct_ui_text(srna, "Main MetaBall", "Collection of metaballs");
|
||||
RNA_def_struct_ui_text(srna, "Main MetaBalls", "Collection of metaballs");
|
||||
|
||||
func= RNA_def_function(srna, "new", "rna_Main_metaballs_new");
|
||||
RNA_def_function_ui_description(func, "Add a new metaball to the main database");
|
||||
|
@ -1680,7 +1680,7 @@ static void rna_def_softbody(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_estimate_matrix", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "solverflags", SBSO_ESTIMATEIPO);
|
||||
RNA_def_property_ui_text(prop, "Estimate matrix", "estimate matrix .. split to COM , ROT ,SCALE ");
|
||||
RNA_def_property_ui_text(prop, "Estimate matrix", "Estimate matrix... split to COM, ROT, SCALE");
|
||||
|
||||
|
||||
/***********************************************************************************/
|
||||
@ -1722,7 +1722,7 @@ static void rna_def_softbody(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "use_stiff_quads", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_stiff_quads_get", "rna_SoftBodySettings_stiff_quads_set");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Stiff Quads", "Adds diagonal springs on 4-gons");
|
||||
RNA_def_property_ui_text(prop, "Stiff Quads", "Add diagonal springs on 4-gons");
|
||||
RNA_def_property_update(prop, 0, "rna_softbody_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_edge_collision", PROP_BOOLEAN, PROP_NONE);
|
||||
|
@ -2068,7 +2068,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "courant_target", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.01, 10);
|
||||
RNA_def_property_float_default(prop, 0.2);
|
||||
RNA_def_property_ui_text(prop, "Adaptive Subframe Threshold", "The relative distance a particle can move before requiring more subframes (target Courant number). 0.1-0.3 is the recommended range");
|
||||
RNA_def_property_ui_text(prop, "Adaptive Subframe Threshold", "The relative distance a particle can move before requiring more subframes (target Courant number); 0.1-0.3 is the recommended range");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_reset");
|
||||
|
||||
prop= RNA_def_property(srna, "jitter_factor", PROP_FLOAT, PROP_NONE);
|
||||
|
@ -1242,7 +1242,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_snap_self", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "snap_flag", SCE_SNAP_NO_SELF);
|
||||
RNA_def_property_ui_text(prop, "Project to Self", "Snap onto its self (editmode)");
|
||||
RNA_def_property_ui_text(prop, "Project to Self", "Snap onto itself (editmode)");
|
||||
RNA_def_property_ui_icon(prop, ICON_ORTHO, 0);
|
||||
RNA_def_property_update(prop, NC_SCENE|ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||
|
||||
@ -1874,19 +1874,19 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "depth", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, NULL, "depth");
|
||||
RNA_def_property_range(prop, 8, 32);
|
||||
RNA_def_property_ui_text(prop, "Bits", "Displays bit depth of full screen display");
|
||||
RNA_def_property_ui_text(prop, "Bits", "Display bit depth of full screen display");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
|
||||
// Do we need it here ? (since we already have it in World
|
||||
prop= RNA_def_property(srna, "frequency", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "freqplay");
|
||||
RNA_def_property_range(prop, 4, 2000);
|
||||
RNA_def_property_ui_text(prop, "Freq", "Displays clock frequency of fullscreen display");
|
||||
RNA_def_property_ui_text(prop, "Freq", "Display clock frequency of fullscreen display");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "show_fullscreen", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "fullscreen", 1.0);
|
||||
RNA_def_property_ui_text(prop, "Fullscreen", "Starts player in a new fullscreen display");
|
||||
RNA_def_property_ui_text(prop, "Fullscreen", "Start player in a new fullscreen display");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
|
||||
/* Framing */
|
||||
|
@ -148,9 +148,9 @@ static void rna_def_area(BlenderRNA *brna)
|
||||
RNA_def_property_collection_sdna(prop, NULL, "spacedata", NULL);
|
||||
RNA_def_property_struct_type(prop, "Space");
|
||||
RNA_def_property_ui_text(prop, "Spaces",
|
||||
"Spaces contained in this area, the first being the active space. "
|
||||
"NOTE: Useful for example to restore a previously used 3d view space "
|
||||
"in a certain area to get the old view orientation");
|
||||
"Spaces contained in this area, the first being the active space "
|
||||
"(NOTE: Useful for example to restore a previously used 3D view space "
|
||||
"in a certain area to get the old view orientation)");
|
||||
rna_def_area_spaces(brna, prop);
|
||||
|
||||
prop= RNA_def_property(srna, "regions", PROP_COLLECTION, PROP_NONE);
|
||||
|
@ -559,7 +559,8 @@ static void rna_Sequence_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *p
|
||||
{
|
||||
Editing *ed= seq_give_editing(scene, FALSE);
|
||||
|
||||
free_imbuf_seq(scene, &ed->seqbase, FALSE, TRUE);
|
||||
if(ed)
|
||||
free_imbuf_seq(scene, &ed->seqbase, FALSE, TRUE);
|
||||
}
|
||||
|
||||
static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
|
||||
@ -820,16 +821,14 @@ static void rna_def_strip_proxy(BlenderRNA *brna)
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem seq_tc_items[]= {
|
||||
{SEQ_PROXY_TC_NONE, "NONE", 0, "No TC in use", ""},
|
||||
{SEQ_PROXY_TC_NONE, "NONE", 0, "No TC in use", ""},
|
||||
{SEQ_PROXY_TC_RECORD_RUN, "RECORD_RUN", 0, "Record Run",
|
||||
"use images in the order as they are recorded"},
|
||||
{SEQ_PROXY_TC_FREE_RUN, "FREE_RUN", 0, "Free Run",
|
||||
"use global timestamp written by recording device"},
|
||||
{SEQ_PROXY_TC_INTERP_REC_DATE_FREE_RUN, "FREE_RUN_REC_DATE",
|
||||
0, "Free Run (rec date)",
|
||||
"interpolate a global timestamp using the "
|
||||
"record date and time written by recording "
|
||||
"device"},
|
||||
"Use images in the order as they are recorded"},
|
||||
{SEQ_PROXY_TC_FREE_RUN, "FREE_RUN", 0, "Free Run",
|
||||
"Use global timestamp written by recording device"},
|
||||
{SEQ_PROXY_TC_INTERP_REC_DATE_FREE_RUN, "FREE_RUN_REC_DATE", 0, "Free Run (rec date)",
|
||||
"Interpolate a global timestamp using the "
|
||||
"record date and time written by recording device"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
srna = RNA_def_struct(brna, "SequenceProxy", NULL);
|
||||
|
@ -255,7 +255,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "smooth_emitter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_HIGH_SMOOTH);
|
||||
RNA_def_property_ui_text(prop, "Smooth Emitter", "Smoothens emitted smoke to avoid blockiness");
|
||||
RNA_def_property_ui_text(prop, "Smooth Emitter", "Smoothen emitted smoke to avoid blockiness");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Smoke_reset");
|
||||
|
||||
prop= RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE);
|
||||
@ -305,11 +305,11 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_outflow", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "type", MOD_SMOKE_FLOW_TYPE_OUTFLOW);
|
||||
RNA_def_property_ui_text(prop, "Outflow", "Deletes smoke from simulation");
|
||||
RNA_def_property_ui_text(prop, "Outflow", "Delete smoke from simulation");
|
||||
|
||||
prop= RNA_def_property(srna, "use_absolute", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_ABSOLUTE);
|
||||
RNA_def_property_ui_text(prop, "Absolute Density", "Only allows given density value in emitter area");
|
||||
RNA_def_property_ui_text(prop, "Absolute Density", "Only allow given density value in emitter area");
|
||||
|
||||
prop= RNA_def_property(srna, "initial_velocity", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_INITVELOCITY);
|
||||
|
@ -2068,7 +2068,7 @@ static void rna_def_space_graph(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "use_beauty_drawing", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_BEAUTYDRAW_OFF);
|
||||
RNA_def_property_ui_text(prop, "Use High Quality Drawing",
|
||||
"Draw F-Curves using Anti-Aliasing and other fancy effects. Disable for better performance");
|
||||
"Draw F-Curves using Anti-Aliasing and other fancy effects (disable for better performance)");
|
||||
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_GRAPH, NULL);
|
||||
|
||||
/* editing */
|
||||
@ -2144,7 +2144,7 @@ static void rna_def_space_nla(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "show_strip_curves", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NOSTRIPCURVES);
|
||||
RNA_def_property_ui_text(prop, "Show Control Curves", "Show influence curves on strips");
|
||||
RNA_def_property_ui_text(prop, "Show Control F-Curves", "Show influence F-Curves on strips");
|
||||
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_NLA, NULL);
|
||||
|
||||
/* editing */
|
||||
@ -2516,7 +2516,7 @@ static void rna_def_space_node(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_auto_render", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_AUTO_RENDER);
|
||||
RNA_def_property_ui_text(prop, "Auto Render", "Re-render and composite changed layer on 3D edits");
|
||||
RNA_def_property_ui_text(prop, "Auto Render", "Re-render and composite changed layers on 3D edits");
|
||||
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_NODE_VIEW, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "backdrop_zoom", PROP_FLOAT, PROP_NONE);
|
||||
|
@ -57,20 +57,23 @@ EnumPropertyItem texture_filter_items[] = {
|
||||
|
||||
EnumPropertyItem texture_type_items[] = {
|
||||
{0, "NONE", 0, "None", ""},
|
||||
{TEX_BLEND, "BLEND", ICON_TEXTURE, "Blend", "Procedural - Creates a ramp texture"},
|
||||
{TEX_CLOUDS, "CLOUDS", ICON_TEXTURE, "Clouds", "Procedural - Creates a cloud-like fractal noise texture"},
|
||||
{TEX_DISTNOISE, "DISTORTED_NOISE", ICON_TEXTURE, "Distorted Noise", "Procedural - Noise texture distorted by two noise algorithms"},
|
||||
{TEX_ENVMAP, "ENVIRONMENT_MAP", ICON_IMAGE_DATA, "Environment Map", "Creates a render of the environment mapped to a texture"},
|
||||
{TEX_IMAGE, "IMAGE", ICON_IMAGE_DATA, "Image or Movie", "Allows for images or movies to be used as textures"},
|
||||
{TEX_BLEND, "BLEND", ICON_TEXTURE, "Blend", "Procedural - create a ramp texture"},
|
||||
{TEX_CLOUDS, "CLOUDS", ICON_TEXTURE, "Clouds", "Procedural - create a cloud-like fractal noise texture"},
|
||||
{TEX_DISTNOISE, "DISTORTED_NOISE", ICON_TEXTURE,
|
||||
"Distorted Noise", "Procedural - Noise texture distorted by two noise algorithms"},
|
||||
{TEX_ENVMAP, "ENVIRONMENT_MAP", ICON_IMAGE_DATA,
|
||||
"Environment Map", "Create a render of the environment mapped to a texture"},
|
||||
{TEX_IMAGE, "IMAGE", ICON_IMAGE_DATA, "Image or Movie", "Allow for images or movies to be used as textures"},
|
||||
{TEX_MAGIC, "MAGIC", ICON_TEXTURE, "Magic", "Procedural - Color texture based on trigonometric functions"},
|
||||
{TEX_MARBLE, "MARBLE", ICON_TEXTURE, "Marble", "Procedural - Marble-like noise texture with wave generated bands"},
|
||||
{TEX_MUSGRAVE, "MUSGRAVE", ICON_TEXTURE, "Musgrave", "Procedural - Highly flexible fractal noise texture"},
|
||||
{TEX_NOISE, "NOISE", ICON_TEXTURE, "Noise", "Procedural - Random noise, gives a different result every time, for every frame, for every pixel"},
|
||||
{TEX_NOISE, "NOISE", ICON_TEXTURE, "Noise",
|
||||
"Procedural - Random noise, gives a different result every time, for every frame, for every pixel"},
|
||||
//{TEX_PLUGIN, "PLUGIN", ICON_PLUGIN, "Plugin", ""}, /* Nothing yet */
|
||||
{TEX_POINTDENSITY, "POINT_DENSITY", ICON_TEXTURE, "Point Density", ""},
|
||||
{TEX_STUCCI, "STUCCI", ICON_TEXTURE, "Stucci", "Procedural - Creates a fractal noise texture"},
|
||||
{TEX_VORONOI, "VORONOI", ICON_TEXTURE, "Voronoi", "Procedural - Creates cell-like patterns based on Worley noise"},
|
||||
{TEX_VOXELDATA, "VOXEL_DATA", ICON_TEXTURE, "Voxel Data", "Creates a 3d texture based on volumetric data"},
|
||||
{TEX_STUCCI, "STUCCI", ICON_TEXTURE, "Stucci", "Procedural - Create a fractal noise texture"},
|
||||
{TEX_VORONOI, "VORONOI", ICON_TEXTURE, "Voronoi", "Procedural - Create cell-like patterns based on Worley noise"},
|
||||
{TEX_VOXELDATA, "VOXEL_DATA", ICON_TEXTURE, "Voxel Data", "Create a 3d texture based on volumetric data"},
|
||||
{TEX_WOOD, "WOOD", ICON_TEXTURE, "Wood", "Procedural - Wave generated bands or rings, with optional noise"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
@ -493,25 +496,26 @@ static void rna_def_mtex(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "offset", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_float_sdna(prop, NULL, "ofs");
|
||||
RNA_def_property_ui_range(prop, -10, 10, 10, 2);
|
||||
RNA_def_property_ui_text(prop, "Offset", "Fine tunes texture mapping X, Y and Z locations");
|
||||
RNA_def_property_ui_text(prop, "Offset", "Fine tune of the texture mapping X, Y and Z locations");
|
||||
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
|
||||
|
||||
prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
|
||||
RNA_def_property_float_sdna(prop, NULL, "size");
|
||||
RNA_def_property_ui_range(prop, -100, 100, 10, 2);
|
||||
RNA_def_property_ui_text(prop, "Size", "Sets scaling for the texture's X, Y and Z sizes");
|
||||
RNA_def_property_ui_text(prop, "Size", "Set scaling for the texture's X, Y and Z sizes");
|
||||
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
|
||||
|
||||
prop= RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "r");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Color", "The default color for textures that don't return RGB or when RGB to intensity is enabled");
|
||||
RNA_def_property_ui_text(prop, "Color",
|
||||
"Default color for textures that don't return RGB or when RGB to intensity is enabled");
|
||||
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
|
||||
|
||||
prop= RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "blendtype");
|
||||
RNA_def_property_enum_items(prop, prop_blend_type_items);
|
||||
RNA_def_property_ui_text(prop, "Blend Type", "The mode used to apply the texture");
|
||||
RNA_def_property_ui_text(prop, "Blend Type", "Mode used to apply the texture");
|
||||
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_stencil", PROP_BOOLEAN, PROP_NONE);
|
||||
@ -521,12 +525,12 @@ static void rna_def_mtex(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_NEGATIVE);
|
||||
RNA_def_property_ui_text(prop, "Negate", "Inverts the values of the texture to reverse its effect");
|
||||
RNA_def_property_ui_text(prop, "Negate", "Invert the values of the texture to reverse its effect");
|
||||
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_rgb_to_intensity", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_RGBTOINT);
|
||||
RNA_def_property_ui_text(prop, "RGB to Intensity", "Converts texture RGB values to intensity (gray) values");
|
||||
RNA_def_property_ui_text(prop, "RGB to Intensity", "Convert texture RGB values to intensity (gray) values");
|
||||
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
|
||||
|
||||
prop= RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_NONE);
|
||||
@ -567,13 +571,15 @@ static void rna_def_filter_common(StructRNA *srna)
|
||||
prop= RNA_def_property(srna, "filter_probes", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "afmax");
|
||||
RNA_def_property_range(prop, 1, 256);
|
||||
RNA_def_property_ui_text(prop, "Filter Probes", "Maximum number of samples. Higher gives less blur at distant/oblique angles, but is also slower");
|
||||
RNA_def_property_ui_text(prop, "Filter Probes",
|
||||
"Maximum number of samples. Higher gives less blur at distant/oblique angles, but is also slower");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop= RNA_def_property(srna, "filter_eccentricity", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "afmax");
|
||||
RNA_def_property_range(prop, 1, 256);
|
||||
RNA_def_property_ui_text(prop, "Filter Eccentricity", "Maximum eccentricity. Higher gives less blur at distant/oblique angles, but is also slower");
|
||||
RNA_def_property_ui_text(prop, "Filter Eccentricity",
|
||||
"Maximum eccentricity. Higher gives less blur at distant/oblique angles, but is also slower");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_filter_size_min", PROP_BOOLEAN, PROP_NONE);
|
||||
@ -662,7 +668,7 @@ static void rna_def_environment_map(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "depth", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_range(prop, 0, 5);
|
||||
RNA_def_property_ui_text(prop, "Depth", "Number of times a map will be rendered recursively (mirror effects.)");
|
||||
RNA_def_property_ui_text(prop, "Depth", "Number of times a map will be rendered recursively (mirror effects)");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop= RNA_def_property(srna, "is_valid", PROP_BOOLEAN, 0);
|
||||
@ -926,13 +932,13 @@ static void rna_def_texture_blend(BlenderRNA *brna)
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem prop_blend_progression[] = {
|
||||
{TEX_LIN, "LINEAR", 0, "Linear", "Creates a linear progression"},
|
||||
{TEX_QUAD, "QUADRATIC", 0, "Quadratic", "Creates a quadratic progression"},
|
||||
{TEX_EASE, "EASING", 0, "Easing", "Creates a progression easing from one step to the next"},
|
||||
{TEX_DIAG, "DIAGONAL", 0, "Diagonal", "Creates a diagonal progression"},
|
||||
{TEX_SPHERE, "SPHERICAL", 0, "Spherical", "Creates a spherical progression"},
|
||||
{TEX_HALO, "QUADRATIC_SPHERE", 0, "Quadratic sphere", "Creates a quadratic progression in the shape of a sphere"},
|
||||
{TEX_RAD, "RADIAL", 0, "Radial", "Creates a radial progression"},
|
||||
{TEX_LIN, "LINEAR", 0, "Linear", "Create a linear progression"},
|
||||
{TEX_QUAD, "QUADRATIC", 0, "Quadratic", "Create a quadratic progression"},
|
||||
{TEX_EASE, "EASING", 0, "Easing", "Create a progression easing from one step to the next"},
|
||||
{TEX_DIAG, "DIAGONAL", 0, "Diagonal", "Create a diagonal progression"},
|
||||
{TEX_SPHERE, "SPHERICAL", 0, "Spherical", "Create a spherical progression"},
|
||||
{TEX_HALO, "QUADRATIC_SPHERE", 0, "Quadratic sphere", "Create a quadratic progression in the shape of a sphere"},
|
||||
{TEX_RAD, "RADIAL", 0, "Radial", "Create a radial progression"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static const EnumPropertyItem prop_flip_axis_items[]= {
|
||||
@ -1021,11 +1027,12 @@ static void rna_def_texture_image(BlenderRNA *brna)
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem prop_image_extension[] = {
|
||||
{TEX_EXTEND, "EXTEND", 0, "Extend", "Extends by repeating edge pixels of the image"},
|
||||
{TEX_CLIP, "CLIP", 0, "Clip", "Clips to image size and sets exterior pixels as transparent"},
|
||||
{TEX_CLIPCUBE, "CLIP_CUBE", 0, "Clip Cube", "Clips to cubic-shaped area around the image and sets exterior pixels as transparent"},
|
||||
{TEX_REPEAT, "REPEAT", 0, "Repeat", "Causes the image to repeat horizontally and vertically"},
|
||||
{TEX_CHECKER, "CHECKER", 0, "Checker", "Causes the image to repeat in checker board pattern"},
|
||||
{TEX_EXTEND, "EXTEND", 0, "Extend", "Extend by repeating edge pixels of the image"},
|
||||
{TEX_CLIP, "CLIP", 0, "Clip", "Clip to image size and sets exterior pixels as transparent"},
|
||||
{TEX_CLIPCUBE, "CLIP_CUBE", 0, "Clip Cube",
|
||||
"Clip to cubic-shaped area around the image and sets exterior pixels as transparent"},
|
||||
{TEX_REPEAT, "REPEAT", 0, "Repeat", "Cause the image to repeat horizontally and vertically"},
|
||||
{TEX_CHECKER, "CHECKER", 0, "Checker", "Cause the image to repeat in checker board pattern"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
srna= RNA_def_struct(brna, "ImageTexture", "Texture");
|
||||
@ -1219,11 +1226,15 @@ static void rna_def_texture_musgrave(BlenderRNA *brna)
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem prop_musgrave_type[] = {
|
||||
{TEX_MFRACTAL, "MULTIFRACTAL", 0, "Multifractal", "Fractal noise algorithm. Multifractal: Uses Perlin noise as a basis"},
|
||||
{TEX_RIDGEDMF, "RIDGED_MULTIFRACTAL", 0, "Ridged Multifractal", "Fractal noise algorithm. Ridged Multifractal: Uses Perlin noise with inflection as a basis"},
|
||||
{TEX_HYBRIDMF, "HYBRID_MULTIFRACTAL", 0, "Hybrid Multifractal", "Fractal noise algorithm.Hybrid Multifractal: Uses Perlin noise as a basis, with extended controls"},
|
||||
{TEX_MFRACTAL, "MULTIFRACTAL", 0, "Multifractal",
|
||||
"Fractal noise algorithm. Multifractal: Uses Perlin noise as a basis"},
|
||||
{TEX_RIDGEDMF, "RIDGED_MULTIFRACTAL", 0, "Ridged Multifractal",
|
||||
"Fractal noise algorithm. Ridged Multifractal: Uses Perlin noise with inflection as a basis"},
|
||||
{TEX_HYBRIDMF, "HYBRID_MULTIFRACTAL", 0, "Hybrid Multifractal",
|
||||
"Fractal noise algorithm.Hybrid Multifractal: Uses Perlin noise as a basis, with extended controls"},
|
||||
{TEX_FBM, "FBM", 0, "fBM", "Fractal noise algorithm. Fractal Brownian Motion: Uses Brownian noise as a basis"},
|
||||
{TEX_HTERRAIN, "HETERO_TERRAIN", 0, "Hetero Terrain", "Fractal noise algorithm. Hetero Terrain: similar to multifractal"},
|
||||
{TEX_HTERRAIN, "HETERO_TERRAIN", 0, "Hetero Terrain",
|
||||
"Fractal noise algorithm. Hetero Terrain: similar to multifractal"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
srna= RNA_def_struct(brna, "MusgraveTexture", "Texture");
|
||||
@ -1298,13 +1309,28 @@ static void rna_def_texture_voronoi(BlenderRNA *brna)
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem prop_distance_metric_items[] = {
|
||||
{TEX_DISTANCE, "DISTANCE", 0, "Actual Distance", "Algorithm used to calculate distance of sample points to feature points. Actual Distance: sqrt(x*x+y*y+z*z)"},
|
||||
{TEX_DISTANCE_SQUARED, "DISTANCE_SQUARED", 0, "Distance Squared", "Algorithm used to calculate distance of sample points to feature points. Distance squared: (x*x+y*y+z*z)"},
|
||||
{TEX_MANHATTAN, "MANHATTAN", 0, "Manhattan", "Algorithm used to calculate distance of sample points to feature points. Manhattan: The length of the distance in axial directions"},
|
||||
{TEX_CHEBYCHEV, "CHEBYCHEV", 0, "Chebychev", "Algorithm used to calculate distance of sample points to feature points. Chebychev: The length of the longest Axial journey"},
|
||||
{TEX_MINKOVSKY_HALF, "MINKOVSKY_HALF", 0, "Minkovsky 1/2", "Algorithm used to calculate distance of sample points to feature points. Minovsky 1/2: Sets Minkovsky variable to 0.5"},
|
||||
{TEX_MINKOVSKY_FOUR, "MINKOVSKY_FOUR", 0, "Minkovsky 4", "Algorithm used to calculate distance of sample points to feature points. Minkovsky 4: Sets Minkovsky variable to 4"},
|
||||
{TEX_MINKOVSKY, "MINKOVSKY", 0, "Minkovsky", "Algorithm used to calculate distance of sample points to feature points. Minkovsky: Uses the Minkowsky function to calculate distance. Exponent value determines the shape of the boundaries"},
|
||||
{TEX_DISTANCE, "DISTANCE", 0, "Actual Distance",
|
||||
"Algorithm used to calculate distance of sample points to feature points; "
|
||||
"Actual Distance: sqrt(x*x+y*y+z*z)"},
|
||||
{TEX_DISTANCE_SQUARED, "DISTANCE_SQUARED", 0, "Distance Squared",
|
||||
"Algorithm used to calculate distance of sample points to feature points; "
|
||||
"Distance squared: (x*x+y*y+z*z)"},
|
||||
{TEX_MANHATTAN, "MANHATTAN", 0, "Manhattan",
|
||||
"Algorithm used to calculate distance of sample points to feature points; "
|
||||
"Manhattan: The length of the distance in axial directions"},
|
||||
{TEX_CHEBYCHEV, "CHEBYCHEV", 0, "Chebychev",
|
||||
"Algorithm used to calculate distance of sample points to feature points; "
|
||||
"Chebychev: The length of the longest Axial journey"},
|
||||
{TEX_MINKOVSKY_HALF, "MINKOVSKY_HALF", 0, "Minkovsky 1/2",
|
||||
"Algorithm used to calculate distance of sample points to feature points; "
|
||||
"Minovsky 1/2: Sets Minkovsky variable to 0.5"},
|
||||
{TEX_MINKOVSKY_FOUR, "MINKOVSKY_FOUR", 0, "Minkovsky 4",
|
||||
"Algorithm used to calculate distance of sample points to feature points; "
|
||||
"Minkovsky 4: Sets Minkovsky variable to 4"},
|
||||
{TEX_MINKOVSKY, "MINKOVSKY", 0, "Minkovsky",
|
||||
"Algorithm used to calculate distance of sample points to feature points; "
|
||||
"Minkovsky: Uses the Minkowsky function to calculate distance "
|
||||
"(exponent value determines the shape of the boundaries)"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem prop_coloring_items[] = {
|
||||
@ -1312,7 +1338,8 @@ static void rna_def_texture_voronoi(BlenderRNA *brna)
|
||||
{TEX_INTENSITY, "INTENSITY", 0, "Intensity", "Only calculate intensity"},
|
||||
{TEX_COL1, "POSITION", 0, "Position", "Color cells by position"},
|
||||
{TEX_COL2, "POSITION_OUTLINE", 0, "Position and Outline", "Use position plus an outline based on F2-F.1"},
|
||||
{TEX_COL3, "POSITION_OUTLINE_INTENSITY", 0, "Position, Outline, and Intensity", "Multiply position and outline by intensity"},
|
||||
{TEX_COL3, "POSITION_OUTLINE_INTENSITY", 0, "Position, Outline, and Intensity",
|
||||
"Multiply position and outline by intensity"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
srna= RNA_def_struct(brna, "VoronoiTexture", "Texture");
|
||||
@ -1458,14 +1485,16 @@ static void rna_def_texture_pointdensity(BlenderRNA *brna)
|
||||
static EnumPropertyItem color_source_items[] = {
|
||||
{TEX_PD_COLOR_CONSTANT, "CONSTANT", 0, "Constant", ""},
|
||||
{TEX_PD_COLOR_PARTAGE, "PARTICLE_AGE", 0, "Particle Age", "Lifetime mapped as 0.0 - 1.0 intensity"},
|
||||
{TEX_PD_COLOR_PARTSPEED, "PARTICLE_SPEED", 0, "Particle Speed", "Particle speed (absolute magnitude of velocity) mapped as 0.0-1.0 intensity"},
|
||||
{TEX_PD_COLOR_PARTSPEED, "PARTICLE_SPEED", 0, "Particle Speed",
|
||||
"Particle speed (absolute magnitude of velocity) mapped as 0.0-1.0 intensity"},
|
||||
{TEX_PD_COLOR_PARTVEL, "PARTICLE_VELOCITY", 0, "Particle Velocity", "XYZ velocity mapped to RGB colors"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem turbulence_influence_items[] = {
|
||||
{TEX_PD_NOISE_STATIC, "STATIC", 0, "Static", "Noise patterns will remain unchanged, faster and suitable for stills"},
|
||||
{TEX_PD_NOISE_VEL, "PARTICLE_VELOCITY", 0, "Particle Velocity", "Turbulent noise driven by particle velocity"},
|
||||
{TEX_PD_NOISE_AGE, "PARTICLE_AGE", 0, "Particle Age", "Turbulent noise driven by the particle's age between birth and death"},
|
||||
{TEX_PD_NOISE_AGE, "PARTICLE_AGE", 0, "Particle Age",
|
||||
"Turbulent noise driven by the particle's age between birth and death"},
|
||||
{TEX_PD_NOISE_TIME, "GLOBAL_TIME", 0, "Global Time", "Turbulent noise driven by the global current frame"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
@ -1760,17 +1789,17 @@ static void rna_def_texture(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "bright");
|
||||
RNA_def_property_range(prop, 0, 2);
|
||||
RNA_def_property_ui_text(prop, "Brightness", "Adjusts the brightness of the texture");
|
||||
RNA_def_property_ui_text(prop, "Brightness", "Adjust the brightness of the texture");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop= RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.01, 5);
|
||||
RNA_def_property_ui_text(prop, "Contrast", "Adjusts the contrast of the texture");
|
||||
RNA_def_property_ui_text(prop, "Contrast", "Adjust the contrast of the texture");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop= RNA_def_property(srna, "saturation", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0, 2);
|
||||
RNA_def_property_ui_text(prop, "Saturation", "Adjusts the saturation of colors in the texture");
|
||||
RNA_def_property_ui_text(prop, "Saturation", "Adjust the saturation of colors in the texture");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
/* RGB Factor */
|
||||
|
@ -719,7 +719,7 @@ static void rna_def_header(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "layout");
|
||||
RNA_def_property_struct_type(prop, "UILayout");
|
||||
RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the header in the UI");
|
||||
RNA_def_property_ui_text(prop, "Layout", "Structure of the header in the UI");
|
||||
|
||||
/* registration */
|
||||
prop= RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
|
||||
@ -727,7 +727,7 @@ static void rna_def_header(BlenderRNA *brna)
|
||||
RNA_def_property_flag(prop, PROP_REGISTER|PROP_NEVER_CLAMP);
|
||||
RNA_def_property_ui_text(prop, "ID Name",
|
||||
"If this is set, the header gets a custom ID, otherwise it takes the "
|
||||
"name of the class used to define the panel. For example, if the "
|
||||
"name of the class used to define the panel; for example, if the "
|
||||
"class name is \"OBJECT_HT_hello\", and bl_idname is not set by the "
|
||||
"script, then bl_idname = \"OBJECT_HT_hello\"");
|
||||
|
||||
|
@ -2003,10 +2003,16 @@ static void rna_def_userdef_solidlight(BlenderRNA *brna)
|
||||
static void rna_def_userdef_view(BlenderRNA *brna)
|
||||
{
|
||||
static EnumPropertyItem timecode_styles[] = {
|
||||
{USER_TIMECODE_MINIMAL, "MINIMAL", 0, "Minimal Info", "Most compact representation. Uses '+' as separator for sub-second frame numbers, with left and right truncation of the timecode as necessary"},
|
||||
{USER_TIMECODE_SMPTE_FULL, "SMPTE", 0, "SMPTE (Full)", "Full SMPTE timecode. Format is HH:MM:SS:FF"},
|
||||
{USER_TIMECODE_SMPTE_MSF, "SMPTE_COMPACT", 0, "SMPTE (Compact)", "SMPTE timecode showing minutes, seconds, and frames only. Hours are also shown if necessary, but not by default"},
|
||||
{USER_TIMECODE_MILLISECONDS, "MILLISECONDS", 0, "Compact with Milliseconds", "Similar to SMPTE (Compact), except that instead of frames, milliseconds are shown instead"},
|
||||
{USER_TIMECODE_MINIMAL, "MINIMAL", 0, "Minimal Info",
|
||||
"Most compact representation, uses '+' as separator for sub-second frame numbers, "
|
||||
"with left and right truncation of the timecode as necessary"},
|
||||
{USER_TIMECODE_SMPTE_FULL, "SMPTE", 0, "SMPTE (Full)", "Full SMPTE timecode (format is HH:MM:SS:FF)"},
|
||||
{USER_TIMECODE_SMPTE_MSF, "SMPTE_COMPACT", 0, "SMPTE (Compact)",
|
||||
"SMPTE timecode showing minutes, seconds, and frames only - "
|
||||
"hours are also shown if necessary, but not by default"},
|
||||
{USER_TIMECODE_MILLISECONDS, "MILLISECONDS", 0, "Compact with Milliseconds",
|
||||
"Similar to SMPTE (Compact), except that instead of frames, "
|
||||
"milliseconds are shown instead"},
|
||||
{USER_TIMECODE_SECONDS_ONLY, "SECONDS_ONLY", 0, "Only Seconds", "Direct conversion of frame numbers to seconds"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
@ -2036,7 +2042,7 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_global_scene", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_SCENEGLOBAL);
|
||||
RNA_def_property_ui_text(prop, "Global Scene", "Forces the current Scene to be displayed in all Screens");
|
||||
RNA_def_property_ui_text(prop, "Global Scene", "Force the current Scene to be displayed in all Screens");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
prop= RNA_def_property(srna, "show_large_cursors", PROP_BOOLEAN, PROP_NONE);
|
||||
@ -2055,34 +2061,40 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "show_playback_fps", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_SHOW_FPS);
|
||||
RNA_def_property_ui_text(prop, "Show Playback FPS", "Show the frames per second screen refresh rate, while animation is played back");
|
||||
RNA_def_property_ui_text(prop, "Show Playback FPS",
|
||||
"Show the frames per second screen refresh rate, while animation is played back");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
/* menus */
|
||||
prop= RNA_def_property(srna, "use_mouse_over_open", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_MENUOPENAUTO);
|
||||
RNA_def_property_ui_text(prop, "Open On Mouse Over", "Open menu buttons and pulldowns automatically when the mouse is hovering");
|
||||
RNA_def_property_ui_text(prop, "Open On Mouse Over",
|
||||
"Open menu buttons and pulldowns automatically when the mouse is hovering");
|
||||
|
||||
prop= RNA_def_property(srna, "open_toplevel_delay", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "menuthreshold1");
|
||||
RNA_def_property_range(prop, 1, 40);
|
||||
RNA_def_property_ui_text(prop, "Top Level Menu Open Delay", "Time delay in 1/10 seconds before automatically opening top level menus");
|
||||
RNA_def_property_ui_text(prop, "Top Level Menu Open Delay",
|
||||
"Time delay in 1/10 seconds before automatically opening top level menus");
|
||||
|
||||
prop= RNA_def_property(srna, "open_sublevel_delay", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "menuthreshold2");
|
||||
RNA_def_property_range(prop, 1, 40);
|
||||
RNA_def_property_ui_text(prop, "Sub Level Menu Open Delay", "Time delay in 1/10 seconds before automatically opening sub level menus");
|
||||
RNA_def_property_ui_text(prop, "Sub Level Menu Open Delay",
|
||||
"Time delay in 1/10 seconds before automatically opening sub level menus");
|
||||
|
||||
/* Toolbox click-hold delay */
|
||||
prop= RNA_def_property(srna, "open_left_mouse_delay", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "tb_leftmouse");
|
||||
RNA_def_property_range(prop, 1, 40);
|
||||
RNA_def_property_ui_text(prop, "Hold LMB Open Toolbox Delay", "Time in 1/10 seconds to hold the Left Mouse Button before opening the toolbox");
|
||||
RNA_def_property_ui_text(prop, "Hold LMB Open Toolbox Delay",
|
||||
"Time in 1/10 seconds to hold the Left Mouse Button before opening the toolbox");
|
||||
|
||||
prop= RNA_def_property(srna, "open_right_mouse_delay", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "tb_rightmouse");
|
||||
RNA_def_property_range(prop, 1, 40);
|
||||
RNA_def_property_ui_text(prop, "Hold RMB Open Toolbox Delay", "Time in 1/10 seconds to hold the Right Mouse Button before opening the toolbox");
|
||||
RNA_def_property_ui_text(prop, "Hold RMB Open Toolbox Delay",
|
||||
"Time in 1/10 seconds to hold the Right Mouse Button before opening the toolbox");
|
||||
|
||||
prop= RNA_def_property(srna, "show_column_layout", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_PLAINMENUS);
|
||||
@ -2090,7 +2102,8 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_directional_menus", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag", USER_MENUFIXEDORDER);
|
||||
RNA_def_property_ui_text(prop, "Contents Follow Opening Direction", "Otherwise menus, etc will always be top to bottom, left to right, no matter opening direction");
|
||||
RNA_def_property_ui_text(prop, "Contents Follow Opening Direction",
|
||||
"Otherwise menus, etc will always be top to bottom, left to right, no matter opening direction");
|
||||
|
||||
prop= RNA_def_property(srna, "use_global_pivot", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_LOCKAROUND);
|
||||
@ -2102,17 +2115,22 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_camera_lock_parent", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag", USER_CAM_LOCK_NO_PARENT);
|
||||
RNA_def_property_ui_text(prop, "Camera Parent Lock", "When the camera is locked to the view and in fly mode, transform the parent rather than the camera");
|
||||
RNA_def_property_ui_text(prop, "Camera Parent Lock",
|
||||
"When the camera is locked to the view and in fly mode, "
|
||||
"transform the parent rather than the camera");
|
||||
|
||||
/* view zoom */
|
||||
prop= RNA_def_property(srna, "use_zoom_to_mouse", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ZOOM_TO_MOUSEPOS);
|
||||
RNA_def_property_ui_text(prop, "Zoom To Mouse Position", "Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center");
|
||||
RNA_def_property_ui_text(prop, "Zoom To Mouse Position",
|
||||
"Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center");
|
||||
|
||||
/* view rotation */
|
||||
prop= RNA_def_property(srna, "use_auto_perspective", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_AUTOPERSP);
|
||||
RNA_def_property_ui_text(prop, "Auto Perspective", "Automatically switch between orthographic and perspective when changing from top/front/side views");
|
||||
RNA_def_property_ui_text(prop, "Auto Perspective",
|
||||
"Automatically switch between orthographic and perspective when changing "
|
||||
"from top/front/side views");
|
||||
|
||||
prop= RNA_def_property(srna, "use_rotate_around_active", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ORBIT_SELECTION);
|
||||
@ -2121,30 +2139,30 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
||||
/* mini axis */
|
||||
prop= RNA_def_property(srna, "show_mini_axis", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_SHOW_ROTVIEWICON);
|
||||
RNA_def_property_ui_text(prop, "Show Mini Axis", "Show a small rotating 3D axis in the bottom left corner of the 3D View");
|
||||
RNA_def_property_ui_text(prop, "Show Mini Axes", "Show a small rotating 3D axes in the bottom left corner of the 3D View");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
prop= RNA_def_property(srna, "mini_axis_size", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "rvisize");
|
||||
RNA_def_property_range(prop, 10, 64);
|
||||
RNA_def_property_ui_text(prop, "Mini Axis Size", "The axis icon's size");
|
||||
RNA_def_property_ui_text(prop, "Mini Axes Size", "The axes icon's size");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
prop= RNA_def_property(srna, "mini_axis_brightness", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "rvibright");
|
||||
RNA_def_property_range(prop, 0, 10);
|
||||
RNA_def_property_ui_text(prop, "Mini Axis Brightness", "The brightness of the icon");
|
||||
RNA_def_property_ui_text(prop, "Mini Axes Brightness", "Brightness of the icon");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
prop= RNA_def_property(srna, "smooth_view", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "smooth_viewtx");
|
||||
RNA_def_property_range(prop, 0, 1000);
|
||||
RNA_def_property_ui_text(prop, "Smooth View", "The time to animate the view in milliseconds, zero to disable");
|
||||
RNA_def_property_ui_text(prop, "Smooth View", "Time to animate the view in milliseconds, zero to disable");
|
||||
|
||||
prop= RNA_def_property(srna, "rotation_angle", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "pad_rot_angle");
|
||||
RNA_def_property_range(prop, 0, 90);
|
||||
RNA_def_property_ui_text(prop, "Rotation Angle", "The rotation step for numerical pad keys (2 4 6 8)");
|
||||
RNA_def_property_ui_text(prop, "Rotation Angle", "Rotation step for numerical pad keys (2 4 6 8)");
|
||||
|
||||
/* 3D transform widget */
|
||||
prop= RNA_def_property(srna, "show_manipulator", PROP_BOOLEAN, PROP_NONE);
|
||||
@ -2182,7 +2200,8 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "view2d_grid_spacing_min", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "v2d_min_gridsize");
|
||||
RNA_def_property_range(prop, 1, 500); // XXX: perhaps the lower range should only go down to 5?
|
||||
RNA_def_property_ui_text(prop, "2D View Minimum Grid Spacing", "Minimum number of pixels between each gridline in 2D Viewports");
|
||||
RNA_def_property_ui_text(prop, "2D View Minimum Grid Spacing",
|
||||
"Minimum number of pixels between each gridline in 2D Viewports");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
// TODO: add a setter for this, so that we can bump up the minimum size as necessary...
|
||||
@ -2190,7 +2209,8 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
||||
RNA_def_property_enum_items(prop, timecode_styles);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "timecode_style");
|
||||
RNA_def_property_enum_funcs(prop, NULL, "rna_userdef_timecode_style_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "TimeCode Style", "Format of Time Codes displayed when not displaying timing in terms of frames");
|
||||
RNA_def_property_ui_text(prop, "TimeCode Style",
|
||||
"Format of Time Codes displayed when not displaying timing in terms of frames");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
}
|
||||
|
||||
@ -2210,7 +2230,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static const EnumPropertyItem object_align_items[]= {
|
||||
{0, "WORLD", 0, "World", "Align newly added objects to the world coordinates"},
|
||||
{0, "WORLD", 0, "World", "Align newly added objects to the world coordinate system"},
|
||||
{USER_ADD_VIEWALIGNED, "VIEW", 0, "View", "Align newly added objects facing the active 3D View direction"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
@ -2224,12 +2244,14 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "material_link", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
|
||||
RNA_def_property_enum_items(prop, material_link_items);
|
||||
RNA_def_property_ui_text(prop, "Material Link To", "Toggle whether the material is linked to object data or the object block");
|
||||
RNA_def_property_ui_text(prop, "Material Link To",
|
||||
"Toggle whether the material is linked to object data or the object block");
|
||||
|
||||
prop= RNA_def_property(srna, "object_align", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
|
||||
RNA_def_property_enum_items(prop, object_align_items);
|
||||
RNA_def_property_ui_text(prop, "Align Object To", "When adding objects from a 3D View menu, either align them to that view's direction or the world coordinates");
|
||||
RNA_def_property_ui_text(prop, "Align Object To",
|
||||
"When adding objects from a 3D View menu, either align them with that view or with the world");
|
||||
|
||||
prop= RNA_def_property(srna, "use_enter_edit_mode", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_ADD_EDITMODE);
|
||||
@ -2252,22 +2274,26 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_global_undo", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_GLOBALUNDO);
|
||||
RNA_def_property_ui_text(prop, "Global Undo", "Global undo works by keeping a full copy of the file itself in memory, so takes extra memory");
|
||||
RNA_def_property_ui_text(prop, "Global Undo",
|
||||
"Global undo works by keeping a full copy of the file itself in memory, so takes extra memory");
|
||||
|
||||
/* auto keyframing */
|
||||
prop= RNA_def_property(srna, "use_auto_keying", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "autokey_mode", AUTOKEY_ON);
|
||||
RNA_def_property_ui_text(prop, "Auto Keying Enable", "Automatic keyframe insertion for Objects and Bones (default setting used for new Scenes)");
|
||||
RNA_def_property_ui_text(prop, "Auto Keying Enable",
|
||||
"Automatic keyframe insertion for Objects and Bones (default setting used for new Scenes)");
|
||||
RNA_def_property_ui_icon(prop, ICON_REC, 0);
|
||||
|
||||
prop= RNA_def_property(srna, "auto_keying_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, auto_key_modes);
|
||||
RNA_def_property_enum_funcs(prop, "rna_userdef_autokeymode_get", "rna_userdef_autokeymode_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Auto Keying Mode", "Mode of automatic keyframe insertion for Objects and Bones (default setting used for new Scenes)");
|
||||
RNA_def_property_ui_text(prop, "Auto Keying Mode",
|
||||
"Mode of automatic keyframe insertion for Objects and Bones "
|
||||
"(default setting used for new Scenes)");
|
||||
|
||||
prop= RNA_def_property(srna, "use_keyframe_insert_available", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_INSERTAVAIL);
|
||||
RNA_def_property_ui_text(prop, "Auto Keyframe Insert Available", "Automatic keyframe insertion in available curves");
|
||||
RNA_def_property_ui_text(prop, "Auto Keyframe Insert Available", "Automatic keyframe insertion in available F-Curves");
|
||||
|
||||
/* keyframing settings */
|
||||
prop= RNA_def_property(srna, "use_keyframe_insert_needed", PROP_BOOLEAN, PROP_NONE);
|
||||
@ -2280,12 +2306,16 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_insertkey_xyz_to_rgb", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_XYZ2RGB);
|
||||
RNA_def_property_ui_text(prop, "New F-Curve Colors - XYZ to RGB", "Color for newly added transformation F-Curves (Location, Rotation, Scale) and also Color is based on the transform axis");
|
||||
RNA_def_property_ui_text(prop, "New F-Curve Colors - XYZ to RGB",
|
||||
"Color for newly added transformation F-Curves (Location, Rotation, Scale) "
|
||||
"and also Color is based on the transform axis");
|
||||
|
||||
prop= RNA_def_property(srna, "keyframe_new_interpolation_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, beztriple_interpolation_mode_items);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "ipo_new");
|
||||
RNA_def_property_ui_text(prop, "New Interpolation Type", "Interpolation mode used for first keyframe on newly added F-Curves. Subsequent keyframes take interpolation from preceeding keyframe");
|
||||
RNA_def_property_ui_text(prop, "New Interpolation Type",
|
||||
"Interpolation mode used for first keyframe on newly added F-Curves "
|
||||
"(subsequent keyframes take interpolation from preceeding keyframe)");
|
||||
|
||||
prop= RNA_def_property(srna, "keyframe_new_handle_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, keyframe_handle_type_items);
|
||||
@ -2306,7 +2336,8 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "grease_pencil_euclidean_distance", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "gp_euclideandist");
|
||||
RNA_def_property_range(prop, 0, 100);
|
||||
RNA_def_property_ui_text(prop, "Grease Pencil Euclidean Distance", "Distance moved by mouse when drawing stroke (in pixels) to include");
|
||||
RNA_def_property_ui_text(prop, "Grease Pencil Euclidean Distance",
|
||||
"Distance moved by mouse when drawing stroke (in pixels) to include");
|
||||
|
||||
prop= RNA_def_property(srna, "use_grease_pencil_smooth_stroke", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "gp_settings", GP_PAINT_DOSMOOTH);
|
||||
@ -2459,10 +2490,14 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
|
||||
static EnumPropertyItem draw_method_items[] = {
|
||||
{USER_DRAW_AUTOMATIC, "AUTOMATIC", 0, "Automatic", "Automatically set based on graphics card and driver"},
|
||||
{USER_DRAW_TRIPLE, "TRIPLE_BUFFER", 0, "Triple Buffer", "Use a third buffer for minimal redraws at the cost of more memory"},
|
||||
{USER_DRAW_TRIPLE, "TRIPLE_BUFFER", 0, "Triple Buffer",
|
||||
"Use a third buffer for minimal redraws at the cost of more memory"},
|
||||
{USER_DRAW_OVERLAP, "OVERLAP", 0, "Overlap", "Redraw all overlapping regions, minimal memory usage but more redraws"},
|
||||
{USER_DRAW_OVERLAP_FLIP, "OVERLAP_FLIP", 0, "Overlap Flip", "Redraw all overlapping regions, minimal memory usage but more redraws (for graphics drivers that do flipping)"},
|
||||
{USER_DRAW_FULL, "FULL", 0, "Full", "Do a full redraw each time, slow, only use for reference or when all else fails"},
|
||||
{USER_DRAW_OVERLAP_FLIP, "OVERLAP_FLIP", 0, "Overlap Flip",
|
||||
"Redraw all overlapping regions, minimal memory usage but more redraws "
|
||||
"(for graphics drivers that do flipping)"},
|
||||
{USER_DRAW_FULL, "FULL", 0, "Full",
|
||||
"Do a full redraw each time, slow, only use for reference or when everything else fails"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem color_picker_types[] = {
|
||||
@ -2536,7 +2571,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "language", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, language_items);
|
||||
RNA_def_property_ui_text(prop, "Language", "Language use for translation");
|
||||
RNA_def_property_ui_text(prop, "Language", "Language used for translation");
|
||||
RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_language_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_translate_tooltips", PROP_BOOLEAN, PROP_NONE);
|
||||
@ -2563,7 +2598,8 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_weight_color_range", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_CUSTOM_RANGE);
|
||||
RNA_def_property_ui_text(prop, "Use Weight Color Range", "Enable color range used for weight visualization in weight painting mode");
|
||||
RNA_def_property_ui_text(prop, "Use Weight Color Range",
|
||||
"Enable color range used for weight visualization in weight painting mode");
|
||||
RNA_def_property_update(prop, 0, "rna_UserDef_weight_color_update");
|
||||
|
||||
prop= RNA_def_property(srna, "weight_color_range", PROP_POINTER, PROP_NONE);
|
||||
@ -2580,16 +2616,20 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_preview_images", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ALLWINCODECS);
|
||||
RNA_def_property_ui_text(prop, "Enable All Codecs", "Enables automatic saving of preview images in the .blend file (Windows only)");
|
||||
RNA_def_property_ui_text(prop, "Enable All Codecs",
|
||||
"Allow user to choose any codec (Windows only, might generate instability)");
|
||||
|
||||
prop= RNA_def_property(srna, "use_scripts_auto_execute", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_SCRIPT_AUTOEXEC_DISABLE);
|
||||
RNA_def_property_ui_text(prop, "Auto Run Python Scripts", "Allow any .blend file to run scripts automatically (unsafe with blend files from an untrusted source)");
|
||||
RNA_def_property_ui_text(prop, "Auto Run Python Scripts",
|
||||
"Allow any .blend file to run scripts automatically "
|
||||
"(unsafe with blend files from an untrusted source)");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_script_autoexec_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_tabs_as_spaces", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_TXT_TABSTOSPACES_DISABLE);
|
||||
RNA_def_property_ui_text(prop, "Tabs as Spaces", "Automatically converts all new tabs into spaces for new and loaded text files");
|
||||
RNA_def_property_ui_text(prop, "Tabs as Spaces",
|
||||
"Automatically convert all new tabs into spaces for new and loaded text files");
|
||||
|
||||
prop= RNA_def_property(srna, "prefetch_frames", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "prefetchframes");
|
||||
@ -2615,12 +2655,14 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_mipmaps", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_MIPMAP);
|
||||
RNA_def_property_ui_text(prop, "Mipmaps", "Scale textures for the 3D View (looks nicer but uses more memory and slows image reloading)");
|
||||
RNA_def_property_ui_text(prop, "Mipmaps",
|
||||
"Scale textures for the 3D View (looks nicer but uses more memory and slows image reloading)");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_mipmap_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_vertex_buffer_objects", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_VBO);
|
||||
RNA_def_property_ui_text(prop, "VBOs", "Use Vertex Buffer Objects (or Vertex Arrays, if unsupported) for viewport rendering");
|
||||
RNA_def_property_ui_text(prop, "VBOs",
|
||||
"Use Vertex Buffer Objects (or Vertex Arrays, if unsupported) for viewport rendering");
|
||||
|
||||
prop= RNA_def_property(srna, "use_antialiasing", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_AA);
|
||||
@ -2630,7 +2672,8 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
RNA_def_property_enum_sdna(prop, NULL, "anisotropic_filter");
|
||||
RNA_def_property_enum_items(prop, anisotropic_items);
|
||||
RNA_def_property_enum_default(prop, 1);
|
||||
RNA_def_property_ui_text(prop, "Anisotropic Filter", "The quality of the anisotropic filtering (values greater than 1.0 enable anisotropic filtering)");
|
||||
RNA_def_property_ui_text(prop, "Anisotropic Filter",
|
||||
"Quality of the anisotropic filtering (values greater than 1.0 enable anisotropic filtering)");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_anisotropic_update");
|
||||
|
||||
prop= RNA_def_property(srna, "gl_texture_limit", PROP_ENUM, PROP_NONE);
|
||||
@ -2642,12 +2685,15 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "texture_time_out", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "textimeout");
|
||||
RNA_def_property_range(prop, 0, 3600);
|
||||
RNA_def_property_ui_text(prop, "Texture Time Out", "Time since last access of a GL texture in seconds after which it is freed. (Set to 0 to keep textures allocated.)");
|
||||
RNA_def_property_ui_text(prop, "Texture Time Out",
|
||||
"Time since last access of a GL texture in seconds after which it is freed "
|
||||
"(set to 0 to keep textures allocated)");
|
||||
|
||||
prop= RNA_def_property(srna, "texture_collection_rate", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "texcollectrate");
|
||||
RNA_def_property_range(prop, 1, 3600);
|
||||
RNA_def_property_ui_text(prop, "Texture Collection Rate", "Number of seconds between each run of the GL texture garbage collector");
|
||||
RNA_def_property_ui_text(prop, "Texture Collection Rate",
|
||||
"Number of seconds between each run of the GL texture garbage collector");
|
||||
|
||||
prop= RNA_def_property(srna, "window_draw_method", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "wmdrawmethod");
|
||||
@ -2658,31 +2704,31 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "audio_mixing_buffer", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "mixbufsize");
|
||||
RNA_def_property_enum_items(prop, audio_mixing_samples_items);
|
||||
RNA_def_property_ui_text(prop, "Audio Mixing Buffer", "Sets the number of samples used by the audio mixing buffer");
|
||||
RNA_def_property_ui_text(prop, "Audio Mixing Buffer", "Number of samples used by the audio mixing buffer");
|
||||
RNA_def_property_update(prop, 0, "rna_UserDef_audio_update");
|
||||
|
||||
prop= RNA_def_property(srna, "audio_device", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "audiodevice");
|
||||
RNA_def_property_enum_items(prop, audio_device_items);
|
||||
RNA_def_property_ui_text(prop, "Audio Device", "Sets the audio output device");
|
||||
RNA_def_property_ui_text(prop, "Audio Device", "Audio output device");
|
||||
RNA_def_property_update(prop, 0, "rna_UserDef_audio_update");
|
||||
|
||||
prop= RNA_def_property(srna, "audio_sample_rate", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "audiorate");
|
||||
RNA_def_property_enum_items(prop, audio_rate_items);
|
||||
RNA_def_property_ui_text(prop, "Audio Sample Rate", "Sets the audio sample rate");
|
||||
RNA_def_property_ui_text(prop, "Audio Sample Rate", "Audio sample rate");
|
||||
RNA_def_property_update(prop, 0, "rna_UserDef_audio_update");
|
||||
|
||||
prop= RNA_def_property(srna, "audio_sample_format", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "audioformat");
|
||||
RNA_def_property_enum_items(prop, audio_format_items);
|
||||
RNA_def_property_ui_text(prop, "Audio Sample Format", "Sets the audio sample format");
|
||||
RNA_def_property_ui_text(prop, "Audio Sample Format", "Audio sample format");
|
||||
RNA_def_property_update(prop, 0, "rna_UserDef_audio_update");
|
||||
|
||||
prop= RNA_def_property(srna, "audio_channels", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "audiochannels");
|
||||
RNA_def_property_enum_items(prop, audio_channel_items);
|
||||
RNA_def_property_ui_text(prop, "Audio Channels", "Sets the audio channel count");
|
||||
RNA_def_property_ui_text(prop, "Audio Channels", "Audio channel count");
|
||||
RNA_def_property_update(prop, 0, "rna_UserDef_audio_update");
|
||||
|
||||
prop= RNA_def_property(srna, "screencast_fps", PROP_INT, PROP_NONE);
|
||||
@ -2703,11 +2749,11 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
#if 0
|
||||
prop= RNA_def_property(srna, "verse_master", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "versemaster");
|
||||
RNA_def_property_ui_text(prop, "Verse Master", "The Verse Master-server IP");
|
||||
RNA_def_property_ui_text(prop, "Verse Master", "Verse Master-server IP");
|
||||
|
||||
prop= RNA_def_property(srna, "verse_username", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "verseuser");
|
||||
RNA_def_property_ui_text(prop, "Verse Username", "The Verse user name");
|
||||
RNA_def_property_ui_text(prop, "Verse Username", "Verse user name");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2728,13 +2774,13 @@ static void rna_def_userdef_input(BlenderRNA *brna)
|
||||
|
||||
static EnumPropertyItem view_zoom_styles[] = {
|
||||
{USER_ZOOM_CONT, "CONTINUE", 0, "Continue", "Old style zoom, continues while moving mouse up or down"},
|
||||
{USER_ZOOM_DOLLY, "DOLLY", 0, "Dolly", "Zooms in and out based on vertical mouse movement"},
|
||||
{USER_ZOOM_SCALE, "SCALE", 0, "Scale", "Zooms in and out like scaling the view, mouse movements relative to center"},
|
||||
{USER_ZOOM_DOLLY, "DOLLY", 0, "Dolly", "Zoom in and out based on vertical mouse movement"},
|
||||
{USER_ZOOM_SCALE, "SCALE", 0, "Scale", "Zoom in and out like scaling the view, mouse movements relative to center"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem view_zoom_axes[] = {
|
||||
{0, "VERTICAL", 0, "Vertical", "Zooms in and out based on vertical mouse movement"},
|
||||
{USER_ZOOM_HORIZ, "HORIZONTAL", 0, "Horizontal", "Zooms in and out based on horizontal mouse movement"},
|
||||
{0, "VERTICAL", 0, "Vertical", "Zoom in and out based on vertical mouse movement"},
|
||||
{USER_ZOOM_HORIZ, "HORIZONTAL", 0, "Horizontal", "Zoom in and out based on horizontal mouse movement"},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
srna= RNA_def_struct(brna, "UserPreferencesInput", NULL);
|
||||
@ -2746,7 +2792,7 @@ static void rna_def_userdef_input(BlenderRNA *brna)
|
||||
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
|
||||
RNA_def_property_enum_items(prop, select_mouse_items);
|
||||
RNA_def_property_enum_funcs(prop, NULL, "rna_userdef_select_mouse_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Select Mouse", "The mouse button used for selection");
|
||||
RNA_def_property_ui_text(prop, "Select Mouse", "Mouse button used for selection");
|
||||
|
||||
prop= RNA_def_property(srna, "view_zoom_method", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "viewzoom");
|
||||
@ -2769,7 +2815,8 @@ static void rna_def_userdef_input(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "use_mouse_continuous", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_CONTINUOUS_MOUSE);
|
||||
RNA_def_property_ui_text(prop, "Continuous Grab", "Allow moving the mouse outside the view on some manipulations (transform, ui control drag)");
|
||||
RNA_def_property_ui_text(prop, "Continuous Grab",
|
||||
"Allow moving the mouse outside the view on some manipulations (transform, ui control drag)");
|
||||
|
||||
/* tweak tablet & mouse preset */
|
||||
prop= RNA_def_property(srna, "drag_threshold", PROP_INT, PROP_NONE);
|
||||
@ -2846,15 +2893,16 @@ static void rna_def_userdef_input(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "mouse_double_click_time", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "dbl_click_time");
|
||||
RNA_def_property_range(prop, 1, 1000);
|
||||
RNA_def_property_ui_text(prop, "Double Click Timeout", "The time (in ms) for a double click");
|
||||
RNA_def_property_ui_text(prop, "Double Click Timeout", "Time/delay (in ms) for a double click");
|
||||
|
||||
prop= RNA_def_property(srna, "use_mouse_emulate_3_button", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_TWOBUTTONMOUSE);
|
||||
RNA_def_property_ui_text(prop, "Emulate 3 Button Mouse", "Emulates Middle Mouse with Alt+Left Mouse (doesn't work with Left Mouse Select option)");
|
||||
RNA_def_property_ui_text(prop, "Emulate 3 Button Mouse",
|
||||
"Emulate Middle Mouse with Alt+Left Mouse (doesn't work with Left Mouse Select option)");
|
||||
|
||||
prop= RNA_def_property(srna, "use_emulate_numpad", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_NONUMPAD);
|
||||
RNA_def_property_ui_text(prop, "Emulate Numpad", "Causes the 1 to 0 keys to act as the numpad (useful for laptops)");
|
||||
RNA_def_property_ui_text(prop, "Emulate Numpad", "Main 1 to 0 keys act as the numpad ones (useful for laptops)");
|
||||
|
||||
/* middle mouse button */
|
||||
prop= RNA_def_property(srna, "use_mouse_mmb_paste", PROP_BOOLEAN, PROP_NONE);
|
||||
@ -2868,7 +2916,7 @@ static void rna_def_userdef_input(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "wheel_scroll_lines", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "wheellinescroll");
|
||||
RNA_def_property_range(prop, 0, 32);
|
||||
RNA_def_property_ui_text(prop, "Wheel Scroll Lines", "The number of lines scrolled at a time with the mouse wheel");
|
||||
RNA_def_property_ui_text(prop, "Wheel Scroll Lines", "Number of lines scrolled at a time with the mouse wheel");
|
||||
|
||||
prop= RNA_def_property(srna, "active_keyconfig", PROP_STRING, PROP_DIRPATH);
|
||||
RNA_def_property_string_sdna(prop, NULL, "keyconfigstr");
|
||||
@ -2897,7 +2945,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "show_hidden_files_datablocks", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_HIDE_DOT);
|
||||
RNA_def_property_ui_text(prop, "Hide Dot Files/Datablocks", "Hide files/datablocks that start with a dot(.*)");
|
||||
RNA_def_property_ui_text(prop, "Hide Dot Files/Datablocks", "Hide files/datablocks that start with a dot (.*)");
|
||||
|
||||
prop= RNA_def_property(srna, "use_filter_files", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_FILTERFILEEXTS);
|
||||
@ -2945,7 +2993,9 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "script_directory", PROP_STRING, PROP_DIRPATH);
|
||||
RNA_def_property_string_sdna(prop, NULL, "pythondir");
|
||||
RNA_def_property_ui_text(prop, "Python Scripts Directory", "Alternate script path, matching the default layout with subdirs: startup, addons & modules (requires restart)");
|
||||
RNA_def_property_ui_text(prop, "Python Scripts Directory",
|
||||
"Alternate script path, matching the default layout with subdirs: "
|
||||
"startup, addons & modules (requires restart)");
|
||||
/* TODO, editing should reset sys.path! */
|
||||
|
||||
prop= RNA_def_property(srna, "sound_directory", PROP_STRING, PROP_DIRPATH);
|
||||
@ -2976,11 +3026,13 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
|
||||
prop= RNA_def_property(srna, "save_version", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "versions");
|
||||
RNA_def_property_range(prop, 0, 32);
|
||||
RNA_def_property_ui_text(prop, "Save Versions", "The number of old versions to maintain in the current directory, when manually saving");
|
||||
RNA_def_property_ui_text(prop, "Save Versions",
|
||||
"The number of old versions to maintain in the current directory, when manually saving");
|
||||
|
||||
prop= RNA_def_property(srna, "use_auto_save_temporary_files", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_AUTOSAVE);
|
||||
RNA_def_property_ui_text(prop, "Auto Save Temporary Files", "Automatic saving of temporary files in temp directory, uses process ID");
|
||||
RNA_def_property_ui_text(prop, "Auto Save Temporary Files",
|
||||
"Automatic saving of temporary files in temp directory, uses process ID");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_autosave_update");
|
||||
|
||||
prop= RNA_def_property(srna, "auto_save_time", PROP_INT, PROP_NONE);
|
||||
@ -3006,7 +3058,7 @@ void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
|
||||
RNA_def_property_srna(cprop, "Addons");
|
||||
srna= RNA_def_struct(brna, "Addons", NULL);
|
||||
RNA_def_struct_ui_text(srna, "User Add-Ons", "Collection of add-ons");
|
||||
RNA_def_struct_ui_text(srna, "User Addons", "Collection of addons");
|
||||
|
||||
func= RNA_def_function(srna, "new", "rna_userdef_addon_new");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
@ -3031,7 +3083,7 @@ void RNA_def_userdef(BlenderRNA *brna)
|
||||
{USER_SECTION_INTERFACE, "INTERFACE", 0, "Interface", ""},
|
||||
{USER_SECTION_EDIT, "EDITING", 0, "Editing", ""},
|
||||
{USER_SECTION_INPUT, "INPUT", 0, "Input", ""},
|
||||
{USER_SECTION_ADDONS, "ADDONS", 0, "Add-Ons", ""},
|
||||
{USER_SECTION_ADDONS, "ADDONS", 0, "Addons", ""},
|
||||
{USER_SECTION_THEME, "THEMES", 0, "Themes", ""},
|
||||
{USER_SECTION_FILE, "FILES", 0, "File", ""},
|
||||
{USER_SECTION_SYSTEM, "SYSTEM", 0, "System", ""},
|
||||
|
@ -558,7 +558,9 @@ static DerivedMesh * cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
|
||||
int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2");
|
||||
int *facepa = emd->facepa;
|
||||
int *fs, totesplit=0,totfsplit=0,curdupface=0;
|
||||
int i,j,v1,v2,v3,v4,esplit, v[4], uv[4];
|
||||
int i,j,v1,v2,v3,v4,esplit,
|
||||
v[4] = {0, 0, 0, 0}, /* To quite gcc barking... */
|
||||
uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */
|
||||
int numlayer;
|
||||
|
||||
edgehash= BLI_edgehash_new();
|
||||
|
@ -267,6 +267,18 @@ static int bpy_prop_callback_assign(struct PropertyRNA *prop, PyObject *update_c
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* utility function we need for parsing int's in an if statement */
|
||||
static int py_long_as_int(PyObject *py_long, int *r_int)
|
||||
{
|
||||
if(PyLong_CheckExact(py_long)) {
|
||||
*r_int= (int)PyLong_AS_LONG(py_long);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* this define runs at the start of each function and deals with
|
||||
* returning a deferred property (to be registered later) */
|
||||
#define BPY_PROPDEF_HEAD(_func) \
|
||||
@ -914,6 +926,7 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i
|
||||
|
||||
for(i=0; i<seq_len; i++) {
|
||||
EnumPropertyItem tmp= {0, "", 0, "", ""};
|
||||
Py_ssize_t item_size;
|
||||
Py_ssize_t id_str_size;
|
||||
Py_ssize_t name_str_size;
|
||||
Py_ssize_t desc_str_size;
|
||||
@ -921,13 +934,17 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i
|
||||
item= PySequence_Fast_GET_ITEM(seq_fast, i);
|
||||
|
||||
if( (PyTuple_CheckExact(item)) &&
|
||||
(PyTuple_GET_SIZE(item) == 3) &&
|
||||
(item_size= PyTuple_GET_SIZE(item)) &&
|
||||
(item_size == 3 || item_size == 4) &&
|
||||
(tmp.identifier= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) &&
|
||||
(tmp.name= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) &&
|
||||
(tmp.description= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size))
|
||||
(tmp.description= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) &&
|
||||
(item_size < 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1) /* TODO, number isnt ensured to be unique from the script author */
|
||||
) {
|
||||
if(is_enum_flag) {
|
||||
tmp.value= 1<<i;
|
||||
if(item_size < 4) {
|
||||
tmp.value= 1<<i;
|
||||
}
|
||||
|
||||
if(def && PySet_Contains(def, PyTuple_GET_ITEM(item, 0))) {
|
||||
*defvalue |= tmp.value;
|
||||
@ -935,7 +952,9 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i
|
||||
}
|
||||
}
|
||||
else {
|
||||
tmp.value= i;
|
||||
if(item_size < 4) {
|
||||
tmp.value= i;
|
||||
}
|
||||
|
||||
if(def && def_used == 0 && strcmp(def_cmp, tmp.identifier)==0) {
|
||||
*defvalue= tmp.value;
|
||||
@ -950,7 +969,10 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i
|
||||
}
|
||||
else {
|
||||
MEM_freeN(items);
|
||||
PyErr_SetString(PyExc_TypeError, "EnumProperty(...): expected an tuple containing (identifier, name description)");
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"EnumProperty(...): expected an tuple containing "
|
||||
"(identifier, name description) and optionally a "
|
||||
"unique number");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1081,8 +1103,9 @@ BPY_PROPDEF_DESC_DOC
|
||||
" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'ENUM_FLAG'].\n"
|
||||
" :type options: set\n"
|
||||
" :arg items: sequence of enum items formatted:\n"
|
||||
" [(identifier, name, description), ...] where the identifier is used\n"
|
||||
" [(identifier, name, description, number), ...] where the identifier is used\n"
|
||||
" for python access and other values are used for the interface.\n"
|
||||
" Note the item is optional.\n"
|
||||
" For dynamic values a callback can be passed which returns a list in\n"
|
||||
" the same format as the static list.\n"
|
||||
" This function must take 2 arguments (self, context)\n"
|
||||
|
@ -6238,7 +6238,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
|
||||
ParameterIterator iter;
|
||||
PointerRNA funcptr;
|
||||
int err= 0, i, flag, ret_len=0;
|
||||
int is_static= RNA_function_flag(func) & FUNC_NO_SELF;
|
||||
const char is_static= (RNA_function_flag(func) & FUNC_NO_SELF) != 0;
|
||||
|
||||
/* annoying!, need to check if the screen gets set to NULL which is a
|
||||
* hint that the file was actually re-loaded. */
|
||||
char is_valid_wm;
|
||||
|
||||
PropertyRNA *pret_single= NULL;
|
||||
void *retdata_single= NULL;
|
||||
@ -6265,6 +6269,8 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
|
||||
if(C==NULL)
|
||||
C= BPy_GetContext();
|
||||
|
||||
is_valid_wm= (CTX_wm_manager(C) != NULL);
|
||||
|
||||
bpy_context_set(C, &gilstate);
|
||||
|
||||
if (!is_static) {
|
||||
@ -6498,7 +6504,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
|
||||
if(err != 0) {
|
||||
ReportList *reports;
|
||||
/* alert the user, else they wont know unless they see the console. */
|
||||
if (!is_static && ptr->data && RNA_struct_is_a(ptr->type, &RNA_Operator)) {
|
||||
if ( (!is_static) &&
|
||||
(ptr->data) &&
|
||||
(RNA_struct_is_a(ptr->type, &RNA_Operator)) &&
|
||||
(is_valid_wm == (CTX_wm_manager(C) != NULL)))
|
||||
{
|
||||
wmOperator *op= ptr->data;
|
||||
reports= op->reports;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user