Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt20
-rw-r--r--build_files/buildbot/config/user-config-glibc211-i686.py5
-rw-r--r--build_files/buildbot/config/user-config-glibc211-x86_64.py5
-rw-r--r--build_files/buildbot/config/user-config-player-glibc211-i686.py5
-rw-r--r--build_files/buildbot/config/user-config-player-glibc211-x86_64.py5
-rw-r--r--build_files/cmake/macros.cmake4
-rw-r--r--build_files/scons/tools/Blender.py6
-rw-r--r--build_files/scons/tools/btools.py5
-rw-r--r--intern/audaspace/CMakeLists.txt6
-rw-r--r--intern/audaspace/SConscript2
-rw-r--r--intern/audaspace/intern/AUD_C-API.cpp28
-rw-r--r--intern/audaspace/intern/AUD_C-API.h9
-rw-r--r--intern/audaspace/jack/AUD_JackDevice.cpp66
-rw-r--r--intern/audaspace/jack/AUD_JackDevice.h7
-rw-r--r--intern/audaspace/jack/AUD_JackLibrary.cpp116
-rw-r--r--intern/audaspace/jack/AUD_JackLibrary.h104
-rw-r--r--intern/cycles/kernel/shaders/node_brightness.osl8
-rw-r--r--intern/cycles/kernel/shaders/node_normal_map.osl5
-rw-r--r--intern/cycles/kernel/shaders/node_sky_texture.osl2
-rw-r--r--intern/cycles/kernel/shaders/node_texture.h2
-rw-r--r--intern/cycles/kernel/shaders/node_vector_curves.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_ward_bsdf.osl2
-rw-r--r--intern/cycles/render/nodes.cpp2
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_spell_check.py1
-rw-r--r--release/scripts/startup/bl_ui/space_node.py4
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py3
-rw-r--r--source/blender/blenkernel/BKE_brush.h1
-rw-r--r--source/blender/blenkernel/BKE_image.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h68
-rw-r--r--source/blender/blenkernel/BKE_sound.h3
-rw-r--r--source/blender/blenkernel/intern/brush.c37
-rw-r--r--source/blender/blenkernel/intern/curve.c6
-rw-r--r--source/blender/blenkernel/intern/displist.c2
-rw-r--r--source/blender/blenkernel/intern/image.c12
-rw-r--r--source/blender/blenkernel/intern/node.c63
-rw-r--r--source/blender/blenkernel/intern/packedFile.c2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c18
-rw-r--r--source/blender/blenkernel/intern/sound.c15
-rw-r--r--source/blender/blenkernel/intern/text.c19
-rw-r--r--source/blender/blenlib/intern/path_util.c5
-rw-r--r--source/blender/blenloader/intern/readfile.c13
-rw-r--r--source/blender/bmesh/CMakeLists.txt2
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c127
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c28
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c27
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h6
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api_inline.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c19
-rw-r--r--source/blender/bmesh/intern/bmesh_operators_private.h1
-rw-r--r--source/blender/bmesh/operators/bmo_create.c1280
-rw-r--r--source/blender/bmesh/operators/bmo_edgeloop_fill.c157
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c1270
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c10
-rw-r--r--source/blender/editors/render/CMakeLists.txt4
-rw-r--r--source/blender/editors/render/SConscript7
-rw-r--r--source/blender/editors/render/render_shading.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c9
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c1
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c3
-rw-r--r--source/blender/editors/space_clip/clip_editor.c3
-rw-r--r--source/blender/editors/space_clip/clip_toolbar.c3
-rw-r--r--source/blender/editors/space_file/file_panels.c5
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c5
-rw-r--r--source/blender/editors/space_image/image_buttons.c3
-rw-r--r--source/blender/editors/space_image/image_ops.c18
-rw-r--r--source/blender/editors/space_info/space_info.c1
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c18
-rw-r--r--source/blender/editors/space_node/node_add.c11
-rw-r--r--source/blender/editors/space_node/node_buttons.c16
-rw-r--r--source/blender/editors/space_node/node_header.c3
-rw-r--r--source/blender/editors/space_node/node_intern.h5
-rw-r--r--source/blender/editors/space_node/node_ops.c12
-rw-r--r--source/blender/editors/space_node/node_select.c106
-rw-r--r--source/blender/editors/space_node/node_view.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_buttons.c1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c9
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c104
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c7
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c56
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c6
-rw-r--r--source/blender/editors/transform/transform_conversions.c2
-rw-r--r--source/blender/editors/transform/transform_generics.c2
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c13
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c4
-rw-r--r--source/blender/makesrna/SConscript9
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c64
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c19
-rw-r--r--source/blender/render/intern/source/pipeline.c9
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp4
96 files changed, 2545 insertions, 1654 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 58f0fb08318..382e0108978 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -229,6 +229,9 @@ option(WITH_OPENCOLLADA "Enable OpenCollada Support (http://www.opencollada.org
option(WITH_SDL "Enable SDL for sound and joystick support" ON)
option(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON)
option(WITH_JACK "Enable Jack Support (http://www.jackaudio.org)" OFF)
+if(UNIX AND NOT APPLE)
+ option(WITH_JACK_DYNLOAD "Enable runtime dynamic Jack libraries loading" OFF)
+endif()
# Compression
option(WITH_LZO "Enable fast LZO compression (used for pointcache)" ON)
@@ -408,11 +411,6 @@ if(WITH_PYTHON_MODULE)
set(WITH_HEADLESS ON)
endif()
-# auto enable openimageio for cycles
-if(WITH_CYCLES)
- set(WITH_OPENIMAGEIO ON)
-endif()
-
# enable boost for cycles, booleans, audaspace or i18n
# otherwise if the user disabled
if(NOT WITH_BOOST)
@@ -431,6 +429,17 @@ else()
set(WITH_BOOST OFF)
endif()
+# auto enable openimageio for cycles
+if(WITH_CYCLES)
+ set(WITH_OPENIMAGEIO ON)
+endif()
+
+# auto enable openimageio linking dependencies
+if(WITH_OPENIMAGEIO)
+ set(WITH_IMAGE_OPENEXR ON)
+ set(WITH_IMAGE_TIFF ON)
+endif()
+
# auto enable llvm for cycles_osl
if(WITH_CYCLES_OSL)
set(WITH_LLVM ON CACHE BOOL "ON" FORCE)
@@ -2205,6 +2214,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_OPENAL)
info_cfg_option(WITH_SDL)
info_cfg_option(WITH_JACK)
+ info_cfg_option(WITH_JACK_DYNLOAD)
info_cfg_option(WITH_CODEC_AVI)
info_cfg_option(WITH_CODEC_FFMPEG)
info_cfg_option(WITH_CODEC_SNDFILE)
diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py
index 540416ee1fb..616ddb94354 100644
--- a/build_files/buildbot/config/user-config-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-glibc211-i686.py
@@ -104,9 +104,8 @@ WITH_BF_FFTW3 = True
WITH_BF_STATICFFTW3 = True
# JACK
-WITH_BF_JACK = False
-WITH_BF_STATICJACK = True
-BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'
+WITH_BF_JACK = True
+WITH_BF_JACK_DYNLOAD = True
# Cycles
WITH_BF_CYCLES = True
diff --git a/build_files/buildbot/config/user-config-glibc211-x86_64.py b/build_files/buildbot/config/user-config-glibc211-x86_64.py
index c0ba8060712..023eb2539fa 100644
--- a/build_files/buildbot/config/user-config-glibc211-x86_64.py
+++ b/build_files/buildbot/config/user-config-glibc211-x86_64.py
@@ -104,9 +104,8 @@ WITH_BF_FFTW3 = True
WITH_BF_STATICFFTW3 = True
# JACK
-WITH_BF_JACK = False
-WITH_BF_STATICJACK = True
-BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'
+WITH_BF_JACK = True
+WITH_BF_JACK_DYNLOAD = True
# Cycles
WITH_BF_CYCLES = True
diff --git a/build_files/buildbot/config/user-config-player-glibc211-i686.py b/build_files/buildbot/config/user-config-player-glibc211-i686.py
index a99337f03e6..9f345931684 100644
--- a/build_files/buildbot/config/user-config-player-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-player-glibc211-i686.py
@@ -103,9 +103,8 @@ BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBP
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# JACK
-WITH_BF_JACK = False
-WITH_BF_STATICJACK = True
-BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'
+WITH_BF_JACK = True
+WITH_BF_JACK_DYNLOAD = True
# Motion Tracking
WITH_BF_LIBMV = False
diff --git a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
index c17cff2893d..c58da9dcffb 100644
--- a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
+++ b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py
@@ -103,9 +103,8 @@ BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBP
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# JACK
-WITH_BF_JACK = False
-WITH_BF_STATICJACK = True
-BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'
+WITH_BF_JACK = True
+WITH_BF_JACK_DYNLOAD = True
# Motion Tracking
WITH_BF_LIBMV = False
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 9fe76df20b9..2b5cfbc31cc 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -228,7 +228,7 @@ macro(SETUP_LIBDIRS)
if(WITH_OPENAL)
link_directories(${OPENAL_LIBPATH})
endif()
- if(WITH_JACK)
+ if(WITH_JACK AND NOT WITH_JACK_DYNLOAD)
link_directories(${JACK_LIBPATH})
endif()
if(WITH_CODEC_SNDFILE)
@@ -293,7 +293,7 @@ macro(setup_liblinks
if(WITH_FFTW3)
target_link_libraries(${target} ${FFTW3_LIBRARIES})
endif()
- if(WITH_JACK)
+ if(WITH_JACK AND NOT WITH_JACK_DYNLOAD)
target_link_libraries(${target} ${JACK_LIBRARIES})
endif()
if(WITH_CODEC_SNDFILE)
diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py
index 4572ee7f742..816287cdc73 100644
--- a/build_files/scons/tools/Blender.py
+++ b/build_files/scons/tools/Blender.py
@@ -147,10 +147,8 @@ def setup_staticlibs(lenv):
libincs += Split(lenv['BF_PYTHON_LIBPATH'])
if lenv['WITH_BF_SDL']:
libincs += Split(lenv['BF_SDL_LIBPATH'])
- if lenv['WITH_BF_JACK']:
+ if lenv['WITH_BF_JACK'] and not lenv['WITH_BF_JACK_DYNLOAD']:
libincs += Split(lenv['BF_JACK_LIBPATH'])
- if lenv['WITH_BF_STATICJACK']:
- statlibs += Split(lenv['BF_JACK_LIB_STATIC'])
if lenv['WITH_BF_SNDFILE']:
libincs += Split(lenv['BF_SNDFILE_LIBPATH'])
if lenv['WITH_BF_OPENEXR']:
@@ -292,7 +290,7 @@ def setup_syslibs(lenv):
syslibs += Split(lenv['BF_FFMPEG_LIB'])
if lenv['WITH_BF_OGG']:
syslibs += Split(lenv['BF_OGG_LIB'])
- if lenv['WITH_BF_JACK'] and not lenv['WITH_BF_STATICJACK']:
+ if lenv['WITH_BF_JACK'] and not lenv['WITH_BF_JACK_DYNLOAD']:
syslibs += Split(lenv['BF_JACK_LIB'])
if lenv['WITH_BF_SNDFILE'] and not lenv['WITH_BF_STATICSNDFILE']:
syslibs += Split(lenv['BF_SNDFILE_LIB'])
diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py
index 9a31ba650f5..31003d14a0f 100644
--- a/build_files/scons/tools/btools.py
+++ b/build_files/scons/tools/btools.py
@@ -99,7 +99,7 @@ def validate_arguments(args, bc):
'WITH_BF_PYTHON', 'WITH_BF_PYTHON_SAFETY', 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'WITH_BF_STATICPYTHON', 'WITH_OSX_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', 'BF_PYTHON_DLL', 'BF_PYTHON_ABI_FLAGS',
'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_STATICOPENAL', 'BF_OPENAL_LIB_STATIC',
'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH',
- 'WITH_BF_JACK', 'BF_JACK', 'BF_JACK_INC', 'BF_JACK_LIB', 'BF_JACK_LIBPATH', 'WITH_BF_STATICJACK', 'BF_JACK_LIB_STATIC',
+ 'WITH_BF_JACK', 'BF_JACK', 'BF_JACK_INC', 'BF_JACK_LIB', 'BF_JACK_LIBPATH', 'WITH_BF_JACK_DYNLOAD',
'WITH_BF_SNDFILE', 'BF_SNDFILE', 'BF_SNDFILE_INC', 'BF_SNDFILE_LIB', 'BF_SNDFILE_LIBPATH', 'WITH_BF_STATICSNDFILE', 'BF_SNDFILE_LIB_STATIC',
'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH',
'WITH_BF_OPENEXR', 'BF_OPENEXR', 'BF_OPENEXR_INC', 'BF_OPENEXR_LIB', 'BF_OPENEXR_LIBPATH', 'WITH_BF_STATICOPENEXR', 'BF_OPENEXR_LIB_STATIC',
@@ -289,12 +289,11 @@ def read_opts(env, cfg, args):
('BF_SDL_LIBPATH', 'SDL library path', ''),
(BoolVariable('WITH_BF_JACK', 'Enable jack support if true', True)),
- (BoolVariable('WITH_BF_STATICJACK', 'Staticly link to jack', False)),
('BF_JACK', 'jack base path', ''),
('BF_JACK_INC', 'jack include path', ''),
('BF_JACK_LIB', 'jack library', ''),
('BF_JACK_LIBPATH', 'jack library path', ''),
- ('BF_JACK_LIB_STATIC', 'jack static library', ''),
+ (BoolVariable('WITH_BF_JACK_DYNLOAD', 'Enable runtime dynamic Jack libraries loading (works only on Linux)', False)),
(BoolVariable('WITH_BF_SNDFILE', 'Enable sndfile support if true', True)),
('BF_SNDFILE', 'sndfile base path', ''),
diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt
index ec66cffea3b..21a42553935 100644
--- a/intern/audaspace/CMakeLists.txt
+++ b/intern/audaspace/CMakeLists.txt
@@ -253,9 +253,15 @@ if(WITH_JACK)
)
list(APPEND SRC
jack/AUD_JackDevice.cpp
+ jack/AUD_JackLibrary.cpp
jack/AUD_JackDevice.h
+ jack/AUD_JackLibrary.h
)
+
+ if(WITH_JACK_DYNLOAD)
+ add_definitions(-DWITH_JACK_DYNLOAD)
+ endif()
endif()
if(WITH_CODEC_SNDFILE)
diff --git a/intern/audaspace/SConscript b/intern/audaspace/SConscript
index ba549530e64..cc338629c85 100644
--- a/intern/audaspace/SConscript
+++ b/intern/audaspace/SConscript
@@ -46,6 +46,8 @@ if env['WITH_BF_JACK']:
sources += env.Glob('jack/*.cpp')
incs += ' jack ' + env['BF_JACK_INC']
defs.append('WITH_JACK')
+ if env['WITH_BF_JACK_DYNLOAD']:
+ defs.append('WITH_JACK_DYNLOAD')
if env['WITH_BF_SNDFILE']:
sources += env.Glob('sndfile/*.cpp')
diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp
index e15964151c9..42fd87e3b8d 100644
--- a/intern/audaspace/intern/AUD_C-API.cpp
+++ b/intern/audaspace/intern/AUD_C-API.cpp
@@ -79,6 +79,7 @@
#ifdef WITH_JACK
#include "AUD_JackDevice.h"
+#include "AUD_JackLibrary.h"
#endif
@@ -110,6 +111,16 @@ void AUD_initOnce()
#ifdef WITH_FFMPEG
av_register_all();
#endif
+#ifdef WITH_JACK
+ AUD_jack_init();
+#endif
+}
+
+void AUD_exitOnce()
+{
+#ifdef WITH_JACK
+ AUD_jack_exit();
+#endif
}
int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
@@ -144,14 +155,16 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
// No break, fall through to default, to return false
}
else
- {
#endif
+ if (!AUD_jack_supported()) {
+ printf("Warning: Jack cllient not installed\n");
+ // No break, fall through to default, to return false
+ }
+ else {
dev = boost::shared_ptr<AUD_IDevice>(new AUD_JackDevice("Blender", specs, buffersize));
break;
-#ifdef __APPLE__
}
#endif
-#endif
default:
return false;
}
@@ -1262,3 +1275,12 @@ AUD_I3DDevice *AUD_get3DDevice()
{
return AUD_3ddevice;
}
+
+int AUD_isJackSupported(void)
+{
+#ifdef WITH_JACK
+ return AUD_jack_supported();
+#else
+ return 0;
+#endif
+}
diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h
index 9c6611fe04a..64a3d06bd5f 100644
--- a/intern/audaspace/intern/AUD_C-API.h
+++ b/intern/audaspace/intern/AUD_C-API.h
@@ -61,11 +61,16 @@ typedef struct
#endif
/**
- * Initializes FFMPEG if it is enabled.
+ * Initializes audio rutines (FFMPEG/Jack if it is enabled).
*/
extern void AUD_initOnce(void);
/**
+ * Unitinitializes an audio routines.
+ */
+extern void AUD_exitOnce(void);
+
+/**
* Initializes an audio device.
* \param device The device type that should be used.
* \param specs The audio specification to be used.
@@ -752,6 +757,8 @@ extern void *AUD_getPythonFactory(AUD_Sound *sound);
extern AUD_Sound *AUD_getPythonSound(void *sound);
#endif
+extern int AUD_isJackSupported(void);
+
#ifdef __cplusplus
}
diff --git a/intern/audaspace/jack/AUD_JackDevice.cpp b/intern/audaspace/jack/AUD_JackDevice.cpp
index a83098ac496..cfbf80ac110 100644
--- a/intern/audaspace/jack/AUD_JackDevice.cpp
+++ b/intern/audaspace/jack/AUD_JackDevice.cpp
@@ -56,17 +56,17 @@ void AUD_JackDevice::updateRingBuffers()
{
if(m_syncFunc)
{
- state = jack_transport_query(m_client, &position);
+ state = AUD_jack_transport_query(m_client, &position);
m_syncFunc(m_syncFuncData, state != JackTransportStopped, position.frame / (float) m_specs.rate);
}
for(i = 0; i < channels; i++)
- jack_ringbuffer_reset(m_ringbuffers[i]);
+ AUD_jack_ringbuffer_reset(m_ringbuffers[i]);
}
- size = jack_ringbuffer_write_space(m_ringbuffers[0]);
+ size = AUD_jack_ringbuffer_write_space(m_ringbuffers[0]);
for(i = 1; i < channels; i++)
- if((temp = jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
+ if((temp = AUD_jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
size = temp;
while(size > samplesize)
@@ -77,12 +77,12 @@ void AUD_JackDevice::updateRingBuffers()
{
for(j = 0; j < size; j++)
deinterleave[i * size + j] = buffer[i + j * channels];
- jack_ringbuffer_write(m_ringbuffers[i], (char*)(deinterleave + i * size), size * sizeof(float));
+ AUD_jack_ringbuffer_write(m_ringbuffers[i], (char*)(deinterleave + i * size), size * sizeof(float));
}
- size = jack_ringbuffer_write_space(m_ringbuffers[0]);
+ size = AUD_jack_ringbuffer_write_space(m_ringbuffers[0]);
for(i = 1; i < channels; i++)
- if((temp = jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
+ if((temp = AUD_jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
size = temp;
}
@@ -107,22 +107,22 @@ int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data)
{
// play silence while syncing
for(unsigned int i = 0; i < count; i++)
- memset(jack_port_get_buffer(device->m_ports[i], length), 0, length * sizeof(float));
+ memset(AUD_jack_port_get_buffer(device->m_ports[i], length), 0, length * sizeof(float));
}
else
{
size_t temp;
- size_t readsamples = jack_ringbuffer_read_space(device->m_ringbuffers[0]);
+ size_t readsamples = AUD_jack_ringbuffer_read_space(device->m_ringbuffers[0]);
for(i = 1; i < count; i++)
- if((temp = jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples)
+ if((temp = AUD_jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples)
readsamples = temp;
readsamples = AUD_MIN(readsamples / sizeof(float), length);
for(unsigned int i = 0; i < count; i++)
{
- buffer = (char*)jack_port_get_buffer(device->m_ports[i], length);
- jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float));
+ buffer = (char*)AUD_jack_port_get_buffer(device->m_ports[i], length);
+ AUD_jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float));
if(readsamples < length)
memset(buffer + readsamples * sizeof(float), 0, (length - readsamples) * sizeof(float));
}
@@ -193,14 +193,14 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff
jack_status_t status;
// open client
- m_client = jack_client_open(name.c_str(), options, &status);
+ m_client = AUD_jack_client_open(name.c_str(), options, &status);
if(m_client == NULL)
AUD_THROW(AUD_ERROR_JACK, clientopen_error);
// set callbacks
- jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this);
- jack_on_shutdown(m_client, AUD_JackDevice::jack_shutdown, this);
- jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this);
+ AUD_jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this);
+ AUD_jack_on_shutdown(m_client, AUD_JackDevice::jack_shutdown, this);
+ AUD_jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this);
// register our output channels which are called ports in jack
m_ports = new jack_port_t*[m_specs.channels];
@@ -211,7 +211,7 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff
for(int i = 0; i < m_specs.channels; i++)
{
sprintf(portname, "out %d", i+1);
- m_ports[i] = jack_port_register(m_client, portname,
+ m_ports[i] = AUD_jack_port_register(m_client, portname,
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if(m_ports[i] == NULL)
@@ -220,17 +220,17 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff
}
catch(AUD_Exception&)
{
- jack_client_close(m_client);
+ AUD_jack_client_close(m_client);
delete[] m_ports;
throw;
}
- m_specs.rate = (AUD_SampleRate)jack_get_sample_rate(m_client);
+ m_specs.rate = (AUD_SampleRate)AUD_jack_get_sample_rate(m_client);
buffersize *= sizeof(sample_t);
m_ringbuffers = new jack_ringbuffer_t*[specs.channels];
for(unsigned int i = 0; i < specs.channels; i++)
- m_ringbuffers[i] = jack_ringbuffer_create(buffersize);
+ m_ringbuffers[i] = AUD_jack_ringbuffer_create(buffersize);
buffersize *= specs.channels;
m_deinterleavebuf.resize(buffersize);
m_buffer.resize(buffersize);
@@ -240,18 +240,18 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff
m_valid = true;
m_sync = 0;
m_syncFunc = NULL;
- m_nextState = m_state = jack_transport_query(m_client, NULL);
+ m_nextState = m_state = AUD_jack_transport_query(m_client, NULL);
pthread_mutex_init(&m_mixingLock, NULL);
pthread_cond_init(&m_mixingCondition, NULL);
// activate the client
- if(jack_activate(m_client))
+ if(AUD_jack_activate(m_client))
{
- jack_client_close(m_client);
+ AUD_jack_client_close(m_client);
delete[] m_ports;
for(unsigned int i = 0; i < specs.channels; i++)
- jack_ringbuffer_free(m_ringbuffers[i]);
+ AUD_jack_ringbuffer_free(m_ringbuffers[i]);
delete[] m_ringbuffers;
pthread_mutex_destroy(&m_mixingLock);
pthread_cond_destroy(&m_mixingCondition);
@@ -260,12 +260,12 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff
AUD_THROW(AUD_ERROR_JACK, activate_error);
}
- const char** ports = jack_get_ports(m_client, NULL, NULL,
+ const char** ports = AUD_jack_get_ports(m_client, NULL, NULL,
JackPortIsPhysical | JackPortIsInput);
if(ports != NULL)
{
for(int i = 0; i < m_specs.channels && ports[i]; i++)
- jack_connect(m_client, jack_port_name(m_ports[i]), ports[i]);
+ AUD_jack_connect(m_client, AUD_jack_port_name(m_ports[i]), ports[i]);
free(ports);
}
@@ -282,7 +282,7 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff
AUD_JackDevice::~AUD_JackDevice()
{
if(m_valid)
- jack_client_close(m_client);
+ AUD_jack_client_close(m_client);
m_valid = false;
delete[] m_ports;
@@ -295,7 +295,7 @@ AUD_JackDevice::~AUD_JackDevice()
pthread_cond_destroy(&m_mixingCondition);
pthread_mutex_destroy(&m_mixingLock);
for(unsigned int i = 0; i < m_specs.channels; i++)
- jack_ringbuffer_free(m_ringbuffers[i]);
+ AUD_jack_ringbuffer_free(m_ringbuffers[i]);
delete[] m_ringbuffers;
destroy();
@@ -308,20 +308,20 @@ void AUD_JackDevice::playing(bool playing)
void AUD_JackDevice::startPlayback()
{
- jack_transport_start(m_client);
+ AUD_jack_transport_start(m_client);
m_nextState = JackTransportRolling;
}
void AUD_JackDevice::stopPlayback()
{
- jack_transport_stop(m_client);
+ AUD_jack_transport_stop(m_client);
m_nextState = JackTransportStopped;
}
void AUD_JackDevice::seekPlayback(float time)
{
if(time >= 0.0f)
- jack_transport_locate(m_client, time * m_specs.rate);
+ AUD_jack_transport_locate(m_client, time * m_specs.rate);
}
void AUD_JackDevice::setSyncCallback(AUD_syncFunction sync, void* data)
@@ -333,13 +333,13 @@ void AUD_JackDevice::setSyncCallback(AUD_syncFunction sync, void* data)
float AUD_JackDevice::getPlaybackPosition()
{
jack_position_t position;
- jack_transport_query(m_client, &position);
+ AUD_jack_transport_query(m_client, &position);
return position.frame / (float) m_specs.rate;
}
bool AUD_JackDevice::doesPlayback()
{
- jack_transport_state_t state = jack_transport_query(m_client, NULL);
+ jack_transport_state_t state = AUD_jack_transport_query(m_client, NULL);
if(state != m_state)
m_nextState = m_state = state;
diff --git a/intern/audaspace/jack/AUD_JackDevice.h b/intern/audaspace/jack/AUD_JackDevice.h
index dc90c5249a2..a82a6bc5c38 100644
--- a/intern/audaspace/jack/AUD_JackDevice.h
+++ b/intern/audaspace/jack/AUD_JackDevice.h
@@ -36,12 +36,7 @@
#include <string>
-#if defined(__APPLE__) // always first include for jack weaklinking !
-#include <weakjack.h>
-#endif
-
-#include <jack.h>
-#include <ringbuffer.h>
+#include <AUD_JackLibrary.h>
typedef void (*AUD_syncFunction)(void*, int, float);
diff --git a/intern/audaspace/jack/AUD_JackLibrary.cpp b/intern/audaspace/jack/AUD_JackLibrary.cpp
new file mode 100644
index 00000000000..150d22b324c
--- /dev/null
+++ b/intern/audaspace/jack/AUD_JackLibrary.cpp
@@ -0,0 +1,116 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2013 Blender Foundation
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace 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.
+ *
+ * AudaSpace 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 Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/jack/AUD_JacLibrary.cpp
+ * \ingroup audjack
+ */
+
+#define AUD_JACK_LIBRARY_IMPL
+
+#include "AUD_JackLibrary.h"
+
+#ifdef WITH_JACK_DYNLOAD
+# include <dlfcn.h>
+# include <stdio.h>
+#endif
+
+#ifdef WITH_JACK_DYNLOAD
+static void *jack_handle = NULL;
+#endif
+
+static bool jack_supported = false;
+
+void AUD_jack_init(void)
+{
+#ifdef WITH_JACK_DYNLOAD
+ jack_handle = dlopen("libjack.so", RTLD_LAZY);
+
+ if (!jack_handle) {
+ fprintf(stderr, "%s\n", dlerror());
+ return;
+ }
+
+# define JACK_SYMBOL(sym) \
+ { \
+ char *error; \
+ *(void **) (&(AUD_##sym)) = dlsym(jack_handle, #sym); \
+ if ((error = dlerror()) != NULL) { \
+ fprintf(stderr, "%s\n", error); \
+ return; \
+ } \
+ } (void)0
+
+ dlerror(); /* Clear any existing error */
+#else // WITH_JACK_DYNLOAD
+# define JACK_SYMBOL(sym) AUD_##sym = sym
+#endif // WITH_JACK_DYNLOAD
+
+ JACK_SYMBOL(jack_transport_query);
+ JACK_SYMBOL(jack_transport_locate);
+
+ JACK_SYMBOL(jack_transport_start);
+ JACK_SYMBOL(jack_transport_stop);
+
+ JACK_SYMBOL(jack_ringbuffer_reset);
+ JACK_SYMBOL(jack_ringbuffer_write);
+ JACK_SYMBOL(jack_ringbuffer_write_space);
+ JACK_SYMBOL(jack_ringbuffer_write_advance);
+ JACK_SYMBOL(jack_ringbuffer_read);
+ JACK_SYMBOL(jack_ringbuffer_create);
+ JACK_SYMBOL(jack_ringbuffer_free);
+ JACK_SYMBOL(jack_ringbuffer_read_space);
+ JACK_SYMBOL(jack_set_sync_callback);
+
+ JACK_SYMBOL(jack_port_get_buffer);
+
+ JACK_SYMBOL(jack_client_open);
+ JACK_SYMBOL(jack_set_process_callback);
+ JACK_SYMBOL(jack_on_shutdown);
+ JACK_SYMBOL(jack_port_register);
+ JACK_SYMBOL(jack_client_close);
+ JACK_SYMBOL(jack_get_sample_rate);
+ JACK_SYMBOL(jack_activate);
+ JACK_SYMBOL(jack_get_ports);
+ JACK_SYMBOL(jack_port_name);
+ JACK_SYMBOL(jack_connect);
+
+ jack_supported = true;
+
+#undef JACK_SYMBOL
+}
+
+void AUD_jack_exit(void)
+{
+#ifdef WITH_JACK_DYNLOAD
+ if (jack_handle) {
+ dlclose(jack_handle);
+ }
+#endif
+ jack_supported = false;
+}
+
+bool AUD_jack_supported(void)
+{
+ return jack_supported;
+}
diff --git a/intern/audaspace/jack/AUD_JackLibrary.h b/intern/audaspace/jack/AUD_JackLibrary.h
new file mode 100644
index 00000000000..c4f50796381
--- /dev/null
+++ b/intern/audaspace/jack/AUD_JackLibrary.h
@@ -0,0 +1,104 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2013 Blender Foundation
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace 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.
+ *
+ * AudaSpace 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 Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/jack/AUD_JacLibrary.cpp
+ * \ingroup audjack
+ */
+
+#ifndef __AUD_JACKLIBRARY__
+#define __AUD_JACKLIBRARY__
+
+#if defined(__APPLE__) // always first include for jack weaklinking !
+#include <weakjack.h>
+#endif
+
+#include <jack.h>
+#include <ringbuffer.h>
+
+#ifdef AUD_JACK_LIBRARY_IMPL
+# define JACK_SYM
+#else
+# define JACK_SYM extern
+#endif
+
+/* All loadable Jack sumbols, prototypes from original jack.h */
+
+JACK_SYM jack_transport_state_t (*AUD_jack_transport_query) (
+ const jack_client_t *client,
+ jack_position_t *pos);
+
+JACK_SYM int (*AUD_jack_transport_locate) (jack_client_t *client,
+ jack_nframes_t frame);
+
+JACK_SYM void (*AUD_jack_transport_start) (jack_client_t *client);
+JACK_SYM void (*AUD_jack_transport_stop) (jack_client_t *client);
+
+JACK_SYM void (*AUD_jack_ringbuffer_reset) (jack_ringbuffer_t *rb);
+JACK_SYM size_t (*AUD_jack_ringbuffer_write) (jack_ringbuffer_t *rb,
+ const char *src, size_t cnt);
+JACK_SYM size_t (*AUD_jack_ringbuffer_write_space) (const jack_ringbuffer_t *rb);
+JACK_SYM void (*AUD_jack_ringbuffer_write_advance) (jack_ringbuffer_t *rb,
+ size_t cnt);
+JACK_SYM size_t (*AUD_jack_ringbuffer_read) (jack_ringbuffer_t *rb, char *dest,
+ size_t cnt);
+JACK_SYM jack_ringbuffer_t *(*AUD_jack_ringbuffer_create) (size_t sz);
+JACK_SYM void (*AUD_jack_ringbuffer_free) (jack_ringbuffer_t *rb);
+JACK_SYM size_t (*AUD_jack_ringbuffer_read_space) (const jack_ringbuffer_t *rb);
+JACK_SYM int (*AUD_jack_set_sync_callback) (jack_client_t *client,
+ JackSyncCallback sync_callback,
+ void *arg);
+
+JACK_SYM void *(*AUD_jack_port_get_buffer) (jack_port_t *, jack_nframes_t);
+
+JACK_SYM jack_client_t *(*AUD_jack_client_open) (const char *client_name,
+ jack_options_t options,
+ jack_status_t *status, ...);
+JACK_SYM int (*AUD_jack_set_process_callback) (jack_client_t *client,
+ JackProcessCallback process_callback, void *arg);
+JACK_SYM void (*AUD_jack_on_shutdown) (jack_client_t *client,
+ JackShutdownCallback function, void *arg);
+JACK_SYM jack_port_t *(*AUD_jack_port_register) (jack_client_t *client,
+ const char *port_name,
+ const char *port_type,
+ unsigned long flags,
+ unsigned long buffer_size);
+JACK_SYM int (*AUD_jack_client_close) (jack_client_t *client);
+JACK_SYM jack_nframes_t (*AUD_jack_get_sample_rate) (jack_client_t *);
+JACK_SYM int (*AUD_jack_activate) (jack_client_t *client);
+JACK_SYM const char **(*AUD_jack_get_ports) (jack_client_t *,
+ const char *port_name_pattern,
+ const char *type_name_pattern,
+ unsigned long flags);
+JACK_SYM const char *(*AUD_jack_port_name) (const jack_port_t *port);
+JACK_SYM int (*AUD_jack_connect) (jack_client_t *,
+ const char *source_port,
+ const char *destination_port);
+
+/* Public API */
+
+void AUD_jack_init(void);
+void AUD_jack_exit(void);
+bool AUD_jack_supported(void);
+
+#endif // __AUD_JACKLIBRARY__
diff --git a/intern/cycles/kernel/shaders/node_brightness.osl b/intern/cycles/kernel/shaders/node_brightness.osl
index 2de3c94ecc1..7b1db8efbde 100644
--- a/intern/cycles/kernel/shaders/node_brightness.osl
+++ b/intern/cycles/kernel/shaders/node_brightness.osl
@@ -25,10 +25,10 @@ shader node_brightness(
output color ColorOut = 0.8)
{
float a = 1.0 + Contrast;
- float b = Bright - Contrast*0.5;
+ float b = Bright - Contrast * 0.5;
- ColorOut[0] = max(a*ColorIn[0] + b, 0.0);
- ColorOut[1] = max(a*ColorIn[1] + b, 0.0);
- ColorOut[2] = max(a*ColorIn[2] + b, 0.0);
+ ColorOut[0] = max(a * ColorIn[0] + b, 0.0);
+ ColorOut[1] = max(a * ColorIn[1] + b, 0.0);
+ ColorOut[2] = max(a * ColorIn[2] + b, 0.0);
}
diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl
index 21382fab06f..4428a12ac41 100644
--- a/intern/cycles/kernel/shaders/node_normal_map.osl
+++ b/intern/cycles/kernel/shaders/node_normal_map.osl
@@ -35,9 +35,10 @@ shader node_normal_map(
float tangent_sign;
// get _unnormalized_ interpolated normal and tangent
- if(!getattribute(attr_name, tangent) ||
+ if (!getattribute(attr_name, tangent) ||
!getattribute(attr_sign_name, tangent_sign) ||
- !getattribute("geom:N", ninterp)) {
+ !getattribute("geom:N", ninterp))
+ {
Normal = normal(0, 0, 0);
}
else {
diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl
index 13f958d65bd..e9f7dfb3a2a 100644
--- a/intern/cycles/kernel/shaders/node_sky_texture.osl
+++ b/intern/cycles/kernel/shaders/node_sky_texture.osl
@@ -107,7 +107,7 @@ void precompute_sunsky(vector dir, float turbidity, output KernelSunSky sunsky)
sunsky.dir = dir;
float theta2 = theta * theta;
- float theta3 = theta * theta * theta;
+ float theta3 = theta2 * theta;
float T = turbidity;
float T2 = T * T;
diff --git a/intern/cycles/kernel/shaders/node_texture.h b/intern/cycles/kernel/shaders/node_texture.h
index f2aedb098d4..0a73c0907d9 100644
--- a/intern/cycles/kernel/shaders/node_texture.h
+++ b/intern/cycles/kernel/shaders/node_texture.h
@@ -202,8 +202,6 @@ float noise_basis_hard(point p, string basis, int hard)
float noise_wave(string wave, float a)
{
- float result = 0.0;
-
if (wave == "Sine") {
return 0.5 + 0.5 * sin(a);
}
diff --git a/intern/cycles/kernel/shaders/node_vector_curves.osl b/intern/cycles/kernel/shaders/node_vector_curves.osl
index 94082287f4d..d1477467836 100644
--- a/intern/cycles/kernel/shaders/node_vector_curves.osl
+++ b/intern/cycles/kernel/shaders/node_vector_curves.osl
@@ -21,7 +21,7 @@
float ramp_lookup(color ramp[RAMP_TABLE_SIZE], float at, int component)
{
- float f = clamp((at + 1.0)*0.5, 0.0, 1.0) * (RAMP_TABLE_SIZE - 1);
+ float f = clamp((at + 1.0) * 0.5, 0.0, 1.0) * (RAMP_TABLE_SIZE - 1);
/* clamp int as well in case of NaN */
int i = (int)f;
@@ -34,7 +34,7 @@ float ramp_lookup(color ramp[RAMP_TABLE_SIZE], float at, int component)
if (t > 0.0)
result = (1.0 - t) * result + t * ramp[i + 1][component];
- return result*2.0 - 1.0;
+ return result * 2.0 - 1.0;
}
shader node_vector_curves(
diff --git a/intern/cycles/kernel/shaders/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl
index bae55bcceaf..35c2b514328 100644
--- a/intern/cycles/kernel/shaders/node_ward_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_ward_bsdf.osl
@@ -31,7 +31,7 @@ shader node_ward_bsdf(
vector T = Tangent;
if (Rotation != 0.0)
- T = rotate(T, Rotation*2.0*M_PI, point(0.0, 0.0, 0.0), Normal);
+ T = rotate(T, Rotation * 2.0 * M_PI, point(0.0, 0.0, 0.0), Normal);
/* compute roughness */
float RoughnessU, RoughnessV;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 398b9f0a758..a4ffc2518fb 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -393,7 +393,7 @@ static void sky_texture_precompute(KernelSunSky *ksunsky, float3 dir, float turb
ksunsky->phi = phi;
float theta2 = theta*theta;
- float theta3 = theta*theta*theta;
+ float theta3 = theta2*theta;
float T = turbidity;
float T2 = T * T;
diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
index 574553d75b7..3dbddc30f0d 100644
--- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
@@ -374,6 +374,7 @@ class SpellChecker():
"fluidsim",
"frameserver",
"enum",
+ "gpencil",
"idcol",
"keyframe", "keyframes", "keyframing", "keyframed",
"metaball", "metaballs", "mball",
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index e739c5ea5d4..6e92b55f88c 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -152,8 +152,8 @@ class NODE_MT_select(Menu):
layout.operator("node.select_linked_from")
layout.operator("node.select_linked_to")
layout.operator("node.select_same_type")
- layout.operator("node.select_same_type_next")
- layout.operator("node.select_same_type_prev")
+ layout.operator("node.select_same_type_step").prev = True
+ layout.operator("node.select_same_type_step").prev = False
class NODE_MT_node(Menu):
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index aa445b9500d..ae9e0f72009 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -284,6 +284,9 @@ class SEQUENCER_MT_strip(Menu):
layout.operator("transform.transform", text="Grab/Move").mode = 'TRANSLATION'
layout.operator("transform.transform", text="Grab/Extend from frame").mode = 'TIME_EXTEND'
+ layout.operator("sequencer.gap_remove")
+ layout.operator("sequencer.gap_insert")
+
# uiItemO(layout, NULL, 0, "sequencer.strip_snap"); // TODO - add this operator
layout.separator()
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 17ef8e901f4..503c7a7f435 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -67,6 +67,7 @@ int BKE_brush_clone_image_delete(struct Brush *brush);
/* jitter */
void BKE_brush_jitter_pos(const struct Scene *scene, struct Brush *brush,
const float pos[2], float jitterpos[2]);
+void BKE_brush_randomize_texture_coordinates(struct UnifiedPaintSettings *ups);
/* brush curve */
void BKE_brush_curve_preset(struct Brush *b, int preset);
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 26ac2cc8bb4..0f8e25b9df5 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -232,6 +232,8 @@ void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, in
unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame);
float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame);
+/* Guess offset for the first frame in the sequence */
+int BKE_image_sequence_guess_offset(struct Image *image);
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index e62994576a3..e234d6c519e 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -628,70 +628,46 @@ void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree);
*
* Examples:
*
- * FOREACH_NODETREE(bmain, nodetree)
+ * FOREACH_NODETREE(bmain, nodetree) {
* if (id == nodetree)
* printf("This is a linkable node tree");
- * FOREACH_NODETREE_END
+ * } FOREACH_NODETREE_END
*
- * FOREACH_NODETREE(bmain, nodetree)
+ * FOREACH_NODETREE(bmain, nodetree) {
* if (nodetree->idname == "ShaderNodeTree")
* printf("This is a shader node tree);
* if (GS(id) == ID_MA)
* printf(" and it's owned by a material");
- * FOREACH_NODETREE_END
+ * } FOREACH_NODETREE_END
*/
+/* should be an opaque type, only for internal use by BKE_node_tree_iter_*** */
+struct NodeTreeIterStore {
+ bNodeTree *ngroup;
+ Scene *scene;
+ Material *mat;
+ Tex *tex;
+ Lamp *lamp;
+ World *world;
+};
+
+void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain);
+bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
+ struct bNodeTree **r_nodetree, struct ID **r_id);
+
#define FOREACH_NODETREE(bmain, _nodetree, _id) \
{ \
+ struct NodeTreeIterStore _nstore; \
bNodeTree *_nodetree; \
ID *_id; \
- bNodeTree *_ngroup = bmain->nodetree.first; \
- Scene *_scene = bmain->scene.first; \
- Material *_mat = bmain->mat.first; \
- Tex *_tex = bmain->tex.first; \
- Lamp *_lamp = bmain->lamp.first; \
- World *_world = bmain->world.first; \
/* avoid compiler warning about unused variables */ \
- (void)_id; \
- (void)_nodetree; \
- do { \
- if (_ngroup) { \
- _nodetree = _ngroup; \
- _id = (ID *)_ngroup; \
- _ngroup = _ngroup->id.next; \
- } \
- else if (_scene) { \
- _nodetree = _scene->nodetree; \
- _id = (ID *)_scene; \
- _scene = _scene->id.next; \
- } \
- else if (_mat) { \
- _nodetree = _mat->nodetree; \
- _id = (ID *)_mat; \
- _mat = _mat->id.next; \
- } \
- else if (_tex) { \
- _nodetree = _tex->nodetree; \
- _id = (ID *)_tex; \
- _tex = _tex->id.next; \
- } \
- else if (_lamp) { \
- _nodetree = _lamp->nodetree; \
- _id = (ID *)_lamp; \
- _lamp = _lamp->id.next; \
- } \
- else if (_world) { \
- _nodetree = _world->nodetree; \
- _id = (ID *)_world; \
- _world = _world->id.next; \
- } \
- else \
- break; \
+ BKE_node_tree_iter_init(&_nstore, bmain); \
+ while (BKE_node_tree_iter_step(&_nstore, &_nodetree, &_id) == true) { \
if (_nodetree) {
#define FOREACH_NODETREE_END \
} \
- } while (TRUE); \
+ } \
}
/* ************** SHADER NODES *************** */
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index ec1b6577469..64f0b97c3f0 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -47,6 +47,7 @@ typedef struct SoundWaveform {
} SoundWaveform;
void sound_init_once(void);
+void sound_exit_once(void);
void sound_init(struct Main *main);
@@ -139,4 +140,6 @@ void *sound_get_factory(void *sound);
float sound_get_length(struct bSound *sound);
+int sound_is_jack_supported(void);
+
#endif
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 888426735c5..2f666bf5922 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -525,21 +525,16 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
float radius = 1.0f; /* Quite warnings */
float co[3];
- if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW ||
- mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM)
- {
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
/* keep coordinates relative to mouse */
rotation += ups->brush_rotation;
- point_2d[0] -= ups->tex_mouse[0];
- point_2d[1] -= ups->tex_mouse[1];
+ x = point_2d[0] - ups->tex_mouse[0];
+ y = point_2d[1] - ups->tex_mouse[1];
/* use pressure adjusted size for fixed mode */
radius = ups->pixel_radius;
-
- x = point_2d[0];
- y = point_2d[1];
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
/* leave the coordinates relative to the screen */
@@ -550,6 +545,14 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
x = point_2d[0];
y = point_2d[1];
}
+ else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) {
+ rotation += ups->brush_rotation;
+ /* these contain a random coordinate */
+ x = point_2d[0] - ups->tex_mouse[0];
+ y = point_2d[1] - ups->tex_mouse[1];
+
+ radius = ups->pixel_radius;
+ }
x /= radius;
y /= radius;
@@ -661,6 +664,14 @@ float BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2
rotation += ups->brush_rotation;
radius = ups->pixel_radius;
}
+ else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) {
+ rotation += ups->brush_rotation;
+ /* these contain a random coordinate */
+ x -= ups->tex_mouse[0];
+ y -= ups->tex_mouse[1];
+
+ radius = ups->pixel_radius;
+ }
x /= radius;
y /= radius;
@@ -981,6 +992,14 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2],
}
}
+void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups)
+{
+ /* we multiply with brush radius as an optimization for the brush
+ * texture sampling functions */
+ ups->tex_mouse[0] = BLI_rng_get_float(brush_rng) * ups->pixel_radius;
+ ups->tex_mouse[1] = BLI_rng_get_float(brush_rng) * ups->pixel_radius;
+}
+
/* Uses the brush curve control to find a strength value between 0 and 1 */
float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len)
{
@@ -1021,7 +1040,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
- /*do normalized cannonical view coords for texture*/
+ /* do normalized cannonical view coords for texture */
for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
co[0] = x;
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 853a55b49c2..56f2237a61f 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -1653,7 +1653,7 @@ static int cu_isectLL(const float v1[3], const float v2[3], const float v3[3], c
}
-static short bevelinside(BevList *bl1, BevList *bl2)
+static bool bevelinside(BevList *bl1, BevList *bl2)
{
/* is bl2 INSIDE bl1 ? with left-right method and "lambda's" */
/* returns '1' if correct hole */
@@ -1701,9 +1701,7 @@ static short bevelinside(BevList *bl1, BevList *bl2)
bevp++;
}
- if ( (links & 1) && (rechts & 1) )
- return 1;
- return 0;
+ return (links & 1) && (rechts & 1);
}
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 0b55c732ade..9a012f9c009 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -1540,7 +1540,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
}
if (bottom_capbase.first) {
- BKE_displist_fill(&bottom_capbase, dispbase, 1);
+ BKE_displist_fill(&bottom_capbase, dispbase, 0);
BKE_displist_fill(&top_capbase, dispbase, 0);
BKE_displist_free(&bottom_capbase);
BKE_displist_free(&top_capbase);
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 26651d76f68..c9034cfe7bb 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -3430,3 +3430,15 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame)
return pixels;
}
+
+int BKE_image_sequence_guess_offset(Image *image)
+{
+ unsigned short numlen;
+ char head[FILE_MAX], tail[FILE_MAX];
+ char num[FILE_MAX] = {0};
+
+ BLI_stringdec(image->name, head, tail, &numlen);
+ BLI_strncpy(num, image->name + strlen(head), numlen + 1);
+
+ return atoi(num);
+}
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 1c1102d91ba..7fcbc14a593 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -126,11 +126,11 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
/* initialize the node name with the node label.
* note: do this after the initfunc so nodes get their data set which may be used in naming
* (node groups for example) */
- /* XXX Do not use nodeLabel() here, it returns translated content, which should *only* be used
- * in UI, *never* in data...
+ /* XXX Do not use nodeLabel() here, it returns translated content for UI, which should *only* be used
+ * in UI, *never* in data... Data have their own translation option!
* This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler
- * than adding a "no translate" flag to this func (and labelfunc() as well). */
- BLI_strncpy(node->name, ntype->ui_name, NODE_MAXSTR);
+ * than adding "do_translate" flags to this func (and labelfunc() as well). */
+ BLI_strncpy(node->name, DATA_(ntype->ui_name), NODE_MAXSTR);
nodeUniqueName(ntree, node);
node_add_sockets_from_type(ntree, node, ntype);
@@ -816,7 +816,7 @@ bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type)
NODE_TYPES_BEGIN(ntype)
if (ntype->type == type) {
- idname = ntype->idname;
+ idname = DATA_(ntype->idname);
break;
}
NODE_TYPES_END
@@ -3593,3 +3593,56 @@ void clear_scene_in_nodes(Main *bmain, Scene *sce)
}
}
}
+
+
+/* -------------------------------------------------------------------- */
+/* NodeTree Iterator Helpers (FOREACH_NODETREE) */
+
+void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain)
+{
+ ntreeiter->ngroup = bmain->nodetree.first;
+ ntreeiter->scene = bmain->scene.first;
+ ntreeiter->mat = bmain->mat.first;
+ ntreeiter->tex = bmain->tex.first;
+ ntreeiter->lamp = bmain->lamp.first;
+ ntreeiter->world = bmain->world.first;
+}
+bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
+ bNodeTree **r_nodetree, struct ID **r_id)
+{
+ if (ntreeiter->ngroup) {
+ *r_nodetree = ntreeiter->ngroup;
+ *r_id = (ID *)ntreeiter->ngroup;
+ ntreeiter->ngroup = ntreeiter->ngroup->id.next;
+ }
+ else if (ntreeiter->scene) {
+ *r_nodetree = ntreeiter->scene->nodetree;
+ *r_id = (ID *)ntreeiter->scene;
+ ntreeiter->scene = ntreeiter->scene->id.next;
+ }
+ else if (ntreeiter->mat) {
+ *r_nodetree = ntreeiter->mat->nodetree;
+ *r_id = (ID *)ntreeiter->mat;
+ ntreeiter->mat = ntreeiter->mat->id.next;
+ }
+ else if (ntreeiter->tex) {
+ *r_nodetree = ntreeiter->tex->nodetree;
+ *r_id = (ID *)ntreeiter->tex;
+ ntreeiter->tex = ntreeiter->tex->id.next;
+ }
+ else if (ntreeiter->lamp) {
+ *r_nodetree = ntreeiter->lamp->nodetree;
+ *r_id = (ID *)ntreeiter->lamp;
+ ntreeiter->lamp = ntreeiter->lamp->id.next;
+ }
+ else if (ntreeiter->world) {
+ *r_nodetree = ntreeiter->world->nodetree;
+ *r_id = (ID *)ntreeiter->world;
+ ntreeiter->world = ntreeiter->world->id.next;
+ }
+ else {
+ return false;
+ }
+
+ return true;
+}
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 5a02d929b76..af67ada7765 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -263,7 +263,7 @@ void packAll(Main *bmain, ReportList *reports)
}
if (tot == 0)
- BKE_report(reports, RPT_INFO, "No files have been packed");
+ BKE_report(reports, RPT_INFO, "No new files have been packed");
else
BKE_reportf(reports, RPT_INFO, "Packed %d files", tot);
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index bccc6f9a93b..eaf385fbfcf 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -1001,26 +1001,26 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o
/* get effectors present in the group specified by effector_weights */
effectors = pdInitEffectors(scene, ob, NULL, effector_weights);
if (effectors) {
- float force[3] = {0.0f, 0.0f, 0.0f};
- float loc[3], vel[3];
+ float eff_force[3] = {0.0f, 0.0f, 0.0f};
+ float eff_loc[3], eff_vel[3];
/* create dummy 'point' which represents last known position of object as result of sim */
// XXX: this can create some inaccuracies with sim position, but is probably better than using unsimulated vals?
- RB_body_get_position(rbo->physics_object, loc);
- RB_body_get_linear_velocity(rbo->physics_object, vel);
+ RB_body_get_position(rbo->physics_object, eff_loc);
+ RB_body_get_linear_velocity(rbo->physics_object, eff_vel);
- pd_point_from_loc(scene, loc, vel, 0, &epoint);
+ pd_point_from_loc(scene, eff_loc, eff_vel, 0, &epoint);
/* calculate net force of effectors, and apply to sim object
* - we use 'central force' since apply force requires a "relative position" which we don't have...
*/
- pdDoEffectors(effectors, NULL, effector_weights, &epoint, force, NULL);
+ pdDoEffectors(effectors, NULL, effector_weights, &epoint, eff_force, NULL);
if (G.f & G_DEBUG)
- printf("\tapplying force (%f,%f,%f) to '%s'\n", force[0], force[1], force[2], ob->id.name + 2);
+ printf("\tapplying force (%f,%f,%f) to '%s'\n", eff_force[0], eff_force[1], eff_force[2], ob->id.name + 2);
/* activate object in case it is deactivated */
- if (!is_zero_v3(force))
+ if (!is_zero_v3(eff_force))
RB_body_activate(rbo->physics_object);
- RB_body_apply_central_force(rbo->physics_object, force);
+ RB_body_apply_central_force(rbo->physics_object, eff_force);
}
else if (G.f & G_DEBUG)
printf("\tno forces to apply to '%s'\n", ob->id.name + 2);
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index af9d21d8cbc..feff8f95fd7 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -172,7 +172,7 @@ void sound_force_device(int device)
void sound_init_once(void)
{
AUD_initOnce();
- atexit(sound_exit);
+ atexit(sound_exit_once);
}
void sound_init(struct Main *bmain)
@@ -221,6 +221,12 @@ void sound_exit(void)
AUD_exit();
}
+void sound_exit_once(void)
+{
+ AUD_exit();
+ AUD_exitOnce();
+}
+
// XXX unused currently
#if 0
bSound *sound_new_buffer(struct Main *bmain, bSound *source)
@@ -766,6 +772,11 @@ float sound_get_length(bSound *sound)
return info.length;
}
+int sound_is_jack_supported(void)
+{
+ return AUD_isJackSupported();
+}
+
#else // WITH_AUDASPACE
#include "BLI_utildefines.h"
@@ -775,6 +786,7 @@ void sound_force_device(int UNUSED(device)) {}
void sound_init_once(void) {}
void sound_init(struct Main *UNUSED(bmain)) {}
void sound_exit(void) {}
+void sound_exit_once(void) {}
void sound_cache(struct bSound *UNUSED(sound)) { }
void sound_delete_cache(struct bSound *UNUSED(sound)) {}
void sound_load(struct Main *UNUSED(bmain), struct bSound *UNUSED(sound)) {}
@@ -807,4 +819,5 @@ void sound_set_scene_sound_pan(void *handle, float pan, char animated) { (void)h
void sound_set_scene_volume(struct Scene *scene, float volume) { (void)scene; (void)volume; }
void sound_set_scene_sound_pitch(void *handle, float pitch, char animated) { (void)handle; (void)pitch; (void)animated; }
float sound_get_length(struct bSound *sound) { (void)sound; return 0; }
+int sound_is_jack_supported(void) { return 0; }
#endif // WITH_AUDASPACE
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 3936c533a41..29f16775598 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -804,7 +804,7 @@ int txt_utf8_offset_to_column(const char *str, int offset)
int txt_utf8_column_to_offset(const char *str, int column)
{
int offset = 0, pos = 0, col;
- while (pos < column) {
+ while (*(str + offset) && pos < column) {
col = BLI_str_utf8_char_width_safe(str + offset);
if (pos + col > column)
break;
@@ -827,17 +827,6 @@ static int txt_utf8_len(const char *src)
return len;
}
-static int txt_utf8_width(const char *src)
-{
- int col = 0;
-
- for (; *src; src += BLI_str_utf8_size(src)) {
- col += BLI_str_utf8_char_width(src);
- }
-
- return col;
-}
-
void txt_move_up(Text *text, short sel)
{
TextLine **linep;
@@ -851,8 +840,7 @@ void txt_move_up(Text *text, short sel)
if ((*linep)->prev) {
int column = txt_utf8_offset_to_column((*linep)->line, *charp);
*linep = (*linep)->prev;
- if (column > txt_utf8_width((*linep)->line)) *charp = (*linep)->len;
- else *charp = txt_utf8_column_to_offset((*linep)->line, column);
+ *charp = txt_utf8_column_to_offset((*linep)->line, column);
}
else {
@@ -875,8 +863,7 @@ void txt_move_down(Text *text, short sel)
if ((*linep)->next) {
int column = txt_utf8_offset_to_column((*linep)->line, *charp);
*linep = (*linep)->next;
- if (column > txt_utf8_width((*linep)->line)) *charp = (*linep)->len;
- else *charp = txt_utf8_column_to_offset((*linep)->line, column);
+ *charp = txt_utf8_column_to_offset((*linep)->line, column);
}
else {
txt_move_eol(text, sel);
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index bcba2715740..6b9b371a4f3 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -135,7 +135,10 @@ int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *nu
else {
if (tail) strcpy(tail, string + name_end);
if (head) {
- BLI_strncpy(head, string, name_end);
+ /* name_end points to last character of head,
+ * make it +1 so null-terminator is nicely placed
+ */
+ BLI_strncpy(head, string, name_end + 1);
}
if (numlen) *numlen = 0;
return 0;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index a425928130d..a6dc4d242e9 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -4775,11 +4775,14 @@ static void direct_link_object(FileData *fd, Object *ob)
/* weak weak... this was only meant as draw flag, now is used in give_base_to_objects too */
ob->flag &= ~OB_FROMGROUP;
-
+
/* loading saved files with editmode enabled works, but for undo we like
- * to stay in object mode during undo presses so keep editmode disabled */
- if (fd->memfile)
+ * to stay in object mode during undo presses so keep editmode disabled.
+ *
+ * Also when linking in a file don't allow editmode: [#34776] */
+ if (fd->memfile || (ob->id.flag & (LIB_EXTERN | LIB_INDIRECT))) {
ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT);
+ }
ob->disp.first = ob->disp.last = NULL;
@@ -8876,7 +8879,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* Fix for bug #32982, internal_links list could get corrupted from r51630 onward.
* Simply remove bad internal_links lists to avoid NULL pointers.
*/
- FOREACH_NODETREE(main, ntree, id)
+ FOREACH_NODETREE(main, ntree, id) {
bNode *node;
bNodeLink *link, *nextlink;
@@ -8888,7 +8891,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
- FOREACH_NODETREE_END
+ } FOREACH_NODETREE_END
}
if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index c21da46d678..fcf804c8f4f 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -45,6 +45,8 @@ set(SRC
operators/bmo_create.c
operators/bmo_dissolve.c
operators/bmo_dupe.c
+ operators/bmo_edgeloop_fill.c
+ operators/bmo_edgenet.c
operators/bmo_edgesplit.c
operators/bmo_extrude.c
operators/bmo_hull.c
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index fddb7b4bf2c..5599dd6bc28 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -171,7 +171,7 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f)
* #BM_face_create should be considered over this function as it
* avoids some unnecessary work.
*/
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag)
+BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, const int create_flag)
{
BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
BMVert **verts_sort = BLI_array_alloca(verts_sort, len + 1);
@@ -308,6 +308,72 @@ err:
return NULL;
}
+/**
+ * Create an ngon from an array of sorted verts
+ *
+ * Special features this has over other functions.
+ * - Optionally calculate winding based on surrounding edges.
+ * - Optionally create edges between vertices.
+ * - Uses verts so no need to find edges (handy when you only have verts)
+ */
+BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, const int create_flag,
+ const bool calc_winding, const bool create_edges)
+{
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
+ unsigned int winding[2] = {0, 0};
+ int i, i_prev = len - 1;
+
+ BLI_assert(len > 2);
+
+ for (i = 0; i < len; i++) {
+ if (create_edges) {
+ edge_arr[i] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
+ }
+ else {
+ edge_arr[i] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
+ if (edge_arr[i] == NULL) {
+ return NULL;
+ }
+ }
+
+ if (calc_winding) {
+ /* the edge may exist already and be attached to a face
+ * in this case we can find the best winding to use for the new face */
+ if (edge_arr[i]->l) {
+ BMVert *test_v1, *test_v2;
+ /* we want to use the reverse winding to the existing order */
+ BM_edge_ordered_verts(edge_arr[i], &test_v2, &test_v1);
+ winding[(vert_arr[i_prev] == test_v2)]++;
+ }
+ }
+
+ i_prev = i;
+ }
+
+ /* --- */
+
+ if (calc_winding) {
+ if (winding[0] < winding[1]) {
+ winding[0] = 1;
+ winding[1] = 0;
+ }
+ else {
+ winding[0] = 0;
+ winding[1] = 1;
+ }
+ }
+ else {
+ winding[0] = 0;
+ winding[1] = 1;
+ }
+
+ /* --- */
+
+ /* create the face */
+ return BM_face_create_ngon(bm, vert_arr[winding[0]], vert_arr[winding[1]], edge_arr, len, create_flag);
+}
+
+
typedef struct AngleIndexPair {
float angle;
int index;
@@ -337,11 +403,11 @@ static int angle_index_pair_cmp(const void *e1, const void *e2)
*
* \note Since this is a vcloud there is no direction.
*/
-BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, const int create_flag)
+BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag)
{
BMFace *f;
- float totv_inv = 1.0f / (float)totv;
+ float totv_inv = 1.0f / (float)len;
int i = 0;
float cent[3], nor[3];
@@ -358,21 +424,17 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, const
AngleIndexPair *vang;
BMVert **vert_arr_map;
- BMEdge **edge_arr;
- int i_prev;
-
- unsigned int winding[2] = {0, 0};
/* get the center point and collect vector array since we loop over these a lot */
zero_v3(cent);
- for (i = 0; i < totv; i++) {
+ for (i = 0; i < len; i++) {
madd_v3_v3fl(cent, vert_arr[i]->co, totv_inv);
}
/* find the far point from cent */
far_best = 0.0f;
- for (i = 0; i < totv; i++) {
+ for (i = 0; i < len; i++) {
far_dist = len_squared_v3v3(vert_arr[i]->co, cent);
if (far_dist > far_best || far == NULL) {
far = vert_arr[i]->co;
@@ -387,7 +449,7 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, const
/* find a point 90deg about to compare with */
far_cross_best = 0.0f;
- for (i = 0; i < totv; i++) {
+ for (i = 0; i < len; i++) {
if (far == vert_arr[i]->co) {
continue;
@@ -422,9 +484,9 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, const
/* --- */
/* now calculate every points angle around the normal (signed) */
- vang = MEM_mallocN(sizeof(AngleIndexPair) * totv, __func__);
+ vang = MEM_mallocN(sizeof(AngleIndexPair) * len, __func__);
- for (i = 0; i < totv; i++) {
+ for (i = 0; i < len; i++) {
float co[3];
float proj_vec[3];
float angle;
@@ -448,53 +510,20 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, const
}
/* sort by angle and magic! - we have our ngon */
- qsort(vang, totv, sizeof(AngleIndexPair), angle_index_pair_cmp);
+ qsort(vang, len, sizeof(AngleIndexPair), angle_index_pair_cmp);
/* --- */
/* create edges and find the winding (if faces are attached to any existing edges) */
- vert_arr_map = MEM_mallocN(sizeof(BMVert **) * totv, __func__);
- edge_arr = MEM_mallocN(sizeof(BMEdge **) * totv, __func__);
+ vert_arr_map = MEM_mallocN(sizeof(BMVert **) * len, __func__);
- for (i = 0; i < totv; i++) {
+ for (i = 0; i < len; i++) {
vert_arr_map[i] = vert_arr[vang[i].index];
}
MEM_freeN(vang);
- i_prev = totv - 1;
- for (i = 0; i < totv; i++) {
- edge_arr[i] = BM_edge_create(bm, vert_arr_map[i_prev], vert_arr_map[i], NULL, BM_CREATE_NO_DOUBLE);
-
- /* the edge may exist already and be attached to a face
- * in this case we can find the best winding to use for the new face */
- if (edge_arr[i]->l) {
- BMVert *test_v1, *test_v2;
- /* we want to use the reverse winding to the existing order */
- BM_edge_ordered_verts(edge_arr[i], &test_v2, &test_v1);
- winding[(vert_arr_map[i_prev] == test_v2)]++;
-
- }
-
- i_prev = i;
- }
-
- /* --- */
-
- if (winding[0] < winding[1]) {
- winding[0] = 1;
- winding[1] = 0;
- }
- else {
- winding[0] = 0;
- winding[1] = 1;
- }
-
- /* --- */
-
- /* create the face */
- f = BM_face_create_ngon(bm, vert_arr_map[winding[0]], vert_arr_map[winding[1]], edge_arr, totv, create_flag);
+ f = BM_face_create_ngon_verts(bm, vert_arr_map, len, create_flag, true, true);
- MEM_freeN(edge_arr);
MEM_freeN(vert_arr_map);
return f;
diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h
index 0f597dbb1d8..949366309b9 100644
--- a/source/blender/bmesh/intern/bmesh_construct.h
+++ b/source/blender/bmesh/intern/bmesh_construct.h
@@ -36,7 +36,9 @@ BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, B
void BM_face_copy_shared(BMesh *bm, BMFace *f);
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag);
+BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, const int create_flag);
+BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, const int create_flag,
+ const bool calc_winding, const bool create_edges);
BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag);
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index a11d45a7a5a..f46f73c5350 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -308,7 +308,13 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm, const eBMCreateFlag creat
}
/**
- * \brief Main face creation function
+ * Main face creation function
+ *
+ * \param bm The mesh
+ * \param verts A sorted array of verts size of len
+ * \param edges A sorted array of edges size of len
+ * \param len Length of the face
+ * \param create_flag Options for creating the face
*/
BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag)
{
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index 44b76df7432..a1dde035224 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -170,7 +170,7 @@ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, cons
BMElem *ele;
int count = 0;
- for (ele = BM_iter_new(&iter, NULL, itype, data); ele; ele = BM_iter_step(&iter)) {
+ BM_ITER_ELEM (ele, &iter, data, itype) {
if (BM_elem_flag_test_bool(ele, hflag) == value) {
count++;
}
@@ -180,6 +180,30 @@ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, cons
}
/**
+ * \brief Elem Iter Tool Flag Count
+ *
+ * Counts how many flagged / unflagged items are found in this element.
+ */
+int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data,
+ const short oflag, const bool value)
+{
+ BMIter iter;
+ BMElemF *ele;
+ int count = 0;
+
+ /* loops have no header flags */
+ BLI_assert(bm_iter_itype_htype_map[itype] != BM_LOOP);
+
+ BM_ITER_ELEM (ele, &iter, data, itype) {
+ if (BMO_elem_flag_test_bool(bm, ele, oflag) == value) {
+ count++;
+ }
+ }
+ return count;
+}
+
+
+/**
* \brief Mesh Iter Flag Count
*
* Counts how many flagged / unflagged items are found in this mesh.
@@ -190,7 +214,7 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const
BMElem *ele;
int count = 0;
- for (ele = BM_iter_new(&iter, bm, itype, NULL); ele; ele = BM_iter_step(&iter)) {
+ BM_ITER_MESH (ele, &iter, bm, itype) {
if (BM_elem_flag_test_bool(ele, hflag) == value) {
count++;
}
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index 3b795a253bd..5fb226ae11d 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -132,6 +132,7 @@ __attribute__((warn_unused_result))
#endif
;
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value);
+int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, const short oflag, const bool value);
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value);
/* private for bmesh_iterators_inline.c */
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 869c894b66c..7583332c4db 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -527,6 +527,30 @@ static BMOpDefine bmo_bridge_loops_def = {
};
/*
+ * Edge Loop Fill.
+ *
+ * Create faces defined by one or more non overlapping edge loops.
+ */
+static BMOpDefine bmo_edgeloop_fill_def = {
+ "edgeloop_fill",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ /* restricts edges to groups. maps edges to integer */
+ {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
+ {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
+ {{'\0'}},
+ },
+ /* slots_out */
+ /* maps new faces to the group numbers they came from */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
+ {{'\0'}},
+ },
+ bmo_edgeloop_fill_exec,
+ 0,
+};
+
+
+/*
* Edge Net Fill.
*
* Create faces defined by enclosed edges.
@@ -541,7 +565,7 @@ static BMOpDefine bmo_edgenet_fill_def = {
{"use_fill_check", BMO_OP_SLOT_BOOL},
{"exclude_faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* list of faces to ignore for manifold check */
{"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
- {"use_smooth", BMO_OP_SLOT_BOOL}, /* material to use */
+ {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
{{'\0'}},
},
/* slots_out */
@@ -1615,6 +1639,7 @@ const BMOpDefine *bmo_opdefines[] = {
&bmo_dissolve_limit_def,
&bmo_dissolve_verts_def,
&bmo_duplicate_def,
+ &bmo_edgeloop_fill_def,
&bmo_edgenet_fill_def,
&bmo_edgenet_prepare_def,
&bmo_extrude_discrete_faces_def,
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 978aec0c610..180bc53c2e3 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -83,7 +83,7 @@ struct GHashIterator;
#define BMO_elem_flag_toggle( bm, ele, oflag) _bmo_elem_flag_toggle (bm, (ele)->oflags, oflag)
BLI_INLINE short _bmo_elem_flag_test( BMesh *bm, BMFlagLayer *oflags, const short oflag);
-BLI_INLINE short _bmo_elem_flag_test_bool(BMesh *bm, BMFlagLayer *oflags, const short oflag);
+BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, BMFlagLayer *oflags, const short oflag);
BLI_INLINE void _bmo_elem_flag_enable( BMesh *bm, BMFlagLayer *oflags, const short oflag);
BLI_INLINE void _bmo_elem_flag_disable( BMesh *bm, BMFlagLayer *oflags, const short oflag);
BLI_INLINE void _bmo_elem_flag_set( BMesh *bm, BMFlagLayer *oflags, const short oflag, int val);
@@ -391,10 +391,6 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na
void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot,
const void *element, const void *data, const int len);
-/* Counts the number of edges with tool flag toolflag around
- */
-int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag);
-
/* flags all elements in a mapping. note that the mapping must only have
* bmesh elements in it.*/
void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
index 0e1d4fec4d3..724ddcf3b04 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
@@ -43,7 +43,7 @@ BLI_INLINE short _bmo_elem_flag_test(BMesh *bm, BMFlagLayer *oflags, const short
return oflags[bm->stackdepth - 1].f & oflag;
}
-BLI_INLINE short _bmo_elem_flag_test_bool(BMesh *bm, BMFlagLayer *oflags, const short oflag)
+BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
return (oflags[bm->stackdepth - 1].f & oflag) != 0;
}
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index f52dd7f2be9..a358623834f 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -1075,25 +1075,6 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm,
}
}
-int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag)
-{
- int count = 0;
-
- if (v->e) {
- BMEdge *curedge;
- const int len = bmesh_disk_count(v);
- int i;
-
- for (i = 0, curedge = v->e; i < len; i++) {
- if (BMO_elem_flag_test(bm, curedge, oflag))
- count++;
- curedge = bmesh_disk_edge_next(curedge, v);
- }
- }
-
- return count;
-}
-
/**
* \brief BMO_FLAG_BUFFER
*
diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h
index 1aa4383d761..79e688bd5ff 100644
--- a/source/blender/bmesh/intern/bmesh_operators_private.h
+++ b/source/blender/bmesh/intern/bmesh_operators_private.h
@@ -57,6 +57,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op);
void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op);
void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op);
void bmo_duplicate_exec(BMesh *bm, BMOperator *op);
+void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op);
void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op);
void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op);
void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op);
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index 9fab89f8e0a..86904155cd3 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -27,1247 +27,13 @@
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
-#include "BLI_math.h"
-#include "BLI_array.h"
-#include "BLI_smallhash.h"
-#include "BLI_rand.h"
-#include "BLI_heap.h"
#include "bmesh.h"
#include "intern/bmesh_operators_private.h" /* own include */
-#define EDGE_MARK 1
-#define EDGE_VIS 2
-
-#define FACE_NEW 1
-
#define ELE_NEW 1
#define ELE_OUT 2
-#define ELE_ORIG 4
-
-#define FACE_IGNORE 16
-
-typedef struct EPathNode {
- struct EPathNode *next, *prev;
- BMVert *v;
- BMEdge *e;
- BMEdge *cure;
-} EPathNode;
-
-typedef struct EPath {
- ListBase nodes;
- float weight;
- int group;
-} EPath;
-
-typedef struct PathBase {
- BLI_mempool *nodepool, *pathpool;
-} PathBase;
-
-typedef struct EdgeData {
- int tag;
- int ftag;
- BMDiskLink v1_disk_link, v2_disk_link;
-} EdgeData;
-
-typedef struct VertData {
- BMEdge *e;
- float no[3], offco[3], sco[3]; /* offco is vertex coordinate slightly offset randomly */
- int tag;
-} VertData;
-
-static int count_edge_faces(BMesh *bm, BMEdge *e);
-
-/**** rotation system code * */
-
-BLI_INLINE BMDiskLink *rs_edge_link_get(BMEdge *e, BMVert *v, EdgeData *e_data)
-{
- return v == ((BMEdge *)e)->v1 ? &(((EdgeData *)e_data)->v1_disk_link) :
- &(((EdgeData *)e_data)->v2_disk_link);
-}
-
-static bool rotsys_append_edge(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *vdata)
-{
- EdgeData *ed = &edata[BM_elem_index_get(e)];
- VertData *vd = &vdata[BM_elem_index_get(v)];
-
- if (!vd->e) {
- Link *e1 = (Link *)rs_edge_link_get(e, v, ed);
-
- vd->e = e;
- e1->next = e1->prev = (Link *)e;
- }
- else {
- BMDiskLink *dl1, *dl2, *dl3;
- EdgeData *ved = &edata[BM_elem_index_get(vd->e)];
-
- dl1 = rs_edge_link_get(e, v, ed);
- dl2 = rs_edge_link_get(vd->e, v, ved);
- dl3 = dl2->prev ? rs_edge_link_get(dl2->prev, v, &edata[BM_elem_index_get(dl2->prev)]) : NULL;
-
- dl1->next = vd->e;
- dl1->prev = dl2->prev;
-
- dl2->prev = e;
- if (dl3) {
- dl3->next = e;
- }
- }
-
- return true;
-}
-
-static void UNUSED_FUNCTION(rotsys_remove_edge)(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *vdata)
-{
- EdgeData *ed = edata + BM_elem_index_get(e);
- VertData *vd = vdata + BM_elem_index_get(v);
- BMDiskLink *e1, *e2;
-
- e1 = rs_edge_link_get(e, v, ed);
- if (e1->prev) {
- e2 = rs_edge_link_get(e1->prev, v, ed);
- e2->next = e1->next;
- }
-
- if (e1->next) {
- e2 = rs_edge_link_get(e1->next, v, ed);
- e2->prev = e1->prev;
- }
-
- if (vd->e == e)
- vd->e = (e != e1->next) ? e1->next : NULL;
-
- e1->next = e1->prev = NULL;
-}
-
-static BMEdge *rotsys_nextedge(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *UNUSED(vdata))
-{
- if (v == e->v1)
- return edata[BM_elem_index_get(e)].v1_disk_link.next;
- if (v == e->v2)
- return edata[BM_elem_index_get(e)].v2_disk_link.next;
- return NULL;
-}
-
-static BMEdge *rotsys_prevedge(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *UNUSED(vdata))
-{
- if (v == e->v1)
- return edata[BM_elem_index_get(e)].v1_disk_link.prev;
- if (v == e->v2)
- return edata[BM_elem_index_get(e)].v2_disk_link.prev;
- return NULL;
-}
-
-static void rotsys_reverse(BMEdge *UNUSED(e), BMVert *v, EdgeData *edata, VertData *vdata)
-{
- BMEdge **edges = NULL;
- BMEdge *e_first;
- BMEdge *e;
- BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
- int i, totedge;
-
- e = e_first = vdata[BM_elem_index_get(v)].e;
- do {
- BLI_array_append(edges, e);
- e = rotsys_nextedge(e, v, edata, vdata);
- } while (e != e_first);
-
- totedge = BLI_array_count(edges);
- for (i = 0; i < totedge / 2; i++) {
- SWAP(BMEdge *, edges[i], edges[totedge - 1 - i]);
- }
-
- vdata[BM_elem_index_get(v)].e = NULL;
- for (i = 0; i < totedge; i++) {
- rotsys_append_edge(edges[i], v, edata, vdata);
- }
-
- BLI_array_free(edges);
-}
-
-static int UNUSED_FUNCTION(rotsys_count)(BMVert *v, EdgeData *edata, VertData *vdata)
-{
- BMEdge *e = vdata[BM_elem_index_get(v)].e;
- int i = 0;
-
- if (!e)
- return 0;
-
- do {
- if (!e)
- return 0;
- e = rotsys_nextedge(e, v, edata, vdata);
-
- if (i >= (1 << 20)) {
- printf("bmesh error: infinite loop in disk cycle!\n");
- return 0;
- }
-
- i += 1;
- } while (e != vdata[BM_elem_index_get(v)].e);
-
- return i;
-}
-
-static int UNUSED_FUNCTION(rotsys_fill_faces)(BMesh *bm, EdgeData *edata, VertData *vdata)
-{
- BMIter iter;
- BMEdge *e, **edges = NULL;
- BLI_array_declare(edges);
- BMVert *v, **verts = NULL;
- BMFace *f;
- BLI_array_declare(verts);
- SmallHash visithash, *hash = &visithash;
- int i;
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMEdge *e2, *starte;
- BMVert *startv;
- int rad, ok;
-
- rad = count_edge_faces(bm, e);
-
- if (rad < 2) {
- starte = e;
- }
- else {
- continue;
- }
-
- /* do two passes, going forward then backward */
- for (i = 0; i < 2; i++) {
- BLI_smallhash_init(hash);
-
- BLI_array_empty(verts);
- BLI_array_empty(edges);
-
- startv = v = starte->v1;
- e2 = starte;
- ok = 1;
- if (!v || !e2)
- continue;
-
- do {
- if (BLI_smallhash_haskey(hash, (intptr_t)e2) ||
- BLI_smallhash_haskey(hash, (intptr_t)v))
- {
- ok = 0;
- break;
- }
-
- BLI_array_append(verts, v);
- BLI_array_append(edges, e2);
-
- BLI_smallhash_insert(hash, (intptr_t)e2, NULL);
-
- v = BM_edge_other_vert(e2, v);
- e2 = i ? rotsys_prevedge(e2, v, edata, vdata) : rotsys_nextedge(e2, v, edata, vdata);
- } while (e2 != starte && v != startv);
-
- BLI_smallhash_release(hash);
-
- if (!ok || BLI_array_count(edges) < 3)
- continue;
-
- f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), BM_CREATE_NO_DOUBLE);
- if (UNLIKELY(f == NULL)) {
- continue;
- }
- }
- }
-
- return 0;
-}
-
-static void rotsys_make_consistent(BMesh *bm, EdgeData *edata, VertData *vdata)
-{
- BMIter iter;
- BMEdge *e;
- BMVert *v, **stack = NULL;
- BLI_array_declare(stack);
- int i;
-
- for (i = 0; i < bm->totvert; i++) {
- vdata[i].tag = 0;
- }
-
- while (1) {
- VertData *vd;
- BMVert *startv = NULL;
- float dis;
-
- v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL);
- for (i = 0; i < bm->totvert; i++, BM_iter_step(&iter)) {
- vd = vdata + BM_elem_index_get(v);
-
- if (vd->tag)
- continue;
-
- if (!startv || dot_v3v3(vd->offco, vd->offco) > dis) {
- dis = dot_v3v3(vd->offco, vd->offco);
- startv = v;
- }
- }
-
- if (!startv)
- break;
-
- vd = vdata + BM_elem_index_get(startv);
-
- BLI_array_empty(stack);
- BLI_array_append(stack, startv);
-
- vd->tag = 1;
-
- while (BLI_array_count(stack)) {
- v = BLI_array_pop(stack);
- vd = vdata + BM_elem_index_get(v);
-
- if (!vd->e)
- continue;
-
- e = vd->e;
- do {
- BMVert *v2 = BM_edge_other_vert(e, v);
- VertData *vd2 = vdata + BM_elem_index_get(v2);
-
- if (dot_v3v3(vd->no, vd2->no) < 0.0f + FLT_EPSILON * 2) {
- rotsys_reverse(e, v2, edata, vdata);
- mul_v3_fl(vd2->no, -1.0f);
- }
-
- if (!vd2->tag) {
- BLI_array_append(stack, v2);
- vd2->tag = 1;
- }
-
- e = rotsys_nextedge(e, v, edata, vdata);
- } while (e != vd->e);
- }
- }
-
- BLI_array_free(stack);
-}
-
-static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata)
-{
- BMIter iter;
- BMEdge *e;
- BMEdge **edges = NULL;
- BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
- BMVert *v;
- /* BMVert **verts = NULL; */
- /* BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); */ /* UNUSE */
- int i;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BMIter eiter;
- float no[3], cent[3];
- int j, k = 0, totedge = 0;
-
- if (BM_elem_index_get(v) == -1)
- continue;
-
- BLI_array_empty(edges);
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- BLI_array_append(edges, e);
- totedge++;
- }
- }
-
- copy_v3_v3(cent, v->co);
-
- zero_v3(no);
- for (i = 0; i < totedge; i++) {
- BMEdge *e1, *e2;
- float cno[3], vec1[3], vec2[3];
-
- e1 = edges[i];
- e2 = edges[(i + 1) % totedge];
-
- sub_v3_v3v3(vec1, (BM_edge_other_vert(e1, v))->co, v->co);
- sub_v3_v3v3(vec2, (BM_edge_other_vert(e2, v))->co, v->co);
-
- cross_v3_v3v3(cno, vec1, vec2);
- normalize_v3(cno);
-
- if (i && dot_v3v3(cno, no) < 0.0f + FLT_EPSILON * 10)
- mul_v3_fl(cno, -1.0f);
-
- add_v3_v3(no, cno);
- normalize_v3(no);
- }
-
- /* generate plane-flattened coordinates */
- for (i = 0; i < totedge; i++) {
- BMEdge *e1;
- BMVert *v2;
- float cvec[3], vec1[3];
-
- e1 = edges[i];
- v2 = BM_edge_other_vert(e1, v);
-
- sub_v3_v3v3(vec1, v2->co, v->co);
-
- cross_v3_v3v3(cvec, vec1, no);
- cross_v3_v3v3(vec1, cvec, no);
- normalize_v3(vec1);
-
- mul_v3_fl(vec1, len_v3v3(v2->co, v->co));
- add_v3_v3(vec1, v->co);
-
- copy_v3_v3(vdata[BM_elem_index_get(v2)].sco, vec1);
- }
-
- BLI_srandom(0);
-
- /* first, ensure no 0 or 180 angles between adjacent
- * (and that adjacent's adjacent) edges */
- for (i = 0, k = 0; i < totedge; i++) {
- BMEdge *e1, *e2, *e3 = NULL;
- BMVert *v1, *v2, *v3;
- VertData *vd1, *vd2, *vd3;
- float vec1[3], vec2[3], vec3[3], size;
- int s1, s2, s3;
-
- if (totedge < 3)
- continue;
-
- e1 = edges[(i + totedge - 1) % totedge];
- e2 = edges[i];
- e3 = edges[(i + 1) % totedge];
-
- v1 = BM_edge_other_vert(e1, v);
- v2 = BM_edge_other_vert(e2, v);
- v3 = BM_edge_other_vert(e3, v);
-
- vd1 = vdata + BM_elem_index_get(v1);
- vd2 = vdata + BM_elem_index_get(v2);
- vd3 = vdata + BM_elem_index_get(v3);
-
- sub_v3_v3v3(vec1, vd1->sco, cent);
- sub_v3_v3v3(vec2, vd2->sco, cent);
- sub_v3_v3v3(vec3, vd3->sco, cent);
-
- size = (len_v3(vec1) + len_v3(vec3)) * 0.01f;
- normalize_v3(vec1); normalize_v3(vec2); normalize_v3(vec3);
-
-#ifdef STRAIGHT
-#undef STRAIGHT
-#endif
-#define STRAIGHT(vec11, vec22) (fabsf(dot_v3v3((vec11), (vec22))) > 1.0f - ((float)FLT_EPSILON * 1000.0f))
-
- s1 = STRAIGHT(vec1, vec2); s2 = STRAIGHT(vec2, vec3); s3 = STRAIGHT(vec1, vec3);
-
- if (s1 || s2 || s3) {
- copy_v3_v3(cent, v->co);
-
- for (j = 0; j < 3; j++) {
- float fac = (BLI_frand() - 0.5f) * size;
- cent[j] += fac;
- }
-
- if (k < 2000) {
- i = 0;
- k++;
- continue;
- }
- else {
- k++;
- continue;
- }
-
- }
- }
-
- copy_v3_v3(vdata[BM_elem_index_get(v)].offco, cent);
- //copy_v3_v3(v->co, cent);
-
- /* now, sort edges so the triangle fan of all edges
- * has a consistent normal. this is the same as
- * sorting by polar coordinates along a group normal */
- for (j = 0; j < totedge; j++) {
- for (i = 0; i < totedge; i++) {
- BMEdge *e1, *e2, *e3 = NULL;
- BMVert *v1, *v2, *v3;
- VertData *vd1, *vd2, *vd3;
- float vec1[3], vec2[3], vec3[3], n1[3], n2[3], n3[3];
-
- e1 = edges[(i + totedge - 1) % totedge];
- e2 = edges[i];
- e3 = edges[(i + 1) % totedge];
-
- v1 = BM_edge_other_vert(e1, v);
- v2 = BM_edge_other_vert(e2, v);
- v3 = BM_edge_other_vert(e3, v);
-
- vd1 = vdata + BM_elem_index_get(v1);
- vd2 = vdata + BM_elem_index_get(v2);
- vd3 = vdata + BM_elem_index_get(v3);
-
- sub_v3_v3v3(vec1, vd1->sco, cent);
- sub_v3_v3v3(vec2, vd2->sco, cent);
- sub_v3_v3v3(vec3, vd3->sco, cent);
-
- cross_v3_v3v3(n1, vec1, vec2);
- cross_v3_v3v3(n2, vec2, vec3);
- cross_v3_v3v3(n3, vec1, vec3);
-
- /* this case happens often enough and probably not worth bothering users with,
- * maybe enable for debugging code but not for everyday use - campbell */
-#if 0
- /* Other way to determine if two vectors approach are (nearly) parallel: the
- * cross product of the two vectors will approach zero */
- {
- int s1, s2, s3;
- s1 = (dot_v3v3(n1, n1) < (0.0f + FLT_EPSILON * 10));
- s2 = (dot_v3v3(n2, n2) < (0.0f + FLT_EPSILON * 10));
- s3 = (totedge < 3) ? 0 : (dot_v3v3(n3, n3) < (0.0f + FLT_EPSILON * 10));
-
- if (s1 || s2 || s3) {
- fprintf(stderr, "%s: s1: %d, s2: %d, s3: %dx (bmesh internal error)\n", __func__, s1, s2, s3);
- }
- }
-#endif
-
- normalize_v3(n1); normalize_v3(n2); normalize_v3(n3);
-
-
- if (dot_v3v3(n1, n2) < 0.0f) {
- if (dot_v3v3(n1, n3) >= 0.0f + FLT_EPSILON * 10) {
- SWAP(BMEdge *, edges[i], edges[(i + 1) % totedge]);
- }
- else {
- SWAP(BMEdge *, edges[(i + totedge - 1) % totedge], edges[(i + 1) % totedge]);
- SWAP(BMEdge *, edges[i], edges[(i + 1) % totedge]);
- }
- }
- }
- }
-
-#undef STRAIGHT
-
- zero_v3(no);
-
- /* yay, edges are sorted */
- for (i = 0; i < totedge; i++) {
- BMEdge *e1 = edges[i], *e2 = edges[(i + 1) % totedge];
- float eno[3];
-
- normal_tri_v3(eno, BM_edge_other_vert(e1, v)->co, v->co, BM_edge_other_vert(e2, v)->co);
- add_v3_v3(no, eno);
-
- rotsys_append_edge(edges[i], v, edata, vdata);
- }
-
- normalize_v3(no);
- copy_v3_v3(vdata[BM_elem_index_get(v)].no, no);
- }
-
- /* now, make sure rotation system is topologically consistent
- * (e.g. vert normals consistently point either inside or outside) */
- rotsys_make_consistent(bm, edata, vdata);
-
- //rotsys_fill_faces(bm, edata, vdata);
-
-#if 0
- /* create visualizing geometry */
- BMVert *lastv;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BMVert *v2;
- BMFace *f;
- int totedge = BM_vert_edge_count(v);
-
- if (BM_elem_index_get(v) == -1)
- continue;
-
- //cv = BM_vert_create(bm, cent, v);
- //BM_elem_index_set(cv, -1); /* set_dirty! */
- i = 0;
- e = vdata[BM_elem_index_get(v)].e;
- lastv = NULL;
- do {
- BMEdge *e2;
- BMVert *v2;
- float f = ((float)i / (float)totedge) * 0.35 + 0.05;
- float co[3];
-
- if (!e)
- break;
-
- if (!BM_edge_other_vert(e, v))
- continue;
-
- sub_v3_v3v3(co, (BM_edge_other_vert(e, v))->co, vdata[BM_elem_index_get(v)].offco);
- mul_v3_fl(co, f);
- add_v3_v3(co, vdata[BM_elem_index_get(v)].offco);
-
- v2 = BM_vert_create(bm, co, NULL);
- BM_elem_index_set(v2, -1); /* set_dirty! */
- //BM_edge_create(bm, cv, v2, NULL, 0);
-
- BM_vert_select_set(bm, v2, true);
- if (lastv) {
- e2 = BM_edge_create(bm, lastv, v2, NULL, 0);
- BM_edge_select_set(bm, e2, true);
- }
-
- lastv = v2;
-
- e = rotsys_nextedge(e, v, edata, vdata);
- i++;
- } while (e != vdata[BM_elem_index_get(v)].e);
- }
-#endif
-
- BLI_array_free(edges);
-}
-
-static PathBase *edge_pathbase_new(void)
-{
- PathBase *pb = MEM_callocN(sizeof(PathBase), "PathBase");
-
- pb->nodepool = BLI_mempool_create(sizeof(EPathNode), 1, 512, BLI_MEMPOOL_SYSMALLOC);
- pb->pathpool = BLI_mempool_create(sizeof(EPath), 1, 512, BLI_MEMPOOL_SYSMALLOC);
-
- return pb;
-}
-
-static void edge_pathbase_free(PathBase *pathbase)
-{
- BLI_mempool_destroy(pathbase->nodepool);
- BLI_mempool_destroy(pathbase->pathpool);
- MEM_freeN(pathbase);
-}
-
-static EPath *edge_copy_add_path(PathBase *pb, EPath *path, BMVert *appendv, BMEdge *e)
-{
- EPath *path2;
- EPathNode *node, *node2;
-
- path2 = BLI_mempool_alloc(pb->pathpool);
- path2->nodes.first = path2->nodes.last = NULL;
- path2->weight = 0.0f;
- path2->group = path->group;
-
- for (node = path->nodes.first; node; node = node->next) {
- node2 = BLI_mempool_alloc(pb->nodepool);
- *node2 = *node;
- BLI_addtail(&path2->nodes, node2);
- }
-
- node2 = BLI_mempool_alloc(pb->nodepool);
- node2->v = appendv;
- node2->e = e;
- node2->cure = NULL;
-
- BLI_addtail(&path2->nodes, node2);
-
- return path2;
-}
-
-static EPath *edge_path_new(PathBase *pb, BMVert *start, BMEdge *starte)
-{
- EPath *path;
- EPathNode *node;
-
- path = BLI_mempool_alloc(pb->pathpool);
- node = BLI_mempool_alloc(pb->nodepool);
-
- path->nodes.first = path->nodes.last = NULL;
-
- node->v = start;
- node->e = starte;
- node->cure = NULL;
-
- BLI_addtail(&path->nodes, node);
- path->weight = 0.0f;
-
- return path;
-}
-
-static float edge_weight_path(EPath *path, EdgeData *edata, VertData *UNUSED(vdata))
-{
- EPathNode *node, *first = path->nodes.first;
- float w = 0.0;
-
- for (node = path->nodes.first; node; node = node->next) {
- if (node->e && node != path->nodes.first) {
- w += edata[BM_elem_index_get(node->e)].ftag;
- if (node->prev) {
- /* BMESH_TOD */
- (void)first;
- //w += len_v3v3(node->v->co, first->e->v1->co) * 0.0001f;
- //w += len_v3v3(node->v->co, first->e->v2->co) * 0.0001f;
- }
- }
-
- w += 1.0f;
- }
-
- return w;
-}
-
-
-static void edge_free_path(PathBase *pathbase, EPath *path)
-{
- EPathNode *node, *next;
-
- for (node = path->nodes.first; node; node = next) {
- next = node->next;
- BLI_mempool_free(pathbase->nodepool, node);
- }
-
- BLI_mempool_free(pathbase->pathpool, path);
-}
-
-static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, EdgeData *edata,
- VertData *vdata, PathBase *pathbase, int group)
-{
- BMEdge *e;
- GHash *gh = BLI_ghash_ptr_new("createops find shortest path");
- BMVert *v1, *v2;
- BMVert **verts = NULL;
- BLI_array_staticdeclare(verts, 1024);
- Heap *heap = BLI_heap_new();
- EPath *path = NULL, *path2;
- BMVert *startv;
- BMVert *endv;
- EPathNode *node;
- int i;
- const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
- BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
-
-
- startv = edata[BM_elem_index_get(edge)].ftag ? edge->v2 : edge->v1;
- endv = edata[BM_elem_index_get(edge)].ftag ? edge->v1 : edge->v2;
-
- path = edge_path_new(pathbase, startv, edge);
- BLI_ghash_insert(gh, startv, NULL);
- BLI_heap_insert(heap, path->weight, path);
- path->group = group;
-
- while (BLI_heap_size(heap)) {
- VertData *vd;
- EPathNode *last;
- BMFace *f = NULL;
-
- path = BLI_heap_popmin(heap);
- last = path->nodes.last;
- v1 = last->v;
-
- if (v1 == endv) {
- /* make sure this path loop doesn't already exists */
- i = 0;
- BLI_array_empty(verts);
- for (i = 0, node = path->nodes.first; node; node = node->next, i++) {
- BLI_array_grow_one(verts);
- verts[i] = node->v;
- }
-
- if (BM_face_exists(verts, i, &f)) {
- if (!BMO_elem_flag_test(bm, f, FACE_IGNORE)) {
- BLI_ghash_remove(gh, endv, NULL, NULL);
- continue;
- }
- }
- break;
- }
-
- vd = vdata + BM_elem_index_get(v1);
- if (!vd->e)
- continue;
-
- v2 = NULL;
- while (1) {
- if (!last->cure) {
- last->cure = e = vdata[BM_elem_index_get(last->v)].e;
- }
- else {
- last->cure = e = rotsys_nextedge(last->cure, last->v, edata, vdata);
- if (last->cure == vdata[BM_elem_index_get(last->v)].e) {
- v2 = NULL;
- break;
- }
- }
-
- if (e == edge || !BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- continue;
- }
-
- v2 = BM_edge_other_vert(e, last->v);
-
- if (BLI_ghash_haskey(gh, v2)) {
- v2 = NULL;
- continue;
- }
-
- if (use_restrict) {
- int *group_flag = (int *)BMO_slot_map_data_get(slot_restrict, e);
- if (group_flag) {
- if (!(*group_flag & path->group)) {
- v2 = NULL;
- continue;
- }
- }
- }
-
- break;
- }
-
- if (!v2) {
- if (path) {
- edge_free_path(pathbase, path);
- path = NULL;
- }
- continue;
- }
-
- /* add path back into heap */
- BLI_heap_insert(heap, path->weight, path);
-
- /* put v2 in gh ma */
- BLI_ghash_insert(gh, v2, NULL);
-
- path2 = edge_copy_add_path(pathbase, path, v2, e);
- path2->weight = edge_weight_path(path2, edata, vdata);
-
- BLI_heap_insert(heap, path2->weight, path2);
- }
-
- if (path && ((EPathNode *)path->nodes.last)->v != endv) {
- edge_free_path(pathbase, path);
- path = NULL;
- }
-
- BLI_array_free(verts);
- BLI_heap_free(heap, NULL);
- BLI_ghash_free(gh, NULL, NULL);
-
- return path;
-}
-
-static int count_edge_faces(BMesh *bm, BMEdge *e)
-{
- int i = 0;
- BMLoop *l = e->l;
-
- if (!l) {
- return 0;
- }
-
- do {
- if (!BMO_elem_flag_test(bm, l->f, FACE_IGNORE)) {
- i++;
- }
-
- l = l->radial_next;
- } while (l != e->l);
-
- return i;
-}
-
-BLI_INLINE void vote_on_winding(BMEdge *edge, EPathNode *node, unsigned int winding[2])
-{
- BMVert *test_v1, *test_v2;
- /* we want to use the reverse winding to the existing order */
- BM_edge_ordered_verts(edge, &test_v2, &test_v1);
-
- /* edges vote on which winding wins out */
- winding[(test_v1 == node->v)]++;
-}
-
-void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
-{
- BMIter iter;
- BMOIter siter;
- BMFace *f;
- BMEdge *e, *edge;
- BMVert **verts = NULL;
- BLI_array_declare(verts);
- EPath *path;
- EPathNode *node;
- EdgeData *edata;
- VertData *vdata;
- BMEdge **edges = NULL;
- PathBase *pathbase;
- BLI_array_declare(edges);
- const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
- const bool use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check");
- const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
- const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
- int i, j, group = 0;
- unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */
- BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
- BMOpSlot *slot_face_groupmap_out = BMO_slot_get(op->slots_out, "face_groupmap.out");
-
- if (!bm->totvert || !bm->totedge)
- return;
-
- pathbase = edge_pathbase_new();
-
- edata = MEM_callocN(sizeof(EdgeData) * bm->totedge, "EdgeData");
- vdata = MEM_callocN(sizeof(VertData) * bm->totvert, "VertData");
-
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "exclude_faces", BM_FACE, FACE_IGNORE);
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BMO_elem_flag_enable(bm, f, ELE_ORIG);
- }
-
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- BM_elem_index_set(e, i); /* set_inline */
-
- if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- edata[i].tag = 2;
- }
- }
- bm->elem_index_dirty &= ~BM_EDGE;
-
- init_rotsys(bm, edata, vdata);
-
- while (1) {
- edge = NULL;
- group = 0;
-
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- /* if restrict is on, only start on faces in the restrict map */
- if (use_restrict && !BMO_slot_map_contains(slot_restrict, e))
- continue;
-
- if (edata[BM_elem_index_get(e)].tag < 2) {
- edge = e;
-
- if (use_restrict) {
- int i = 0, j = 0, gi = 0;
-
- group = BMO_slot_map_int_get(slot_restrict, e);
-
- for (i = 0; i < 30; i++) {
- if (group & (1 << i)) {
- j++;
- gi = i;
-
- if (j - 1 == edata[BM_elem_index_get(e)].tag) {
- break;
- }
- }
- }
-
- group = (1 << gi);
- }
-
- break;
- }
- }
-
- if (!edge)
- break;
-
- edata[BM_elem_index_get(edge)].tag += 1;
-
- path = edge_find_shortest_path(bm, op, edge, edata, vdata, pathbase, group);
- if (!path)
- continue;
-
- winding[0] = winding[1] = 0;
-
- BLI_array_empty(edges);
- BLI_array_empty(verts);
- i = 0;
- for (node = path->nodes.first; node; node = node->next) {
- if (!node->next)
- continue;
-
- e = BM_edge_exists(node->v, node->next->v);
-
- /* this should never happe */
- if (!e)
- break;
-
- /* check on the winding */
- if (e->l) {
- vote_on_winding(e, node, winding);
- }
-
- edata[BM_elem_index_get(e)].ftag++;
- BLI_array_grow_one(edges);
- edges[i++] = e;
-
- BLI_array_append(verts, node->v);
- }
-
- if (edge->l) {
- vote_on_winding(edge, path->nodes.last, winding);
- }
-
- BLI_array_grow_one(edges);
- edges[i++] = edge;
- edata[BM_elem_index_get(edge)].ftag++;
-
- for (j = 0; j < i; j++) {
- if (count_edge_faces(bm, edges[j]) >= 2) {
- edge_free_path(pathbase, path);
- break;
- }
- }
-
- if (j != i) {
- continue;
- }
-
- if (i) {
- BMVert *v1, *v2;
-
- /* to define the winding order must select first edge,
- * otherwise we could leave this as-is */
- edge = edges[0];
-
- /* if these are even it doesn't really matter what to do,
- * with consistent geometry one will be zero, the choice is clear */
- if (winding[0] < winding[1]) {
- v1 = verts[0];
- v2 = verts[1];
- }
- else {
- v1 = verts[1];
- v2 = verts[0];
- }
-
- if ((use_fill_check == false) ||
- /* fairly expensive check - see if there are already faces filling this area */
- (BM_face_exists_multi_edge(edges, i) == false))
- {
- f = BM_face_create_ngon(bm, v1, v2, edges, i, BM_CREATE_NO_DOUBLE);
- if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) {
- BMO_elem_flag_enable(bm, f, FACE_NEW);
- f->mat_nr = mat_nr;
- if (use_smooth) {
- BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
- }
- }
-
- if (use_restrict) {
- BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group);
- }
- }
- }
-
- edge_free_path(pathbase, path);
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW);
-
- BLI_array_free(edges);
- BLI_array_free(verts);
- edge_pathbase_free(pathbase);
- MEM_freeN(edata);
- MEM_freeN(vdata);
-}
-
-static BMEdge *edge_next(BMesh *bm, BMEdge *e)
-{
- BMIter iter;
- BMEdge *e2;
- int i;
-
- for (i = 0; i < 2; i++) {
- BM_ITER_ELEM (e2, &iter, i ? e->v2 : e->v1, BM_EDGES_OF_VERT) {
- if ((BMO_elem_flag_test(bm, e2, EDGE_MARK)) &&
- (!BMO_elem_flag_test(bm, e2, EDGE_VIS)) &&
- (e2 != e))
- {
- return e2;
- }
- }
- }
-
- return NULL;
-}
-
-void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op)
-{
- BMOIter siter;
- BMEdge *e;
- BMEdge **edges1 = NULL, **edges2 = NULL, **edges;
- BLI_array_declare(edges1);
- BLI_array_declare(edges2);
- BLI_array_declare(edges);
- int ok = 1;
- int i, count;
-
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
-
- /* validate that each edge has at most one other tagged edge in the
- * disk cycle around each of it's vertices */
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- for (i = 0; i < 2; i++) {
- count = BMO_vert_edge_flags_count(bm, i ? e->v2 : e->v1, EDGE_MARK);
- if (count > 2) {
- ok = 0;
- break;
- }
- }
-
- if (!ok) {
- break;
- }
- }
-
- /* we don't have valid edge layouts, retur */
- if (!ok) {
- return;
- }
-
- /* find connected loops within the input edge */
- count = 0;
- while (1) {
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- if (!BMO_elem_flag_test(bm, e, EDGE_VIS)) {
- if (BMO_vert_edge_flags_count(bm, e->v1, EDGE_MARK) == 1 ||
- BMO_vert_edge_flags_count(bm, e->v2, EDGE_MARK) == 1)
- {
- break;
- }
- }
- }
-
- if (!e) {
- break;
- }
-
- if (!count) {
- edges = edges1;
- }
- else if (count == 1) {
- edges = edges2;
- }
- else {
- break;
- }
-
- i = 0;
- while (e) {
- BMO_elem_flag_enable(bm, e, EDGE_VIS);
- BLI_array_grow_one(edges);
- edges[i] = e;
-
- e = edge_next(bm, e);
- i++;
- }
-
- if (!count) {
- edges1 = edges;
- BLI_array_length_set(edges1, BLI_array_count(edges));
- }
- else {
- edges2 = edges;
- BLI_array_length_set(edges2, BLI_array_count(edges));
- }
-
- BLI_array_empty(edges);
- count++;
- }
-
- if (edges1 && BLI_array_count(edges1) > 2 &&
- BM_edge_share_vert_check(edges1[0], edges1[BLI_array_count(edges1) - 1]))
- {
- if (edges2 && BLI_array_count(edges2) > 2 &&
- BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1]))
- {
- BLI_array_free(edges1);
- BLI_array_free(edges2);
- return;
- }
- else {
- edges1 = edges2;
- edges2 = NULL;
- }
- }
-
- if (edges2 && BLI_array_count(edges2) > 2 &&
- BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1]))
- {
- edges2 = NULL;
- }
-
- /* two unconnected loops, connect the */
- if (edges1 && edges2) {
- BMVert *v1, *v2, *v3, *v4;
- float dvec1[3];
- float dvec2[3];
-
- if (BLI_array_count(edges1) == 1) {
- v1 = edges1[0]->v1;
- v2 = edges1[0]->v2;
- }
- else {
- v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
- i = BLI_array_count(edges1) - 1;
- v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
- }
-
- if (BLI_array_count(edges2) == 1) {
- v3 = edges2[0]->v1;
- v4 = edges2[0]->v2;
- }
- else {
- v3 = BM_vert_in_edge(edges2[1], edges2[0]->v1) ? edges2[0]->v2 : edges2[0]->v1;
- i = BLI_array_count(edges2) - 1;
- v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1;
- }
-
- /* if there is ever bow-tie quads between two edges the problem is here! [#30367] */
-#if 0
- normal_tri_v3(dvec1, v1->co, v2->co, v4->co);
- normal_tri_v3(dvec2, v1->co, v4->co, v3->co);
-#else
- {
- /* save some CPU cycles and skip the sqrt and 1 subtraction */
- float a1[3], a2[3], a3[3];
- sub_v3_v3v3(a1, v1->co, v2->co);
- sub_v3_v3v3(a2, v1->co, v4->co);
- sub_v3_v3v3(a3, v1->co, v3->co);
- cross_v3_v3v3(dvec1, a1, a2);
- cross_v3_v3v3(dvec2, a2, a3);
- }
-#endif
- if (dot_v3v3(dvec1, dvec2) < 0.0f) {
- SWAP(BMVert *, v3, v4);
- }
-
- e = BM_edge_create(bm, v1, v3, NULL, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(bm, e, ELE_NEW);
- e = BM_edge_create(bm, v2, v4, NULL, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(bm, e, ELE_NEW);
- }
- else if (edges1) {
- BMVert *v1, *v2;
-
- if (BLI_array_count(edges1) > 1) {
- v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
- i = BLI_array_count(edges1) - 1;
- v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
- e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(bm, e, ELE_NEW);
- }
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW);
-
- BLI_array_free(edges1);
- BLI_array_free(edges2);
-}
/* This is what runs when pressing the F key
* doing the best thing here isn't always easy create vs dissolve, its nice to support
@@ -1361,11 +127,15 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
e = BM_edge_create(bm, v_free, v_b, NULL, BM_CREATE_NO_DOUBLE);
BMO_elem_flag_enable(bm, e, ELE_NEW);
+ tote += 2;
}
}
/* --- end special case support, continue as normal --- */
- /* call edgenet create */
+
+ /* -------------------------------------------------------------------- */
+ /* EdgeNet Create */
+
/* call edgenet prepare op so additional face creation cases wore */
BMO_op_initf(bm, &op2, op->flag, "edgenet_prepare edges=%fe", ELE_NEW);
BMO_op_exec(bm, &op2);
@@ -1387,8 +157,10 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
}
BMO_op_finish(bm, &op2);
-
- /* now call dissolve face */
+
+
+ /* -------------------------------------------------------------------- */
+ /* Dissolve Face */
BMO_op_initf(bm, &op2, op->flag, "dissolve_faces faces=%ff", ELE_NEW);
BMO_op_exec(bm, &op2);
@@ -1402,6 +174,32 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
BMO_op_finish(bm, &op2);
+
+ /* -------------------------------------------------------------------- */
+ /* Fill EdgeLoop's - fills isolated loops, different from edgenet */
+
+ /* note: in most cases 'edgenet_fill' will handle this case since in common cases
+ * users fill in empty spaces, however its possible to have an edge selection around
+ * existing geometry that makes 'edgenet_fill' fail. */
+ BMO_op_initf(bm, &op2, op->flag, "edgeloop_fill edges=%fe", ELE_NEW);
+ BMO_op_exec(bm, &op2);
+
+ /* return if edge loop fill did something */
+ if (BMO_slot_buffer_count(op2.slots_out, "faces.out")) {
+ BMO_slot_copy(&op2, slots_out, "faces.out",
+ op, slots_out, "faces.out");
+ BMO_op_finish(bm, &op2);
+ return;
+ }
+
+ BMO_op_finish(bm, &op2);
+
+
+
+ /* -------------------------------------------------------------------- */
+ /* Continue with ad-hoc fill methods since operators fail,
+ * edge, vcloud... may add more */
+
/* now, count how many verts we have */
amount = 0;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -1419,6 +217,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
/* create edge */
e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE);
BMO_elem_flag_enable(bm, e, ELE_OUT);
+ tote += 1;
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
}
else if (0) { /* nice feature but perhaps it should be a different tool? */
@@ -1469,8 +268,9 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
/* done creating edges */
}
else if (amount > 2) {
- /* TODO, all these verts may be connected by edges.
- * we should check on this before assuming they are a random set of verts */
+ /* TODO, some of these vertes may be connected by edges,
+ * this connectivity could be used rather then treating
+ * them as a bunch of isolated verts. */
BMVert **vert_arr = MEM_mallocN(sizeof(BMVert **) * totv, __func__);
int i = 0;
@@ -1493,4 +293,6 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
MEM_freeN(vert_arr);
}
+
+ (void)tote;
}
diff --git a/source/blender/bmesh/operators/bmo_edgeloop_fill.c b/source/blender/bmesh/operators/bmo_edgeloop_fill.c
new file mode 100644
index 00000000000..3818f449a15
--- /dev/null
+++ b/source/blender/bmesh/operators/bmo_edgeloop_fill.c
@@ -0,0 +1,157 @@
+/*
+ * ***** 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/bmesh/operators/bmo_edgeloop_fill.c
+ * \ingroup bmesh
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+#define VERT_USED 1
+#define EDGE_MARK 2
+#define ELE_OUT 4
+
+void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op)
+{
+ /* first collect an array of unique from the edges */
+ const int tote = BMO_slot_buffer_count(op->slots_in, "edges");
+ const int totv = tote; /* these should be the same */
+ BMVert **verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
+
+ BMVert *v;
+ BMEdge *e;
+ int i;
+ bool ok = true;
+
+ BMOIter oiter;
+
+ const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
+ const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+
+ /* 'VERT_USED' will be disabled, so enable and fill the array */
+ BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
+ BMIter viter;
+ BMO_elem_flag_enable(bm, e, EDGE_MARK);
+ BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+ if (BMO_elem_flag_test(bm, v, VERT_USED) == false) {
+ BMO_elem_flag_enable(bm, v, VERT_USED);
+ verts[i++] = v;
+ if (i > tote) {
+ break;
+ }
+ }
+ }
+ if (i > tote) {
+ break;
+ }
+ }
+
+ /* we have a different number of verts to edges */
+ if (i != tote) {
+ MEM_freeN(verts);
+ return;
+ }
+
+ /* loop over connected flagged edges and fill in faces, this is made slightly more
+ * complicated because there may be multiple disconnected loops to fill. */
+
+ /* sanity check - that each vertex has 2 edge users */
+ for (i = 0; i < totv; i++) {
+ v = verts[i];
+ /* count how many flagged edges this vertex uses */
+ if (BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, v, EDGE_MARK, true) != 2) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok) {
+ /* note: in the case of multiple loops, this over-allocs (which is fine) */
+ BMVert **f_verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
+ BMIter eiter;
+
+ /* build array of connected verts and edges */
+ BMEdge *e_prev = NULL;
+ BMEdge *e_next = NULL;
+ int totv_used = 0;
+
+ while (totv_used < totv) {
+ for (i = 0; i < totv; i++) {
+ v = verts[i];
+ if (BMO_elem_flag_test(bm, v, VERT_USED)) {
+ break;
+ }
+ }
+
+ /* this should never fail, as long as (totv_used < totv)
+ * we should have marked verts available */
+ BLI_assert(BMO_elem_flag_test(bm, v, VERT_USED));
+
+ /* watch it, 'i' is used for final face length */
+ i = 0;
+ do {
+ /* we know that there are 2 edges per vertex so no need to check */
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
+ if (e != e_prev) {
+ e_next = e;
+ break;
+ }
+ }
+ }
+
+ /* fill in the array */
+ f_verts[i] = v;
+ BMO_elem_flag_disable(bm, v, VERT_USED);
+ totv_used++;
+
+ /* step over the edges */
+ v = BM_edge_other_vert(e_next, v);
+ e_prev = e_next;
+ i++;
+ } while ((v != f_verts[0]));
+
+ if (BM_face_exists(f_verts, i, NULL) == false) {
+ BMFace *f;
+
+ /* don't use calc_edges option because we already have the edges */
+ f = BM_face_create_ngon_verts(bm, f_verts, i, 0, true, false);
+ BMO_elem_flag_enable(bm, f, ELE_OUT);
+ f->mat_nr = mat_nr;
+ if (use_smooth) {
+ BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
+ }
+ }
+ }
+ MEM_freeN(f_verts);
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_OUT);
+ }
+
+ MEM_freeN(verts);
+}
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
new file mode 100644
index 00000000000..cf91dfd0f15
--- /dev/null
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -0,0 +1,1270 @@
+/*
+ * ***** 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): Joseph Eagar.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/operators/bmo_edgenet.c
+ * \ingroup bmesh
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_smallhash.h"
+#include "BLI_rand.h"
+#include "BLI_heap.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+#define EDGE_MARK 1
+#define EDGE_VIS 2
+
+#define FACE_NEW 1
+
+#define ELE_NEW 1
+#define ELE_OUT 2
+#define ELE_ORIG 4
+
+#define FACE_IGNORE 16
+
+typedef struct EPathNode {
+ struct EPathNode *next, *prev;
+ BMVert *v;
+ BMEdge *e;
+ BMEdge *cure;
+} EPathNode;
+
+typedef struct EPath {
+ ListBase nodes;
+ float weight;
+ int group;
+} EPath;
+
+typedef struct PathBase {
+ BLI_mempool *nodepool, *pathpool;
+} PathBase;
+
+typedef struct EdgeData {
+ int tag;
+ int ftag;
+ BMDiskLink v1_disk_link, v2_disk_link;
+} EdgeData;
+
+typedef struct VertData {
+ BMEdge *e;
+ float no[3], offco[3], sco[3]; /* offco is vertex coordinate slightly offset randomly */
+ int tag;
+} VertData;
+
+static int count_edge_faces(BMesh *bm, BMEdge *e);
+
+/**** rotation system code * */
+
+BLI_INLINE BMDiskLink *rs_edge_link_get(BMEdge *e, BMVert *v, EdgeData *e_data)
+{
+ return v == ((BMEdge *)e)->v1 ? &(((EdgeData *)e_data)->v1_disk_link) :
+ &(((EdgeData *)e_data)->v2_disk_link);
+}
+
+static bool rotsys_append_edge(BMEdge *e, BMVert *v,
+ EdgeData *edata, VertData *vdata)
+{
+ EdgeData *ed = &edata[BM_elem_index_get(e)];
+ VertData *vd = &vdata[BM_elem_index_get(v)];
+
+ if (!vd->e) {
+ Link *e1 = (Link *)rs_edge_link_get(e, v, ed);
+
+ vd->e = e;
+ e1->next = e1->prev = (Link *)e;
+ }
+ else {
+ BMDiskLink *dl1, *dl2, *dl3;
+ EdgeData *ved = &edata[BM_elem_index_get(vd->e)];
+
+ dl1 = rs_edge_link_get(e, v, ed);
+ dl2 = rs_edge_link_get(vd->e, v, ved);
+ dl3 = dl2->prev ? rs_edge_link_get(dl2->prev, v, &edata[BM_elem_index_get(dl2->prev)]) : NULL;
+
+ dl1->next = vd->e;
+ dl1->prev = dl2->prev;
+
+ dl2->prev = e;
+ if (dl3) {
+ dl3->next = e;
+ }
+ }
+
+ return true;
+}
+
+static void UNUSED_FUNCTION(rotsys_remove_edge)(BMEdge *e, BMVert *v,
+ EdgeData *edata, VertData *vdata)
+{
+ EdgeData *ed = edata + BM_elem_index_get(e);
+ VertData *vd = vdata + BM_elem_index_get(v);
+ BMDiskLink *e1, *e2;
+
+ e1 = rs_edge_link_get(e, v, ed);
+ if (e1->prev) {
+ e2 = rs_edge_link_get(e1->prev, v, ed);
+ e2->next = e1->next;
+ }
+
+ if (e1->next) {
+ e2 = rs_edge_link_get(e1->next, v, ed);
+ e2->prev = e1->prev;
+ }
+
+ if (vd->e == e)
+ vd->e = (e != e1->next) ? e1->next : NULL;
+
+ e1->next = e1->prev = NULL;
+}
+
+static BMEdge *rotsys_nextedge(BMEdge *e, BMVert *v,
+ EdgeData *edata, VertData *UNUSED(vdata))
+{
+ if (v == e->v1)
+ return edata[BM_elem_index_get(e)].v1_disk_link.next;
+ if (v == e->v2)
+ return edata[BM_elem_index_get(e)].v2_disk_link.next;
+ return NULL;
+}
+
+static BMEdge *rotsys_prevedge(BMEdge *e, BMVert *v,
+ EdgeData *edata, VertData *UNUSED(vdata))
+{
+ if (v == e->v1)
+ return edata[BM_elem_index_get(e)].v1_disk_link.prev;
+ if (v == e->v2)
+ return edata[BM_elem_index_get(e)].v2_disk_link.prev;
+ return NULL;
+}
+
+static void rotsys_reverse(BMEdge *UNUSED(e), BMVert *v, EdgeData *edata, VertData *vdata)
+{
+ BMEdge **edges = NULL;
+ BMEdge *e_first;
+ BMEdge *e;
+ BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
+ int i, totedge;
+
+ e = e_first = vdata[BM_elem_index_get(v)].e;
+ do {
+ BLI_array_append(edges, e);
+ e = rotsys_nextedge(e, v, edata, vdata);
+ } while (e != e_first);
+
+ totedge = BLI_array_count(edges);
+ for (i = 0; i < totedge / 2; i++) {
+ SWAP(BMEdge *, edges[i], edges[totedge - 1 - i]);
+ }
+
+ vdata[BM_elem_index_get(v)].e = NULL;
+ for (i = 0; i < totedge; i++) {
+ rotsys_append_edge(edges[i], v, edata, vdata);
+ }
+
+ BLI_array_free(edges);
+}
+
+static int UNUSED_FUNCTION(rotsys_count)(BMVert *v, EdgeData *edata, VertData *vdata)
+{
+ BMEdge *e = vdata[BM_elem_index_get(v)].e;
+ int i = 0;
+
+ if (!e)
+ return 0;
+
+ do {
+ if (!e)
+ return 0;
+ e = rotsys_nextedge(e, v, edata, vdata);
+
+ if (i >= (1 << 20)) {
+ printf("bmesh error: infinite loop in disk cycle!\n");
+ return 0;
+ }
+
+ i += 1;
+ } while (e != vdata[BM_elem_index_get(v)].e);
+
+ return i;
+}
+
+static int UNUSED_FUNCTION(rotsys_fill_faces)(BMesh *bm, EdgeData *edata, VertData *vdata)
+{
+ BMIter iter;
+ BMEdge *e, **edges = NULL;
+ BLI_array_declare(edges);
+ BMVert *v, **verts = NULL;
+ BMFace *f;
+ BLI_array_declare(verts);
+ SmallHash visithash, *hash = &visithash;
+ int i;
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BMEdge *e2, *starte;
+ BMVert *startv;
+ int rad, ok;
+
+ rad = count_edge_faces(bm, e);
+
+ if (rad < 2) {
+ starte = e;
+ }
+ else {
+ continue;
+ }
+
+ /* do two passes, going forward then backward */
+ for (i = 0; i < 2; i++) {
+ BLI_smallhash_init(hash);
+
+ BLI_array_empty(verts);
+ BLI_array_empty(edges);
+
+ startv = v = starte->v1;
+ e2 = starte;
+ ok = 1;
+ if (!v || !e2)
+ continue;
+
+ do {
+ if (BLI_smallhash_haskey(hash, (intptr_t)e2) ||
+ BLI_smallhash_haskey(hash, (intptr_t)v))
+ {
+ ok = 0;
+ break;
+ }
+
+ BLI_array_append(verts, v);
+ BLI_array_append(edges, e2);
+
+ BLI_smallhash_insert(hash, (intptr_t)e2, NULL);
+
+ v = BM_edge_other_vert(e2, v);
+ e2 = i ? rotsys_prevedge(e2, v, edata, vdata) : rotsys_nextedge(e2, v, edata, vdata);
+ } while (e2 != starte && v != startv);
+
+ BLI_smallhash_release(hash);
+
+ if (!ok || BLI_array_count(edges) < 3)
+ continue;
+
+ f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), BM_CREATE_NO_DOUBLE);
+ if (UNLIKELY(f == NULL)) {
+ continue;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void rotsys_make_consistent(BMesh *bm, EdgeData *edata, VertData *vdata)
+{
+ BMIter iter;
+ BMEdge *e;
+ BMVert *v, **stack = NULL;
+ BLI_array_declare(stack);
+ int i;
+
+ for (i = 0; i < bm->totvert; i++) {
+ vdata[i].tag = 0;
+ }
+
+ while (1) {
+ VertData *vd;
+ BMVert *startv = NULL;
+ float dis;
+
+ v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i = 0; i < bm->totvert; i++, BM_iter_step(&iter)) {
+ vd = vdata + BM_elem_index_get(v);
+
+ if (vd->tag)
+ continue;
+
+ if (!startv || dot_v3v3(vd->offco, vd->offco) > dis) {
+ dis = dot_v3v3(vd->offco, vd->offco);
+ startv = v;
+ }
+ }
+
+ if (!startv)
+ break;
+
+ vd = vdata + BM_elem_index_get(startv);
+
+ BLI_array_empty(stack);
+ BLI_array_append(stack, startv);
+
+ vd->tag = 1;
+
+ while (BLI_array_count(stack)) {
+ v = BLI_array_pop(stack);
+ vd = vdata + BM_elem_index_get(v);
+
+ if (!vd->e)
+ continue;
+
+ e = vd->e;
+ do {
+ BMVert *v2 = BM_edge_other_vert(e, v);
+ VertData *vd2 = vdata + BM_elem_index_get(v2);
+
+ if (dot_v3v3(vd->no, vd2->no) < 0.0f + FLT_EPSILON * 2) {
+ rotsys_reverse(e, v2, edata, vdata);
+ mul_v3_fl(vd2->no, -1.0f);
+ }
+
+ if (!vd2->tag) {
+ BLI_array_append(stack, v2);
+ vd2->tag = 1;
+ }
+
+ e = rotsys_nextedge(e, v, edata, vdata);
+ } while (e != vd->e);
+ }
+ }
+
+ BLI_array_free(stack);
+}
+
+static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata)
+{
+ BMIter iter;
+ BMEdge *e;
+ BMEdge **edges = NULL;
+ BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
+ BMVert *v;
+ /* BMVert **verts = NULL; */
+ /* BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); */ /* UNUSE */
+ int i;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BMIter eiter;
+ float no[3], cent[3];
+ int j, k = 0, totedge = 0;
+
+ if (BM_elem_index_get(v) == -1)
+ continue;
+
+ BLI_array_empty(edges);
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
+ BLI_array_append(edges, e);
+ totedge++;
+ }
+ }
+
+ copy_v3_v3(cent, v->co);
+
+ zero_v3(no);
+ for (i = 0; i < totedge; i++) {
+ BMEdge *e1, *e2;
+ float cno[3], vec1[3], vec2[3];
+
+ e1 = edges[i];
+ e2 = edges[(i + 1) % totedge];
+
+ sub_v3_v3v3(vec1, (BM_edge_other_vert(e1, v))->co, v->co);
+ sub_v3_v3v3(vec2, (BM_edge_other_vert(e2, v))->co, v->co);
+
+ cross_v3_v3v3(cno, vec1, vec2);
+ normalize_v3(cno);
+
+ if (i && dot_v3v3(cno, no) < 0.0f + FLT_EPSILON * 10)
+ mul_v3_fl(cno, -1.0f);
+
+ add_v3_v3(no, cno);
+ normalize_v3(no);
+ }
+
+ /* generate plane-flattened coordinates */
+ for (i = 0; i < totedge; i++) {
+ BMEdge *e1;
+ BMVert *v2;
+ float cvec[3], vec1[3];
+
+ e1 = edges[i];
+ v2 = BM_edge_other_vert(e1, v);
+
+ sub_v3_v3v3(vec1, v2->co, v->co);
+
+ cross_v3_v3v3(cvec, vec1, no);
+ cross_v3_v3v3(vec1, cvec, no);
+ normalize_v3(vec1);
+
+ mul_v3_fl(vec1, len_v3v3(v2->co, v->co));
+ add_v3_v3(vec1, v->co);
+
+ copy_v3_v3(vdata[BM_elem_index_get(v2)].sco, vec1);
+ }
+
+ BLI_srandom(0);
+
+ /* first, ensure no 0 or 180 angles between adjacent
+ * (and that adjacent's adjacent) edges */
+ for (i = 0, k = 0; i < totedge; i++) {
+ BMEdge *e1, *e2, *e3 = NULL;
+ BMVert *v1, *v2, *v3;
+ VertData *vd1, *vd2, *vd3;
+ float vec1[3], vec2[3], vec3[3], size;
+ int s1, s2, s3;
+
+ if (totedge < 3)
+ continue;
+
+ e1 = edges[(i + totedge - 1) % totedge];
+ e2 = edges[i];
+ e3 = edges[(i + 1) % totedge];
+
+ v1 = BM_edge_other_vert(e1, v);
+ v2 = BM_edge_other_vert(e2, v);
+ v3 = BM_edge_other_vert(e3, v);
+
+ vd1 = vdata + BM_elem_index_get(v1);
+ vd2 = vdata + BM_elem_index_get(v2);
+ vd3 = vdata + BM_elem_index_get(v3);
+
+ sub_v3_v3v3(vec1, vd1->sco, cent);
+ sub_v3_v3v3(vec2, vd2->sco, cent);
+ sub_v3_v3v3(vec3, vd3->sco, cent);
+
+ size = (len_v3(vec1) + len_v3(vec3)) * 0.01f;
+ normalize_v3(vec1); normalize_v3(vec2); normalize_v3(vec3);
+
+#ifdef STRAIGHT
+#undef STRAIGHT
+#endif
+#define STRAIGHT(vec11, vec22) (fabsf(dot_v3v3((vec11), (vec22))) > 1.0f - ((float)FLT_EPSILON * 1000.0f))
+
+ s1 = STRAIGHT(vec1, vec2); s2 = STRAIGHT(vec2, vec3); s3 = STRAIGHT(vec1, vec3);
+
+ if (s1 || s2 || s3) {
+ copy_v3_v3(cent, v->co);
+
+ for (j = 0; j < 3; j++) {
+ float fac = (BLI_frand() - 0.5f) * size;
+ cent[j] += fac;
+ }
+
+ if (k < 2000) {
+ i = 0;
+ k++;
+ continue;
+ }
+ else {
+ k++;
+ continue;
+ }
+
+ }
+ }
+
+ copy_v3_v3(vdata[BM_elem_index_get(v)].offco, cent);
+ //copy_v3_v3(v->co, cent);
+
+ /* now, sort edges so the triangle fan of all edges
+ * has a consistent normal. this is the same as
+ * sorting by polar coordinates along a group normal */
+ for (j = 0; j < totedge; j++) {
+ for (i = 0; i < totedge; i++) {
+ BMEdge *e1, *e2, *e3 = NULL;
+ BMVert *v1, *v2, *v3;
+ VertData *vd1, *vd2, *vd3;
+ float vec1[3], vec2[3], vec3[3], n1[3], n2[3], n3[3];
+
+ e1 = edges[(i + totedge - 1) % totedge];
+ e2 = edges[i];
+ e3 = edges[(i + 1) % totedge];
+
+ v1 = BM_edge_other_vert(e1, v);
+ v2 = BM_edge_other_vert(e2, v);
+ v3 = BM_edge_other_vert(e3, v);
+
+ vd1 = vdata + BM_elem_index_get(v1);
+ vd2 = vdata + BM_elem_index_get(v2);
+ vd3 = vdata + BM_elem_index_get(v3);
+
+ sub_v3_v3v3(vec1, vd1->sco, cent);
+ sub_v3_v3v3(vec2, vd2->sco, cent);
+ sub_v3_v3v3(vec3, vd3->sco, cent);
+
+ cross_v3_v3v3(n1, vec1, vec2);
+ cross_v3_v3v3(n2, vec2, vec3);
+ cross_v3_v3v3(n3, vec1, vec3);
+
+ /* this case happens often enough and probably not worth bothering users with,
+ * maybe enable for debugging code but not for everyday use - campbell */
+#if 0
+ /* Other way to determine if two vectors approach are (nearly) parallel: the
+ * cross product of the two vectors will approach zero */
+ {
+ int s1, s2, s3;
+ s1 = (dot_v3v3(n1, n1) < (0.0f + FLT_EPSILON * 10));
+ s2 = (dot_v3v3(n2, n2) < (0.0f + FLT_EPSILON * 10));
+ s3 = (totedge < 3) ? 0 : (dot_v3v3(n3, n3) < (0.0f + FLT_EPSILON * 10));
+
+ if (s1 || s2 || s3) {
+ fprintf(stderr, "%s: s1: %d, s2: %d, s3: %dx (bmesh internal error)\n", __func__, s1, s2, s3);
+ }
+ }
+#endif
+
+ normalize_v3(n1); normalize_v3(n2); normalize_v3(n3);
+
+
+ if (dot_v3v3(n1, n2) < 0.0f) {
+ if (dot_v3v3(n1, n3) >= 0.0f + FLT_EPSILON * 10) {
+ SWAP(BMEdge *, edges[i], edges[(i + 1) % totedge]);
+ }
+ else {
+ SWAP(BMEdge *, edges[(i + totedge - 1) % totedge], edges[(i + 1) % totedge]);
+ SWAP(BMEdge *, edges[i], edges[(i + 1) % totedge]);
+ }
+ }
+ }
+ }
+
+#undef STRAIGHT
+
+ zero_v3(no);
+
+ /* yay, edges are sorted */
+ for (i = 0; i < totedge; i++) {
+ BMEdge *e1 = edges[i], *e2 = edges[(i + 1) % totedge];
+ float eno[3];
+
+ normal_tri_v3(eno, BM_edge_other_vert(e1, v)->co, v->co, BM_edge_other_vert(e2, v)->co);
+ add_v3_v3(no, eno);
+
+ rotsys_append_edge(edges[i], v, edata, vdata);
+ }
+
+ normalize_v3(no);
+ copy_v3_v3(vdata[BM_elem_index_get(v)].no, no);
+ }
+
+ /* now, make sure rotation system is topologically consistent
+ * (e.g. vert normals consistently point either inside or outside) */
+ rotsys_make_consistent(bm, edata, vdata);
+
+ //rotsys_fill_faces(bm, edata, vdata);
+
+#if 0
+ /* create visualizing geometry */
+ BMVert *lastv;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BMVert *v2;
+ BMFace *f;
+ int totedge = BM_vert_edge_count(v);
+
+ if (BM_elem_index_get(v) == -1)
+ continue;
+
+ //cv = BM_vert_create(bm, cent, v);
+ //BM_elem_index_set(cv, -1); /* set_dirty! */
+ i = 0;
+ e = vdata[BM_elem_index_get(v)].e;
+ lastv = NULL;
+ do {
+ BMEdge *e2;
+ BMVert *v2;
+ float f = ((float)i / (float)totedge) * 0.35 + 0.05;
+ float co[3];
+
+ if (!e)
+ break;
+
+ if (!BM_edge_other_vert(e, v))
+ continue;
+
+ sub_v3_v3v3(co, (BM_edge_other_vert(e, v))->co, vdata[BM_elem_index_get(v)].offco);
+ mul_v3_fl(co, f);
+ add_v3_v3(co, vdata[BM_elem_index_get(v)].offco);
+
+ v2 = BM_vert_create(bm, co, NULL);
+ BM_elem_index_set(v2, -1); /* set_dirty! */
+ //BM_edge_create(bm, cv, v2, NULL, 0);
+
+ BM_vert_select_set(bm, v2, true);
+ if (lastv) {
+ e2 = BM_edge_create(bm, lastv, v2, NULL, 0);
+ BM_edge_select_set(bm, e2, true);
+ }
+
+ lastv = v2;
+
+ e = rotsys_nextedge(e, v, edata, vdata);
+ i++;
+ } while (e != vdata[BM_elem_index_get(v)].e);
+ }
+#endif
+
+ BLI_array_free(edges);
+}
+
+static PathBase *edge_pathbase_new(void)
+{
+ PathBase *pb = MEM_callocN(sizeof(PathBase), "PathBase");
+
+ pb->nodepool = BLI_mempool_create(sizeof(EPathNode), 1, 512, BLI_MEMPOOL_SYSMALLOC);
+ pb->pathpool = BLI_mempool_create(sizeof(EPath), 1, 512, BLI_MEMPOOL_SYSMALLOC);
+
+ return pb;
+}
+
+static void edge_pathbase_free(PathBase *pathbase)
+{
+ BLI_mempool_destroy(pathbase->nodepool);
+ BLI_mempool_destroy(pathbase->pathpool);
+ MEM_freeN(pathbase);
+}
+
+static EPath *edge_copy_add_path(PathBase *pb, EPath *path, BMVert *appendv, BMEdge *e)
+{
+ EPath *path2;
+ EPathNode *node, *node2;
+
+ path2 = BLI_mempool_alloc(pb->pathpool);
+ path2->nodes.first = path2->nodes.last = NULL;
+ path2->weight = 0.0f;
+ path2->group = path->group;
+
+ for (node = path->nodes.first; node; node = node->next) {
+ node2 = BLI_mempool_alloc(pb->nodepool);
+ *node2 = *node;
+ BLI_addtail(&path2->nodes, node2);
+ }
+
+ node2 = BLI_mempool_alloc(pb->nodepool);
+ node2->v = appendv;
+ node2->e = e;
+ node2->cure = NULL;
+
+ BLI_addtail(&path2->nodes, node2);
+
+ return path2;
+}
+
+static EPath *edge_path_new(PathBase *pb, BMVert *start, BMEdge *starte)
+{
+ EPath *path;
+ EPathNode *node;
+
+ path = BLI_mempool_alloc(pb->pathpool);
+ node = BLI_mempool_alloc(pb->nodepool);
+
+ path->nodes.first = path->nodes.last = NULL;
+
+ node->v = start;
+ node->e = starte;
+ node->cure = NULL;
+
+ BLI_addtail(&path->nodes, node);
+ path->weight = 0.0f;
+
+ return path;
+}
+
+static float edge_weight_path(EPath *path, EdgeData *edata, VertData *UNUSED(vdata))
+{
+ EPathNode *node, *first = path->nodes.first;
+ float w = 0.0;
+
+ for (node = path->nodes.first; node; node = node->next) {
+ if (node->e && node != path->nodes.first) {
+ w += edata[BM_elem_index_get(node->e)].ftag;
+ if (node->prev) {
+ /* BMESH_TOD */
+ (void)first;
+ //w += len_v3v3(node->v->co, first->e->v1->co) * 0.0001f;
+ //w += len_v3v3(node->v->co, first->e->v2->co) * 0.0001f;
+ }
+ }
+
+ w += 1.0f;
+ }
+
+ return w;
+}
+
+
+static void edge_free_path(PathBase *pathbase, EPath *path)
+{
+ EPathNode *node, *next;
+
+ for (node = path->nodes.first; node; node = next) {
+ next = node->next;
+ BLI_mempool_free(pathbase->nodepool, node);
+ }
+
+ BLI_mempool_free(pathbase->pathpool, path);
+}
+
+static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, EdgeData *edata,
+ VertData *vdata, PathBase *pathbase, int group)
+{
+ BMEdge *e;
+ GHash *gh = BLI_ghash_ptr_new("createops find shortest path");
+ BMVert *v1, *v2;
+ BMVert **verts = NULL;
+ BLI_array_staticdeclare(verts, 1024);
+ Heap *heap = BLI_heap_new();
+ EPath *path = NULL, *path2;
+ BMVert *startv;
+ BMVert *endv;
+ EPathNode *node;
+ int i;
+ const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
+ BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
+
+
+ startv = edata[BM_elem_index_get(edge)].ftag ? edge->v2 : edge->v1;
+ endv = edata[BM_elem_index_get(edge)].ftag ? edge->v1 : edge->v2;
+
+ path = edge_path_new(pathbase, startv, edge);
+ BLI_ghash_insert(gh, startv, NULL);
+ BLI_heap_insert(heap, path->weight, path);
+ path->group = group;
+
+ while (BLI_heap_size(heap)) {
+ VertData *vd;
+ EPathNode *last;
+ BMFace *f = NULL;
+
+ path = BLI_heap_popmin(heap);
+ last = path->nodes.last;
+ v1 = last->v;
+
+ if (v1 == endv) {
+ /* make sure this path loop doesn't already exists */
+ i = 0;
+ BLI_array_empty(verts);
+ for (i = 0, node = path->nodes.first; node; node = node->next, i++) {
+ BLI_array_grow_one(verts);
+ verts[i] = node->v;
+ }
+
+ if (BM_face_exists(verts, i, &f)) {
+ if (!BMO_elem_flag_test(bm, f, FACE_IGNORE)) {
+ BLI_ghash_remove(gh, endv, NULL, NULL);
+ continue;
+ }
+ }
+ break;
+ }
+
+ vd = vdata + BM_elem_index_get(v1);
+ if (!vd->e)
+ continue;
+
+ v2 = NULL;
+ while (1) {
+ if (!last->cure) {
+ last->cure = e = vdata[BM_elem_index_get(last->v)].e;
+ }
+ else {
+ last->cure = e = rotsys_nextedge(last->cure, last->v, edata, vdata);
+ if (last->cure == vdata[BM_elem_index_get(last->v)].e) {
+ v2 = NULL;
+ break;
+ }
+ }
+
+ if (e == edge || !BMO_elem_flag_test(bm, e, EDGE_MARK)) {
+ continue;
+ }
+
+ v2 = BM_edge_other_vert(e, last->v);
+
+ if (BLI_ghash_haskey(gh, v2)) {
+ v2 = NULL;
+ continue;
+ }
+
+ if (use_restrict) {
+ int *group_flag = (int *)BMO_slot_map_data_get(slot_restrict, e);
+ if (group_flag) {
+ if (!(*group_flag & path->group)) {
+ v2 = NULL;
+ continue;
+ }
+ }
+ }
+
+ break;
+ }
+
+ if (!v2) {
+ if (path) {
+ edge_free_path(pathbase, path);
+ path = NULL;
+ }
+ continue;
+ }
+
+ /* add path back into heap */
+ BLI_heap_insert(heap, path->weight, path);
+
+ /* put v2 in gh ma */
+ BLI_ghash_insert(gh, v2, NULL);
+
+ path2 = edge_copy_add_path(pathbase, path, v2, e);
+ path2->weight = edge_weight_path(path2, edata, vdata);
+
+ BLI_heap_insert(heap, path2->weight, path2);
+ }
+
+ if (path && ((EPathNode *)path->nodes.last)->v != endv) {
+ edge_free_path(pathbase, path);
+ path = NULL;
+ }
+
+ BLI_array_free(verts);
+ BLI_heap_free(heap, NULL);
+ BLI_ghash_free(gh, NULL, NULL);
+
+ return path;
+}
+
+static int count_edge_faces(BMesh *bm, BMEdge *e)
+{
+ int i = 0;
+ BMLoop *l = e->l;
+
+ if (!l) {
+ return 0;
+ }
+
+ do {
+ if (!BMO_elem_flag_test(bm, l->f, FACE_IGNORE)) {
+ i++;
+ }
+
+ l = l->radial_next;
+ } while (l != e->l);
+
+ return i;
+}
+
+BLI_INLINE void vote_on_winding(BMEdge *edge, EPathNode *node, unsigned int winding[2])
+{
+ BMVert *test_v1, *test_v2;
+ /* we want to use the reverse winding to the existing order */
+ BM_edge_ordered_verts(edge, &test_v2, &test_v1);
+
+ /* edges vote on which winding wins out */
+ winding[(test_v1 == node->v)]++;
+}
+
+void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter iter;
+ BMOIter siter;
+ BMFace *f;
+ BMEdge *e;
+ BMVert **verts = NULL;
+ BLI_array_declare(verts);
+ EPath *path;
+ EPathNode *node;
+ EdgeData *edata;
+ VertData *vdata;
+ BMEdge **edges = NULL;
+ PathBase *pathbase;
+ BLI_array_declare(edges);
+ const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
+ const bool use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check");
+ const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
+ const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+ int i, j;
+ unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */
+ BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
+ BMOpSlot *slot_face_groupmap_out = BMO_slot_get(op->slots_out, "face_groupmap.out");
+
+ if (!bm->totvert || !bm->totedge)
+ return;
+
+ pathbase = edge_pathbase_new();
+
+ edata = MEM_callocN(sizeof(EdgeData) * bm->totedge, "EdgeData");
+ vdata = MEM_callocN(sizeof(VertData) * bm->totvert, "VertData");
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "exclude_faces", BM_FACE, FACE_IGNORE);
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BMO_elem_flag_enable(bm, f, ELE_ORIG);
+ }
+
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ BM_elem_index_set(e, i); /* set_inline */
+
+ if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) {
+ edata[i].tag = 2;
+ }
+ }
+ bm->elem_index_dirty &= ~BM_EDGE;
+
+ init_rotsys(bm, edata, vdata);
+
+ while (1) {
+ BMEdge *edge = NULL;
+ int group = 0;
+
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ /* if restrict is on, only start on faces in the restrict map */
+ if (use_restrict && !BMO_slot_map_contains(slot_restrict, e))
+ continue;
+
+ if (edata[BM_elem_index_get(e)].tag < 2) {
+ edge = e;
+
+ if (use_restrict) {
+ int gi_iter = 0, gi_count = 0, gi = 0;
+
+ group = BMO_slot_map_int_get(slot_restrict, e);
+
+ for (gi_iter = 0; gi_iter < 30; gi_iter++) {
+ if (group & (1 << gi_iter)) {
+ gi_count++;
+ gi = gi_iter;
+
+ if (gi_count - 1 == edata[BM_elem_index_get(e)].tag) {
+ break;
+ }
+ }
+ }
+
+ group = (1 << gi);
+ }
+
+ break;
+ }
+ }
+
+ if (!edge)
+ break;
+
+ edata[BM_elem_index_get(edge)].tag += 1;
+
+ path = edge_find_shortest_path(bm, op, edge, edata, vdata, pathbase, group);
+ if (!path)
+ continue;
+
+ winding[0] = winding[1] = 0;
+
+ BLI_array_empty(edges);
+ BLI_array_empty(verts);
+ i = 0;
+ for (node = path->nodes.first; node; node = node->next) {
+ if (!node->next)
+ continue;
+
+ e = BM_edge_exists(node->v, node->next->v);
+
+ /* this should never happe */
+ if (!e)
+ break;
+
+ /* check on the winding */
+ if (e->l) {
+ vote_on_winding(e, node, winding);
+ }
+
+ edata[BM_elem_index_get(e)].ftag++;
+ BLI_array_grow_one(edges);
+ edges[i++] = e;
+
+ BLI_array_append(verts, node->v);
+ }
+
+ if (edge->l) {
+ vote_on_winding(edge, path->nodes.last, winding);
+ }
+
+ BLI_array_grow_one(edges);
+ edges[i++] = edge;
+ edata[BM_elem_index_get(edge)].ftag++;
+
+ for (j = 0; j < i; j++) {
+ if (count_edge_faces(bm, edges[j]) >= 2) {
+ edge_free_path(pathbase, path);
+ break;
+ }
+ }
+
+ if (j != i) {
+ continue;
+ }
+
+ if (i) {
+ BMVert *v1, *v2;
+
+ /* to define the winding order must select first edge,
+ * otherwise we could leave this as-is */
+ edge = edges[0];
+
+ /* if these are even it doesn't really matter what to do,
+ * with consistent geometry one will be zero, the choice is clear */
+ if (winding[0] < winding[1]) {
+ v1 = verts[0];
+ v2 = verts[1];
+ }
+ else {
+ v1 = verts[1];
+ v2 = verts[0];
+ }
+
+ if ((use_fill_check == false) ||
+ /* fairly expensive check - see if there are already faces filling this area */
+ (BM_face_exists_multi_edge(edges, i) == false))
+ {
+ f = BM_face_create_ngon(bm, v1, v2, edges, i, BM_CREATE_NO_DOUBLE);
+ if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) {
+ BMO_elem_flag_enable(bm, f, FACE_NEW);
+ f->mat_nr = mat_nr;
+ if (use_smooth) {
+ BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
+ }
+ }
+
+ if (use_restrict) {
+ BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group);
+ }
+ }
+ }
+
+ edge_free_path(pathbase, path);
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW);
+
+ BLI_array_free(edges);
+ BLI_array_free(verts);
+ edge_pathbase_free(pathbase);
+ MEM_freeN(edata);
+ MEM_freeN(vdata);
+}
+
+static BMEdge *edge_next(BMesh *bm, BMEdge *e)
+{
+ BMIter iter;
+ BMEdge *e2;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ BM_ITER_ELEM (e2, &iter, i ? e->v2 : e->v1, BM_EDGES_OF_VERT) {
+ if ((BMO_elem_flag_test(bm, e2, EDGE_MARK)) &&
+ (!BMO_elem_flag_test(bm, e2, EDGE_VIS)) &&
+ (e2 != e))
+ {
+ return e2;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMEdge *e;
+ BMEdge **edges1 = NULL, **edges2 = NULL, **edges;
+ BLI_array_declare(edges1);
+ BLI_array_declare(edges2);
+ BLI_array_declare(edges);
+ int ok = 1;
+ int i, count;
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
+
+ /* validate that each edge has at most one other tagged edge in the
+ * disk cycle around each of it's vertices */
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ for (i = 0; i < 2; i++) {
+ count = BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, (i ? e->v2 : e->v1), EDGE_MARK, true);
+ if (count > 2) {
+ ok = 0;
+ break;
+ }
+ }
+
+ if (!ok) {
+ break;
+ }
+ }
+
+ /* we don't have valid edge layouts, retur */
+ if (!ok) {
+ return;
+ }
+
+ /* find connected loops within the input edge */
+ count = 0;
+ while (1) {
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ if (!BMO_elem_flag_test(bm, e, EDGE_VIS)) {
+ if (BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, e->v1, EDGE_MARK, true) == 1 ||
+ BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, e->v2, EDGE_MARK, true) == 1)
+ {
+ break;
+ }
+ }
+ }
+
+ if (!e) {
+ break;
+ }
+
+ if (!count) {
+ edges = edges1;
+ }
+ else if (count == 1) {
+ edges = edges2;
+ }
+ else {
+ break;
+ }
+
+ i = 0;
+ while (e) {
+ BMO_elem_flag_enable(bm, e, EDGE_VIS);
+ BLI_array_grow_one(edges);
+ edges[i] = e;
+
+ e = edge_next(bm, e);
+ i++;
+ }
+
+ if (!count) {
+ edges1 = edges;
+ BLI_array_length_set(edges1, BLI_array_count(edges));
+ }
+ else {
+ edges2 = edges;
+ BLI_array_length_set(edges2, BLI_array_count(edges));
+ }
+
+ BLI_array_empty(edges);
+ count++;
+ }
+
+ if (edges1 && BLI_array_count(edges1) > 2 &&
+ BM_edge_share_vert_check(edges1[0], edges1[BLI_array_count(edges1) - 1]))
+ {
+ if (edges2 && BLI_array_count(edges2) > 2 &&
+ BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1]))
+ {
+ BLI_array_free(edges1);
+ BLI_array_free(edges2);
+ return;
+ }
+ else {
+ edges1 = edges2;
+ edges2 = NULL;
+ }
+ }
+
+ if (edges2 && BLI_array_count(edges2) > 2 &&
+ BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1]))
+ {
+ edges2 = NULL;
+ }
+
+ /* two unconnected loops, connect the */
+ if (edges1 && edges2) {
+ BMVert *v1, *v2, *v3, *v4;
+ float dvec1[3];
+ float dvec2[3];
+
+ if (BLI_array_count(edges1) == 1) {
+ v1 = edges1[0]->v1;
+ v2 = edges1[0]->v2;
+ }
+ else {
+ v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
+ i = BLI_array_count(edges1) - 1;
+ v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
+ }
+
+ if (BLI_array_count(edges2) == 1) {
+ v3 = edges2[0]->v1;
+ v4 = edges2[0]->v2;
+ }
+ else {
+ v3 = BM_vert_in_edge(edges2[1], edges2[0]->v1) ? edges2[0]->v2 : edges2[0]->v1;
+ i = BLI_array_count(edges2) - 1;
+ v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1;
+ }
+
+ /* if there is ever bow-tie quads between two edges the problem is here! [#30367] */
+#if 0
+ normal_tri_v3(dvec1, v1->co, v2->co, v4->co);
+ normal_tri_v3(dvec2, v1->co, v4->co, v3->co);
+#else
+ {
+ /* save some CPU cycles and skip the sqrt and 1 subtraction */
+ float a1[3], a2[3], a3[3];
+ sub_v3_v3v3(a1, v1->co, v2->co);
+ sub_v3_v3v3(a2, v1->co, v4->co);
+ sub_v3_v3v3(a3, v1->co, v3->co);
+ cross_v3_v3v3(dvec1, a1, a2);
+ cross_v3_v3v3(dvec2, a2, a3);
+ }
+#endif
+ if (dot_v3v3(dvec1, dvec2) < 0.0f) {
+ SWAP(BMVert *, v3, v4);
+ }
+
+ e = BM_edge_create(bm, v1, v3, NULL, BM_CREATE_NO_DOUBLE);
+ BMO_elem_flag_enable(bm, e, ELE_NEW);
+ e = BM_edge_create(bm, v2, v4, NULL, BM_CREATE_NO_DOUBLE);
+ BMO_elem_flag_enable(bm, e, ELE_NEW);
+ }
+ else if (edges1) {
+ BMVert *v1, *v2;
+
+ if (BLI_array_count(edges1) > 1) {
+ v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
+ i = BLI_array_count(edges1) - 1;
+ v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
+ e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE);
+ BMO_elem_flag_enable(bm, e, ELE_NEW);
+ }
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW);
+
+ BLI_array_free(edges1);
+ BLI_array_free(edges2);
+}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index e4c7a1edbcb..ad32c5fcccf 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -43,6 +43,8 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "DNA_anim_types.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
@@ -229,7 +231,7 @@ static int gp_data_add_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (*gpd_ptr);
id_us_min(&gpd->id);
- *gpd_ptr = gpencil_data_addnew("GPencil");
+ *gpd_ptr = gpencil_data_addnew(DATA_("GPencil"));
}
/* notifiers */
@@ -312,10 +314,10 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
if (*gpd_ptr == NULL)
- *gpd_ptr = gpencil_data_addnew("GPencil");
-
+ *gpd_ptr = gpencil_data_addnew(DATA_("GPencil"));
+
/* add new layer now */
- gpencil_layer_addnew(*gpd_ptr, "GP_Layer", 1);
+ gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), 1);
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt
index b858d715cfe..f628b2bb210 100644
--- a/source/blender/editors/render/CMakeLists.txt
+++ b/source/blender/editors/render/CMakeLists.txt
@@ -75,4 +75,8 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
blender_add_lib(bf_editor_render "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript
index 25af8080d51..4c5da4dc78a 100644
--- a/source/blender/editors/render/SConscript
+++ b/source/blender/editors/render/SConscript
@@ -35,6 +35,8 @@ incs += ' ../../gpu'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
incs += ' ../../blenloader ../../bmesh ../../blenfont'
+defs = []
+
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
incs += ' ../../../extern/binreloc/include'
@@ -57,4 +59,7 @@ if env['OURPLATFORM'] == 'darwin':
if env['WITH_BF_OPENMP']:
env.Append(CFLAGS=['-DPARALLEL=1'])
-env.BlenderLib ( 'bf_editors_render', sources, Split(incs), [], libtype=['core'], priority=[45])
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+
+env.BlenderLib('bf_editors_render', sources, Split(incs), defs, libtype=['core'], priority=[45])
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 87d83f820c9..5652d4c4b71 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -435,10 +435,12 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
PropertyRNA *prop;
/* add or copy texture */
- if (tex)
+ if (tex) {
tex = BKE_texture_copy(tex);
- else
+ }
+ else {
tex = add_texture(bmain, DATA_("Texture"));
+ }
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
@@ -487,7 +489,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
wo = BKE_world_copy(wo);
}
else {
- wo = add_world(bmain, "World");
+ wo = add_world(bmain, DATA_("World"));
if (BKE_scene_use_new_shading_nodes(scene)) {
ED_node_shader_default(C, &wo->id);
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 9bc232c6a61..a45209de643 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -345,6 +345,7 @@ static void brush_painter_2d_refresh_cache(BrushPainter *painter, const float po
const int diameter = 2 * BKE_brush_size_get(scene, brush);
const float alpha = BKE_brush_alpha_get(scene, brush);
const bool do_tiled = ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_3D);
+ const bool do_random = brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM;
float rotation = -mtex->rot;
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
@@ -354,7 +355,8 @@ static void brush_painter_2d_refresh_cache(BrushPainter *painter, const float po
if (diameter != cache->lastsize ||
alpha != cache->lastalpha ||
brush->jitter != cache->lastjitter ||
- rotation != cache->last_rotation)
+ rotation != cache->last_rotation ||
+ do_random)
{
if (cache->ibuf) {
IMB_freeImBuf(cache->ibuf);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index d7e2d010f03..ca48524096a 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -188,13 +188,10 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
ups->brush_rotation = 0.0f;
}
- if ((brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)) {
- ups->tex_mouse[0] = BLI_frand() * stroke->vc.ar->sizex;
- ups->tex_mouse[1] = BLI_frand() * stroke->vc.ar->sizey;;
- }
- else {
+ if ((brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM))
+ BKE_brush_randomize_texture_coordinates(ups);
+ else
copy_v2_v2(ups->tex_mouse, mouse);
- }
}
if (brush->flag & BRUSH_ANCHORED) {
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 95d43fd334e..072ea504b9f 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -1073,6 +1073,7 @@ void buttons_context_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
strcpy(pt->idname, "BUTTONS_PT_context");
strcpy(pt->label, N_("Context")); /* XXX C panels are not available through RNA (bpy.types)! */
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = buttons_panel_context;
pt->flag = PNL_NO_HEADER;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 9409ce42d3a..8d863193b76 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -79,7 +79,8 @@ void ED_clip_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype clip panel gpencil");
strcpy(pt->idname, "CLIP_PT_gpencil");
- strcpy(pt->label, "Grease Pencil");
+ strcpy(pt->label, N_("Grease Pencil"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
pt->flag |= PNL_DEFAULT_CLOSED;
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 05e05b95967..b00cc564a99 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -1142,6 +1142,9 @@ static bool prefetch_check_early_out(const bContext *C)
if ((user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) == 0)
return true;
}
+ else {
+ return true;
+ }
}
clip_len = BKE_movieclip_get_duration(clip);
diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c
index 10175d07300..42300f88a4f 100644
--- a/source/blender/editors/space_clip/clip_toolbar.c
+++ b/source/blender/editors/space_clip/clip_toolbar.c
@@ -257,7 +257,8 @@ void ED_clip_tool_props_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype clip panel last operator");
strcpy(pt->idname, "CLIP_PT_last_operator");
- strcpy(pt->label, "Operator");
+ strcpy(pt->label, N_("Operator"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = clip_panel_operator_redo_header;
pt->draw = clip_panel_operator_redo;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 9a7f528be78..35179511563 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -219,30 +219,35 @@ void file_panels_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype file system directories");
strcpy(pt->idname, "FILE_PT_system");
strcpy(pt->label, N_("System"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = file_panel_system;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype file system bookmarks");
strcpy(pt->idname, "FILE_PT_system_bookmarks");
strcpy(pt->label, N_("System Bookmarks"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = file_panel_system_bookmarks;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype file bookmarks");
strcpy(pt->idname, "FILE_PT_bookmarks");
strcpy(pt->label, N_("Bookmarks"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = file_panel_bookmarks;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype file recent directories");
strcpy(pt->idname, "FILE_PT_recent");
strcpy(pt->label, N_("Recent"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = file_panel_recent;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype file operator properties");
strcpy(pt->idname, "FILE_PT_operator");
strcpy(pt->label, N_("Operator"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->poll = file_panel_operator_poll;
pt->draw_header = file_panel_operator_header;
pt->draw = file_panel_operator;
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index f1501857b13..f7ec8e8682d 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -803,6 +803,7 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel view");
strcpy(pt->idname, "GRAPH_PT_view");
strcpy(pt->label, N_("View Properties"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_view;
pt->flag |= PNL_DEFAULT_CLOSED;
BLI_addtail(&art->paneltypes, pt);
@@ -810,6 +811,7 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties");
strcpy(pt->idname, "GRAPH_PT_properties");
strcpy(pt->label, N_("Active F-Curve"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_properties;
pt->poll = graph_panel_poll;
BLI_addtail(&art->paneltypes, pt);
@@ -817,6 +819,7 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel properties");
strcpy(pt->idname, "GRAPH_PT_key_properties");
strcpy(pt->label, N_("Active Keyframe"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_key_properties;
pt->poll = graph_panel_poll;
BLI_addtail(&art->paneltypes, pt);
@@ -825,6 +828,7 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel drivers");
strcpy(pt->idname, "GRAPH_PT_drivers");
strcpy(pt->label, N_("Drivers"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_drivers;
pt->poll = graph_panel_drivers_poll;
BLI_addtail(&art->paneltypes, pt);
@@ -832,6 +836,7 @@ void graph_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype graph panel modifiers");
strcpy(pt->idname, "GRAPH_PT_modifiers");
strcpy(pt->label, N_("Modifiers"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = graph_panel_modifiers;
pt->poll = graph_panel_poll;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 70001b59528..5398f886396 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -880,7 +880,8 @@ void image_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
strcpy(pt->idname, "IMAGE_PT_gpencil");
- strcpy(pt->label, "Grease Pencil");
+ strcpy(pt->label, N_("Grease Pencil"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 7e0767bfcfb..4a78c54e9c0 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1707,6 +1707,7 @@ void IMAGE_OT_reload(wmOperatorType *ot)
}
/********************** new image operator *********************/
+#define IMA_DEF_NAME N_("Untitled")
static int image_new_exec(bContext *C, wmOperator *op)
{
@@ -1717,7 +1718,8 @@ static int image_new_exec(bContext *C, wmOperator *op)
Main *bmain;
PointerRNA ptr, idptr;
PropertyRNA *prop;
- char name[MAX_ID_NAME - 2];
+ char _name[MAX_ID_NAME - 2];
+ char *name = _name;
float color[4];
int width, height, floatbuf, gen_type, alpha;
@@ -1727,7 +1729,12 @@ static int image_new_exec(bContext *C, wmOperator *op)
obedit = CTX_data_edit_object(C);
bmain = CTX_data_main(C);
- RNA_string_get(op->ptr, "name", name);
+ prop = RNA_struct_find_property(op->ptr, "name");
+ RNA_property_string_get(op->ptr, prop, name);
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ /* Default value, we can translate! */
+ name = (char *)DATA_(name);
+ }
width = RNA_int_get(op->ptr, "width");
height = RNA_int_get(op->ptr, "height");
floatbuf = RNA_boolean_get(op->ptr, "float");
@@ -1775,8 +1782,9 @@ static int image_new_exec(bContext *C, wmOperator *op)
/* XXX Note: the WM_operator_props_dialog_popup() doesn't work for uiIDContextProperty(), image is not being that way */
static int image_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
+ /* Better for user feedback. */
+ RNA_string_set(op->ptr, "name", DATA_(IMA_DEF_NAME));
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y);
-
}
void IMAGE_OT_new(wmOperatorType *ot)
@@ -1797,7 +1805,7 @@ void IMAGE_OT_new(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
/* properties */
- RNA_def_string(ot->srna, "name", "untitled", MAX_ID_NAME - 2, "Name", "Image datablock name");
+ RNA_def_string(ot->srna, "name", IMA_DEF_NAME, MAX_ID_NAME - 2, "Name", "Image datablock name");
RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
prop = RNA_def_float_color(ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
@@ -1809,6 +1817,8 @@ void IMAGE_OT_new(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
}
+#undef IMA_DEF_NAME
+
/********************* invert operators *********************/
static int image_invert_poll(bContext *C)
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index 1577ac338e7..a3eb7c06876 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -300,6 +300,7 @@ static void recent_files_menu_register(void)
mt = MEM_callocN(sizeof(MenuType), "spacetype info menu recent files");
strcpy(mt->idname, "INFO_MT_file_open_recent");
strcpy(mt->label, N_("Open Recent..."));
+ strcpy(mt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = recent_files_menu_draw;
WM_menutype_add(mt);
}
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index b26d1662f6c..3a9336e7acc 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -502,7 +502,8 @@ void nla_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel animdata");
strcpy(pt->idname, "NLA_PT_animdata");
- strcpy(pt->label, "Animation Data");
+ strcpy(pt->label, N_("Animation Data"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_animdata;
pt->poll = nla_animdata_panel_poll;
pt->flag = PNL_DEFAULT_CLOSED;
@@ -510,35 +511,40 @@ void nla_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel track");
strcpy(pt->idname, "NLA_PT_track");
- strcpy(pt->label, "Active Track");
+ strcpy(pt->label, N_("Active Track"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_track;
pt->poll = nla_track_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_properties");
- strcpy(pt->label, "Active Strip");
+ strcpy(pt->label, N_("Active Strip"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_properties;
pt->poll = nla_strip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_actionclip");
- strcpy(pt->label, "Action Clip");
+ strcpy(pt->label, N_("Action Clip"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_actclip;
pt->poll = nla_strip_actclip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
strcpy(pt->idname, "NLA_PT_evaluation");
- strcpy(pt->label, "Evaluation");
+ strcpy(pt->label, N_("Evaluation"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_evaluation;
pt->poll = nla_strip_eval_panel_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
strcpy(pt->idname, "NLA_PT_modifiers");
- strcpy(pt->label, "Modifiers");
+ strcpy(pt->label, N_("Modifiers"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_modifiers;
pt->poll = nla_strip_eval_panel_poll;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index fb9e1221c38..0201071ada4 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -83,7 +83,7 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx
/* generics */
node->locx = locx;
- node->locy = locy + 60.0f; // arbitrary.. so its visible, (0,0) is top of node
+ node->locy = locy + 60.0f; /* arbitrary... so its visible, (0,0) is top of node */
nodeSetSelected(node, TRUE);
/* node location is mapped */
@@ -436,7 +436,8 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
PointerRNA ptr, idptr;
PropertyRNA *prop;
const char *idname;
- char treename[MAX_ID_NAME - 2] = "NodeTree";
+ char _treename[MAX_ID_NAME - 2];
+ char *treename = _treename;
if (RNA_struct_property_is_set(op->ptr, "type")) {
prop = RNA_struct_find_property(op->ptr, "type");
@@ -445,8 +446,12 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
else if (snode)
idname = snode->tree_idname;
- if (RNA_struct_property_is_set(op->ptr, "name"))
+ if (RNA_struct_property_is_set(op->ptr, "name")) {
RNA_string_get(op->ptr, "name", treename);
+ }
+ else {
+ treename = (char *)DATA_("NodeTree");
+ }
if (!ntreeTypeFind(idname)) {
BKE_reportf(op->reports, RPT_ERROR, "Node tree type %s undefined", idname);
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index efdb7c0d85d..d0a77e273f0 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -211,13 +211,13 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
split = uiLayoutRow(row, TRUE);
col = uiLayoutColumn(split, TRUE);
- uiItemL(col, "Inputs:", ICON_NONE);
+ uiItemL(col, IFACE_("Inputs:"), ICON_NONE);
uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "", &ptr, "inputs", &ptr, "active_input", 0, 0, 0);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_IN);
col = uiLayoutColumn(split, TRUE);
- uiItemL(col, "Outputs:", ICON_NONE);
+ uiItemL(col, IFACE_("Outputs:"), ICON_NONE);
uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "", &ptr, "outputs", &ptr, "active_output", 0, 0, 0);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_OUT);
@@ -248,14 +248,16 @@ void node_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype node panel active node");
strcpy(pt->idname, "NODE_PT_item");
- strcpy(pt->label, IFACE_("Active Node"));
+ strcpy(pt->label, N_("Active Node"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = active_node_panel;
pt->poll = active_node_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype node panel node sockets");
strcpy(pt->idname, "NODE_PT_sockets");
- strcpy(pt->label, "Sockets");
+ strcpy(pt->label, N_("Sockets"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = node_sockets_panel;
pt->poll = node_sockets_poll;
pt->flag |= PNL_DEFAULT_CLOSED;
@@ -263,14 +265,16 @@ void node_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype node panel tree interface");
strcpy(pt->idname, "NODE_PT_node_tree_interface");
- strcpy(pt->label, "Interface");
+ strcpy(pt->label, N_("Interface"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = node_tree_interface_panel;
pt->poll = node_tree_interface_poll;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype node panel gpencil");
strcpy(pt->idname, "NODE_PT_gpencil");
- strcpy(pt->label, "Grease Pencil");
+ strcpy(pt->label, N_("Grease Pencil"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
pt->poll = active_nodetree_poll;
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
index 175bbce756e..8de2daf9e42 100644
--- a/source/blender/editors/space_node/node_header.c
+++ b/source/blender/editors/space_node/node_header.c
@@ -81,7 +81,8 @@ void node_menus_register(void)
mt = MEM_callocN(sizeof(MenuType), "spacetype node menu add");
strcpy(mt->idname, "NODE_MT_add");
- strcpy(mt->label, "Add");
+ strcpy(mt->label, N_("Add"));
+ strcpy(mt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = node_menu_add;
WM_menutype_add(mt);
}
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 48051014c58..7e4397a6cb0 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -121,10 +121,11 @@ void NODE_OT_select_linked_from(struct wmOperatorType *ot);
void NODE_OT_select_border(struct wmOperatorType *ot);
void NODE_OT_select_lasso(struct wmOperatorType *ot);
void NODE_OT_select_same_type(struct wmOperatorType *ot);
-void NODE_OT_select_same_type_next(struct wmOperatorType *ot);
-void NODE_OT_select_same_type_prev(struct wmOperatorType *ot);
+void NODE_OT_select_same_type_step(struct wmOperatorType *ot);
/* node_view.c */
+int space_node_view_flag(struct bContext *C, SpaceNode *snode, ARegion *ar, const int node_flag);
+
void NODE_OT_view_all(struct wmOperatorType *ot);
void NODE_OT_view_selected(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 1e4e02b6ae1..4d229c6fe18 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -58,9 +58,8 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_select_border);
WM_operatortype_append(NODE_OT_select_lasso);
WM_operatortype_append(NODE_OT_select_same_type);
- WM_operatortype_append(NODE_OT_select_same_type_next);
- WM_operatortype_append(NODE_OT_select_same_type_prev);
-
+ WM_operatortype_append(NODE_OT_select_same_type_step);
+
WM_operatortype_append(NODE_OT_view_all);
WM_operatortype_append(NODE_OT_view_selected);
@@ -318,9 +317,12 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_select_linked_to", LKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_select_linked_from", LKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_select_same_type", GKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "NODE_OT_select_same_type_next", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "NODE_OT_select_same_type_prev", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_select_same_type_step", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "prev", FALSE);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_select_same_type_step", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "prev", TRUE);
+
node_group_operators(keymap, "ShaderNodeGroup");
node_group_operators(keymap, "CompositorNodeGroup");
node_group_operators(keymap, "TextureNodeGroup");
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index faebeabdbba..cdb89a66867 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -762,57 +762,93 @@ void NODE_OT_select_same_type(wmOperatorType *ot)
/* ****** Select The Next/Prev Node Of The Same Type ****** */
-static int node_select_same_type_next_exec(bContext *C, wmOperator *UNUSED(op))
-{
- SpaceNode *snode = CTX_wm_space_node(C);
-
- node_select_same_type_np(snode, 0);
+/* ************************** */
- ED_node_sort(snode->edittree);
-
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_select_same_type_next(wmOperatorType *ot)
+static int node_select_same_type_step_exec(bContext *C, wmOperator *op)
{
- /* identifiers */
- ot->name = "Select Same Type Next";
- ot->description = "Select the next node of the same type";
- ot->idname = "NODE_OT_select_same_type_next";
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+ bNode **node_array;
+ bNode *active = nodeGetActive(snode->edittree);
+ int totnodes;
+ int revert = RNA_boolean_get(op->ptr, "prev");
+ int same_type = 1;
- /* api callbacks */
- ot->exec = node_select_same_type_next_exec;
- ot->poll = ED_operator_node_active;
+ ntreeGetDependencyList(snode->edittree, &node_array, &totnodes);
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int node_select_same_type_prev_exec(bContext *C, wmOperator *UNUSED(op))
-{
- SpaceNode *snode = CTX_wm_space_node(C);
-
- node_select_same_type_np(snode, 1);
+ if (totnodes > 1) {
+ int a;
+
+ for (a = 0; a < totnodes; a++) {
+ if (node_array[a] == active)
+ break;
+ }
+
+ if (same_type) {
+ bNode *node = NULL;
+
+ while (node == NULL) {
+ if (revert) a--;
+ else a++;
+
+ if (a < 0 || a >= totnodes)
+ break;
+
+ node = node_array[a];
+
+ if (node->type == active->type)
+ break;
+ else node = NULL;
+ }
+ if (node)
+ active = node;
+ }
+ else {
+ if (revert) {
+ if (a == 0)
+ active = node_array[totnodes - 1];
+ else
+ active = node_array[a - 1];
+ }
+ else {
+ if (a == totnodes - 1)
+ active = node_array[0];
+ else
+ active = node_array[a + 1];
+ }
+ }
+
+ node_select_single(C, active);
- ED_node_sort(snode->edittree);
+ /* is note outside view? */
+ if (active->totr.xmax < ar->v2d.cur.xmin || active->totr.xmin > ar->v2d.cur.xmax ||
+ active->totr.ymax < ar->v2d.cur.ymin || active->totr.ymin > ar->v2d.cur.ymax)
+ space_node_view_flag(C, snode, CTX_wm_region(C), NODE_SELECT);
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ }
+
+ if (node_array)
+ MEM_freeN(node_array);
+
return OPERATOR_FINISHED;
}
-void NODE_OT_select_same_type_prev(wmOperatorType *ot)
+void NODE_OT_select_same_type_step(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Same Type Prev";
- ot->description = "Select the prev node of the same type";
- ot->idname = "NODE_OT_select_same_type_prev";
+ ot->name = "Activate Same Type Next/Prev";
+ ot->description = "Activate and view same node type, step by step";
+ ot->idname = "NODE_OT_select_same_type_step";
/* api callbacks */
- ot->exec = node_select_same_type_prev_exec;
+ ot->exec = node_select_same_type_step_exec;
ot->poll = ED_operator_node_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "prev", 0, "Previous", "");
+
}
+
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index 293913dff11..eed8a10a1db 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -66,7 +66,7 @@
/* **************** View All Operator ************** */
-static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, const int node_flag)
+int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, const int node_flag)
{
bNode *node;
rctf cur_new;
diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c
index 21128408a97..197cc64dea4 100644
--- a/source/blender/editors/space_sequencer/sequencer_buttons.c
+++ b/source/blender/editors/space_sequencer/sequencer_buttons.c
@@ -67,6 +67,7 @@ void sequencer_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel gpencil");
strcpy(pt->idname, "SEQUENCER_PT_gpencil");
strcpy(pt->label, N_("Grease Pencil"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
pt->poll = sequencer_grease_pencil_panel_poll;
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 7ebe04f666b..1a4d461c3c1 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -1061,9 +1061,12 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
- if (sseq->flag & SEQ_USE_ALPHA) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ /* only draw alpha for main buffer */
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ if (sseq->flag & SEQ_USE_ALPHA) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
}
glBegin(GL_QUADS);
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index f0ed8d4107d..135fddfd348 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -866,11 +866,11 @@ static int cut_seq_list(Scene *scene, ListBase *slist, int cutframe,
return (seq_first_new != NULL);
}
-static int insert_gap(Scene *scene, int gap, int cfra)
+static bool insert_gap(Scene *scene, int gap, int cfra)
{
Sequence *seq;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
- int done = FALSE;
+ bool done = false;
/* all strips >= cfra are shifted */
@@ -881,7 +881,7 @@ static int insert_gap(Scene *scene, int gap, int cfra)
if (seq->startdisp >= cfra) {
seq->start += gap;
BKE_sequence_calc(scene, seq);
- done = TRUE;
+ done = true;
}
}
SEQ_END
@@ -988,30 +988,99 @@ static void UNUSED_FUNCTION(seq_remap_paths) (Scene *scene)
}
-static void UNUSED_FUNCTION(no_gaps) (Scene *scene)
+static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
{
- Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
- int cfra, first = 0, done;
-
+ Scene *scene = CTX_data_scene(C);
+ rctf rectf;
+ int cfra, efra, sfra;
+ bool first = false, done;
+ bool do_all = RNA_boolean_get(op->ptr, "all");
+
+ /* get first and last frame */
+ boundbox_seq(scene, &rectf);
+ sfra = (int)rectf.xmin;
+ efra = (int)rectf.xmax;
+
+ /* first check if the current frame has a gap already */
+ for (cfra = CFRA; cfra >= sfra; cfra--) {
+ if (BKE_sequencer_evaluate_frame(scene, cfra)) {
+ first = true;
+ break;
+ }
+ }
- if (ed == NULL) return;
-
- for (cfra = CFRA; cfra <= EFRA; cfra++) {
- if (first == 0) {
- if (BKE_sequencer_evaluate_frame(scene, cfra) ) first = 1;
+ for ( ; cfra < efra; cfra++) {
+ /* first == 0 means there's still no strip to remove a gap for */
+ if (first == false) {
+ if (BKE_sequencer_evaluate_frame(scene, cfra) ) first = true;
}
- else {
- done = TRUE;
+ else if (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
+ done = true;
while (BKE_sequencer_evaluate_frame(scene, cfra) == 0) {
done = insert_gap(scene, -1, cfra);
- if (done == 0) break;
+ if (done == false) break;
}
- if (done == 0) break;
+ if (done == false || do_all == false) break;
}
}
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
+
+}
+
+
+void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Gaps";
+ ot->idname = "SEQUENCER_OT_gap_remove";
+ ot->description = "Remove gap at current frame to first strip at the right, independent of selection or locked state of strips";
+
+ /* api callbacks */
+// ot->invoke = sequencer_snap_invoke;
+ ot->exec = sequencer_gap_remove_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "all", 0, "All Gaps", "Do all gaps to right of current frame");
}
+static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ int frames = RNA_int_get(op->ptr, "frames");
+
+ insert_gap(scene, frames, CFRA);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
+
+}
+
+void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Insert Gaps";
+ ot->idname = "SEQUENCER_OT_gap_insert";
+ ot->description = "Insert gap at current frame to first strips at the right, independent of selection or locked state of strips";
+
+ /* api callbacks */
+ // ot->invoke = sequencer_snap_invoke;
+ ot->exec = sequencer_gap_insert_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "frames", 10, 0, INT_MAX, "Frames", "Frames to insert after current strip", 0, 1000);
+}
+
+
#if 0
static int seq_get_snaplimit(View2D *v2d)
{
@@ -2259,6 +2328,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
View2D *v2d = UI_view2d_fromcontext(C);
ARegion *ar = CTX_wm_region(C);
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
+ Sequence *last_seq = BKE_sequencer_active_get(scene);
Sequence *seq;
rctf cur_new = v2d->cur;
@@ -2275,7 +2345,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- if (seq->flag & SELECT) {
+ if ((seq->flag & SELECT) || (seq == last_seq)) {
xmin = min_ii(xmin, seq->startdisp);
xmax = max_ii(xmax, seq->enddisp);
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index cd79c43eac2..32a6c49da89 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -97,7 +97,11 @@ void SEQUENCER_OT_images_separate(struct wmOperatorType *ot);
void SEQUENCER_OT_meta_toggle(struct wmOperatorType *ot);
void SEQUENCER_OT_meta_make(struct wmOperatorType *ot);
void SEQUENCER_OT_meta_separate(struct wmOperatorType *ot);
+
+void SEQUENCER_OT_gap_remove(struct wmOperatorType *ot);
+void SEQUENCER_OT_gap_insert(struct wmOperatorType *ot);
void SEQUENCER_OT_snap(struct wmOperatorType *ot);
+
void SEQUENCER_OT_strip_jump(struct wmOperatorType *ot);
void SEQUENCER_OT_swap(struct wmOperatorType *ot);
void SEQUENCER_OT_swap_data(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index 70b288a59e6..a236a97a803 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -72,6 +72,9 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_meta_toggle);
WM_operatortype_append(SEQUENCER_OT_meta_make);
WM_operatortype_append(SEQUENCER_OT_meta_separate);
+
+ WM_operatortype_append(SEQUENCER_OT_gap_remove);
+ WM_operatortype_append(SEQUENCER_OT_gap_insert);
WM_operatortype_append(SEQUENCER_OT_snap);
WM_operatortype_append(SEQUENCER_OT_strip_jump);
WM_operatortype_append(SEQUENCER_OT_swap);
@@ -213,6 +216,10 @@ void sequencer_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_swap", LEFTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "side", SEQ_SIDE_LEFT);
RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_swap", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "side", SEQ_SIDE_RIGHT);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_gap_remove", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "all", FALSE);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_gap_remove", BACKSPACEKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "all", TRUE);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_gap_insert", EQUALKEY, KM_PRESS, KM_SHIFT, 0);
+
WM_keymap_add_item(keymap, "SEQUENCER_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "SEQUENCER_OT_swap_inputs", SKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index 6ed34a79510..c8b70c0ce4a 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -107,20 +107,20 @@ static void wform_put_border(unsigned char *tgt, int w, int h)
for (x = 0; x < w; x++) {
unsigned char *p = tgt + 4 * x;
- p[1] = p[3] = 255.0;
- p[4 * w + 1] = p[4 * w + 3] = 255.0;
+ p[1] = p[3] = 155;
+ p[4 * w + 1] = p[4 * w + 3] = 155;
p = tgt + 4 * (w * (h - 1) + x);
- p[1] = p[3] = 255.0;
- p[-4 * w + 1] = p[-4 * w + 3] = 255.0;
+ p[1] = p[3] = 155;
+ p[-4 * w + 1] = p[-4 * w + 3] = 155;
}
for (y = 0; y < h; y++) {
unsigned char *p = tgt + 4 * w * y;
- p[1] = p[3] = 255.0;
- p[4 + 1] = p[4 + 3] = 255.0;
+ p[1] = p[3] = 155;
+ p[4 + 1] = p[4 + 3] = 155;
p = tgt + 4 * (w * y + w - 1);
- p[1] = p[3] = 255.0;
- p[-4 + 1] = p[-4 + 3] = 255.0;
+ p[1] = p[3] = 155;
+ p[-4 + 1] = p[-4 + 3] = 155;
}
}
@@ -156,7 +156,8 @@ static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf)
unsigned char wtable[256];
wform_put_grid(tgt, w, h);
-
+ wform_put_border(tgt, w, h);
+
for (x = 0; x < 256; x++) {
wtable[x] = (unsigned char) (pow(((float) x + 1) / 256, waveform_gamma) * 255);
}
@@ -181,8 +182,6 @@ static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf)
}
}
- wform_put_border(tgt, w, h);
-
return rval;
}
@@ -454,8 +453,8 @@ static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col)
static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
{
ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect);
- int c, x, y;
- unsigned int n;
+ int x, y;
+ unsigned int nr, ng, nb;
unsigned char *src = (unsigned char *) ibuf->rect;
unsigned int bins[3][HIS_STEPS];
@@ -487,19 +486,28 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
}
}
- n = 0;
- for (c = 0; c < 3; c++) {
- for (x = 0; x < HIS_STEPS; x++) {
- if (bins[c][x] > n) {
- n = bins[c][x];
- }
- }
+ nr = nb = ng = 0;
+ for (x = 0; x < HIS_STEPS; x++) {
+ if (bins[0][x] > nr)
+ nr = bins[0][x];
+ if (bins[1][x] > ng)
+ ng = bins[1][x];
+ if (bins[2][x] > nb)
+ nb = bins[2][x];
}
- for (c = 0; c < 3; c++) {
- for (x = 0; x < HIS_STEPS; x++) {
- draw_histogram_bar(rval, x * 2 + 1, ((float) bins[c][x]) / n, c);
- draw_histogram_bar(rval, x * 2 + 2, ((float) bins[c][x]) / n, c);
+ for (x = 0; x < HIS_STEPS; x++) {
+ if (nr) {
+ draw_histogram_bar(rval, x * 2 + 1, ((float) bins[0][x]) / nr, 0);
+ draw_histogram_bar(rval, x * 2 + 2, ((float) bins[0][x]) / nr, 0);
+ }
+ if (ng) {
+ draw_histogram_bar(rval, x * 2 + 1, ((float) bins[1][x]) / ng, 1);
+ draw_histogram_bar(rval, x * 2 + 2, ((float) bins[1][x]) / ng, 1);
+ }
+ if (nb) {
+ draw_histogram_bar(rval, x * 2 + 1, ((float) bins[2][x]) / nb, 2);
+ draw_histogram_bar(rval, x * 2 + 2, ((float) bins[2][x]) / nb, 2);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 533bb30d8d1..a439b5b5b87 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -1270,12 +1270,14 @@ void view3d_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel object");
strcpy(pt->idname, "VIEW3D_PT_object");
strcpy(pt->label, N_("Transform")); /* XXX C panels not available through RNA (bpy.types)! */
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = view3d_panel_object;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil");
strcpy(pt->idname, "VIEW3D_PT_gpencil");
strcpy(pt->label, N_("Grease Pencil")); /* XXX C panels are not available through RNA (bpy.types)! */
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
BLI_addtail(&art->paneltypes, pt);
@@ -1283,6 +1285,7 @@ void view3d_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup");
strcpy(pt->idname, "VIEW3D_PT_vgroup");
strcpy(pt->label, N_("Vertex Groups")); /* XXX C panels are not available through RNA (bpy.types)! */
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = view3d_panel_vgroup;
pt->poll = view3d_panel_vgroup_poll;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index d3bf8a30792..603d9a1595c 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -238,7 +238,8 @@ void view3d_toolshelf_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel tools");
strcpy(pt->idname, "VIEW3D_PT_tool_shelf");
- strcpy(pt->label, "Tool Shelf");
+ strcpy(pt->label, N_("Tool Shelf"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = view3d_panel_tool_shelf;
BLI_addtail(&art->paneltypes, pt);
}
@@ -249,7 +250,8 @@ void view3d_tool_props_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel last operator");
strcpy(pt->idname, "VIEW3D_PT_last_operator");
- strcpy(pt->label, "Operator");
+ strcpy(pt->label, N_("Operator"));
+ strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw_header = view3d_panel_operator_redo_header;
pt->draw = view3d_panel_operator_redo;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index cf960c953c3..f84c967711c 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -6469,7 +6469,7 @@ void createTransData(bContext *C, TransInfo *t)
sort_trans_data_dist(t);
}
}
- else {
+ else if (t->obedit) {
createTransUVs(C, t);
if (t->data && (t->flag & T_PROP_EDIT)) {
sort_trans_data(t); // makes selected become first in array
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 2a3b0bc8726..3d3b8009c99 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1160,7 +1160,7 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even
t->options |= CTX_MASK;
}
else {
- BLI_assert(0);
+ /* image not in uv edit, nor in mask mode, can happen for some tools */
}
}
else if (t->spacetype == SPACE_NODE) {
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 778795bb3a1..60b0c655691 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -721,7 +721,7 @@ static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = ED_operator_view3d_active;
+ ot->poll = ED_operator_screenactive;
RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index b80862d4db5..ba8b26c9083 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -1339,8 +1339,14 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
}
}
else if (camera) {
- struct ProjCameraInfo *uci = BLI_uvproject_camera_info(v3d->camera, obedit->obmat, scene->r.xsch, scene->r.ysch);
+ const bool camera_bounds = RNA_boolean_get(op->ptr, "camera_bounds");
+ struct ProjCameraInfo *uci = BLI_uvproject_camera_info(v3d->camera, obedit->obmat,
+ camera_bounds ? (scene->r.xsch * scene->r.xasp) : 1.0f,
+ camera_bounds ? (scene->r.ysch * scene->r.yasp) : 1.0f);
+
+ // BLI_uvproject_camera_info_scale
+
if (uci) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
@@ -1401,7 +1407,10 @@ void UV_OT_project_from_view(wmOperatorType *ot)
ot->poll = uv_from_view_poll;
/* properties */
- RNA_def_boolean(ot->srna, "orthographic", 0, "Orthographic", "Use orthographic projection");
+ RNA_def_boolean(ot->srna, "orthographic", 0, "Orthographic",
+ "Use orthographic projection");
+ RNA_def_boolean(ot->srna, "camera_bounds", 1, "Camera Bounds",
+ "Map UVs to the camera region taking resolution and aspect into account");
uv_map_clip_correct_properties(ot);
}
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index c7a421a49fc..c455e8f7642 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -402,7 +402,7 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
}
else {
glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
- format, type, NULL);
+ format, type, NULL);
if (fpixels) {
glTexSubImage2D(tex->target, 0, 0, 0, w, h,
@@ -677,7 +677,7 @@ GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
/* Now we tweak some of the settings */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, size, size, 0, GL_RG, GL_FLOAT, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, size, size, 0, GL_RG, GL_FLOAT, NULL);
GPU_texture_unbind(tex);
}
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index 3b6745de470..62a7cb674fc 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -97,6 +97,15 @@ if env['WITH_BF_OCEANSIM']:
if env['WITH_BF_CYCLES']:
defs.append('WITH_CYCLES')
+if env['WITH_BF_SDL']:
+ defs.append('WITH_SDL')
+
+if env['WITH_BF_OPENAL']:
+ defs.append('WITH_OPENAL')
+
+if env['WITH_BF_JACK']:
+ defs.append('WITH_JACK')
+
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
incs += ' ../../../extern/binreloc/include'
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index c9a9cca3147..b118f5bc970 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -58,6 +58,20 @@ static EnumPropertyItem compute_device_type_items[] = {
};
#endif
+static EnumPropertyItem audio_device_items[] = {
+ {0, "NONE", 0, "None", "Null device - there will be no audio output"},
+#ifdef WITH_SDL
+ {1, "SDL", 0, "SDL", "SDL device - simple direct media layer, recommended for sequencer usage"},
+#endif
+#ifdef WITH_OPENAL
+ {2, "OPENAL", 0, "OpenAL", "OpenAL device - supports 3D audio, recommended for game engine usage"},
+#endif
+#ifdef WITH_JACK
+ {3, "JACK", 0, "Jack", "JACK - Audio Connection Kit, recommended for pro audio users"},
+#endif
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include "DNA_object_types.h"
@@ -434,6 +448,41 @@ static EnumPropertyItem *rna_userdef_compute_device_itemf(bContext *UNUSED(C), P
}
#endif
+static EnumPropertyItem *rna_userdef_audio_device_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop), int *free)
+{
+#ifdef WITH_JACK
+ int jack_supported = sound_is_jack_supported();
+
+ if (jack_supported) {
+ return audio_device_items;
+ }
+ else {
+ int index = 0;
+ int totitem = 0;
+ EnumPropertyItem *item = NULL;
+
+ /* NONE */
+ RNA_enum_item_add(&item, &totitem, &audio_device_items[index++]);
+
+#ifdef WITH_SDL
+ RNA_enum_item_add(&item, &totitem, &audio_device_items[index++]);
+#endif
+
+#ifdef WITH_OPENAL
+ RNA_enum_item_add(&item, &totitem, &audio_device_items[index++]);
+#endif
+
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+ }
+#else
+ return audio_device_items;
+#endif
+}
+
#ifdef WITH_INTERNATIONAL
static EnumPropertyItem *rna_lang_enum_properties_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), int *free)
@@ -3244,20 +3293,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem audio_device_items[] = {
- {0, "NONE", 0, "None", "Null device - there will be no audio output"},
-#ifdef WITH_SDL
- {1, "SDL", 0, "SDL", "SDL device - simple direct media layer, recommended for sequencer usage"},
-#endif
-#ifdef WITH_OPENAL
- {2, "OPENAL", 0, "OpenAL", "OpenAL device - supports 3D audio, recommended for game engine usage"},
-#endif
-#ifdef WITH_JACK
- {3, "JACK", 0, "Jack", "JACK - Audio Connection Kit, recommended for pro audio users"},
-#endif
- {0, NULL, 0, NULL, NULL}
- };
-
static EnumPropertyItem audio_rate_items[] = {
/* {8000, "RATE_8000", 0, "8 kHz", "Set audio sampling rate to 8000 samples per second"}, */
/* {11025, "RATE_11025", 0, "11.025 kHz", "Set audio sampling rate to 11025 samples per second"}, */
@@ -3534,6 +3569,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
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_enum_funcs(prop, NULL, NULL, "rna_userdef_audio_device_itemf");
RNA_def_property_ui_text(prop, "Audio Device", "Audio output device");
RNA_def_property_update(prop, 0, "rna_UserDef_audio_update");
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index c09903ad6c5..9b0a435f9a9 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -174,11 +174,24 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
{
Image *ima= (Image *)node->id;
if (ima) {
- ImageUser *iuser= node->storage;
+ ImageUser *iuser = node->storage;
+ ImageUser load_iuser = {NULL};
ImBuf *ibuf;
-
+ int offset = BKE_image_sequence_guess_offset(ima);
+
+ /* It is possible that image user in this node is not
+ * properly updated yet. In this case loading image will
+ * fail and sockets detection will go wrong.
+ *
+ * So we manually construct image user to be sure first
+ * image from sequence (that one which is set as fileanme
+ * for image datablock) is used for sockets detection
+ */
+ load_iuser.ok = 1;
+ load_iuser.framenr = offset;
+
/* make sure ima->type is correct */
- ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+ ibuf = BKE_image_acquire_ibuf(ima, &load_iuser, NULL);
if (ima->rr) {
RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 721bfa01a92..1450af4ff83 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -2373,6 +2373,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
char name[FILE_MAX];
RenderResult rres;
Object *camera = RE_GetCamera(re);
+ double render_time;
int ok = 1;
RE_AcquireResultImage(re, &rres);
@@ -2456,11 +2457,17 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
RE_ReleaseResultImage(re);
+ render_time = re->i.lastframetime;
+ re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
+
BLI_timestr(re->i.lastframetime, name);
printf(" Time: %s", name);
-
+
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_RENDER_STATS);
+ BLI_timestr(re->i.lastframetime - render_time, name);
+ printf(" (Saving: %s)\n", name);
+
fputc('\n', stdout);
fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index e2fb9573129..b96d25e04d9 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -199,7 +199,7 @@ void KX_Dome::CreateGLImages(void)
for (int j=0;j<m_numfaces;j++) {
glBindTexture(GL_TEXTURE_2D, domefacesId[j]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, m_imagesize, m_imagesize, 0, GL_RGB8,
- GL_UNSIGNED_BYTE, 0);
+ GL_UNSIGNED_BYTE, NULL);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, m_imagesize, m_imagesize, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -209,7 +209,7 @@ void KX_Dome::CreateGLImages(void)
if (warp.usemesh) {
glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagesize, warp.imagesize, 0, GL_RGB8,
- GL_UNSIGNED_BYTE, 0);
+ GL_UNSIGNED_BYTE, NULL);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, warp.imagesize, warp.imagesize, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);