Merge branch 'master' into blender2.8

This commit is contained in:
Campbell Barton 2017-03-12 03:00:06 +11:00
commit fbb1b311ea
60 changed files with 873 additions and 336 deletions

@ -928,7 +928,7 @@ if(WITH_X11)
if(WITH_X11_ALPHA)
find_library(X11_Xrender_LIB Xrender ${X11_LIB_SEARCH_PATH})
mark_as_advanced(X11_Xrender_LIB)
if (X11_Xrender_LIB)
if(X11_Xrender_LIB)
list(APPEND PLATFORM_LINKLIBS ${X11_Xrender_LIB})
else()
set(WITH_X11_ALPHA OFF)

@ -1,4 +1,4 @@
# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
# -*- mode: gnumakefile; tab-width: 4; indent-tabs-mode: t; -*-
# vim: tabstop=4
#
# ##### BEGIN GPL LICENSE BLOCK #####
@ -113,7 +113,7 @@ CMAKE_CONFIG = cmake $(BUILD_CMAKE_ARGS) \
# X11 spesific
ifdef DISPLAY
CMAKE_CONFIG_TOOL = cmake-gui
else
else
CMAKE_CONFIG_TOOL = ccmake
endif
@ -127,7 +127,7 @@ all: .FORCE
# # if test ! -f $(BUILD_DIR)/CMakeCache.txt ; then \
# # $(CMAKE_CONFIG); \
# # fi
# # do this always incase of failed initial build, could be smarter here...
@$(CMAKE_CONFIG)

@ -56,7 +56,7 @@ if(EXISTS ${SOURCE_DIR}/.git)
string(REGEX REPLACE "[\r\n]+" ";" _git_contains_branches "${_git_contains_branches}")
string(REGEX REPLACE ";[ \t]+" ";" _git_contains_branches "${_git_contains_branches}")
foreach(_branch ${_git_contains_branches})
if (NOT "${_branch}" MATCHES "\\(HEAD.*")
if(NOT "${_branch}" MATCHES "\\(HEAD.*")
set(MY_WC_BRANCH "${_branch}")
break()
endif()

@ -1575,24 +1575,24 @@ macro(openmp_delayload
endmacro()
MACRO(WINDOWS_SIGN_TARGET target)
if (WITH_WINDOWS_CODESIGN)
if (!SIGNTOOL_EXE)
if(WITH_WINDOWS_CODESIGN)
if(!SIGNTOOL_EXE)
error("Codesigning is enabled, but signtool is not found")
else()
if (WINDOWS_CODESIGN_PFX_PASSWORD)
if(WINDOWS_CODESIGN_PFX_PASSWORD)
set(CODESIGNPASSWORD /p ${WINDOWS_CODESIGN_PFX_PASSWORD})
else()
if ($ENV{PFXPASSWORD})
if($ENV{PFXPASSWORD})
set(CODESIGNPASSWORD /p $ENV{PFXPASSWORD})
else()
message( FATAL_ERROR "WITH_WINDOWS_CODESIGN is on but WINDOWS_CODESIGN_PFX_PASSWORD not set, and environment variable PFXPASSWORD not found, unable to sign code.")
message(FATAL_ERROR "WITH_WINDOWS_CODESIGN is on but WINDOWS_CODESIGN_PFX_PASSWORD not set, and environment variable PFXPASSWORD not found, unable to sign code.")
endif()
endif()
add_custom_command(TARGET ${target}
POST_BUILD
COMMAND ${SIGNTOOL_EXE} sign /f ${WINDOWS_CODESIGN_PFX} ${CODESIGNPASSWORD} $<TARGET_FILE:${target}>
VERBATIM
)
POST_BUILD
COMMAND ${SIGNTOOL_EXE} sign /f ${WINDOWS_CODESIGN_PFX} ${CODESIGNPASSWORD} $<TARGET_FILE:${target}>
VERBATIM
)
endif()
endif()
ENDMACRO()

@ -40,8 +40,8 @@ unset(MY_WC_HASH)
# Force Package Name
execute_process(COMMAND date "+%Y%m%d" OUTPUT_VARIABLE CPACK_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
if (MSVC)
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
if(MSVC)
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(PACKAGE_ARCH windows64)
else()
set(PACKAGE_ARCH windows32)
@ -50,7 +50,7 @@ else(MSVC)
set(PACKAGE_ARCH ${CMAKE_SYSTEM_PROCESSOR})
endif()
if (CPACK_OVERRIDE_PACKAGENAME)
if(CPACK_OVERRIDE_PACKAGENAME)
set(CPACK_PACKAGE_FILE_NAME ${CPACK_OVERRIDE_PACKAGENAME}-${PACKAGE_ARCH})
else()
set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME_LOWER}-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-git${CPACK_DATE}.${BUILD_REV}-${PACKAGE_ARCH})

@ -33,7 +33,7 @@ endmacro()
macro(windows_find_package package_name
)
if(WITH_WINDOWS_FIND_MODULES)
find_package( ${package_name})
find_package(${package_name})
endif(WITH_WINDOWS_FIND_MODULES)
endmacro()

@ -34,7 +34,7 @@ add_subdirectory(mikktspace)
add_subdirectory(glew-mx)
add_subdirectory(eigen)
if (WITH_GAMEENGINE_DECKLINK)
if(WITH_GAMEENGINE_DECKLINK)
add_subdirectory(decklink)
endif()

@ -588,8 +588,8 @@ static void attr_create_pointiness(Scene *scene,
sorted_vert_indeices[other_sorted_vert_index];
const float3 &other_vert_co = mesh->verts[other_vert_index];
/* We are too far away now, we wouldn't have duplicate. */
if ((other_vert_co.x + other_vert_co.y + other_vert_co.z) -
(vert_co.x + vert_co.y + vert_co.z) > 3 * FLT_EPSILON)
if((other_vert_co.x + other_vert_co.y + other_vert_co.z) -
(vert_co.x + vert_co.y + vert_co.z) > 3 * FLT_EPSILON)
{
break;
}

@ -72,7 +72,7 @@ public:
virtual SplitKernelFunction* get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&);
virtual int2 split_kernel_local_size();
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
virtual size_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads);
virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads);
};
class CPUDevice : public Device
@ -860,7 +860,7 @@ int2 CPUSplitKernel::split_kernel_global_size(device_memory& /*kg*/, device_memo
return task->requested_tile_size;
}
size_t CPUSplitKernel::state_buffer_size(device_memory& kernel_globals, device_memory& /*data*/, size_t num_threads) {
uint64_t CPUSplitKernel::state_buffer_size(device_memory& kernel_globals, device_memory& /*data*/, size_t num_threads) {
KernelGlobals *kg = (KernelGlobals*)kernel_globals.device_pointer;
return split_data_buffer_size(kg, num_threads);

@ -89,7 +89,7 @@ class CUDASplitKernel : public DeviceSplitKernel {
public:
explicit CUDASplitKernel(CUDADevice *device);
virtual size_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads);
virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads);
virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim,
RenderTile& rtile,
@ -1473,9 +1473,9 @@ CUDASplitKernel::CUDASplitKernel(CUDADevice *device) : DeviceSplitKernel(device)
{
}
size_t CUDASplitKernel::state_buffer_size(device_memory& /*kg*/, device_memory& /*data*/, size_t num_threads)
uint64_t CUDASplitKernel::state_buffer_size(device_memory& /*kg*/, device_memory& /*data*/, size_t num_threads)
{
device_vector<uint> size_buffer;
device_vector<uint64_t> size_buffer;
size_buffer.resize(1);
device->mem_alloc(NULL, size_buffer, MEM_READ_WRITE);
@ -1504,7 +1504,7 @@ size_t CUDASplitKernel::state_buffer_size(device_memory& /*kg*/, device_memory&
device->cuda_pop_context();
device->mem_copy_from(size_buffer, 0, 1, 1, sizeof(uint));
device->mem_copy_from(size_buffer, 0, 1, 1, sizeof(uint64_t));
device->mem_free(size_buffer);
return *size_buffer.get_data();

@ -48,7 +48,8 @@ enum DataType {
TYPE_UINT,
TYPE_INT,
TYPE_FLOAT,
TYPE_HALF
TYPE_HALF,
TYPE_UINT64,
};
static inline size_t datatype_size(DataType datatype)
@ -59,6 +60,7 @@ static inline size_t datatype_size(DataType datatype)
case TYPE_UINT: return sizeof(uint);
case TYPE_INT: return sizeof(int);
case TYPE_HALF: return sizeof(half);
case TYPE_UINT64: return sizeof(uint64_t);
default: return 0;
}
}
@ -160,6 +162,11 @@ template<> struct device_type_traits<half4> {
static const int num_elements = 4;
};
template<> struct device_type_traits<uint64_t> {
static const DataType data_type = TYPE_UINT64;
static const int num_elements = 1;
};
/* Device Memory */
class device_memory

@ -105,9 +105,9 @@ bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_fe
return true;
}
size_t DeviceSplitKernel::max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, size_t max_buffer_size)
size_t DeviceSplitKernel::max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, uint64_t max_buffer_size)
{
size_t size_per_element = state_buffer_size(kg, data, 1024) / 1024;
uint64_t size_per_element = state_buffer_size(kg, data, 1024) / 1024;
return max_buffer_size / size_per_element;
}

@ -105,8 +105,8 @@ public:
device_memory& kgbuffer,
device_memory& kernel_data);
virtual size_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads) = 0;
size_t max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, size_t max_buffer_size);
virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads) = 0;
size_t max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, uint64_t max_buffer_size);
virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim,
RenderTile& rtile,

@ -334,11 +334,11 @@ void OpenCLDeviceBase::mem_zero(device_memory& mem)
size_t num_threads = global_size[0] * global_size[1];
cl_mem d_buffer = CL_MEM_PTR(mem.device_pointer);
unsigned long long d_offset = 0;
unsigned long long d_size = 0;
cl_ulong d_offset = 0;
cl_ulong d_size = 0;
while(d_offset < mem.memory_size()) {
d_size = std::min<unsigned long long>(num_threads*sizeof(float4), mem.memory_size() - d_offset);
d_size = std::min<cl_ulong>(num_threads*sizeof(float4), mem.memory_size() - d_offset);
kernel_set_args(ckZeroBuffer, 0, d_buffer, d_size, d_offset);

@ -227,9 +227,9 @@ public:
return kernel;
}
virtual size_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads)
virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads)
{
device_vector<uint> size_buffer;
device_vector<uint64_t> size_buffer;
size_buffer.resize(1);
device->mem_alloc(NULL, size_buffer, MEM_READ_WRITE);
@ -249,7 +249,7 @@ public:
device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel");
device->mem_copy_from(size_buffer, 0, 1, 1, sizeof(uint));
device->mem_copy_from(size_buffer, 0, 1, 1, sizeof(uint64_t));
device->mem_free(size_buffer);
if(device->ciErr != CL_SUCCESS) {
@ -346,8 +346,8 @@ public:
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask */*task*/)
{
size_t max_buffer_size;
clGetDeviceInfo(device->cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(size_t), &max_buffer_size, NULL);
cl_ulong max_buffer_size;
clGetDeviceInfo(device->cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_buffer_size, NULL);
VLOG(1) << "Maximum device allocation side: "
<< string_human_readable_number(max_buffer_size) << " bytes. ("
<< string_human_readable_size(max_buffer_size) << ").";

@ -454,7 +454,7 @@ ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg,
Transform space1 = bvh_unaligned_node_fetch_space(kg, node_addr, 1);
float3 aligned_dir0 = transform_direction(&space0, dir),
aligned_dir1 = transform_direction(&space1, dir);;
aligned_dir1 = transform_direction(&space1, dir);
float3 aligned_P0 = transform_point(&space0, P),
aligned_P1 = transform_point(&space1, P);
float3 nrdir0 = -bvh_inverse_direction(aligned_dir0),
@ -516,7 +516,7 @@ ccl_device_forceinline int bvh_unaligned_node_intersect_robust(KernelGlobals *kg
Transform space1 = bvh_unaligned_node_fetch_space(kg, node_addr, 1);
float3 aligned_dir0 = transform_direction(&space0, dir),
aligned_dir1 = transform_direction(&space1, dir);;
aligned_dir1 = transform_direction(&space1, dir);
float3 aligned_P0 = transform_point(&space0, P),
aligned_P1 = transform_point(&space1, P);
float3 nrdir0 = -bvh_inverse_direction(aligned_dir0),

@ -90,13 +90,13 @@ CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_CUDA__
# define __KERNEL_SHADING__
# define __KERNEL_ADV_SHADING__
# define __VOLUME__
# define __VOLUME_SCATTER__
# define __SUBSURFACE__
# define __SHADOW_RECORD_ALL__
# ifndef __SPLIT_KERNEL__
# define __BRANCHED_PATH__
# define __VOLUME__
# define __VOLUME_SCATTER__
# define __SUBSURFACE__
# define __CMJ__
# define __SHADOW_RECORD_ALL__
# endif
#endif /* __KERNEL_CUDA__ */
@ -107,6 +107,10 @@ CCL_NAMESPACE_BEGIN
# ifdef __KERNEL_OPENCL_NVIDIA__
# define __KERNEL_SHADING__
# define __KERNEL_ADV_SHADING__
# define __SUBSURFACE__
# define __VOLUME__
# define __VOLUME_SCATTER__
# define __SHADOW_RECORD_ALL__
# ifdef __KERNEL_EXPERIMENTAL__
# define __CMJ__
# endif

@ -28,20 +28,25 @@
#include "../../split/kernel_path_init.h"
#include "../../split/kernel_scene_intersect.h"
#include "../../split/kernel_lamp_emission.h"
#include "../../split/kernel_do_volume.h"
#include "../../split/kernel_queue_enqueue.h"
#include "../../split/kernel_background_buffer_update.h"
#include "../../split/kernel_indirect_background.h"
#include "../../split/kernel_shader_eval.h"
#include "../../split/kernel_holdout_emission_blurring_pathtermination_ao.h"
#include "../../split/kernel_subsurface_scatter.h"
#include "../../split/kernel_direct_lighting.h"
#include "../../split/kernel_shadow_blocked.h"
#include "../../split/kernel_shadow_blocked_ao.h"
#include "../../split/kernel_shadow_blocked_dl.h"
#include "../../split/kernel_next_iteration_setup.h"
#include "../../split/kernel_indirect_subsurface.h"
#include "../../split/kernel_buffer_update.h"
#include "../../kernel_film.h"
/* kernels */
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
kernel_cuda_state_buffer_size(uint num_threads, uint *size)
kernel_cuda_state_buffer_size(uint num_threads, uint64_t *size)
{
*size = split_data_buffer_size(NULL, num_threads);
}
@ -91,13 +96,18 @@ kernel_cuda_path_trace_data_init(
DEFINE_SPLIT_KERNEL_FUNCTION(path_init)
DEFINE_SPLIT_KERNEL_FUNCTION(scene_intersect)
DEFINE_SPLIT_KERNEL_FUNCTION(lamp_emission)
DEFINE_SPLIT_KERNEL_FUNCTION(do_volume)
DEFINE_SPLIT_KERNEL_FUNCTION(queue_enqueue)
DEFINE_SPLIT_KERNEL_FUNCTION(background_buffer_update)
DEFINE_SPLIT_KERNEL_FUNCTION(indirect_background)
DEFINE_SPLIT_KERNEL_FUNCTION(shader_eval)
DEFINE_SPLIT_KERNEL_FUNCTION(holdout_emission_blurring_pathtermination_ao)
DEFINE_SPLIT_KERNEL_FUNCTION(subsurface_scatter)
DEFINE_SPLIT_KERNEL_FUNCTION(direct_lighting)
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked)
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao)
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl)
DEFINE_SPLIT_KERNEL_FUNCTION(next_iteration_setup)
DEFINE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
DEFINE_SPLIT_KERNEL_FUNCTION(buffer_update)
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)

@ -21,7 +21,7 @@ __kernel void kernel_ocl_path_trace_state_buffer_size(
KernelGlobals *kg,
ccl_constant KernelData *data,
uint num_threads,
ccl_global uint *size)
ccl_global uint64_t *size)
{
kg->data = data;
*size = split_data_buffer_size(kg, num_threads);

@ -22,11 +22,11 @@
CCL_NAMESPACE_BEGIN
ccl_device_inline size_t split_data_buffer_size(KernelGlobals *kg, size_t num_elements)
ccl_device_inline uint64_t split_data_buffer_size(KernelGlobals *kg, size_t num_elements)
{
(void)kg; /* Unused on CPU. */
size_t size = 0;
uint64_t size = 0;
#define SPLIT_DATA_ENTRY(type, name, num) + align_up(num_elements * num * sizeof(type), 16)
size = size SPLIT_DATA_ENTRIES;
#undef SPLIT_DATA_ENTRY

@ -43,41 +43,41 @@ CCL_NAMESPACE_BEGIN
/* Division */
#ifndef M_PI_F
#define M_PI_F ((float)3.14159265358979323846264338327950288) /* pi */
#define M_PI_F (3.1415926535897932f) /* pi */
#endif
#ifndef M_PI_2_F
#define M_PI_2_F ((float)1.57079632679489661923132169163975144) /* pi/2 */
#define M_PI_2_F (1.5707963267948966f) /* pi/2 */
#endif
#ifndef M_PI_4_F
#define M_PI_4_F ((float)0.785398163397448309615660845819875721) /* pi/4 */
#define M_PI_4_F (0.7853981633974830f) /* pi/4 */
#endif
#ifndef M_1_PI_F
#define M_1_PI_F ((float)0.318309886183790671537767526745028724) /* 1/pi */
#define M_1_PI_F (0.3183098861837067f) /* 1/pi */
#endif
#ifndef M_2_PI_F
#define M_2_PI_F ((float)0.636619772367581343075535053490057448) /* 2/pi */
#define M_2_PI_F (0.6366197723675813f) /* 2/pi */
#endif
/* Multiplication */
#ifndef M_2PI_F
#define M_2PI_F ((float)6.283185307179586476925286766559005768) /* 2*pi */
#define M_2PI_F (6.2831853071795864f) /* 2*pi */
#endif
#ifndef M_4PI_F
#define M_4PI_F ((float)12.56637061435917295385057353311801153) /* 4*pi */
#define M_4PI_F (12.566370614359172f) /* 4*pi */
#endif
/* Float sqrt variations */
#ifndef M_SQRT2_F
#define M_SQRT2_F ((float)1.41421356237309504880) /* sqrt(2) */
#define M_SQRT2_F (1.4142135623730950f) /* sqrt(2) */
#endif
#ifndef M_LN2_F
#define M_LN2_F ((float)0.6931471805599453) /* ln(2) */
#define M_LN2_F (0.6931471805599453f) /* ln(2) */
#endif
#ifndef M_LN10_F
#define M_LN10_F ((float)2.3025850929940457) /* ln(10) */
#define M_LN10_F (2.3025850929940457f) /* ln(10) */
#endif
/* Scalar */

@ -106,10 +106,16 @@ typedef unsigned int uint;
#endif
#ifndef __KERNEL_GPU__
/* Fixed Bits Types */
#ifdef __KERNEL_OPENCL__
typedef ulong uint64_t;
#endif
#ifndef __KERNEL_GPU__
#ifdef _WIN32
typedef signed char int8_t;
@ -474,17 +480,17 @@ ccl_device_inline int4 make_int4(const float3& f)
#endif
ccl_device_inline int align_up(int offset, int alignment)
ccl_device_inline size_t align_up(size_t offset, size_t alignment)
{
return (offset + alignment - 1) & ~(alignment - 1);
}
ccl_device_inline int round_up(int x, int multiple)
ccl_device_inline size_t round_up(size_t x, size_t multiple)
{
return ((x + multiple - 1) / multiple) * multiple;
}
ccl_device_inline int round_down(int x, int multiple)
ccl_device_inline size_t round_down(size_t x, size_t multiple)
{
return (x / multiple) * multiple;
}

@ -34,14 +34,14 @@ set(SRC
DeckLinkAPI.h
)
if (WIN32)
if(WIN32)
list(APPEND SRC
win/DeckLinkAPI_h.h
win/DeckLinkAPI_i.c
)
endif()
if (UNIX AND NOT APPLE)
if(UNIX AND NOT APPLE)
list(APPEND SRC
linux/DeckLinkAPI.h
linux/DeckLinkAPIConfiguration.h

@ -128,16 +128,15 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level):
else:
box = col.column()
split = box.split(percentage=0.01)
split = box.split()
# header bar
row = split.row()
row = split.row(align=True)
row.prop(kmi, "show_expanded", text="", emboss=False)
row = split.row()
row.prop(kmi, "active", text="", emboss=False)
if km.is_modal:
row.separator()
row.prop(kmi, "propvalue", text="")
else:
row.label(text=kmi.name)

@ -55,7 +55,7 @@ void BKE_cachefile_reload(const struct Main *bmain, struct CacheFile *cache_file
void BKE_cachefile_ensure_handle(const struct Main *bmain, struct CacheFile *cache_file);
void BKE_cachefile_update_frame(struct Main *bmain, struct Scene *scene,const float ctime, const float fps);
void BKE_cachefile_update_frame(struct Main *bmain, struct Scene *scene, const float ctime, const float fps);
bool BKE_cachefile_filepath_get(
const struct Main *bmain, const struct CacheFile *cache_file, float frame,

@ -207,7 +207,7 @@ typedef struct ParticleCollisionElement {
typedef struct ParticleCollision {
struct Object *current;
struct Object *hit;
struct Object *skip[PARTICLE_COLLISION_MAX_COLLISIONS+1];
struct Object *skip[PARTICLE_COLLISION_MAX_COLLISIONS + 1];
struct Object *emitter;
struct CollisionModifierData *md; // collision modifier for current object;

@ -508,7 +508,7 @@ static void calchandle_curvemap(
if ((bezt->h2 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
const float ydiff1 = prev->vec[1][1] - bezt->vec[1][1];
const float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f)||
if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) ||
(ydiff1 >= 0.0f && ydiff2 >= 0.0f))
{
bezt->vec[2][1] = bezt->vec[1][1];

@ -2460,8 +2460,7 @@ static void dynamic_paint_find_island_border(
const unsigned int *other_loop_idx = mlooptri[lt_index].tri;
/* Check edges for match, looping in the same order as the outer loop. */
for (int j = 0; j < 3; j++)
{
for (int j = 0; j < 3; j++) {
const int overt0 = mloop[other_loop_idx[(j + 0)]].v;
const int overt1 = mloop[other_loop_idx[(j + 1) % 3]].v;
@ -2525,8 +2524,7 @@ static void dynamic_paint_find_island_border(
int final_pixel[2] = { (int)floorf(tgt_pixel[0] * w), (int)floorf(tgt_pixel[1] * h) };
/* If current pixel uv is outside of texture */
if (final_pixel[0] < 0 || final_pixel[0] >= w || final_pixel[1] < 0 || final_pixel[1] >= h)
{
if (final_pixel[0] < 0 || final_pixel[0] >= w || final_pixel[1] < 0 || final_pixel[1] >= h) {
if (bdata->best_index == NOT_FOUND)
bdata->best_index = OUT_OF_TEXTURE;

@ -642,10 +642,10 @@ static void emDM_recalcLoopTri(DerivedMesh *dm)
MLoopTri *lt = &mlooptri[i];
ARRAY_SET_ITEMS(
lt->tri,
BM_elem_index_get(ltri[0]),
BM_elem_index_get(ltri[1]),
BM_elem_index_get(ltri[2]));
lt->tri,
BM_elem_index_get(ltri[0]),
BM_elem_index_get(ltri[1]),
BM_elem_index_get(ltri[2]));
lt->poly = BM_elem_index_get(ltri[0]->f);
}
}

@ -1217,6 +1217,7 @@ bool driver_get_variable_property(
return true;
}
#if 0
/* Helper function to obtain a pointer to a Pose Channel (for evaluating drivers) */
static bPoseChannel *dtar_get_pchan_ptr(ChannelDriver *driver, DriverTarget *dtar)
{
@ -1239,6 +1240,32 @@ static bPoseChannel *dtar_get_pchan_ptr(ChannelDriver *driver, DriverTarget *dta
return NULL;
}
}
#endif
static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar)
{
short valid_targets = 0;
DRIVER_TARGETS_USED_LOOPER(dvar)
{
Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
/* check if this target has valid data */
if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
/* invalid target, so will not have enough targets */
driver->flag |= DRIVER_FLAG_INVALID;
dtar->flag |= DTAR_FLAG_INVALID;
}
else {
/* target seems to be OK now... */
dtar->flag &= ~DTAR_FLAG_INVALID;
valid_targets++;
}
}
DRIVER_TARGETS_LOOPER_END
return valid_targets;
}
/* ......... */
@ -1252,62 +1279,54 @@ static float dvar_eval_singleProp(ChannelDriver *driver, DriverVar *dvar)
/* evaluate 'rotation difference' driver variable */
static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
{
DriverTarget *dtar1 = &dvar->targets[0];
DriverTarget *dtar2 = &dvar->targets[1];
bPoseChannel *pchan, *pchan2;
float q1[4], q2[4], quat[4], angle;
/* get pose channels, and check if we've got two */
pchan = dtar_get_pchan_ptr(driver, dtar1);
pchan2 = dtar_get_pchan_ptr(driver, dtar2);
if (ELEM(NULL, pchan, pchan2)) {
/* disable this driver, since it doesn't work correctly... */
driver->flag |= DRIVER_FLAG_INVALID;
/* check what the error was */
if ((pchan == NULL) && (pchan2 == NULL)) {
if (G.debug & G_DEBUG) {
printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid\n");
}
dtar1->flag |= DTAR_FLAG_INVALID;
dtar2->flag |= DTAR_FLAG_INVALID;
short valid_targets = driver_check_valid_targets(driver, dvar);
/* make sure we have enough valid targets to use - all or nothing for now... */
if (driver_check_valid_targets(driver, dvar) != 2) {
if (G.debug & G_DEBUG) {
printf("RotDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)\n",
valid_targets, dvar->targets[0].id, dvar->targets[1].id);
}
else if (pchan == NULL) {
if (G.debug & G_DEBUG) {
printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel\n");
}
dtar1->flag |= DTAR_FLAG_INVALID;
dtar2->flag &= ~DTAR_FLAG_INVALID;
}
else if (pchan2 == NULL) {
if (G.debug & G_DEBUG) {
printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel\n");
}
dtar1->flag &= ~DTAR_FLAG_INVALID;
dtar2->flag |= DTAR_FLAG_INVALID;
}
/* stop here... */
return 0.0f;
}
else {
dtar1->flag &= ~DTAR_FLAG_INVALID;
dtar2->flag &= ~DTAR_FLAG_INVALID;
float (*mat[2])[4];
/* NOTE: for now, these are all just worldspace */
for (int i = 0; i < 2; i++) {
/* get pointer to loc values to store in */
DriverTarget *dtar = &dvar->targets[i];
Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
bPoseChannel *pchan;
/* after the checks above, the targets should be valid here... */
BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB));
/* try to get posechannel */
pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
/* check if object or bone */
if (pchan) {
/* bone */
mat[i] = pchan->pose_mat;
}
else {
/* object */
mat[i] = ob->obmat;
}
}
float q1[4], q2[4], quat[4], angle;
/* use the final posed locations */
mat4_to_quat(q1, pchan->pose_mat);
mat4_to_quat(q2, pchan2->pose_mat);
mat4_to_quat(q1, mat[0]);
mat4_to_quat(q2, mat[1]);
invert_qt_normalized(q1);
mul_qt_qtqt(quat, q1, q2);
angle = 2.0f * (saacos(quat[0]));
angle = ABS(angle);
return (angle > (float)M_PI) ? (float)((2.0f * (float)M_PI) - angle) : (float)(angle);
}
@ -1317,32 +1336,8 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
{
float loc1[3] = {0.0f, 0.0f, 0.0f};
float loc2[3] = {0.0f, 0.0f, 0.0f};
short valid_targets = 0;
/* Perform two passes
*
* FIRST PASS - to just check that everything works...
* NOTE: we use loops here to reduce code duplication, though in practice,
* there can only be 2 items or else we run into some problems later
*/
DRIVER_TARGETS_USED_LOOPER(dvar)
{
Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
/* check if this target has valid data */
if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
/* invalid target, so will not have enough targets */
driver->flag |= DRIVER_FLAG_INVALID;
dtar->flag |= DTAR_FLAG_INVALID;
}
else {
/* target seems to be OK now... */
dtar->flag &= ~DTAR_FLAG_INVALID;
valid_targets++;
}
}
DRIVER_TARGETS_LOOPER_END
short valid_targets = driver_check_valid_targets(driver, dvar);
/* make sure we have enough valid targets to use - all or nothing for now... */
if (valid_targets < dvar->num_targets) {
if (G.debug & G_DEBUG) {
@ -1351,8 +1346,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
}
return 0.0f;
}
/* SECOND PASS: get two location values */
/* NOTE: for now, these are all just worldspace */
DRIVER_TARGETS_USED_LOOPER(dvar)
@ -1570,7 +1564,7 @@ static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = {
BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF)
dvar_eval_rotDiff, /* eval callback */
2, /* number of targets used */
{"Bone 1", "Bone 2"}, /* UI names for targets */
{"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */
{DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */
END_DVAR_TYPEDEF,

@ -1863,7 +1863,7 @@ void BKE_library_make_local(
/* Special case for objects because we don't want proxy pointers to be
* cleared yet. This will happen down the road in this function.
*/
BKE_object_make_local_ex(bmain, (Object*)id, true, false);
BKE_object_make_local_ex(bmain, (Object *)id, true, false);
}
else {
id_make_local(bmain, id, false, true);

@ -991,7 +991,6 @@ static void loop_split_worker(TaskPool * __restrict UNUSED(pool), void *taskdata
#endif
}
/* Note we use data_buff to detect whether we are in threaded context or not, in later case it is NULL. */
static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const bool threaded)
{
MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
@ -1010,7 +1009,7 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const
int data_idx = 0;
/* Temp edge vectors stack, only used when computing lnor spacearr (and we are not multi-threading). */
BLI_Stack *edge_vectors = (lnors_spacearr && !data_buff) ? BLI_stack_new(sizeof(float[3]), __func__) : NULL;
BLI_Stack *edge_vectors = NULL;
#ifdef DEBUG_TIME
TIMEIT_START(loop_split_generator);
@ -1019,6 +1018,10 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const
if (!threaded) {
memset(&data_mem, 0, sizeof(data_mem));
data = &data_mem;
if (lnors_spacearr) {
edge_vectors = BLI_stack_new(sizeof(float[3]), __func__);
}
}
/* We now know edges that can be smoothed (with their vector, and their two loops), and edges that will be hard!

@ -515,7 +515,7 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make
* artifacts which will then not happen in final render.
*/
IMB_colormanagement_transform_byte_threaded(
(unsigned char*)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels,
(unsigned char *)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels,
from_colorspace, to_colorspace);
}
else {
@ -524,7 +524,7 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make
*/
imb_addrectfloatImBuf(ibuf);
IMB_colormanagement_transform_from_byte_threaded(
ibuf->rect_float, (unsigned char*)ibuf->rect,
ibuf->rect_float, (unsigned char *)ibuf->rect,
ibuf->x, ibuf->y, ibuf->channels,
from_colorspace, to_colorspace);
/* We don't need byte buffer anymore. */

@ -588,8 +588,13 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
DerivedMesh *ss_mesh = NULL;
ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
/* remove loop dependencies on derived meshes (TODO should this be done elsewhere?) */
if (smd->target == ob) smd->target = NULL;
/* remove loop dependencies on derived meshes (TODO should this be done elsewhere?)
* This also ensure the target is of type OBJ_MESH avoiding crash in `object_get_derived_final` (see T50899). */
if (smd->target) {
if (smd->target->type != OB_MESH || smd->target == ob) {
smd->target = NULL;
}
}
if (smd->auxTarget == ob) smd->auxTarget = NULL;

@ -734,7 +734,7 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
TaskThreadLocalStorage *tls = get_task_tls(pool, pool->thread_id);
TaskScheduler *scheduler = pool->scheduler;
if (atomic_fetch_and_and_uint8((uint8_t*)&pool->is_suspended, 0)) {
if (atomic_fetch_and_and_uint8((uint8_t *)&pool->is_suspended, 0)) {
if (pool->num_suspended) {
task_pool_num_increase(pool, pool->num_suspended);
BLI_mutex_lock(&scheduler->queue_mutex);
@ -869,7 +869,7 @@ BLI_INLINE bool parallel_range_next_iter_get(
int * __restrict iter, int * __restrict count)
{
uint32_t uval = atomic_fetch_and_add_uint32((uint32_t *)(&state->iter), state->chunk_size);
int previter = *(int32_t*)&uval;
int previter = *(int32_t *)&uval;
*iter = previter;
*count = max_ii(0, min_ii(state->chunk_size, state->stop - previter));

@ -152,6 +152,8 @@ set(SRC
tools/bmesh_path_region.h
tools/bmesh_region_match.c
tools/bmesh_region_match.h
tools/bmesh_separate.c
tools/bmesh_separate.h
tools/bmesh_triangulate.c
tools/bmesh_triangulate.h
tools/bmesh_wireframe.c

@ -43,6 +43,7 @@ extern "C" {
#include "tools/bmesh_path.h"
#include "tools/bmesh_path_region.h"
#include "tools/bmesh_region_match.h"
#include "tools/bmesh_separate.h"
#include "tools/bmesh_triangulate.h"
#ifdef __cplusplus

@ -2692,10 +2692,12 @@ BMVert *bmesh_urmv_loop_multi(
{
BMVert *v_sep = larr[0]->v;
BMVert *v_new;
int edges_len = 0;
int i;
bool is_mixed_any = false;
BLI_SMALLSTACK_DECLARE(edges, BMEdge *);
/* any edges not owned by 'larr' loops connected to 'v_sep'? */
bool is_mixed_edge_any = false;
/* any loops not owned by 'larr' radially connected to 'larr' loop edges? */
bool is_mixed_loop_any = false;
#define LOOP_VISIT _FLAG_WALK
#define EDGE_VISIT _FLAG_WALK
@ -2713,58 +2715,73 @@ BMVert *bmesh_urmv_loop_multi(
* while doing a radial loop (where loops may be adjacent) */
BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT);
BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT);
}
for (i = 0; i < larr_len; i++) {
BMLoop *l_sep = larr[i];
BMLoop *loop_pair[2] = {l_sep, l_sep->prev};
int j;
for (j = 0; j < ARRAY_SIZE(loop_pair); j++) {
for (int j = 0; j < ARRAY_SIZE(loop_pair); j++) {
BMEdge *e = loop_pair[j]->e;
if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) {
BMLoop *l_iter, *l_first;
bool is_mixed = false;
BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT);
l_iter = l_first = e->l;
do {
if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
is_mixed = true;
is_mixed_any = true;
break;
}
} while ((l_iter = l_iter->radial_next) != l_first);
if (is_mixed) {
/* ensure the first loop is one we don't own so we can do a quick check below
* on the edge's loop-flag to see if the edge is mixed or not. */
e->l = l_iter;
}
BLI_SMALLSTACK_PUSH(edges, e);
edges_len += 1;
}
}
}
if (is_mixed_any == false) {
BMEdge **edges = BLI_array_alloca(edges, edges_len);
STACK_DECLARE(edges);
STACK_INIT(edges, edges_len);
{
BMEdge *e_first, *e_iter;
e_iter = e_first = v_sep->e;
do {
if (BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)) {
BMLoop *l_iter, *l_first;
bool is_mixed_loop = false;
l_iter = l_first = e_iter->l;
do {
if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
is_mixed_loop = true;
break;
}
} while ((l_iter = l_iter->radial_next) != l_first);
if (is_mixed_loop) {
/* ensure the first loop is one we don't own so we can do a quick check below
* on the edge's loop-flag to see if the edge is mixed or not. */
e_iter->l = l_iter;
is_mixed_loop_any = true;
}
STACK_PUSH(edges, e_iter);
} else {
/* at least one edge attached isn't connected to our loops */
is_mixed_edge_any = true;
}
} while ((e_iter = bmesh_disk_edge_next(e_iter, v_sep)) != e_first);
}
BLI_assert(edges_len == STACK_SIZE(edges));
if (is_mixed_loop_any == false && is_mixed_edge_any == false) {
/* all loops in 'larr' are the sole owners of their edges.
* nothing to split away from, this is a no-op */
v_new = v_sep;
}
else {
BMEdge *e;
BLI_assert(!BLI_SMALLSTACK_IS_EMPTY(edges));
v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP);
while ((e = BLI_SMALLSTACK_POP(edges))) {
for (i = 0; i < STACK_SIZE(edges); i++) {
BMEdge *e = edges[i];
BMLoop *l_iter, *l_first, *l_next;
BMEdge *e_new;
/* disable so copied edge isn't left dirty (loop edges are cleared last too) */
BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
/* will always be false when (is_mixed_loop_any == false) */
if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) {
/* edge has some loops owned by us, some owned by other loops */
BMVert *e_new_v_pair[2];

@ -378,6 +378,10 @@ void BMO_dupe_from_flag(BMesh *bm, int htype, const char hflag)
* BMOP_DUPE_VOUTPUT: Buffer containing pointers to the split mesh vertices
* BMOP_DUPE_EOUTPUT: Buffer containing pointers to the split mesh edges
* BMOP_DUPE_FOUTPUT: Buffer containing pointers to the split mesh faces
*
* \note Lower level uses of this operator may want to use #BM_mesh_separate_faces
* Since it's faster for the 'use_only_faces' case.
*
*/
void bmo_split_exec(BMesh *bm, BMOperator *op)
{

@ -0,0 +1,133 @@
/*
* ***** 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 *****
*/
/** \file blender/bmesh/tools/bmesh_separate.c
* \ingroup bmesh
*
* BMesh separate, disconnects a set of faces from all others,
* so they don't share any vertices/edges with other faces.
*/
#include <limits.h>
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_buffer.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
#include "bmesh_separate.h" /* own include */
/**
* Split all faces that match `filter_fn`.
* \note
*/
void BM_mesh_separate_faces(
BMesh *bm,
BMFaceFilterFunc filter_fn, void *user_data)
{
BMFace **faces_array_all = MEM_mallocN(bm->totface * sizeof(BMFace *), __func__);
/*
* - Create an array of faces based on 'filter_fn'.
* First part of array for match, for non-match.
*
* - Enable all vertex tags, then clear all tagged vertices from 'faces_b'.
*
* - Loop over 'faces_a', checking each vertex,
* splitting out any which aren't tagged (and therefor shared), disabling tags as we go.
*/
BMFace *f;
BMIter iter;
unsigned int faces_a_len = 0;
unsigned int faces_b_len = 0;
{
int i_a = 0;
int i_b = bm->totface;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
faces_array_all[filter_fn(f, user_data) ? i_a++ : --i_b] = f;
}
faces_a_len = i_a;
faces_b_len = bm->totface - i_a;
}
BMFace **faces_a = faces_array_all;
BMFace **faces_b = faces_array_all + faces_a_len;
/* Enable for all */
BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
/* Disable vert tag on faces_b */
for (unsigned int i = 0; i < faces_b_len; i++) {
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(faces_b[i]);
do {
BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
} while ((l_iter = l_iter->next) != l_first);
}
BLI_buffer_declare_static(BMLoop **, loop_split, 0, 128);
/* Check shared verts ('faces_a' tag and disable) */
for (unsigned int i = 0; i < faces_a_len; i++) {
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(faces_a[i]);
do {
if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
BMVert *v = l_iter->v;
/* Enable, since we may visit this vertex again on other faces */
BM_elem_flag_enable(v, BM_ELEM_TAG);
/* We know the vertex is shared, collect all vertices and split them off. */
/* Fill 'loop_split' */
{
BMEdge *e_first, *e_iter;
e_iter = e_first = l_iter->e;
do {
if (e_iter->l != NULL) {
BMLoop *l_radial_first, *l_radial_iter;
l_radial_first = l_radial_iter = e_iter->l;
do {
if (l_radial_iter->v == v) {
if (filter_fn(l_radial_iter->f, user_data)) {
BLI_buffer_append(&loop_split, BMLoop *, l_radial_iter);
}
}
} while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
}
} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
}
/* Perform the split */
bmesh_urmv_loop_multi(bm, loop_split.data, loop_split.count);
BLI_buffer_empty(&loop_split);
}
} while ((l_iter = l_iter->next) != l_first);
}
BLI_buffer_free(&loop_split);
MEM_freeN(faces_array_all);
}

@ -0,0 +1,32 @@
/*
* ***** 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 *****
*/
#ifndef __BMESH_SEPARATE_H__
#define __BMESH_SEPARATE_H__
/** \file blender/bmesh/tools/bmesh_separate.h
* \ingroup bmesh
*/
void BM_mesh_separate_faces(
BMesh *bm,
BMFaceFilterFunc filter_fn, void *user_data);
#endif /* __BMESH_SEPARATE_H__ */

@ -2781,7 +2781,7 @@ static bAnimChannelType ACF_DSMCLIP =
acf_generic_indention_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name , /* name */
acf_generic_idblock_name, /* name */
acf_generic_idfill_name_prop, /* name prop */
acf_dsmclip_icon, /* icon */

@ -103,11 +103,12 @@ static void change_frame_apply(bContext *C, wmOperator *op)
}
/* set the new frame number */
CFRA = (int)frame;
if (scene->r.flag & SCER_SHOW_SUBFRAME) {
CFRA = (int)frame;
SUBFRA = frame - (int)frame;
}
else {
CFRA = iroundf(frame);
SUBFRA = 0.0f;
}
FRAMENUMBER_MIN_CLAMP(CFRA);
@ -134,15 +135,12 @@ static float frame_from_event(bContext *C, const wmEvent *event)
{
ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
float viewx;
float frame;
/* convert from region coordinates to View2D 'tot' space */
viewx = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
/* round result to nearest int (frames are ints!) */
frame = viewx;
frame = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
/* respect preview range restrictions (if only allowed to move around within that range) */
if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
CLAMP(frame, PSFRA, PEFRA);
}

@ -98,8 +98,11 @@ typedef struct tPoseSlideOp {
int prevFrame; /* frame before current frame (blend-from) */
int nextFrame; /* frame after current frame (blend-to) */
int mode; /* sliding mode (ePoseSlide_Modes) */
int flag; /* unused for now, but can later get used for storing runtime settings.... */
short mode; /* sliding mode (ePoseSlide_Modes) */
short flag; /* unused for now, but can later get used for storing runtime settings.... */
short channels; /* which transforms/channels are affected (ePoseSlide_Channels) */
short axislock; /* axis-limits for transforms (ePoseSlide_AxisLock) */
float percentage; /* 0-1 value for determining the influence of whatever is relevant */
@ -113,6 +116,49 @@ typedef enum ePoseSlide_Modes {
POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */
} ePoseSlide_Modes;
/* Transforms/Channels to Affect */
typedef enum ePoseSlide_Channels {
PS_TFM_ALL = 0, /* All transforms and properties */
PS_TFM_LOC, /* Loc/Rot/Scale */
PS_TFM_ROT,
PS_TFM_SIZE,
PS_TFM_BBONE_SHAPE, /* Bendy Bones */
PS_TFM_PROPS /* Custom Properties */
} ePoseSlide_Channels;
/* Property enum for ePoseSlide_Channels */
static EnumPropertyItem prop_channels_types[] = {
{PS_TFM_ALL, "ALL", 0, "All Properties",
"All properties, including transforms, bendy bone shape, and custom properties"},
{PS_TFM_LOC, "LOC", 0, "Location", "Location only"},
{PS_TFM_ROT, "ROT", 0, "Rotation", "Rotation only"},
{PS_TFM_SIZE, "SIZE", 0, "Scale", "Scale only"},
{PS_TFM_BBONE_SHAPE, "BBONE", 0, "Bendy Bone", "Bendy Bone shape properties"},
{PS_TFM_PROPS, "CUSTOM", 0, "Custom Properties", "Custom properties"},
{0, NULL, 0, NULL, NULL}
};
/* Axis Locks */
typedef enum ePoseSlide_AxisLock {
PS_LOCK_X = (1 << 0),
PS_LOCK_Y = (1 << 1),
PS_LOCK_Z = (1 << 2)
} ePoseSlide_AxisLock;
/* Property enum for ePoseSlide_AxisLock */
static EnumPropertyItem prop_axis_lock_types[] = {
{0, "FREE", 0, "Free", "All axes are affected"},
{PS_LOCK_X, "X", 0, "X", "Only X-axis transforms are affected"},
{PS_LOCK_Y, "Y", 0, "Y", "Only Y-axis transforms are affected"},
{PS_LOCK_Z, "Z", 0, "Z", "Only Z-axis transforms are affected"},
/* TODO: Combinations? */
{0, NULL, 0, NULL, NULL}
};
/* ------------------------------------ */
/* operator init */
@ -139,6 +185,10 @@ static int pose_slide_init(bContext *C, wmOperator *op, short mode)
pso->prevFrame = RNA_int_get(op->ptr, "prev_frame");
pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
/* get the set of properties/axes that can be operated on */
pso->channels = RNA_enum_get(op->ptr, "channels");
pso->axislock = RNA_enum_get(op->ptr, "axis_lock");
/* check the settings from the context */
if (ELEM(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
return 0;
@ -293,10 +343,20 @@ static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, floa
/* using this path, find each matching F-Curve for the variables we're interested in */
while ( (ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path)) ) {
FCurve *fcu = (FCurve *)ld->data;
/* just work on these channels one by one... there's no interaction between values */
const int idx = fcu->array_index;
const int lock = pso->axislock;
/* check if this F-Curve is ok given the current axis locks */
BLI_assert(fcu->array_index < 3);
pose_slide_apply_val(pso, fcu, &vec[fcu->array_index]);
if ((lock == 0) ||
((lock & PS_LOCK_X) && (idx == 0)) ||
((lock & PS_LOCK_Y) && (idx == 1)) ||
((lock & PS_LOCK_Z) && (idx == 2)))
{
/* just work on these channels one by one... there's no interaction between values */
pose_slide_apply_val(pso, fcu, &vec[fcu->array_index]);
}
}
/* free the temp path we got */
@ -494,17 +554,17 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
*/
bPoseChannel *pchan = pfl->pchan;
if (pchan->flag & POSE_LOC) {
if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
/* calculate these for the 'location' vector, and use location curves */
pose_slide_apply_vec3(pso, pfl, pchan->loc, "location");
}
if (pchan->flag & POSE_SIZE) {
if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) {
/* calculate these for the 'scale' vector, and use scale curves */
pose_slide_apply_vec3(pso, pfl, pchan->size, "scale");
}
if (pchan->flag & POSE_ROT) {
if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
/* everything depends on the rotation mode */
if (pchan->rotmode > 0) {
/* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */
@ -519,12 +579,12 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
}
}
if (pchan->flag & POSE_BBONE_SHAPE) {
if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
/* bbone properties - they all start a "bbone_" prefix */
pose_slide_apply_props(pso, pfl, "bbone_");
}
if (pfl->oldprops) {
if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
/* not strictly a transform, but custom properties contribute to the pose produced in many rigs
* (e.g. the facial rigs used in Sintel)
*/
@ -553,9 +613,12 @@ static void pose_slide_reset(tPoseSlideOp *pso)
/* ------------------------------------ */
/* draw percentage indicator in header */
// TODO: Include hints about locks here...
static void pose_slide_draw_status(tPoseSlideOp *pso)
{
char status_str[UI_MAX_DRAW_STR];
char limits_str[UI_MAX_DRAW_STR];
char axis_str[50];
char mode_str[32];
switch (pso->mode) {
@ -575,16 +638,58 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
break;
}
switch (pso->axislock) {
case PS_LOCK_X:
BLI_strncpy(axis_str, "[X]/Y/Z axis only (X to clear)", sizeof(axis_str));
break;
case PS_LOCK_Y:
BLI_strncpy(axis_str, "X/[Y]/Z axis only (Y to clear)", sizeof(axis_str));
break;
case PS_LOCK_Z:
BLI_strncpy(axis_str, "X/Y/[Z] axis only (Z to clear)", sizeof(axis_str));
break;
default:
if (ELEM(pso->channels, PS_TFM_LOC, PS_TFM_ROT, PS_TFM_SIZE)) {
BLI_strncpy(axis_str, "X/Y/Z = Axis Constraint", sizeof(axis_str));
}
else {
axis_str[0] = '\0';
}
break;
}
switch (pso->channels) {
case PS_TFM_LOC:
BLI_snprintf(limits_str, sizeof(limits_str), "[G]/R/S/B/C - Location only (G to clear) | %s", axis_str);
break;
case PS_TFM_ROT:
BLI_snprintf(limits_str, sizeof(limits_str), "G/[R]/S/B/C - Rotation only (R to clear) | %s", axis_str);
break;
case PS_TFM_SIZE:
BLI_snprintf(limits_str, sizeof(limits_str), "G/R/[S]/B/C - Scale only (S to clear) | %s", axis_str);
break;
case PS_TFM_BBONE_SHAPE:
BLI_strncpy(limits_str, "G/R/S/[B]/C - Bendy Bone properties only (B to clear) | %s", sizeof(limits_str));
break;
case PS_TFM_PROPS:
BLI_strncpy(limits_str, "G/R/S/B/[C] - Custom Properties only (C to clear) | %s", sizeof(limits_str));
break;
default:
BLI_strncpy(limits_str, "G/R/S/B/C - Limit to Transform/Property Set", sizeof(limits_str));
break;
}
if (hasNumInput(&pso->num)) {
Scene *scene = pso->scene;
char str_offs[NUM_STR_REP_LEN];
outputNumInput(&pso->num, str_offs, &scene->unit);
BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, str_offs);
BLI_snprintf(status_str, sizeof(status_str), "%s: %s | %s", mode_str, str_offs, limits_str);
}
else {
BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", mode_str, (int)(pso->percentage * 100.0f));
BLI_snprintf(status_str, sizeof(status_str), "%s: %d %% | %s", mode_str, (int)(pso->percentage * 100.0f), limits_str);
}
ED_area_headerprint(pso->sa, status_str);
@ -675,11 +780,58 @@ static void pose_slide_mouse_update_percentage(tPoseSlideOp *pso, wmOperator *op
RNA_float_set(op->ptr, "percentage", pso->percentage);
}
/* handle an event to toggle channels mode */
static void pose_slide_toggle_channels_mode(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_Channels channel)
{
/* Turn channel on or off? */
if (pso->channels == channel) {
/* Already limiting to transform only, so pressing this again turns it off */
pso->channels = PS_TFM_ALL;
}
else {
/* Only this set of channels */
pso->channels = channel;
}
RNA_enum_set(op->ptr, "channels", pso->channels);
/* Reset axis limits too for good measure */
pso->axislock = 0;
RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
}
/* handle an event to toggle axis locks - returns whether any change in state is needed */
static bool pose_slide_toggle_axis_locks(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_AxisLock axis)
{
/* Axis can only be set when a transform is set - it doesn't make sense otherwise */
if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE, PS_TFM_PROPS)) {
pso->axislock = 0;
RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
return false;
}
/* Turn on or off? */
if (pso->axislock == axis) {
/* Already limiting on this axis, so turn off */
pso->axislock = 0;
}
else {
/* Only this axis */
pso->axislock = axis;
}
RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
/* Setting changed, so pose update is needed */
return true;
}
/* common code for modal() */
static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso = op->customdata;
wmWindow *win = CTX_wm_window(C);
bool do_pose_update = false;
const bool has_numinput = hasNumInput(&pso->num);
switch (event->type) {
@ -718,7 +870,8 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* canceled! */
return OPERATOR_CANCELLED;
}
/* Percentage Chane... */
case MOUSEMOVE: /* calculate new position */
{
/* only handle mousemove if not doing numinput */
@ -726,14 +879,8 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* update percentage based on position of mouse */
pose_slide_mouse_update_percentage(pso, op, event);
/* update percentage indicator in header */
pose_slide_draw_status(pso);
/* reset transforms (to avoid accumulation errors) */
pose_slide_reset(pso);
/* apply... */
pose_slide_apply(C, pso);
/* update pose to reflect the new values (see below) */
do_pose_update = true;
}
break;
}
@ -751,16 +898,75 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
CLAMP(pso->percentage, 0.0f, 1.0f);
RNA_float_set(op->ptr, "percentage", pso->percentage);
/* update percentage indicator in header */
pose_slide_draw_status(pso);
/* reset transforms (to avoid accumulation errors) */
pose_slide_reset(pso);
/* apply... */
pose_slide_apply(C, pso);
/* Update pose to reflect the new values (see below) */
do_pose_update = true;
break;
}
else if (event->val == KM_PRESS) {
switch (event->type) {
/* Transform Channel Limits */
/* XXX: Replace these hardcoded hotkeys with a modalmap that can be customised */
case GKEY: /* Location */
{
pose_slide_toggle_channels_mode(op, pso, PS_TFM_LOC);
do_pose_update = true;
break;
}
case RKEY: /* Rotation */
{
pose_slide_toggle_channels_mode(op, pso, PS_TFM_ROT);
do_pose_update = true;
break;
}
case SKEY: /* Scale */
{
pose_slide_toggle_channels_mode(op, pso, PS_TFM_SIZE);
do_pose_update = true;
break;
}
case BKEY: /* Bendy Bones */
{
pose_slide_toggle_channels_mode(op, pso, PS_TFM_BBONE_SHAPE);
do_pose_update = true;
break;
}
case CKEY: /* Custom Properties */
{
pose_slide_toggle_channels_mode(op, pso, PS_TFM_PROPS);
do_pose_update = true;
break;
}
/* Axis Locks */
/* XXX: Hardcoded... */
case XKEY:
{
if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_X)) {
do_pose_update = true;
}
break;
}
case YKEY:
{
if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Y)) {
do_pose_update = true;
}
break;
}
case ZKEY:
{
if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Z)) {
do_pose_update = true;
}
break;
}
default: /* Some other unhandled key... */
break;
}
}
else {
/* unhandled event - maybe it was some view manip? */
/* allow to pass through */
@ -768,6 +974,19 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
/* perform pose updates - in response to some user action (e.g. pressing a key or moving the mouse) */
if (do_pose_update) {
/* update percentage indicator in header */
pose_slide_draw_status(pso);
/* reset transforms (to avoid accumulation errors) */
pose_slide_reset(pso);
/* apply... */
pose_slide_apply(C, pso);
}
/* still running... */
return OPERATOR_RUNNING_MODAL;
}
@ -795,11 +1014,16 @@ static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso
}
/* common code for defining RNA properties */
/* TODO: Skip save on these? */
static void pose_slide_opdef_properties(wmOperatorType *ot)
{
RNA_def_float_percentage(ot->srna, "percentage", 0.5f, 0.0f, 1.0f, "Percentage", "Weighting factor for which keyframe is favored more", 0.3, 0.7);
RNA_def_int(ot->srna, "prev_frame", 0, MINAFRAME, MAXFRAME, "Previous Keyframe", "Frame number of keyframe immediately before the current frame", 0, 50);
RNA_def_int(ot->srna, "next_frame", 0, MINAFRAME, MAXFRAME, "Next Keyframe", "Frame number of keyframe immediately after the current frame", 0, 50);
RNA_def_float_percentage(ot->srna, "percentage", 0.5f, 0.0f, 1.0f, "Percentage", "Weighting factor for the sliding operation", 0.3, 0.7);
RNA_def_enum(ot->srna, "channels", prop_channels_types, PS_TFM_ALL, "Channels", "Set of properties that are affected");
RNA_def_enum(ot->srna, "axis_lock", prop_axis_lock_types, 0, "Axis Lock", "Transform axis to restrict effects to");
}
/* ------------------------------------ */

@ -1082,7 +1082,7 @@ static int depthdropper_poll(bContext *C)
return 1;
}
}
else {
else {
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d && rv3d->persp == RV3D_CAMOB) {
View3D *v3d = CTX_wm_view3d(C);

@ -2238,8 +2238,9 @@ static void ui_litem_layout_row(uiLayout *litem)
/* add extra pixel */
uiItem *last_item = litem->items.last;
extra_pixel = litem->w - (x - litem->x);
if (extra_pixel > 0 && litem->alignment == UI_LAYOUT_ALIGN_EXPAND &&
last_free_item && last_item && last_item->flag & UI_ITEM_FIXED) {
if (extra_pixel > 0 && litem->alignment == UI_LAYOUT_ALIGN_EXPAND &&
last_free_item && last_item && last_item->flag & UI_ITEM_FIXED)
{
ui_item_move(last_free_item, 0, extra_pixel);
for (item = last_free_item->next; item; item = item->next)
ui_item_move(item, extra_pixel, extra_pixel);

@ -739,6 +739,7 @@ static int editsource_text_edit(
if (text == NULL) {
text = BKE_text_load(bmain, filepath, bmain->name);
id_us_ensure_real(&text->id);
}
if (text == NULL) {

@ -1598,7 +1598,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* Icons on the left with optional text label on the right */
else if (but->flag & UI_HAS_ICON || show_menu_icon) {
const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE;
const float icon_size = ICON_DEFAULT_WIDTH;
const float icon_size = ICON_DEFAULT_WIDTH_SCALE;
/* menu item - add some more padding so menus don't feel cramped. it must
* be part of the button so that this area is still clickable */

@ -124,9 +124,9 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
.use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"),
.compression_type = RNA_enum_get(op->ptr, "compression_type"),
.packuv = RNA_boolean_get(op->ptr, "packuv"),
.triangulate = RNA_boolean_get(op->ptr, "triangulate"),
.quad_method = RNA_enum_get(op->ptr, "quad_method"),
.ngon_method = RNA_enum_get(op->ptr, "ngon_method"),
.triangulate = RNA_boolean_get(op->ptr, "triangulate"),
.quad_method = RNA_enum_get(op->ptr, "quad_method"),
.ngon_method = RNA_enum_get(op->ptr, "ngon_method"),
.global_scale = RNA_float_get(op->ptr, "global_scale"),
};

@ -51,6 +51,7 @@
#include "mesh_intern.h" /* own include */
#include "tools/bmesh_intersect.h"
#include "tools/bmesh_separate.h"
/* detect isolated holes and fill them */
@ -196,13 +197,9 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
if (use_separate_cut) {
/* detach selected/un-selected faces */
BMOperator bmop;
EDBM_op_init(em, &bmop, op, "split geom=%hf use_only_faces=%b", BM_ELEM_SELECT, true);
BMO_op_exec(em->bm, &bmop);
if (!EDBM_op_finish(em, &bmop, op, true)) {
/* should never happen! */
BKE_report(op->reports, RPT_ERROR, "Error separating");
}
BM_mesh_separate_faces(
bm,
BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
}
if (has_isect) {

@ -616,30 +616,31 @@ static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar *
Object *ob2 = (Object *)dtar2->id;
PointerRNA dtar_ptr, dtar2_ptr;
uiLayout *col;
/* initialize RNA pointer to the target */
RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
/* Bone 1 */
RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
/* Object 1 */
col = uiLayoutColumn(layout, true);
uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Bone 1"), ICON_NONE);
uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE);
if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) {
PointerRNA tar_ptr;
RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
/* Object 2 */
col = uiLayoutColumn(layout, true);
uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Bone 2"), ICON_NONE);
uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE);
if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) {
PointerRNA tar_ptr;
RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
@ -658,8 +659,8 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
/* initialize RNA pointer to the target */
RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
/* Bone 1 */
/* Object 1 */
col = uiLayoutColumn(layout, true);
uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE);
@ -673,7 +674,8 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
uiLayoutSetRedAlert(col, false); /* we can clear it again now - it's only needed when creating the ID/Bone fields */
uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE);
/* Object 2 */
col = uiLayoutColumn(layout, true);
uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE);

@ -8159,8 +8159,9 @@ static void drawtexspace(Object *ob, const unsigned char ob_wire_col[3])
}
/* draws wire outline */
static void drawObjectSelect(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base,
const unsigned char ob_wire_col[4])
static void draw_object_selected_outline(
Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base,
const unsigned char ob_wire_col[4])
{
RegionView3D *rv3d = ar->regiondata;
Object *ob = base->object;
@ -8648,7 +8649,7 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) {
if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) {
if (!(ob->dtx & OB_DRAWWIRE) && (base->flag & BASE_SELECTED) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) {
drawObjectSelect(scene, sl, v3d, ar, base, ob_wire_col);
draw_object_selected_outline(scene, sl, v3d, ar, base, ob_wire_col);
}
}
}

@ -737,7 +737,7 @@ static void add_streamline(float (*verts)[3], float(*colors)[3], float center[3]
copy_v3_v3(verts[(*offset)++], center);
}
typedef void (*vector_draw_func)(float(*)[3], float(*)[3], float*, float*, float, float, int*);
typedef void (*vector_draw_func)(float(*)[3], float(*)[3], float *, float *, float, float, int *);
#endif /* WITH_SMOKE */
void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3])

@ -1963,9 +1963,12 @@ void flushTransParticles(TransInfo *t)
/* ********************* mesh ****************** */
static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other,
float *dists, const float *dists_prev,
float mtx[3][3])
static bool bmesh_test_dist_add(
BMVert *v, BMVert *v_other,
float *dists, const float *dists_prev,
/* optionally track original index */
int *index, const int *index_prev,
float mtx[3][3])
{
if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) &&
(BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0))
@ -1980,6 +1983,9 @@ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other,
dist_other = dists_prev[i] + len_v3(vec);
if (dist_other < dists[i_other]) {
dists[i_other] = dist_other;
if (index != NULL) {
index[i_other] = index_prev[i];
}
return true;
}
}
@ -1987,11 +1993,13 @@ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other,
return false;
}
static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists)
/**
* \parm mtx: Measure disatnce in this space.
* \parm dists: Store the closest connected distance to selected vertices.
* \parm index: Optionally store the original index we're measuring the distance to (can be NULL).
*/
static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index)
{
/* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
float *dists_prev = MEM_mallocN(bm->totvert * sizeof(float), __func__);
BLI_LINKSTACK_DECLARE(queue, BMVert *);
/* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */
@ -2012,17 +2020,27 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
dist = FLT_MAX;
if (index != NULL) {
index[i] = i;
}
}
else {
BLI_LINKSTACK_PUSH(queue, v);
dist = 0.0f;
if (index != NULL) {
index[i] = i;
}
}
dists[i] = dists_prev[i] = dist;
dists[i] = dist;
}
bm->elem_index_dirty &= ~BM_VERT;
}
/* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
float *dists_prev = MEM_dupallocN(dists);
int *index_prev = MEM_dupallocN(index); /* may be NULL */
do {
BMVert *v;
LinkNode *lnk;
@ -2051,7 +2069,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
/* edge distance */
{
BMVert *v_other = BM_edge_other_vert(e_iter, v);
if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
BM_elem_flag_enable(v_other, BM_ELEM_TAG);
BLI_LINKSTACK_PUSH(queue_next, v_other);
@ -2076,7 +2094,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
(BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0))
{
BMVert *v_other = l_iter_radial->next->next->v;
if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
BM_elem_flag_enable(v_other, BM_ELEM_TAG);
BLI_LINKSTACK_PUSH(queue_next, v_other);
@ -2100,6 +2118,9 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
/* keep in sync, avoid having to do full memcpy each iteration */
dists_prev[i] = dists[i];
if (index != NULL) {
index_prev[i] = index[i];
}
}
BLI_LINKSTACK_SWAP(queue, queue_next);
@ -2113,9 +2134,14 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
BLI_LINKSTACK_FREE(queue_next);
MEM_freeN(dists_prev);
if (index_prev != NULL) {
MEM_freeN(index_prev);
}
}
static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r_island_tot, int **r_island_vert_map)
static struct TransIslandData *editmesh_islands_info_calc(
BMEditMesh *em, int *r_island_tot, int **r_island_vert_map,
bool calc_single_islands)
{
BMesh *bm = em->bm;
struct TransIslandData *trans_islands;
@ -2227,6 +2253,42 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r
MEM_freeN(groups_array);
MEM_freeN(group_index);
/* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
if (calc_single_islands) {
BMIter viter;
BMVert *v;
int group_tot_single = 0;
BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
group_tot_single += 1;
}
}
if (group_tot_single != 0) {
trans_islands = MEM_reallocN(trans_islands, group_tot + group_tot_single);
BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
struct TransIslandData *v_island = &trans_islands[group_tot];
vert_map[i] = group_tot;
copy_v3_v3(v_island->co, v->co);
if (is_zero_v3(v->no) != 0.0f) {
axis_dominant_v3_to_m3(v_island->axismtx, v->no);
invert_m3(v_island->axismtx);
}
else {
unit_m3(v_island->axismtx);
}
group_tot += 1;
}
}
}
}
*r_island_tot = group_tot;
*r_island_vert_map = vert_map;
@ -2326,6 +2388,11 @@ static void createTransEditVerts(TransInfo *t)
int island_info_tot;
int *island_vert_map = NULL;
const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION);
/* Original index of our connected vertex when connected distances are calculated.
* Optional, allocate if needed. */
int *dists_index = NULL;
if (t->flag & T_MIRROR) {
EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
mirror = 1;
@ -2357,8 +2424,12 @@ static void createTransEditVerts(TransInfo *t)
t->total = count;
/* allocating scratch arrays */
if (prop_mode & T_PROP_CONNECTED)
dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears");
if (prop_mode & T_PROP_CONNECTED) {
dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
if (is_island_center) {
dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
}
}
}
else {
t->total = bm->totvertsel;
@ -2380,7 +2451,7 @@ static void createTransEditVerts(TransInfo *t)
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
if (prop_mode & T_PROP_CONNECTED) {
editmesh_set_connectivity_distance(em->bm, mtx, dists);
editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
}
/* Only in case of rotation and resize, we want the elements of the edited
@ -2388,8 +2459,14 @@ static void createTransEditVerts(TransInfo *t)
*
* TODO: use island_info to detect the closest point when the "Snap Target"
* in Blender UI is "Closest" */
if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION)) {
island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map);
if (is_island_center) {
/* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
const bool calc_single_islands = (
(prop_mode & T_PROP_CONNECTED) &&
(t->around == V3D_AROUND_LOCAL_ORIGINS) &&
(em->selectmode & SCE_SELECT_VERTEX));
island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map, calc_single_islands);
}
/* detect CrazySpace [tm] */
@ -2439,10 +2516,16 @@ static void createTransEditVerts(TransInfo *t)
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ?
&island_info[island_vert_map[a]] : NULL;
struct TransIslandData *v_island = NULL;
float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
if (island_info) {
const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
v_island = (island_vert_map[connected_index] != -1) ?
&island_info[island_vert_map[connected_index]] : NULL;
}
VertsToTransData(t, tob, tx, em, eve, bweight, v_island);
if (tx)
tx++;
@ -2521,6 +2604,8 @@ cleanup:
MEM_freeN(defmats);
if (dists)
MEM_freeN(dists);
if (dists_index)
MEM_freeN(dists_index);
if (t->flag & T_MIRROR) {
EDBM_verts_mirror_cache_end(em);
@ -8022,7 +8107,12 @@ void createTransData(bContext *C, TransInfo *t)
if (t->data && t->flag & T_PROP_EDIT) {
if (ELEM(t->obedit->type, OB_CURVE, OB_MESH)) {
sort_trans_data(t); // makes selected become first in array
set_prop_dist(t, 0);
if ((t->obedit->type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
/* already calculated by editmesh_set_connectivity_distance */
}
else {
set_prop_dist(t, 0);
}
sort_trans_data_dist(t);
}
else {

@ -936,9 +936,10 @@ static bool snapEmpty(
float tmp_co[3];
copy_v3_v3(tmp_co, obmat[3]);
if (test_projected_vert_dist(
snapdata->depth_range, snapdata->mval, tmp_co,
snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc)) {
snapdata->depth_range, snapdata->mval, tmp_co,
snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc))
{
*dist_px = sqrtf(dist_px_sq);
*ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
retval = true;
@ -1119,8 +1120,8 @@ static bool snapDerivedMesh(
/* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
float dist_px_sq = dist_squared_to_projected_aabb_simple(
lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
if (dist_px_sq > SQUARE(*dist_px))
{
return retval;
@ -2078,10 +2079,10 @@ static bool transform_snap_context_project_view3d_mixed_impl(
for (int i = 0; i < 3; i++) {
if (snap_to_flag & (1 << i)) {
if (ED_transform_snap_object_project_view3d(
sctx,
elem_type[i], params,
mval, dist_px, &ray_depth,
r_co, r_no))
sctx,
elem_type[i], params,
mval, dist_px, &ray_depth,
r_co, r_no))
{
is_hit = true;
break;

@ -47,17 +47,17 @@
/* control whether we use older AMD_debug_output extension
* some supported GPU + OS combos do not have the newer extensions */
#define LEGACY_DEBUG 1
# define LEGACY_DEBUG 1
/* Debug callbacks need the same calling convention as OpenGL functions. */
#if defined(_WIN32)
#define APIENTRY __stdcall
#else
#define APIENTRY
#endif
# if defined(_WIN32)
# define APIENTRY __stdcall
# else
# define APIENTRY
# endif
static const char* source_name(GLenum source)
static const char *source_name(GLenum source)
{
switch (source) {
case GL_DEBUG_SOURCE_API: return "API";
@ -70,7 +70,7 @@ static const char* source_name(GLenum source)
}
}
static const char* message_type_name(GLenum message)
static const char *message_type_name(GLenum message)
{
switch (message) {
case GL_DEBUG_TYPE_ERROR: return "error";
@ -107,9 +107,9 @@ static void APIENTRY gpu_debug_proc(
}
}
#if LEGACY_DEBUG
# if LEGACY_DEBUG
static const char* category_name_amd(GLenum category)
static const char *category_name_amd(GLenum category)
{
switch (category) {
case GL_DEBUG_CATEGORY_API_ERROR_AMD: return "API error";
@ -145,9 +145,9 @@ static void APIENTRY gpu_debug_proc_amd(
fflush(stderr);
}
}
#endif /* LEGACY_DEBUG */
# endif /* LEGACY_DEBUG */
#undef APIENTRY
# undef APIENTRY
#endif /* not Apple */
void gpu_debug_init(void)
@ -172,14 +172,14 @@ void gpu_debug_init(void)
glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
GPU_string_marker(success);
}
#if LEGACY_DEBUG
# if LEGACY_DEBUG
else if (GLEW_AMD_debug_output) {
fprintf(stderr, "Using AMD_debug_output extension\n");
glDebugMessageCallbackAMD(gpu_debug_proc_amd, mxGetCurrentContext());
glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
GPU_string_marker(success);
}
#endif
# endif
else {
fprintf(stderr, "Failed to hook OpenGL debug callback.\n");
}
@ -196,11 +196,11 @@ void gpu_debug_exit(void)
else if (GLEW_ARB_debug_output) {
glDebugMessageCallbackARB(NULL, NULL);
}
#if LEGACY_DEBUG
# if LEGACY_DEBUG
else if (GLEW_AMD_debug_output) {
glDebugMessageCallbackAMD(NULL, NULL);
}
#endif
# endif
#endif
}
@ -219,13 +219,13 @@ void GPU_string_marker(const char *buf)
GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_OTHER_ARB, 0,
GL_DEBUG_SEVERITY_LOW_ARB, -1, buf);
}
#if LEGACY_DEBUG
# if LEGACY_DEBUG
else if (GLEW_AMD_debug_output) {
glDebugMessageInsertAMD(
GL_DEBUG_CATEGORY_APPLICATION_AMD, GL_DEBUG_SEVERITY_LOW_AMD, 0,
0, buf);
}
#endif
# endif
#endif /* not Apple */
}

@ -44,6 +44,8 @@
#include "gpu_select_private.h"
#include "BLI_strict_flags.h"
/* #define DEBUG_PRINT */
/* Alloc number for depths */
@ -85,10 +87,10 @@ static void rect_subregion_stride_calc(const rcti *src, const rcti *dst, SubRect
src->ymax >= dst->ymax && src->ymax >= dst->ymax);
BLI_assert(x >= 0 && y >= 0);
r_sub->start = (src_x * y) + x;
r_sub->span = dst_x;
r_sub->span_len = dst_y;
r_sub->skip = src_x - dst_x;
r_sub->start = (unsigned int)((src_x * y) + x);
r_sub->span = (unsigned int)dst_x;
r_sub->span_len = (unsigned int)dst_y;
r_sub->skip = (unsigned int)(src_x - dst_x);
}
/**
@ -308,7 +310,7 @@ void gpu_select_pick_begin(
ps->buffer = buffer;
ps->mode = mode;
const unsigned int rect_len = BLI_rcti_size_x(input) * BLI_rcti_size_y(input);
const unsigned int rect_len = (unsigned int)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
ps->dst.clip_rect = *input;
ps->dst.rect_len = rect_len;
@ -329,9 +331,9 @@ void gpu_select_pick_begin(
glDepthFunc(GL_LEQUAL);
}
glPixelTransferi(GL_DEPTH_BIAS, 0.0);
glPixelTransferi(GL_DEPTH_SCALE, 1.0);
/* set just in case */
glPixelTransferf(GL_DEPTH_BIAS, 0.0);
glPixelTransferf(GL_DEPTH_SCALE, 1.0);
float viewport[4];
glGetFloatv(GL_SCISSOR_BOX, viewport);
@ -339,8 +341,8 @@ void gpu_select_pick_begin(
ps->src.clip_rect = *input;
ps->src.rect_len = rect_len;
ps->gl.clip_readpixels[0] = viewport[0];
ps->gl.clip_readpixels[1] = viewport[1];
ps->gl.clip_readpixels[0] = (int)viewport[0];
ps->gl.clip_readpixels[1] = (int)viewport[1];
ps->gl.clip_readpixels[2] = BLI_rcti_size_x(&ps->src.clip_rect);
ps->gl.clip_readpixels[3] = BLI_rcti_size_y(&ps->src.clip_rect);
@ -643,7 +645,7 @@ unsigned int gpu_select_pick_end(void)
unsigned int hits = 0;
if (depth_data_len > maxhits) {
hits = -1;
hits = (unsigned int)-1;
}
else {
/* leave sorting up to the caller */

@ -29,6 +29,9 @@
* Selection implementations.
*/
#ifndef __GPU_SELECT_PRIVATE_H__
#define __GPU_SELECT_PRIVATE_H__
/* gpu_select_pick */
void gpu_select_pick_begin(unsigned int (*buffer)[4], unsigned int bufsize, const rcti *input, char mode);
bool gpu_select_pick_load_id(unsigned int id);
@ -46,3 +49,5 @@ unsigned int gpu_select_query_end(void);
#define SELECT_ID_NONE ((unsigned int)0xffffffff)
#endif /* __GPU_SELECT_PRIVATE_H__ */

@ -23,7 +23,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/gpu/intern/gpu_select.c
/** \file blender/gpu/intern/gpu_select_sample_query.c
* \ingroup gpu
*
* Interface for accessing gpu-related methods for selection. The semantics will be

@ -243,9 +243,9 @@ static void rna_Scene_alembic_export(
.use_subdiv_schema = use_subdiv_schema,
.compression_type = compression_type,
.packuv = packuv,
.triangulate = triangulate,
.quad_method = quad_method,
.ngon_method = ngon_method,
.triangulate = triangulate,
.quad_method = quad_method,
.ngon_method = ngon_method,
.global_scale = scale,
};