From 23eaf3117c68f0c2bc636171dddb77630f8c8659 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 23 Oct 2020 18:54:45 +0200 Subject: Fix Cycles unnecessary overhead cancelling finished task pool --- intern/cycles/util/util_task.cpp | 15 ++++++++++----- intern/cycles/util/util_task.h | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index 4fb61392e92..50c236ac968 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -24,7 +24,7 @@ CCL_NAMESPACE_BEGIN /* Task Pool */ -TaskPool::TaskPool() : start_time(time_dt()), num_tasks_handled(0) +TaskPool::TaskPool() : start_time(time_dt()), num_tasks_pushed(0) { } @@ -36,7 +36,7 @@ TaskPool::~TaskPool() void TaskPool::push(TaskRunFunction &&task) { tbb_group.run(std::move(task)); - num_tasks_handled++; + num_tasks_pushed++; } void TaskPool::wait_work(Summary *stats) @@ -45,14 +45,19 @@ void TaskPool::wait_work(Summary *stats) if (stats != NULL) { stats->time_total = time_dt() - start_time; - stats->num_tasks_handled = num_tasks_handled; + stats->num_tasks_handled = num_tasks_pushed; } + + num_tasks_pushed = 0; } void TaskPool::cancel() { - tbb_group.cancel(); - tbb_group.wait(); + if (num_tasks_pushed > 0) { + tbb_group.cancel(); + tbb_group.wait(); + num_tasks_pushed = 0; + } } bool TaskPool::canceled() diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h index d3c3c11f8e2..f2718600f30 100644 --- a/intern/cycles/util/util_task.h +++ b/intern/cycles/util/util_task.h @@ -71,8 +71,8 @@ class TaskPool { /* Time time stamp of first task pushed. */ double start_time; - /* Number of all tasks handled by this pool. */ - int num_tasks_handled; + /* Number of all tasks pushed to the pool. Cleared after wait_work() and cancel(). */ + int num_tasks_pushed; }; /* Task Scheduler -- cgit v1.2.3 From 8442d6ca8a01b3f20f907bd298d9460bf57aa45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 23 Oct 2020 19:26:35 +0200 Subject: CLOG: Add getter to know if output supports coloring --- intern/clog/CLG_log.h | 2 ++ intern/clog/clog.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/intern/clog/CLG_log.h b/intern/clog/CLG_log.h index a2841c5c8b3..3e51e228bac 100644 --- a/intern/clog/CLG_log.h +++ b/intern/clog/CLG_log.h @@ -150,6 +150,8 @@ void CLG_level_set(int level); void CLG_logref_init(CLG_LogRef *clg_ref); +int CLG_color_support_get(CLG_LogRef *clg_ref); + /** Declare outside function, declare as extern in header. */ #define CLG_LOGREF_DECLARE_GLOBAL(var, id) \ static CLG_LogRef _static_##var = {id}; \ diff --git a/intern/clog/clog.c b/intern/clog/clog.c index 37c8393f532..2bc3985c71f 100644 --- a/intern/clog/clog.c +++ b/intern/clog/clog.c @@ -755,4 +755,12 @@ void CLG_logref_init(CLG_LogRef *clg_ref) #endif } +int CLG_color_support_get(CLG_LogRef *clg_ref) +{ + if (clg_ref->type == NULL) { + CLG_logref_init(clg_ref); + } + return clg_ref->type->ctx->use_color; +} + /** \} */ -- cgit v1.2.3 From a4f883268ba7f8506cd71eba42e8b734c128519d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 23 Oct 2020 19:29:27 +0200 Subject: GPU: Use CLOG to for debug output This removes the escape color control caracters when the output does not supports it (i.e: file output, windows cmd). --- source/blender/gpu/CMakeLists.txt | 1 + source/blender/gpu/intern/gpu_debug.cc | 2 +- source/blender/gpu/intern/gpu_shader.cc | 60 ++++++++++++++++------- source/blender/gpu/intern/gpu_shader_interface.cc | 1 - source/blender/gpu/intern/gpu_shader_private.hh | 2 +- source/blender/gpu/opengl/gl_debug.cc | 41 +++++++++++----- source/blender/gpu/opengl/gl_shader.cc | 8 +-- 7 files changed, 77 insertions(+), 38 deletions(-) diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 482e4086452..92f540f859f 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -44,6 +44,7 @@ set(INC ../nodes ../nodes/intern + ../../../intern/clog ../../../intern/ghost ../../../intern/glew-mx ../../../intern/guardedalloc diff --git a/source/blender/gpu/intern/gpu_debug.cc b/source/blender/gpu/intern/gpu_debug.cc index d7944f0de50..63e7024b74b 100644 --- a/source/blender/gpu/intern/gpu_debug.cc +++ b/source/blender/gpu/intern/gpu_debug.cc @@ -74,7 +74,7 @@ void GPU_debug_get_groups_names(int name_buf_len, char *r_name_buf) for (StringRef &name : stack) { sz += BLI_snprintf_rlen(r_name_buf + sz, name_buf_len - sz, "%s > ", name.data()); } - r_name_buf[sz - 2] = ':'; + r_name_buf[sz - 3] = '\0'; } /* Return true if inside a debug group with the same name. */ diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index 05c81c2efeb..5f46f57c09a 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -23,6 +23,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_dynstr.h" #include "BLI_math_base.h" #include "BLI_math_vector.h" #include "BLI_path_util.h" @@ -47,8 +48,12 @@ #include "gpu_context_private.hh" #include "gpu_shader_private.hh" +#include "CLG_log.h" + extern "C" char datatoc_gpu_shader_colorspace_lib_glsl[]; +static CLG_LogRef LOG = {"gpu.shader"}; + using namespace blender; using namespace blender::gpu; @@ -56,12 +61,21 @@ using namespace blender::gpu; /** \name Debug functions * \{ */ -void Shader::print_errors(Span sources, char *log, const char *stage) +void Shader::print_log(Span sources, char *log, const char *stage, const bool error) { const char line_prefix[] = " | "; + char err_col[] = "\033[31;1m"; + char warn_col[] = "\033[33;1m"; + char info_col[] = "\033[0;2m"; + char reset_col[] = "\033[0;0m"; char *sources_combined = BLI_string_join_arrayN((const char **)sources.data(), sources.size()); + DynStr *dynstr = BLI_dynstr_new(); + + if (!CLG_color_support_get(&LOG)) { + err_col[0] = warn_col[0] = info_col[0] = reset_col[0] = '\0'; + } - fprintf(stderr, "GPUShader: Compilation Log : %s : %s\n", this->name, stage); + BLI_dynstr_appendf(dynstr, "\n"); char *log_line = log, *line_end; char *error_line_number_end; @@ -136,10 +150,10 @@ void Shader::print_errors(Span sources, char *log, const char *sta } /* Separate from previous block. */ if (last_error_line != error_line) { - fprintf(stderr, "\033[90m%s\033[39m\n", line_prefix); + BLI_dynstr_appendf(dynstr, "%s%s%s\n", info_col, line_prefix, reset_col); } else if (error_char != last_error_char) { - fprintf(stderr, "%s\n", line_prefix); + BLI_dynstr_appendf(dynstr, "%s\n", line_prefix); } /* Print line from the source file that is producing the error. */ if ((error_line != -1) && (error_line != last_error_line || error_char != last_error_char)) { @@ -159,24 +173,24 @@ void Shader::print_errors(Span sources, char *log, const char *sta /* Print error source. */ if (found_line_id) { if (error_line != last_error_line) { - fprintf(stderr, "%5d | ", src_line_index); + BLI_dynstr_appendf(dynstr, "%5d | ", src_line_index); } else { - fprintf(stderr, line_prefix); + BLI_dynstr_appendf(dynstr, line_prefix); } - fwrite(src_line, (src_line_end + 1) - src_line, 1, stderr); + BLI_dynstr_nappend(dynstr, src_line, (src_line_end + 1) - src_line); /* Print char offset. */ - fprintf(stderr, line_prefix); + BLI_dynstr_appendf(dynstr, line_prefix); if (error_char != -1) { for (int i = 0; i < error_char; i++) { - fprintf(stderr, " "); + BLI_dynstr_appendf(dynstr, " "); } - fprintf(stderr, "^"); + BLI_dynstr_appendf(dynstr, "^"); } - fprintf(stderr, "\n"); + BLI_dynstr_appendf(dynstr, "\n"); } } - fprintf(stderr, line_prefix); + BLI_dynstr_appendf(dynstr, line_prefix); /* Skip to message. Avoid redundant info. */ const char *keywords[] = {"error", "warning"}; for (int i = 0; i < ARRAY_SIZE(prefix); i++) { @@ -191,22 +205,32 @@ void Shader::print_errors(Span sources, char *log, const char *sta log_line++; } if (type == 0) { - fprintf(stderr, "\033[31;1mError\033[0;2m: "); + BLI_dynstr_appendf(dynstr, "%s%s%s: ", err_col, "Error", info_col); } else if (type == 1) { - fprintf(stderr, "\033[33;1mWarning\033[0;2m: "); + BLI_dynstr_appendf(dynstr, "%s%s%s: ", warn_col, "Warning", info_col); } /* Print the error itself. */ - fprintf(stderr, "\033[2m"); - fwrite(log_line, (line_end + 1) - log_line, 1, stderr); - fprintf(stderr, "\033[0m"); + BLI_dynstr_appendf(dynstr, info_col); + BLI_dynstr_nappend(dynstr, log_line, (line_end + 1) - log_line); + BLI_dynstr_appendf(dynstr, reset_col); /* Continue to next line. */ log_line = line_end + 1; last_error_line = error_line; last_error_char = error_char; } - fprintf(stderr, "\n"); MEM_freeN(sources_combined); + + CLG_Severity severity = error ? CLG_SEVERITY_ERROR : CLG_SEVERITY_WARN; + + if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= 0)) || + (severity >= CLG_SEVERITY_WARN)) { + const char *_str = BLI_dynstr_get_cstring(dynstr); + CLG_log_str(LOG.type, severity, this->name, stage, _str); + MEM_freeN((void *)_str); + } + + BLI_dynstr_free(dynstr); } /** \} */ diff --git a/source/blender/gpu/intern/gpu_shader_interface.cc b/source/blender/gpu/intern/gpu_shader_interface.cc index 4a7c7bc15a3..e5fb8025e7f 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.cc +++ b/source/blender/gpu/intern/gpu_shader_interface.cc @@ -85,7 +85,6 @@ void ShaderInterface::debug_print(void) char *name_buf = name_buffer_; const char format[] = " | %.8x : %4d : %s\n"; - printf(" \033[1mGPUShaderInterface : \033[0m\n"); if (attrs.size() > 0) { printf("\n Attributes :\n"); } diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh index b7acc0f9353..eac39dccd81 100644 --- a/source/blender/gpu/intern/gpu_shader_private.hh +++ b/source/blender/gpu/intern/gpu_shader_private.hh @@ -70,7 +70,7 @@ class Shader { }; protected: - void print_errors(Span sources, char *log, const char *stage); + void print_log(Span sources, char *log, const char *stage, const bool error); }; /* Syntacting suggar. */ diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index b2b05124463..848c0c462fe 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -33,6 +33,8 @@ #include "GPU_debug.h" #include "GPU_platform.h" +#include "CLG_log.h" + #include "glew-mx.h" #include "gl_context.hh" @@ -42,6 +44,8 @@ #include +static CLG_LogRef LOG = {"gpu.debug"}; + /* Avoid too much NVidia buffer info in the output log. */ #define TRIM_NVIDIA_BUFFER_INFO 1 @@ -61,8 +65,6 @@ namespace blender::gpu::debug { # define APIENTRY #endif -#define VERBOSE 1 - static void APIENTRY debug_callback(GLenum UNUSED(source), GLenum type, GLuint UNUSED(id), @@ -86,36 +88,47 @@ static void APIENTRY debug_callback(GLenum UNUSED(source), const char format[] = "GPUDebug: %s%s%s\033[0m\n"; + const bool use_color = CLG_color_support_get(&LOG); + if (ELEM(severity, GL_DEBUG_SEVERITY_LOW, GL_DEBUG_SEVERITY_NOTIFICATION)) { - if (VERBOSE) { - fprintf(stderr, format, "\033[2m", "", message); + if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= CLG_SEVERITY_INFO))) { + const char *format = use_color ? "\033[2m%s\033[0m" : "%s"; + CLG_logf(LOG.type, CLG_SEVERITY_INFO, "Notification", "", format, message); } } else { char debug_groups[512] = ""; GPU_debug_get_groups_names(sizeof(debug_groups), debug_groups); + CLG_Severity clog_severity; switch (type) { case GL_DEBUG_TYPE_ERROR: case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: - fprintf(stderr, format, "\033[31;1mError\033[39m: ", debug_groups, message); + clog_severity = CLG_SEVERITY_ERROR; break; case GL_DEBUG_TYPE_PORTABILITY: case GL_DEBUG_TYPE_PERFORMANCE: case GL_DEBUG_TYPE_OTHER: case GL_DEBUG_TYPE_MARKER: /* KHR has this, ARB does not */ default: - fprintf(stderr, format, "\033[33;1mWarning\033[39m: ", debug_groups, message); + clog_severity = CLG_SEVERITY_WARN; break; } - if (VERBOSE && severity == GL_DEBUG_SEVERITY_HIGH) { - /* Focus on error message. */ - fprintf(stderr, "\033[2m"); - BLI_system_backtrace(stderr); - fprintf(stderr, "\033[0m\n"); - fflush(stderr); + if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= clog_severity))) { + CLG_logf(LOG.type, clog_severity, debug_groups, "", message); + if (severity == GL_DEBUG_SEVERITY_HIGH) { + /* Focus on error message. */ + if (use_color) { + fprintf(stderr, "\033[2m"); + } + BLI_system_backtrace(stderr); + if (use_color) { + fprintf(stderr, "\033[0m\n"); + } + fflush(stderr); + } } } } @@ -125,6 +138,8 @@ static void APIENTRY debug_callback(GLenum UNUSED(source), /* This function needs to be called once per context. */ void init_gl_callbacks(void) { + CLOG_ENSURE(&LOG); + char msg[256] = ""; const char format[] = "Successfully hooked OpenGL debug callback using %s"; @@ -154,7 +169,7 @@ void init_gl_callbacks(void) msg); } else { - fprintf(stderr, "GPUDebug: Failed to hook OpenGL debug callback. Use fallback debug layer.\n"); + CLOG_STR_WARN(&LOG, "Failed to hook OpenGL debug callback. Use fallback debug layer."); init_debug_layer(); } } diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 9af9bf96503..193e4ee8a70 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -134,13 +134,13 @@ GLuint GLShader::create_shader_stage(GLenum gl_stage, MutableSpan if (log[0] != '\0') { switch (gl_stage) { case GL_VERTEX_SHADER: - this->print_errors(sources, log, "VertShader"); + this->print_log(sources, log, "VertShader", !status); break; case GL_GEOMETRY_SHADER: - this->print_errors(sources, log, "GeomShader"); + this->print_log(sources, log, "GeomShader", !status); break; case GL_FRAGMENT_SHADER: - this->print_errors(sources, log, "FragShader"); + this->print_log(sources, log, "FragShader", !status); break; } } @@ -186,7 +186,7 @@ bool GLShader::finalize(void) char log[5000]; glGetProgramInfoLog(shader_program_, sizeof(log), NULL, log); Span sources; - this->print_errors(sources, log, "Linking"); + this->print_log(sources, log, "Linking", true); return false; } -- cgit v1.2.3 From 70cc0d7121aa70894bb98bb6ae25f8c461918350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 23 Oct 2020 19:31:57 +0200 Subject: GPU: Debug: Trim shader stats from output log We don't make use of it anyway. --- source/blender/gpu/opengl/gl_debug.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index 848c0c462fe..69289d7602e 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -48,6 +48,8 @@ static CLG_LogRef LOG = {"gpu.debug"}; /* Avoid too much NVidia buffer info in the output log. */ #define TRIM_NVIDIA_BUFFER_INFO 1 +/* Avoid unneeded shader statistics. */ +#define TRIM_SHADER_STATS_INFO 1 namespace blender::gpu::debug { @@ -81,12 +83,15 @@ static void APIENTRY debug_callback(GLenum UNUSED(source), if (TRIM_NVIDIA_BUFFER_INFO && GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) && - STREQLEN("Buffer detailed info", message, 20)) { - /** Supress buffer infos flooding the output. */ + STRPREFIX(message, "Buffer detailed info")) { + /** Suppress buffer infos flooding the output. */ return; } - const char format[] = "GPUDebug: %s%s%s\033[0m\n"; + if (TRIM_SHADER_STATS_INFO && STRPREFIX(message, "Shader Stats")) { + /** Suppress buffer infos flooding the output. */ + return; + } const bool use_color = CLG_color_support_get(&LOG); -- cgit v1.2.3 From d65e5e8bc56858997073e960d8aea7112aaaa384 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sat, 24 Oct 2020 13:53:16 -0400 Subject: Fix T82019 Crash loading 2.78 splash demo. The versioning code to default to old booleans for old files was faulty because really old files had a 'solver' field (later removed, but then added back for new booleans). --- source/blender/blenloader/intern/versioning_290.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 00085cb7d59..eeb0dd336a3 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -705,14 +705,12 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } /* Solver and Collections for Boolean. */ - if (!DNA_struct_elem_find(fd->filesdna, "BooleanModifierData", "char", "solver")) { - for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) { - LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { - if (md->type == eModifierType_Boolean) { - BooleanModifierData *bmd = (BooleanModifierData *)md; - bmd->solver = eBooleanModifierSolver_Fast; - bmd->flag = eBooleanModifierFlag_Object; - } + for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) { + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_Boolean) { + BooleanModifierData *bmd = (BooleanModifierData *)md; + bmd->solver = eBooleanModifierSolver_Fast; + bmd->flag = eBooleanModifierFlag_Object; } } } -- cgit v1.2.3 From b37c40a575663ea42d397d57d3ef902b4d9777ec Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 23 Oct 2020 18:54:45 +0200 Subject: Fix Cycles unnecessary overhead cancelling finished task pool --- intern/cycles/util/util_task.cpp | 15 ++++++++++----- intern/cycles/util/util_task.h | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index 4fb61392e92..50c236ac968 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -24,7 +24,7 @@ CCL_NAMESPACE_BEGIN /* Task Pool */ -TaskPool::TaskPool() : start_time(time_dt()), num_tasks_handled(0) +TaskPool::TaskPool() : start_time(time_dt()), num_tasks_pushed(0) { } @@ -36,7 +36,7 @@ TaskPool::~TaskPool() void TaskPool::push(TaskRunFunction &&task) { tbb_group.run(std::move(task)); - num_tasks_handled++; + num_tasks_pushed++; } void TaskPool::wait_work(Summary *stats) @@ -45,14 +45,19 @@ void TaskPool::wait_work(Summary *stats) if (stats != NULL) { stats->time_total = time_dt() - start_time; - stats->num_tasks_handled = num_tasks_handled; + stats->num_tasks_handled = num_tasks_pushed; } + + num_tasks_pushed = 0; } void TaskPool::cancel() { - tbb_group.cancel(); - tbb_group.wait(); + if (num_tasks_pushed > 0) { + tbb_group.cancel(); + tbb_group.wait(); + num_tasks_pushed = 0; + } } bool TaskPool::canceled() diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h index d3c3c11f8e2..f2718600f30 100644 --- a/intern/cycles/util/util_task.h +++ b/intern/cycles/util/util_task.h @@ -71,8 +71,8 @@ class TaskPool { /* Time time stamp of first task pushed. */ double start_time; - /* Number of all tasks handled by this pool. */ - int num_tasks_handled; + /* Number of all tasks pushed to the pool. Cleared after wait_work() and cancel(). */ + int num_tasks_pushed; }; /* Task Scheduler -- cgit v1.2.3 From e856443c99d5175b3de6370590142a8d03054bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 23 Oct 2020 19:26:35 +0200 Subject: CLOG: Add getter to know if output supports coloring --- intern/clog/CLG_log.h | 2 ++ intern/clog/clog.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/intern/clog/CLG_log.h b/intern/clog/CLG_log.h index a2841c5c8b3..3e51e228bac 100644 --- a/intern/clog/CLG_log.h +++ b/intern/clog/CLG_log.h @@ -150,6 +150,8 @@ void CLG_level_set(int level); void CLG_logref_init(CLG_LogRef *clg_ref); +int CLG_color_support_get(CLG_LogRef *clg_ref); + /** Declare outside function, declare as extern in header. */ #define CLG_LOGREF_DECLARE_GLOBAL(var, id) \ static CLG_LogRef _static_##var = {id}; \ diff --git a/intern/clog/clog.c b/intern/clog/clog.c index 37c8393f532..2bc3985c71f 100644 --- a/intern/clog/clog.c +++ b/intern/clog/clog.c @@ -755,4 +755,12 @@ void CLG_logref_init(CLG_LogRef *clg_ref) #endif } +int CLG_color_support_get(CLG_LogRef *clg_ref) +{ + if (clg_ref->type == NULL) { + CLG_logref_init(clg_ref); + } + return clg_ref->type->ctx->use_color; +} + /** \} */ -- cgit v1.2.3 From 0d1f65e5166c4822d9e01e7d3ce20f7df972550b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 23 Oct 2020 19:29:27 +0200 Subject: GPU: Use CLOG to for debug output This removes the escape color control caracters when the output does not supports it (i.e: file output, windows cmd). --- source/blender/gpu/CMakeLists.txt | 1 + source/blender/gpu/intern/gpu_debug.cc | 2 +- source/blender/gpu/intern/gpu_shader.cc | 60 ++++++++++++++++------- source/blender/gpu/intern/gpu_shader_interface.cc | 1 - source/blender/gpu/intern/gpu_shader_private.hh | 2 +- source/blender/gpu/opengl/gl_debug.cc | 41 +++++++++++----- source/blender/gpu/opengl/gl_shader.cc | 8 +-- 7 files changed, 77 insertions(+), 38 deletions(-) diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 482e4086452..92f540f859f 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -44,6 +44,7 @@ set(INC ../nodes ../nodes/intern + ../../../intern/clog ../../../intern/ghost ../../../intern/glew-mx ../../../intern/guardedalloc diff --git a/source/blender/gpu/intern/gpu_debug.cc b/source/blender/gpu/intern/gpu_debug.cc index d7944f0de50..63e7024b74b 100644 --- a/source/blender/gpu/intern/gpu_debug.cc +++ b/source/blender/gpu/intern/gpu_debug.cc @@ -74,7 +74,7 @@ void GPU_debug_get_groups_names(int name_buf_len, char *r_name_buf) for (StringRef &name : stack) { sz += BLI_snprintf_rlen(r_name_buf + sz, name_buf_len - sz, "%s > ", name.data()); } - r_name_buf[sz - 2] = ':'; + r_name_buf[sz - 3] = '\0'; } /* Return true if inside a debug group with the same name. */ diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index 05c81c2efeb..5f46f57c09a 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -23,6 +23,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_dynstr.h" #include "BLI_math_base.h" #include "BLI_math_vector.h" #include "BLI_path_util.h" @@ -47,8 +48,12 @@ #include "gpu_context_private.hh" #include "gpu_shader_private.hh" +#include "CLG_log.h" + extern "C" char datatoc_gpu_shader_colorspace_lib_glsl[]; +static CLG_LogRef LOG = {"gpu.shader"}; + using namespace blender; using namespace blender::gpu; @@ -56,12 +61,21 @@ using namespace blender::gpu; /** \name Debug functions * \{ */ -void Shader::print_errors(Span sources, char *log, const char *stage) +void Shader::print_log(Span sources, char *log, const char *stage, const bool error) { const char line_prefix[] = " | "; + char err_col[] = "\033[31;1m"; + char warn_col[] = "\033[33;1m"; + char info_col[] = "\033[0;2m"; + char reset_col[] = "\033[0;0m"; char *sources_combined = BLI_string_join_arrayN((const char **)sources.data(), sources.size()); + DynStr *dynstr = BLI_dynstr_new(); + + if (!CLG_color_support_get(&LOG)) { + err_col[0] = warn_col[0] = info_col[0] = reset_col[0] = '\0'; + } - fprintf(stderr, "GPUShader: Compilation Log : %s : %s\n", this->name, stage); + BLI_dynstr_appendf(dynstr, "\n"); char *log_line = log, *line_end; char *error_line_number_end; @@ -136,10 +150,10 @@ void Shader::print_errors(Span sources, char *log, const char *sta } /* Separate from previous block. */ if (last_error_line != error_line) { - fprintf(stderr, "\033[90m%s\033[39m\n", line_prefix); + BLI_dynstr_appendf(dynstr, "%s%s%s\n", info_col, line_prefix, reset_col); } else if (error_char != last_error_char) { - fprintf(stderr, "%s\n", line_prefix); + BLI_dynstr_appendf(dynstr, "%s\n", line_prefix); } /* Print line from the source file that is producing the error. */ if ((error_line != -1) && (error_line != last_error_line || error_char != last_error_char)) { @@ -159,24 +173,24 @@ void Shader::print_errors(Span sources, char *log, const char *sta /* Print error source. */ if (found_line_id) { if (error_line != last_error_line) { - fprintf(stderr, "%5d | ", src_line_index); + BLI_dynstr_appendf(dynstr, "%5d | ", src_line_index); } else { - fprintf(stderr, line_prefix); + BLI_dynstr_appendf(dynstr, line_prefix); } - fwrite(src_line, (src_line_end + 1) - src_line, 1, stderr); + BLI_dynstr_nappend(dynstr, src_line, (src_line_end + 1) - src_line); /* Print char offset. */ - fprintf(stderr, line_prefix); + BLI_dynstr_appendf(dynstr, line_prefix); if (error_char != -1) { for (int i = 0; i < error_char; i++) { - fprintf(stderr, " "); + BLI_dynstr_appendf(dynstr, " "); } - fprintf(stderr, "^"); + BLI_dynstr_appendf(dynstr, "^"); } - fprintf(stderr, "\n"); + BLI_dynstr_appendf(dynstr, "\n"); } } - fprintf(stderr, line_prefix); + BLI_dynstr_appendf(dynstr, line_prefix); /* Skip to message. Avoid redundant info. */ const char *keywords[] = {"error", "warning"}; for (int i = 0; i < ARRAY_SIZE(prefix); i++) { @@ -191,22 +205,32 @@ void Shader::print_errors(Span sources, char *log, const char *sta log_line++; } if (type == 0) { - fprintf(stderr, "\033[31;1mError\033[0;2m: "); + BLI_dynstr_appendf(dynstr, "%s%s%s: ", err_col, "Error", info_col); } else if (type == 1) { - fprintf(stderr, "\033[33;1mWarning\033[0;2m: "); + BLI_dynstr_appendf(dynstr, "%s%s%s: ", warn_col, "Warning", info_col); } /* Print the error itself. */ - fprintf(stderr, "\033[2m"); - fwrite(log_line, (line_end + 1) - log_line, 1, stderr); - fprintf(stderr, "\033[0m"); + BLI_dynstr_appendf(dynstr, info_col); + BLI_dynstr_nappend(dynstr, log_line, (line_end + 1) - log_line); + BLI_dynstr_appendf(dynstr, reset_col); /* Continue to next line. */ log_line = line_end + 1; last_error_line = error_line; last_error_char = error_char; } - fprintf(stderr, "\n"); MEM_freeN(sources_combined); + + CLG_Severity severity = error ? CLG_SEVERITY_ERROR : CLG_SEVERITY_WARN; + + if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= 0)) || + (severity >= CLG_SEVERITY_WARN)) { + const char *_str = BLI_dynstr_get_cstring(dynstr); + CLG_log_str(LOG.type, severity, this->name, stage, _str); + MEM_freeN((void *)_str); + } + + BLI_dynstr_free(dynstr); } /** \} */ diff --git a/source/blender/gpu/intern/gpu_shader_interface.cc b/source/blender/gpu/intern/gpu_shader_interface.cc index 4a7c7bc15a3..e5fb8025e7f 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.cc +++ b/source/blender/gpu/intern/gpu_shader_interface.cc @@ -85,7 +85,6 @@ void ShaderInterface::debug_print(void) char *name_buf = name_buffer_; const char format[] = " | %.8x : %4d : %s\n"; - printf(" \033[1mGPUShaderInterface : \033[0m\n"); if (attrs.size() > 0) { printf("\n Attributes :\n"); } diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh index b7acc0f9353..eac39dccd81 100644 --- a/source/blender/gpu/intern/gpu_shader_private.hh +++ b/source/blender/gpu/intern/gpu_shader_private.hh @@ -70,7 +70,7 @@ class Shader { }; protected: - void print_errors(Span sources, char *log, const char *stage); + void print_log(Span sources, char *log, const char *stage, const bool error); }; /* Syntacting suggar. */ diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index b2b05124463..848c0c462fe 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -33,6 +33,8 @@ #include "GPU_debug.h" #include "GPU_platform.h" +#include "CLG_log.h" + #include "glew-mx.h" #include "gl_context.hh" @@ -42,6 +44,8 @@ #include +static CLG_LogRef LOG = {"gpu.debug"}; + /* Avoid too much NVidia buffer info in the output log. */ #define TRIM_NVIDIA_BUFFER_INFO 1 @@ -61,8 +65,6 @@ namespace blender::gpu::debug { # define APIENTRY #endif -#define VERBOSE 1 - static void APIENTRY debug_callback(GLenum UNUSED(source), GLenum type, GLuint UNUSED(id), @@ -86,36 +88,47 @@ static void APIENTRY debug_callback(GLenum UNUSED(source), const char format[] = "GPUDebug: %s%s%s\033[0m\n"; + const bool use_color = CLG_color_support_get(&LOG); + if (ELEM(severity, GL_DEBUG_SEVERITY_LOW, GL_DEBUG_SEVERITY_NOTIFICATION)) { - if (VERBOSE) { - fprintf(stderr, format, "\033[2m", "", message); + if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= CLG_SEVERITY_INFO))) { + const char *format = use_color ? "\033[2m%s\033[0m" : "%s"; + CLG_logf(LOG.type, CLG_SEVERITY_INFO, "Notification", "", format, message); } } else { char debug_groups[512] = ""; GPU_debug_get_groups_names(sizeof(debug_groups), debug_groups); + CLG_Severity clog_severity; switch (type) { case GL_DEBUG_TYPE_ERROR: case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: - fprintf(stderr, format, "\033[31;1mError\033[39m: ", debug_groups, message); + clog_severity = CLG_SEVERITY_ERROR; break; case GL_DEBUG_TYPE_PORTABILITY: case GL_DEBUG_TYPE_PERFORMANCE: case GL_DEBUG_TYPE_OTHER: case GL_DEBUG_TYPE_MARKER: /* KHR has this, ARB does not */ default: - fprintf(stderr, format, "\033[33;1mWarning\033[39m: ", debug_groups, message); + clog_severity = CLG_SEVERITY_WARN; break; } - if (VERBOSE && severity == GL_DEBUG_SEVERITY_HIGH) { - /* Focus on error message. */ - fprintf(stderr, "\033[2m"); - BLI_system_backtrace(stderr); - fprintf(stderr, "\033[0m\n"); - fflush(stderr); + if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= clog_severity))) { + CLG_logf(LOG.type, clog_severity, debug_groups, "", message); + if (severity == GL_DEBUG_SEVERITY_HIGH) { + /* Focus on error message. */ + if (use_color) { + fprintf(stderr, "\033[2m"); + } + BLI_system_backtrace(stderr); + if (use_color) { + fprintf(stderr, "\033[0m\n"); + } + fflush(stderr); + } } } } @@ -125,6 +138,8 @@ static void APIENTRY debug_callback(GLenum UNUSED(source), /* This function needs to be called once per context. */ void init_gl_callbacks(void) { + CLOG_ENSURE(&LOG); + char msg[256] = ""; const char format[] = "Successfully hooked OpenGL debug callback using %s"; @@ -154,7 +169,7 @@ void init_gl_callbacks(void) msg); } else { - fprintf(stderr, "GPUDebug: Failed to hook OpenGL debug callback. Use fallback debug layer.\n"); + CLOG_STR_WARN(&LOG, "Failed to hook OpenGL debug callback. Use fallback debug layer."); init_debug_layer(); } } diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 9af9bf96503..193e4ee8a70 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -134,13 +134,13 @@ GLuint GLShader::create_shader_stage(GLenum gl_stage, MutableSpan if (log[0] != '\0') { switch (gl_stage) { case GL_VERTEX_SHADER: - this->print_errors(sources, log, "VertShader"); + this->print_log(sources, log, "VertShader", !status); break; case GL_GEOMETRY_SHADER: - this->print_errors(sources, log, "GeomShader"); + this->print_log(sources, log, "GeomShader", !status); break; case GL_FRAGMENT_SHADER: - this->print_errors(sources, log, "FragShader"); + this->print_log(sources, log, "FragShader", !status); break; } } @@ -186,7 +186,7 @@ bool GLShader::finalize(void) char log[5000]; glGetProgramInfoLog(shader_program_, sizeof(log), NULL, log); Span sources; - this->print_errors(sources, log, "Linking"); + this->print_log(sources, log, "Linking", true); return false; } -- cgit v1.2.3 From bc0a33a81243481e98e2df92a903da2393a16bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 23 Oct 2020 19:31:57 +0200 Subject: GPU: Debug: Trim shader stats from output log We don't make use of it anyway. --- source/blender/gpu/opengl/gl_debug.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index 848c0c462fe..69289d7602e 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -48,6 +48,8 @@ static CLG_LogRef LOG = {"gpu.debug"}; /* Avoid too much NVidia buffer info in the output log. */ #define TRIM_NVIDIA_BUFFER_INFO 1 +/* Avoid unneeded shader statistics. */ +#define TRIM_SHADER_STATS_INFO 1 namespace blender::gpu::debug { @@ -81,12 +83,15 @@ static void APIENTRY debug_callback(GLenum UNUSED(source), if (TRIM_NVIDIA_BUFFER_INFO && GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) && - STREQLEN("Buffer detailed info", message, 20)) { - /** Supress buffer infos flooding the output. */ + STRPREFIX(message, "Buffer detailed info")) { + /** Suppress buffer infos flooding the output. */ return; } - const char format[] = "GPUDebug: %s%s%s\033[0m\n"; + if (TRIM_SHADER_STATS_INFO && STRPREFIX(message, "Shader Stats")) { + /** Suppress buffer infos flooding the output. */ + return; + } const bool use_color = CLG_color_support_get(&LOG); -- cgit v1.2.3 From ca83649b7dbf7b30f3189393a5a27d9faf0ee73e Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sat, 24 Oct 2020 13:53:16 -0400 Subject: Fix T82019 Crash loading 2.78 splash demo. The versioning code to default to old booleans for old files was faulty because really old files had a 'solver' field (later removed, but then added back for new booleans). --- source/blender/blenloader/intern/versioning_290.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 00085cb7d59..eeb0dd336a3 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -705,14 +705,12 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } /* Solver and Collections for Boolean. */ - if (!DNA_struct_elem_find(fd->filesdna, "BooleanModifierData", "char", "solver")) { - for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) { - LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { - if (md->type == eModifierType_Boolean) { - BooleanModifierData *bmd = (BooleanModifierData *)md; - bmd->solver = eBooleanModifierSolver_Fast; - bmd->flag = eBooleanModifierFlag_Object; - } + for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) { + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_Boolean) { + BooleanModifierData *bmd = (BooleanModifierData *)md; + bmd->solver = eBooleanModifierSolver_Fast; + bmd->flag = eBooleanModifierFlag_Object; } } } -- cgit v1.2.3 From 622b30225a0c86900d73fb2bf6541dabf038eebb Mon Sep 17 00:00:00 2001 From: Yevgeny Makarov Date: Sat, 24 Oct 2020 11:42:17 -0700 Subject: UI: Capitalization Corrections Approximately 141 changes of capitalization to conform to MLA title style. Differential Revision: https://developer.blender.org/D8392 Reviewed by Julian Eisel --- intern/cycles/blender/addon/ui.py | 2 +- release/scripts/startup/bl_operators/anim.py | 2 +- release/scripts/startup/bl_operators/clip.py | 2 +- release/scripts/startup/bl_operators/console.py | 2 +- release/scripts/startup/bl_operators/sequencer.py | 4 ++-- release/scripts/startup/bl_operators/userpref.py | 4 ++-- release/scripts/startup/bl_operators/wm.py | 4 ++-- .../scripts/startup/bl_ui/properties_data_empty.py | 2 +- .../startup/bl_ui/properties_data_gpencil.py | 4 ++-- .../scripts/startup/bl_ui/properties_data_mesh.py | 2 +- .../scripts/startup/bl_ui/properties_freestyle.py | 2 +- .../bl_ui/properties_grease_pencil_common.py | 2 +- .../startup/bl_ui/properties_mask_common.py | 2 +- .../startup/bl_ui/properties_material_gpencil.py | 2 +- release/scripts/startup/bl_ui/properties_object.py | 2 +- .../startup/bl_ui/properties_paint_common.py | 2 +- .../startup/bl_ui/properties_physics_common.py | 4 ++-- .../startup/bl_ui/properties_physics_field.py | 4 ++-- .../startup/bl_ui/properties_physics_fluid.py | 2 +- release/scripts/startup/bl_ui/space_clip.py | 8 +++---- release/scripts/startup/bl_ui/space_dopesheet.py | 2 +- release/scripts/startup/bl_ui/space_sequencer.py | 6 ++--- release/scripts/startup/bl_ui/space_text.py | 2 +- release/scripts/startup/bl_ui/space_userpref.py | 12 +++++----- release/scripts/startup/bl_ui/space_view3d.py | 28 +++++++++++----------- .../scripts/startup/bl_ui/space_view3d_toolbar.py | 2 +- source/blender/editors/armature/armature_naming.c | 2 +- source/blender/editors/armature/armature_select.c | 4 ++-- source/blender/editors/armature/pose_edit.c | 2 +- source/blender/editors/gpencil/gpencil_edit.c | 4 ++-- .../editors/interface/interface_eyedropper.c | 2 +- .../editors/interface/interface_templates.c | 2 +- source/blender/editors/mesh/editmesh_bevel.c | 28 +++++++++++----------- .../blender/editors/mesh/editmesh_select_similar.c | 2 +- source/blender/editors/object/object_modifier.c | 4 ++-- source/blender/editors/object/object_relations.c | 2 +- source/blender/editors/physics/particle_object.c | 4 ++-- source/blender/editors/screen/screen_ops.c | 4 ++-- source/blender/editors/space_clip/tracking_ops.c | 6 ++--- .../blender/editors/space_clip/tracking_select.c | 12 +++++----- .../editors/space_sequencer/sequencer_edit.c | 4 ++-- source/blender/editors/space_text/text_ops.c | 4 ++-- source/blender/editors/transform/transform.c | 18 +++++++------- .../gpencil_modifiers/intern/MOD_gpencilarmature.c | 2 +- source/blender/makesrna/intern/rna_action.c | 2 +- source/blender/makesrna/intern/rna_color.c | 2 +- source/blender/makesrna/intern/rna_nodetree.c | 8 +++---- source/blender/makesrna/intern/rna_scene.c | 22 ++++++++--------- source/blender/makesrna/intern/rna_sculpt_paint.c | 2 +- source/blender/makesrna/intern/rna_sequencer.c | 6 ++--- source/blender/makesrna/intern/rna_space.c | 4 ++-- source/blender/makesrna/intern/rna_texture.c | 4 ++-- source/blender/makesrna/intern/rna_userdef.c | 2 +- source/blender/modifiers/intern/MOD_armature.c | 2 +- source/blender/modifiers/intern/MOD_ui_common.c | 4 ++-- source/blender/windowmanager/intern/wm_operators.c | 4 ++-- 56 files changed, 139 insertions(+), 139 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 72d98e78c4d..6b88be3e7aa 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1271,7 +1271,7 @@ class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel): layout.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False) - col = layout.column(heading="Show in") + col = layout.column(heading="Show In") col.prop(ob, "hide_viewport", text="Viewports", invert_checkbox=True, toggle=False) col.prop(ob, "hide_render", text="Renders", invert_checkbox=True, toggle=False) diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py index d0b4b485d82..8334557d1f6 100644 --- a/release/scripts/startup/bl_operators/anim.py +++ b/release/scripts/startup/bl_operators/anim.py @@ -348,7 +348,7 @@ class UpdateAnimatedTransformConstraint(Operator): bl_options = {'REGISTER', 'UNDO'} use_convert_to_radians: BoolProperty( - name="Convert To Radians", + name="Convert to Radians", description="Convert fcurves/drivers affecting rotations to radians (Warning: use this only once!)", default=True, ) diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py index b4795168a19..a3c54a7b069 100644 --- a/release/scripts/startup/bl_operators/clip.py +++ b/release/scripts/startup/bl_operators/clip.py @@ -1011,7 +1011,7 @@ class CLIP_OT_track_settings_as_default(Operator): """Copy tracking settings from active track to default settings""" bl_idname = "clip.track_settings_as_default" - bl_label = "Track Settings As Default" + bl_label = "Track Settings as Default" bl_options = {'UNDO', 'REGISTER'} @classmethod diff --git a/release/scripts/startup/bl_operators/console.py b/release/scripts/startup/bl_operators/console.py index b62b9310224..bffac4eef55 100644 --- a/release/scripts/startup/bl_operators/console.py +++ b/release/scripts/startup/bl_operators/console.py @@ -85,7 +85,7 @@ class ConsoleAutocomplete(Operator): class ConsoleCopyAsScript(Operator): """Copy the console contents for use in a script""" bl_idname = "console.copy_as_script" - bl_label = "Copy to Clipboard (as script)" + bl_label = "Copy to Clipboard (as Script)" @classmethod def poll(cls, context): diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py index 6b420d20e14..df1098bdd3f 100644 --- a/release/scripts/startup/bl_operators/sequencer.py +++ b/release/scripts/startup/bl_operators/sequencer.py @@ -32,7 +32,7 @@ class SequencerCrossfadeSounds(Operator): """Do cross-fading volume animation of two selected sound strips""" bl_idname = "sequencer.crossfade_sounds" - bl_label = "Crossfade sounds" + bl_label = "Crossfade Sounds" bl_options = {'REGISTER', 'UNDO'} @classmethod @@ -83,7 +83,7 @@ class SequencerSplitMulticam(Operator): """Split multi-cam strip and select camera""" bl_idname = "sequencer.split_multicam" - bl_label = "Split multicam" + bl_label = "Split Multicam" bl_options = {'REGISTER', 'UNDO'} camera: IntProperty( diff --git a/release/scripts/startup/bl_operators/userpref.py b/release/scripts/startup/bl_operators/userpref.py index 31d601debba..07dba491dbd 100644 --- a/release/scripts/startup/bl_operators/userpref.py +++ b/release/scripts/startup/bl_operators/userpref.py @@ -1112,9 +1112,9 @@ class PREFERENCES_OT_studiolight_uninstall(Operator): class PREFERENCES_OT_studiolight_copy_settings(Operator): - """Copy Studio Light settings to the Studio light editor""" + """Copy Studio Light settings to the Studio Light editor""" bl_idname = "preferences.studiolight_copy_settings" - bl_label = "Copy Studio Light settings" + bl_label = "Copy Studio Light Settings" index: IntProperty() def execute(self, context): diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index e9a658bdc10..aa4e4e77993 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1660,7 +1660,7 @@ class WM_OT_owner_disable(Operator): class WM_OT_tool_set_by_id(Operator): """Set the tool by name (for keymaps)""" bl_idname = "wm.tool_set_by_id" - bl_label = "Set Tool By Name" + bl_label = "Set Tool by Name" name: StringProperty( name="Identifier", @@ -1718,7 +1718,7 @@ class WM_OT_tool_set_by_id(Operator): class WM_OT_tool_set_by_index(Operator): """Set the tool by index (for keymaps)""" bl_idname = "wm.tool_set_by_index" - bl_label = "Set Tool By Index" + bl_label = "Set Tool by Index" index: IntProperty( name="Index in toolbar", default=0, diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py index c8a1d9e238c..7ded4c775a7 100644 --- a/release/scripts/startup/bl_ui/properties_data_empty.py +++ b/release/scripts/startup/bl_ui/properties_data_empty.py @@ -54,7 +54,7 @@ class DATA_PT_empty(DataButtonsPanel, Panel): depth_row.prop(ob, "empty_image_depth", text="Depth", expand=True) col.row().prop(ob, "empty_image_side", text="Side", expand=True) - col = layout.column(heading="Show in", align=True) + col = layout.column(heading="Show In", align=True) col.prop(ob, "show_empty_image_orthographic", text="Orthographic") col.prop(ob, "show_empty_image_perspective", text="Perspective") col.prop(ob, "show_empty_image_only_axis_aligned", text="Only Axis Aligned") diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py index 946578937bb..affdba6f693 100644 --- a/release/scripts/startup/bl_ui/properties_data_gpencil.py +++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py @@ -101,7 +101,7 @@ class GPENCIL_MT_layer_context_menu(Menu): layout.separator() layout.operator("gpencil.lock_all", icon='LOCKED', text="Lock All") - layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="UnLock All") + layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="Unlock All") layout.prop(gpd, "use_autolock_layers", text="Autolock Inactive Layers") layout.separator() @@ -263,7 +263,7 @@ class DATA_PT_gpencil_onion_skinning_display(DataButtonsPanel, Panel): layout.use_property_split = True layout.enabled = gpd.users <= 1 - layout.prop(gpd, "use_ghosts_always", text="View In Render") + layout.prop(gpd, "use_ghosts_always", text="View in Render") col = layout.column(align=True) col.prop(gpd, "use_onion_fade", text="Fade") diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 2ea439a7e89..924a89755f8 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -57,7 +57,7 @@ class MESH_MT_vertex_group_context_menu(Menu): layout.separator() props = layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All") props.action, props.mask = 'LOCK', 'ALL' - props = layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="UnLock All") + props = layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock All") props.action, props.mask = 'UNLOCK', 'ALL' props = layout.operator("object.vertex_group_lock", text="Lock Invert All") props.action, props.mask = 'INVERT', 'ALL' diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py index 3a2b26aaebb..3d574fca2ff 100644 --- a/release/scripts/startup/bl_ui/properties_freestyle.py +++ b/release/scripts/startup/bl_ui/properties_freestyle.py @@ -162,7 +162,7 @@ class VIEWLAYER_PT_freestyle(ViewLayerFreestyleButtonsPanel, Panel): if freestyle.mode == 'SCRIPT': row = layout.row() - row.label(text="Style modules:") + row.label(text="Style Modules:") row.operator("scene.freestyle_module_add", text="Add") for module in freestyle.modules: box = layout.box() diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 910d6b64b74..97e87f5451c 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -884,7 +884,7 @@ class GreasePencilLayerDisplayPanel: col.prop(gpl, "channel_color") col = layout.row(align=True) - col.prop(gpl, "use_solo_mode", text="Show Only On Keyframed") + col.prop(gpl, "use_solo_mode", text="Show Only on Keyframed") class GreasePencilFlipTintColors(Operator): diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py index 6ee755722f3..4d25b8ca309 100644 --- a/release/scripts/startup/bl_ui/properties_mask_common.py +++ b/release/scripts/startup/bl_ui/properties_mask_common.py @@ -37,7 +37,7 @@ def draw_mask_context_menu(layout, context): layout.separator() - layout.operator("mask.shape_key_rekey", text="Re-key Shape Points") + layout.operator("mask.shape_key_rekey", text="Re-Key Shape Points") layout.operator("mask.feather_weight_clear") layout.operator("mask.shape_key_feather_reset", text="Reset Feather Animation") diff --git a/release/scripts/startup/bl_ui/properties_material_gpencil.py b/release/scripts/startup/bl_ui/properties_material_gpencil.py index 4ed7b1ac7b9..da54ff1a137 100644 --- a/release/scripts/startup/bl_ui/properties_material_gpencil.py +++ b/release/scripts/startup/bl_ui/properties_material_gpencil.py @@ -39,7 +39,7 @@ class GPENCIL_MT_material_context_menu(Menu): layout.separator() layout.operator("gpencil.material_lock_all", icon='LOCKED', text="Lock All") - layout.operator("gpencil.material_unlock_all", icon='UNLOCKED', text="UnLock All") + layout.operator("gpencil.material_unlock_all", icon='UNLOCKED', text="Unlock All") layout.operator("gpencil.material_lock_unused", text="Lock Unselected") layout.operator("gpencil.lock_layer", text="Lock Unused") diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index b142f6085fa..4530b4bbe48 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -364,7 +364,7 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel): layout.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True) - col = layout.column(heading="Show in") + col = layout.column(heading="Show In") col.prop(ob, "hide_viewport", text="Viewports", toggle=False, invert_checkbox=True) col.prop(ob, "hide_render", text="Renders", toggle=False, invert_checkbox=True) diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index cf44bb36fb5..01454f8ee05 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -330,7 +330,7 @@ class StrokePanel(BrushPanel): col.separator() if brush.use_anchor: - col.prop(brush, "use_edge_to_edge", text="Edge To Edge") + col.prop(brush, "use_edge_to_edge", text="Edge to Edge") if brush.use_airbrush: col.prop(brush, "rate", text="Rate", slider=True) diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py index abc75ceed2c..b8c0035ee6b 100644 --- a/release/scripts/startup/bl_ui/properties_physics_common.py +++ b/release/scripts/startup/bl_ui/properties_physics_common.py @@ -228,7 +228,7 @@ def point_cache_ui(self, cache, enabled, cachetype): sub = col.row() sub.enabled = enabled - sub.operator("ptcache.bake", text="Calculate To Frame").bake = False + sub.operator("ptcache.bake", text="Calculate to Frame").bake = False sub = col.column() sub.enabled = enabled @@ -237,7 +237,7 @@ def point_cache_ui(self, cache, enabled, cachetype): col = flow.column() col.operator("ptcache.bake_all", text="Bake All Dynamics").bake = True col.operator("ptcache.free_bake_all", text="Delete All Bakes") - col.operator("ptcache.bake_all", text="Update All To Frame").bake = False + col.operator("ptcache.bake_all", text="Update All to Frame").bake = False def effector_weights_ui(self, weights, weight_type): diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py index d1ff1dc9f5e..c8c49ee02b0 100644 --- a/release/scripts/startup/bl_ui/properties_physics_field.py +++ b/release/scripts/startup/bl_ui/properties_physics_field.py @@ -102,7 +102,7 @@ class PHYSICS_PT_field_settings(PhysicButtonsPanel, Panel): col.separator() col = flow.column() - col.prop(field, "guide_clump_amount", text="Clumping amount") + col.prop(field, "guide_clump_amount", text="Clumping Amount") col.prop(field, "guide_clump_shape") col.prop(field, "use_max_distance") @@ -378,7 +378,7 @@ class PHYSICS_PT_collision_particle(PhysicButtonsPanel, Panel): class PHYSICS_PT_collision_softbody(PhysicButtonsPanel, Panel): - bl_label = "Softbody And Cloth" + bl_label = "Softbody & Cloth" bl_parent_id = "PHYSICS_PT_collision" COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'} diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py index 779bdb5cd11..15c5e70d8b2 100644 --- a/release/scripts/startup/bl_ui/properties_physics_fluid.py +++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py @@ -196,7 +196,7 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel): col = flow.column() if PhysicButtonsPanel.poll_gas_domain(context): col.prop(domain, "clipping", text="Empty Space") - col.prop(domain, "delete_in_obstacle", text="Delete In Obstacle") + col.prop(domain, "delete_in_obstacle", text="Delete in Obstacle") if domain.cache_type == 'MODULAR': col.separator() diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index a23dfae55b7..4b24f36eace 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -560,7 +560,7 @@ class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel): class CLIP_PT_tools_cleanup(CLIP_PT_tracking_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' - bl_label = "Clean up" + bl_label = "Clean Up" bl_options = {'DEFAULT_CLOSED'} bl_category = "Solve" @@ -1000,9 +1000,9 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel): row.prop(stab, "show_tracks_expanded", text="", emboss=False) if not stab.show_tracks_expanded: - row.label(text="Tracks For Stabilization") + row.label(text="Tracks for Stabilization") else: - row.label(text="Tracks For Location") + row.label(text="Tracks for Location") row = box.row() row.template_list("UI_UL_list", "stabilization_tracks", stab, "tracks", stab, "active_track_index", rows=2) @@ -1018,7 +1018,7 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel): # Usually we don't hide things from interface, but here every pixel of # vertical space is precious. if stab.use_stabilize_rotation: - box.label(text="Tracks For Rotation / Scale") + box.label(text="Tracks for Rotation/Scale") row = box.row() row.template_list("UI_UL_list", "stabilization_rotation_tracks", stab, "rotation_tracks", diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index a866921f326..5e53eec4ae6 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -336,7 +336,7 @@ class DOPESHEET_MT_view(Menu): layout.separator() - layout.prop(st.dopesheet, "use_multi_word_filter", text="Multi-word Match Search") + layout.prop(st.dopesheet, "use_multi_word_filter", text="Multi-Word Match Search") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 72395e1de5e..7d881948466 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -1071,7 +1071,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): flow.prop(strip, "use_only_boost") elif strip_type == 'SPEED': - layout.prop(strip, "use_default_fade", text="Stretch to input strip length") + layout.prop(strip, "use_default_fade", text="Stretch to Input Strip Length") if not strip.use_default_fade: layout.prop(strip, "use_as_speed") if strip.use_as_speed: @@ -1113,7 +1113,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): # The multicam strip needs at least 2 strips to be useful if strip_channel > 2: BT_ROW = 4 - col.label(text=" Cut to") + col.label(text="Cut To") row = col.row() for i in range(1, strip_channel): @@ -1153,7 +1153,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): col.prop(strip, "use_frame_interpolate") elif strip_type in {'CROSS', 'GAMMA_CROSS', 'WIPE', 'ALPHA_OVER', 'ALPHA_UNDER', 'OVER_DROP'}: - col.prop(strip, "use_default_fade", text="Default fade") + col.prop(strip, "use_default_fade", text="Default Fade") if not strip.use_default_fade: col.prop(strip, "effect_fader", text="Effect Fader") elif strip_type == 'GAUSSIAN_BLUR': diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py index 8a45069470b..f1326823fe8 100644 --- a/release/scripts/startup/bl_ui/space_text.py +++ b/release/scripts/startup/bl_ui/space_text.py @@ -177,7 +177,7 @@ class TEXT_PT_find(Panel): row = col.row(align=True) row.operator("text.replace") - row.operator("text.replace", text="Replace all").all = True + row.operator("text.replace", text="Replace All").all = True layout.separator() diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index b4b8a631b93..10b52e1fe3a 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -279,7 +279,7 @@ class USERPREF_PT_interface_temporary_windows(InterfacePanel, CenterAlignMixIn, view = prefs.view col = layout.column() - col.prop(view, "render_display_type", text="Render in") + col.prop(view, "render_display_type", text="Render In") col.prop(view, "filebrowser_display_type", text="File Browser") @@ -373,8 +373,8 @@ class USERPREF_PT_edit_objects_new(EditingPanel, CenterAlignMixIn, Panel): flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - flow.prop(edit, "material_link", text="Link Materials to") - flow.prop(edit, "object_align", text="Align to") + flow.prop(edit, "material_link", text="Link Materials To") + flow.prop(edit, "object_align", text="Align To") flow.prop(edit, "use_enter_edit_mode", text="Enter Edit Mode") flow.prop(edit, "collection_instance_empty_size", text="Instance Empty Size") @@ -479,7 +479,7 @@ class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel): col = layout.column() col.prop(edit, "sculpt_paint_overlay_color", text="Sculpt Overlay Color") - col.prop(edit, "node_margin", text="Node Auto-offset Margin") + col.prop(edit, "node_margin", text="Node Auto-Offset Margin") # ----------------------------------------------------------------------------- @@ -1348,7 +1348,7 @@ class USERPREF_PT_saveload_blend(SaveLoadPanel, CenterAlignMixIn, Panel): col.prop(view, "use_save_prompt") col.prop(paths, "use_save_preview_images") - col = layout.column(heading="Default to") + col = layout.column(heading="Default To") col.prop(paths, "use_relative_paths") col.prop(paths, "use_file_compression") col.prop(paths, "use_load_ui") @@ -1377,7 +1377,7 @@ class USERPREF_PT_saveload_blend_autosave(SaveLoadPanel, CenterAlignMixIn, Panel col = layout.column() col.active = paths.use_auto_save_temporary_files - col.prop(paths, "auto_save_time", text="Timer (mins)") + col.prop(paths, "auto_save_time", text="Timer (Minutes)") class USERPREF_PT_saveload_file_browser(SaveLoadPanel, CenterAlignMixIn, Panel): diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index af6e752227e..cb2ead39e2a 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2257,7 +2257,7 @@ class VIEW3D_MT_object(Menu): ob = context.active_object if ob and ob.type == 'GPENCIL' and context.gpencil_data: - layout.operator_menu_enum("gpencil.convert", "type", text="Convert to") + layout.operator_menu_enum("gpencil.convert", "type", text="Convert To") else: layout.operator_menu_enum("object.convert", "target") @@ -3035,14 +3035,14 @@ class VIEW3D_MT_mask(Menu): layout.separator() - props = layout.operator("sculpt.mask_expand", text="Expand Mask By Topology") + props = layout.operator("sculpt.mask_expand", text="Expand Mask by Topology") props.use_normals = False props.keep_previous_mask = False props.invert = True props.smooth_iterations = 2 props.create_face_set = False - props = layout.operator("sculpt.mask_expand", text="Expand Mask By Curvature") + props = layout.operator("sculpt.mask_expand", text="Expand Mask by Curvature") props.use_normals = True props.keep_previous_mask = True props.invert = False @@ -3428,7 +3428,7 @@ class VIEW3D_MT_pose_constraints(Menu): def draw(self, _context): layout = self.layout - layout.operator("pose.constraint_add_with_targets", text="Add (With Targets)...") + layout.operator("pose.constraint_add_with_targets", text="Add (with Targets)...") layout.operator("pose.constraints_copy") layout.operator("pose.constraints_clear") @@ -3440,9 +3440,9 @@ class VIEW3D_MT_pose_names(Menu): layout = self.layout layout.operator_context = 'EXEC_REGION_WIN' - layout.operator("pose.autoside_names", text="AutoName Left/Right").axis = 'XAXIS' - layout.operator("pose.autoside_names", text="AutoName Front/Back").axis = 'YAXIS' - layout.operator("pose.autoside_names", text="AutoName Top/Bottom").axis = 'ZAXIS' + layout.operator("pose.autoside_names", text="Auto-Name Left/Right").axis = 'XAXIS' + layout.operator("pose.autoside_names", text="Auto-Name Front/Back").axis = 'YAXIS' + layout.operator("pose.autoside_names", text="Auto-Name Top/Bottom").axis = 'ZAXIS' layout.operator("pose.flip_names") @@ -4769,9 +4769,9 @@ class VIEW3D_MT_edit_armature_names(Menu): layout = self.layout layout.operator_context = 'EXEC_REGION_WIN' - layout.operator("armature.autoside_names", text="AutoName Left/Right").type = 'XAXIS' - layout.operator("armature.autoside_names", text="AutoName Front/Back").type = 'YAXIS' - layout.operator("armature.autoside_names", text="AutoName Top/Bottom").type = 'ZAXIS' + layout.operator("armature.autoside_names", text="Auto-Name Left/Right").type = 'XAXIS' + layout.operator("armature.autoside_names", text="Auto-Name Front/Back").type = 'YAXIS' + layout.operator("armature.autoside_names", text="Auto-Name Top/Bottom").type = 'ZAXIS' layout.operator("armature.flip_names", text="Flip Names") @@ -5074,7 +5074,7 @@ class VIEW3D_MT_edit_gpencil_transform(Menu): class VIEW3D_MT_edit_gpencil_showhide(Menu): - bl_label = "Show/hide" + bl_label = "Show/Hide" def draw(self, _context): layout = self.layout @@ -5862,7 +5862,7 @@ class VIEW3D_PT_shading_options(Panel): row = col.row() row.active = not xray_active - row.prop(shading, "use_dof", text="Depth Of Field") + row.prop(shading, "use_dof", text="Depth of Field") if shading.type in {'WIREFRAME', 'SOLID'}: row = layout.split() @@ -6553,7 +6553,7 @@ class VIEW3D_PT_snapping(Panel): layout = self.layout col = layout.column() - col.label(text="Snap to") + col.label(text="Snap To") col.prop(tool_settings, "snap_elements", expand=True) col.separator() @@ -6561,7 +6561,7 @@ class VIEW3D_PT_snapping(Panel): col.prop(tool_settings, "use_snap_grid_absolute") if snap_elements != {'INCREMENT'}: - col.label(text="Snap with") + col.label(text="Snap With") row = col.row(align=True) row.prop(tool_settings, "snap_target", expand=True) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index e9118a8be91..e808c8779c6 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -681,7 +681,7 @@ class VIEW3D_PT_tools_brush_falloff(Panel, View3DPaintPanel, FalloffPanel): class VIEW3D_PT_tools_brush_falloff_frontface(View3DPaintPanel, Panel): bl_context = ".imagepaint" # dot on purpose (access from topbar) - bl_label = "Front-face Falloff" + bl_label = "Front-Face Falloff" bl_parent_id = "VIEW3D_PT_tools_brush_falloff" bl_options = {'DEFAULT_CLOSED'} diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 60a1434ed42..8bcaf72f678 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -606,7 +606,7 @@ void ARMATURE_OT_autoside_names(wmOperatorType *ot) }; /* identifiers */ - ot->name = "AutoName by Axis"; + ot->name = "Auto-Name by Axis"; ot->idname = "ARMATURE_OT_autoside_names"; ot->description = "Automatically renames the selected bones according to which side of the target axis they " diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 27718b61d70..66c12a0d0d7 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -1550,10 +1550,10 @@ enum { static const EnumPropertyItem prop_similar_types[] = { {SIMEDBONE_CHILDREN, "CHILDREN", 0, "Children", ""}, - {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate children", ""}, + {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate Children", ""}, {SIMEDBONE_SIBLINGS, "SIBLINGS", 0, "Siblings", ""}, {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""}, - {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""}, + {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y Axis)", ""}, {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""}, {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""}, {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""}, diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index e8c35958115..857176937dc 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -638,7 +638,7 @@ void POSE_OT_autoside_names(wmOperatorType *ot) }; /* identifiers */ - ot->name = "AutoName by Axis"; + ot->name = "Auto-Name by Axis"; ot->idname = "POSE_OT_autoside_names"; ot->description = "Automatically renames the selected bones according to which side of the target axis they " diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 7d79e748f75..98789706a13 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -3152,8 +3152,8 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot) PropertyRNA *prop; static const EnumPropertyItem cyclic_type[] = { - {GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close all", ""}, - {GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open all", ""}, + {GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close All", ""}, + {GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open All", ""}, {GP_STROKE_CYCLIC_TOGGLE, "TOGGLE", 0, "Toggle", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index a740a152f1c..4d0e1584156 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -78,7 +78,7 @@ wmKeyMap *eyedropper_colorband_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items_point[] = { {EYE_MODAL_POINT_CANCEL, "CANCEL", 0, "Cancel", ""}, - {EYE_MODAL_POINT_SAMPLE, "SAMPLE_SAMPLE", 0, "Sample a point", ""}, + {EYE_MODAL_POINT_SAMPLE, "SAMPLE_SAMPLE", 0, "Sample a Point", ""}, {EYE_MODAL_POINT_CONFIRM, "SAMPLE_CONFIRM", 0, "Confirm Sampling", ""}, {EYE_MODAL_POINT_RESET, "SAMPLE_RESET", 0, "Reset Sampling", ""}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index d4d24b3e3c2..62c387638dc 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -5330,7 +5330,7 @@ static void ui_template_palette_menu(bContext *UNUSED(C), uiLayout *layout, void { uiLayout *row; - uiItemL(layout, IFACE_("Sort by:"), ICON_NONE); + uiItemL(layout, IFACE_("Sort By:"), ICON_NONE); row = uiLayoutRow(layout, false); uiItemEnumO_value(row, IFACE_("Hue"), ICON_NONE, "PALETTE_OT_sort", "type", 1); row = uiLayoutRow(layout, false); diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index a90d6530453..012bca050cf 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -642,56 +642,56 @@ wmKeyMap *bevel_modal_keymap(wmKeyConfig *keyconf) static const EnumPropertyItem modal_items[] = { {BEV_MODAL_CANCEL, "CANCEL", 0, "Cancel", "Cancel bevel"}, {BEV_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", "Confirm bevel"}, - {BEV_MODAL_VALUE_OFFSET, "VALUE_OFFSET", 0, "Change offset", "Value changes offset"}, - {BEV_MODAL_VALUE_PROFILE, "VALUE_PROFILE", 0, "Change profile", "Value changes profile"}, - {BEV_MODAL_VALUE_SEGMENTS, "VALUE_SEGMENTS", 0, "Change segments", "Value changes segments"}, - {BEV_MODAL_SEGMENTS_UP, "SEGMENTS_UP", 0, "Increase segments", "Increase segments"}, - {BEV_MODAL_SEGMENTS_DOWN, "SEGMENTS_DOWN", 0, "Decrease segments", "Decrease segments"}, + {BEV_MODAL_VALUE_OFFSET, "VALUE_OFFSET", 0, "Change Offset", "Value changes offset"}, + {BEV_MODAL_VALUE_PROFILE, "VALUE_PROFILE", 0, "Change Profile", "Value changes profile"}, + {BEV_MODAL_VALUE_SEGMENTS, "VALUE_SEGMENTS", 0, "Change Segments", "Value changes segments"}, + {BEV_MODAL_SEGMENTS_UP, "SEGMENTS_UP", 0, "Increase Segments", "Increase segments"}, + {BEV_MODAL_SEGMENTS_DOWN, "SEGMENTS_DOWN", 0, "Decrease Segments", "Decrease segments"}, {BEV_MODAL_OFFSET_MODE_CHANGE, "OFFSET_MODE_CHANGE", 0, - "Change offset mode", + "Change Offset Mode", "Cycle through offset modes"}, {BEV_MODAL_CLAMP_OVERLAP_TOGGLE, "CLAMP_OVERLAP_TOGGLE", 0, - "Toggle clamp overlap", + "Toggle Clamp Overlap", "Toggle clamp overlap flag"}, {BEV_MODAL_AFFECT_CHANGE, "AFFECT_CHANGE", 0, - "Change affect type", + "Change Affect Type", "Change which geometry type the operation affects, edges or vertices"}, {BEV_MODAL_HARDEN_NORMALS_TOGGLE, "HARDEN_NORMALS_TOGGLE", 0, - "Toggle harden normals", + "Toggle Harden Normals", "Toggle harden normals flag"}, {BEV_MODAL_MARK_SEAM_TOGGLE, "MARK_SEAM_TOGGLE", 0, - "Toggle mark seam", + "Toggle Mark Seam", "Toggle mark seam flag"}, {BEV_MODAL_MARK_SHARP_TOGGLE, "MARK_SHARP_TOGGLE", 0, - "Toggle mark sharp", + "Toggle Mark Sharp", "Toggle mark sharp flag"}, {BEV_MODAL_OUTER_MITER_CHANGE, "OUTER_MITER_CHANGE", 0, - "Change outer miter", + "Change Outer Miter", "Cycle through outer miter kinds"}, {BEV_MODAL_INNER_MITER_CHANGE, "INNER_MITER_CHANGE", 0, - "Change inner miter", + "Change Inner Miter", "Cycle through inner miter kinds"}, {BEV_MODAL_PROFILE_TYPE_CHANGE, "PROFILE_TYPE_CHANGE", 0, "Cycle through profile types", ""}, {BEV_MODAL_VERTEX_MESH_CHANGE, "VERTEX_MESH_CHANGE", 0, - "Change intersection method", + "Change Intersection Method", "Cycle through intersection methods"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index f94d3ba5a70..00349983c57 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -83,7 +83,7 @@ static const EnumPropertyItem prop_similar_types[] = { {SIMFACE_SIDES, "SIDES", 0, "Polygon Sides", ""}, {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""}, {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""}, - {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""}, + {SIMFACE_COPLANAR, "COPLANAR", 0, "Coplanar", ""}, {SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""}, {SIMFACE_FACEMAP, "FACE_MAP", 0, "Face-Map", ""}, #ifdef WITH_FREESTYLE diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 4eed9187d66..b8891b612c9 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -1478,8 +1478,8 @@ static char *modifier_apply_as_shapekey_get_description(struct bContext *UNUSED( void OBJECT_OT_modifier_apply_as_shapekey(wmOperatorType *ot) { - ot->name = "Apply Modifier As Shapekey"; - ot->description = "Apply modifier as a new shapekey and remove from the stack"; + ot->name = "Apply Modifier as Shape Key"; + ot->description = "Apply modifier as a new shape key and remove from the stack"; ot->idname = "OBJECT_OT_modifier_apply_as_shapekey"; ot->invoke = modifier_apply_as_shapekey_invoke; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index de3e5f3d5f9..3d65a9e5fcb 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1359,7 +1359,7 @@ enum { static const EnumPropertyItem prop_make_track_types[] = { {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""}, - {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track To Constraint", ""}, + {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track to Constraint", ""}, {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 56bdc5c21f4..017cd63d9d5 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -691,7 +691,7 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; RNA_def_boolean( - ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh"); + ot->srna, "all", 0, "All Hair", "Disconnect all hair systems from the emitter mesh"); } /* from/to_world_space : whether from/to particles are in world or hair space @@ -981,7 +981,7 @@ void PARTICLE_OT_connect_hair(wmOperatorType *ot) /* No REGISTER, redo does not work due to missing update, see T47750. */ ot->flag = OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh"); + RNA_def_boolean(ot->srna, "all", 0, "All Hair", "Connect all hair systems to the emitter mesh"); } /************************ particle system copy operator *********************/ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 27a1d4e4a50..6f80165ed3c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -5523,8 +5523,8 @@ static void keymap_modal_set(wmKeyConfig *keyconf) static const EnumPropertyItem modal_items[] = { {KM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, {KM_MODAL_APPLY, "APPLY", 0, "Apply", ""}, - {KM_MODAL_SNAP_ON, "SNAP", 0, "Snap on", ""}, - {KM_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap off", ""}, + {KM_MODAL_SNAP_ON, "SNAP", 0, "Snap On", ""}, + {KM_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap Off", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 0631b6ea8a0..4d3e6cf4d6a 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1043,13 +1043,13 @@ static int clear_track_path_exec(bContext *C, wmOperator *op) void CLIP_OT_clear_track_path(wmOperatorType *ot) { static const EnumPropertyItem clear_path_actions[] = { - {TRACK_CLEAR_UPTO, "UPTO", 0, "Clear up-to", "Clear path up to current frame"}, + {TRACK_CLEAR_UPTO, "UPTO", 0, "Clear Up To", "Clear path up to current frame"}, {TRACK_CLEAR_REMAINED, "REMAINED", 0, - "Clear remained", + "Clear Remained", "Clear path at remaining frames (after current)"}, - {TRACK_CLEAR_ALL, "ALL", 0, "Clear all", "Clear the whole path"}, + {TRACK_CLEAR_ALL, "ALL", 0, "Clear All", "Clear the whole path"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index 478d22c7582..063ea9592aa 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -975,15 +975,15 @@ static int select_grouped_exec(bContext *C, wmOperator *op) void CLIP_OT_select_grouped(wmOperatorType *ot) { static const EnumPropertyItem select_group_items[] = { - {0, "KEYFRAMED", 0, "Keyframed tracks", "Select all keyframed tracks"}, - {1, "ESTIMATED", 0, "Estimated tracks", "Select all estimated tracks"}, - {2, "TRACKED", 0, "Tracked tracks", "Select all tracked tracks"}, - {3, "LOCKED", 0, "Locked tracks", "Select all locked tracks"}, - {4, "DISABLED", 0, "Disabled tracks", "Select all disabled tracks"}, + {0, "KEYFRAMED", 0, "Keyframed Tracks", "Select all keyframed tracks"}, + {1, "ESTIMATED", 0, "Estimated Tracks", "Select all estimated tracks"}, + {2, "TRACKED", 0, "Tracked Tracks", "Select all tracked tracks"}, + {3, "LOCKED", 0, "Locked Tracks", "Select all locked tracks"}, + {4, "DISABLED", 0, "Disabled Tracks", "Select all disabled tracks"}, {5, "COLOR", 0, - "Tracks with same color", + "Tracks with Same Color", "Select all tracks with same color as active track"}, {6, "FAILED", 0, "Failed Tracks", "Select all tracks which failed to be reconstructed"}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 8a705ef49dd..9554608ea7c 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -97,11 +97,11 @@ EnumPropertyItem sequencer_prop_effect_types[] = { #define SEQ_SIDE_MOUSE -1 EnumPropertyItem prop_side_types[] = { - {SEQ_SIDE_MOUSE, "MOUSE", 0, "Mouse position", ""}, + {SEQ_SIDE_MOUSE, "MOUSE", 0, "Mouse Position", ""}, {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""}, {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""}, {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""}, - {SEQ_SIDE_NO_CHANGE, "NO_CHANGE", 0, "No change", ""}, + {SEQ_SIDE_NO_CHANGE, "NO_CHANGE", 0, "No Change", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 5c7f84ea386..3c3b11f0786 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -409,7 +409,7 @@ void TEXT_OT_open(wmOperatorType *ot) FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); /* TODO: relative_path. */ RNA_def_boolean( - ot->srna, "internal", 0, "Make internal", "Make text file internal after loading"); + ot->srna, "internal", 0, "Make Internal", "Make text file internal after loading"); } /** \} */ @@ -3693,7 +3693,7 @@ void TEXT_OT_replace(wmOperatorType *ot) /* properties */ PropertyRNA *prop; - prop = RNA_def_boolean(ot->srna, "all", false, "Replace all", "Replace all occurrences"); + prop = RNA_def_boolean(ot->srna, "all", false, "Replace All", "Replace all occurrences"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 4e08b6b1c5d..1b1740cd5bc 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -646,12 +646,12 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) static const EnumPropertyItem modal_items[] = { {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, - {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X axis", ""}, - {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y axis", ""}, - {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z axis", ""}, - {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X plane", ""}, - {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y plane", ""}, - {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z plane", ""}, + {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X Axis", ""}, + {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y Axis", ""}, + {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z Axis", ""}, + {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X Plane", ""}, + {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y Plane", ""}, + {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z Plane", ""}, {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Clear Constraints", ""}, {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Snap Invert", ""}, {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Snap Invert (Off)", ""}, @@ -672,13 +672,13 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) 0, "Decrease Max AutoIK Chain Length", ""}, - {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""}, - {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""}, + {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select Next Edge Slide Edge", ""}, + {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select Previous Edge Slide Edge", ""}, {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""}, {TFM_MODAL_INSERTOFS_TOGGLE_DIR, "INSERTOFS_TOGGLE_DIR", 0, - "Toggle Direction for Node Auto-offset", + "Toggle Direction for Node Auto-Offset", ""}, {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Move", ""}, {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""}, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c index aee345757c6..c67d622ffec 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c @@ -215,7 +215,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropDecorate(sub, false); uiItemR(sub, ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT); - col = uiLayoutColumnWithHeading(layout, true, IFACE_("Bind to")); + col = uiLayoutColumnWithHeading(layout, true, IFACE_("Bind To")); uiItemR(col, ptr, "use_vertex_groups", 0, IFACE_("Vertex Groups"), ICON_NONE); uiItemR(col, ptr, "use_bone_envelopes", 0, IFACE_("Bone Envelopes"), ICON_NONE); diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 89687c1234c..576431b7fd1 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -450,7 +450,7 @@ static void rna_def_dopesheet(BlenderRNA *brna) prop = RNA_def_property(srna, "show_shapekeys", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOSHAPEKEYS); RNA_def_property_ui_text( - prop, "Display Shapekeys", "Include visualization of shape key related animation data"); + prop, "Display Shape Keys", "Include visualization of shape key related animation data"); RNA_def_property_ui_icon(prop, ICON_SHAPEKEY_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 79f2ab70651..b02377f4bb0 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -796,7 +796,7 @@ static void rna_def_curvemapping(BlenderRNA *brna) static const EnumPropertyItem tone_items[] = { {CURVE_TONE_STANDARD, "STANDARD", 0, "Standard", ""}, - {CURVE_TONE_FILMLIKE, "FILMLIKE", 0, "Film like", ""}, + {CURVE_TONE_FILMLIKE, "FILMLIKE", 0, "Filmlike", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 0dea0e47978..78d02795325 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4788,7 +4788,7 @@ static void def_sh_tex_voronoi(StructRNA *srna) {SHD_VORONOI_DISTANCE_TO_EDGE, "DISTANCE_TO_EDGE", 0, - "Distance To Edge", + "Distance to Edge", "Computes the distance to the edge of the voronoi cell"}, {SHD_VORONOI_N_SPHERE_RADIUS, "N_SPHERE_RADIUS", @@ -7725,15 +7725,15 @@ static void def_cmp_viewer(StructRNA *srna) static const EnumPropertyItem tileorder_items[] = { {0, "CENTEROUT", 0, "Center", "Expand from center"}, {1, "RANDOM", 0, "Random", "Random tiles"}, - {2, "BOTTOMUP", 0, "Bottom up", "Expand from bottom"}, - {3, "RULE_OF_THIRDS", 0, "Rule of thirds", "Expand from 9 places"}, + {2, "BOTTOMUP", 0, "Bottom Up", "Expand from bottom"}, + {3, "RULE_OF_THIRDS", 0, "Rule of Thirds", "Expand from 9 places"}, {0, NULL, 0, NULL, NULL}, }; prop = RNA_def_property(srna, "tile_order", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, tileorder_items); - RNA_def_property_ui_text(prop, "Tile order", "Tile order"); + RNA_def_property_ui_text(prop, "Tile Order", "Tile order"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "center_x", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 24cff501b59..62d5917bc10 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -379,7 +379,7 @@ const EnumPropertyItem rna_enum_image_type_items[] = { {R_IMF_IMTYPE_FFMPEG, "FFMPEG", ICON_FILE_MOVIE, - "FFmpeg video", + "FFmpeg Video", "The most versatile way to output video files"}, #endif {0, NULL, 0, NULL, NULL}, @@ -2864,13 +2864,13 @@ static void rna_def_tool_settings(BlenderRNA *brna) }; static const EnumPropertyItem gpencil_stroke_snap_items[] = { - {0, "NONE", 0, "All points", "Snap to all points"}, + {0, "NONE", 0, "All Points", "Snap to all points"}, {GP_PROJECT_DEPTH_STROKE_ENDPOINTS, "ENDS", 0, - "End points", + "End Points", "Snap to first and last points and interpolate"}, - {GP_PROJECT_DEPTH_STROKE_FIRST, "FIRST", 0, "First point", "Snap to first point"}, + {GP_PROJECT_DEPTH_STROKE_FIRST, "FIRST", 0, "First Point", "Snap to first point"}, {0, NULL, 0, NULL, NULL}, }; @@ -5510,12 +5510,12 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) "Constant Bitrate", "Configure constant bit rate, rather than constant output quality"}, {FFM_CRF_LOSSLESS, "LOSSLESS", 0, "Lossless", ""}, - {FFM_CRF_PERC_LOSSLESS, "PERC_LOSSLESS", 0, "Perceptually lossless", ""}, - {FFM_CRF_HIGH, "HIGH", 0, "High quality", ""}, - {FFM_CRF_MEDIUM, "MEDIUM", 0, "Medium quality", ""}, - {FFM_CRF_LOW, "LOW", 0, "Low quality", ""}, - {FFM_CRF_VERYLOW, "VERYLOW", 0, "Very low quality", ""}, - {FFM_CRF_LOWEST, "LOWEST", 0, "Lowest quality", ""}, + {FFM_CRF_PERC_LOSSLESS, "PERC_LOSSLESS", 0, "Perceptually Lossless", ""}, + {FFM_CRF_HIGH, "HIGH", 0, "High Quality", ""}, + {FFM_CRF_MEDIUM, "MEDIUM", 0, "Medium Quality", ""}, + {FFM_CRF_LOW, "LOW", 0, "Low Quality", ""}, + {FFM_CRF_VERYLOW, "VERYLOW", 0, "Very Low Quality", ""}, + {FFM_CRF_LOWEST, "LOWEST", 0, "Lowest Quality", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -5738,7 +5738,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {0, "AUTO", 0, - "Auto-detect", + "Auto-Detect", "Automatically determine the number of threads, based on CPUs"}, {R_FIXED_THREADS, "FIXED", 0, "Fixed", "Manually determine the number of threads"}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index c7bdf7a2dd6..e477bf6d284 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -1151,7 +1151,7 @@ static void rna_def_particle_edit(BlenderRNA *brna) static const EnumPropertyItem edit_type_items[] = { {PE_TYPE_PARTICLES, "PARTICLES", 0, "Particles", ""}, - {PE_TYPE_SOFTBODY, "SOFT_BODY", 0, "Soft body", ""}, + {PE_TYPE_SOFTBODY, "SOFT_BODY", 0, "Soft Body", ""}, {PE_TYPE_CLOTH, "CLOTH", 0, "Cloth", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 9d322d0d09b..e180ab5dfb6 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -1936,7 +1936,7 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", SEQ_CACHE_STORE_PREPROCESSED); RNA_def_property_ui_text( prop, - "Cache Pre-processed", + "Cache Pre-Processed", "Cache pre-processed images, for faster tweaking of effects at the cost of memory usage"); prop = RNA_def_property(srna, "use_cache_composite", PROP_BOOLEAN, PROP_NONE); @@ -2100,7 +2100,7 @@ static void rna_def_editor(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0f, SEQ_CACHE_COST_MAX, 0.1f, 1); RNA_def_property_float_sdna(prop, NULL, "recycle_max_cost"); RNA_def_property_ui_text( - prop, "Recycle Up To Cost", "Only frames with cost lower than this value will be recycled"); + prop, "Recycle Up to Cost", "Only frames with cost lower than this value will be recycled"); } static void rna_def_filter_video(StructRNA *srna) @@ -2822,7 +2822,7 @@ static void rna_def_speed_control(StructRNA *srna) prop = RNA_def_property(srna, "use_frame_interpolate", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", SEQ_SPEED_USE_INTERPOLATION); RNA_def_property_ui_text( - prop, "Frame interpolation", "Do crossfade blending between current and next frame"); + prop, "Frame Interpolation", "Do crossfade blending between current and next frame"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); } diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 3255f335e74..f5f7930964a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -5185,7 +5185,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) prop = RNA_def_property(srna, "show_interpolation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SHOW_INTERPOLATION); RNA_def_property_ui_text(prop, - "Show Handles And Interpolation", + "Show Handles and Interpolation", "Display keyframe handle types and non-bezier interpolation modes"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); @@ -5208,7 +5208,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) /* editing */ prop = RNA_def_property(srna, "use_auto_merge_keyframes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NOTRANSKEYCULL); - RNA_def_property_ui_text(prop, "AutoMerge Keyframes", "Automatically merge nearby keyframes"); + RNA_def_property_ui_text(prop, "Auto-Merge Keyframes", "Automatically merge nearby keyframes"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 4d5f0f6c2fa..fb6d40b3a55 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -1074,8 +1074,8 @@ static void rna_def_texture_stucci(BlenderRNA *brna) static const EnumPropertyItem prop_stucci_stype[] = { {TEX_PLASTIC, "PLASTIC", 0, "Plastic", "Use standard stucci"}, - {TEX_WALLIN, "WALL_IN", 0, "Wall in", "Create Dimples"}, - {TEX_WALLOUT, "WALL_OUT", 0, "Wall out", "Create Ridges"}, + {TEX_WALLIN, "WALL_IN", 0, "Wall In", "Create Dimples"}, + {TEX_WALLOUT, "WALL_OUT", 0, "Wall Out", "Create Ridges"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index c31766efe58..3d389dd9b07 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -4786,7 +4786,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) prop = RNA_def_property(srna, "font_path_ui_mono", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "font_path_ui_mono"); - RNA_def_property_ui_text(prop, "Mono-space Font", "Path to interface mono-space Font"); + RNA_def_property_ui_text(prop, "Monospaced Font", "Path to interface monospaced Font"); RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_font_update"); /* Language. */ diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 324cac3df8b..38fb19e3233 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -258,7 +258,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(col, ptr, "use_deform_preserve_volume", 0, NULL, ICON_NONE); uiItemR(col, ptr, "use_multi_modifier", 0, NULL, ICON_NONE); - col = uiLayoutColumnWithHeading(layout, true, IFACE_("Bind to")); + col = uiLayoutColumnWithHeading(layout, true, IFACE_("Bind To")); uiItemR(col, ptr, "use_vertex_groups", 0, IFACE_("Vertex Groups"), ICON_NONE); uiItemR(col, ptr, "use_bone_envelopes", 0, IFACE_("Bone Envelopes"), ICON_NONE); diff --git a/source/blender/modifiers/intern/MOD_ui_common.c b/source/blender/modifiers/intern/MOD_ui_common.c index bad76a0b559..ba43434aeb3 100644 --- a/source/blender/modifiers/intern/MOD_ui_common.c +++ b/source/blender/modifiers/intern/MOD_ui_common.c @@ -229,14 +229,14 @@ static void modifier_ops_extra_draw(bContext *C, uiLayout *layout, void *md_v) /* Apply as shapekey. */ if (BKE_modifier_is_same_topology(md) && !BKE_modifier_is_non_geometrical(md)) { uiItemBooleanO(layout, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply As Shapekey"), + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"), ICON_SHAPEKEY_DATA, "OBJECT_OT_modifier_apply_as_shapekey", "keep_modifier", false); uiItemBooleanO(layout, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Save As Shapekey"), + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Save as Shape Key"), ICON_SHAPEKEY_DATA, "OBJECT_OT_modifier_apply_as_shapekey", "keep_modifier", diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 613de5a9b17..4604f66d866 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3771,7 +3771,7 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf) {GESTURE_MODAL_CIRCLE_SIZE, "SIZE", 0, "Size", ""}, {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, - {GESTURE_MODAL_DESELECT, "DESELECT", 0, "DeSelect", ""}, + {GESTURE_MODAL_DESELECT, "DESELECT", 0, "Deselect", ""}, {GESTURE_MODAL_NOP, "NOP", 0, "No Operation", ""}, {0, NULL, 0, NULL, NULL}, @@ -3834,7 +3834,7 @@ static void gesture_box_modal_keymap(wmKeyConfig *keyconf) static const EnumPropertyItem modal_items[] = { {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, - {GESTURE_MODAL_DESELECT, "DESELECT", 0, "DeSelect", ""}, + {GESTURE_MODAL_DESELECT, "DESELECT", 0, "Deselect", ""}, {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""}, {0, NULL, 0, NULL, NULL}, -- cgit v1.2.3 From 574d711008ab430228ce26eac05e9de3b0b828f2 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sat, 24 Oct 2020 14:44:28 -0400 Subject: Fix T81884, clamping with percent, addendum. The previous fix forgot the case where there is an intermediate edge and everything isn't in one plane. Differential Revision: https://developer.blender.org/D9336 --- source/blender/bmesh/tools/bmesh_bevel.c | 33 +++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index f54db513d0f..3a6ae9883e2 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1520,9 +1520,16 @@ static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *em * in-between edge emid. Viewed from the vertex normal side, the CCW order of these edges is e1, * emid, e2. Return true if we placed meetco as compromise between where two edges met. If we did, * put the ratio of sines of angles in *r_sinratio too. + * However, if the bp->offset_type is BEVEL_AMT_PERCENT or BEVEL_AMT_ABSOLUTE, we just slide + * along emid by the specified amount. */ -static bool offset_on_edge_between( - EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v, float meetco[3], float *r_sinratio) +static bool offset_on_edge_between(BevelParams *bp, + EdgeHalf *e1, + EdgeHalf *e2, + EdgeHalf *emid, + BMVert *v, + float meetco[3], + float *r_sinratio) { bool retval = false; @@ -1532,6 +1539,22 @@ static bool offset_on_edge_between( float meet1[3], meet2[3]; bool ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1); bool ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2); + if (bp->offset_type == BEVEL_AMT_PERCENT || bp->offset_type == BEVEL_AMT_ABSOLUTE) { + BMVert *v2 = BM_edge_other_vert(emid->e, v); + if (bp->offset_type == BEVEL_AMT_PERCENT) { + interp_v3_v3v3(meetco, v->co, v2->co, bp->offset / 100.0f); + } + else { + float dir[3]; + sub_v3_v3v3(dir, v2->co, v->co); + normalize_v3(dir); + madd_v3_v3v3fl(meetco, v->co, dir, bp->offset); + } + if (r_sinratio) { + *r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1); + } + return true; + } if (ok1 && ok2) { mid_v3_v3v3(meetco, meet1, meet2); if (r_sinratio) { @@ -2953,7 +2976,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) } else if (not_in_plane > 0) { if (bp->loop_slide && not_in_plane == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) { - if (offset_on_edge_between(e, e2, enip, bv->v, co, &r)) { + if (offset_on_edge_between(bp, e, e2, enip, bv->v, co, &r)) { eon = enip; } } @@ -2964,7 +2987,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) else { /* n_in_plane > 0 and n_not_in_plane == 0. */ if (bp->loop_slide && in_plane == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) { - if (offset_on_edge_between(e, e2, eip, bv->v, co, &r)) { + if (offset_on_edge_between(bp, e, e2, eip, bv->v, co, &r)) { eon = eip; } } @@ -7195,7 +7218,7 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb) if (bp->offset_type == BEVEL_AMT_PERCENT || bp->offset_type == BEVEL_AMT_ABSOLUTE) { if (ea->is_bev && ebother != NULL && ebother->prev->is_bev) { if (bp->offset_type == BEVEL_AMT_PERCENT) { - return bp->offset > 50.0f ? 50.0f : 100.f; + return 50.0f; } /* This is only right sometimes. The exact answer is very hard to calculate. */ float blen = BM_edge_calc_length(eb->e); -- cgit v1.2.3 From 2f9068449f97d8a4ca1a8ccc4e0b5bdccb3bffe4 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sat, 24 Oct 2020 15:09:10 -0400 Subject: Fix T81884, clamping with percent, addendum. The previous fix forgot the case where there is an intermediate edge and everything isn't in one plane. --- source/blender/bmesh/tools/bmesh_bevel.c | 33 +++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index f54db513d0f..3a6ae9883e2 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1520,9 +1520,16 @@ static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *em * in-between edge emid. Viewed from the vertex normal side, the CCW order of these edges is e1, * emid, e2. Return true if we placed meetco as compromise between where two edges met. If we did, * put the ratio of sines of angles in *r_sinratio too. + * However, if the bp->offset_type is BEVEL_AMT_PERCENT or BEVEL_AMT_ABSOLUTE, we just slide + * along emid by the specified amount. */ -static bool offset_on_edge_between( - EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v, float meetco[3], float *r_sinratio) +static bool offset_on_edge_between(BevelParams *bp, + EdgeHalf *e1, + EdgeHalf *e2, + EdgeHalf *emid, + BMVert *v, + float meetco[3], + float *r_sinratio) { bool retval = false; @@ -1532,6 +1539,22 @@ static bool offset_on_edge_between( float meet1[3], meet2[3]; bool ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1); bool ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2); + if (bp->offset_type == BEVEL_AMT_PERCENT || bp->offset_type == BEVEL_AMT_ABSOLUTE) { + BMVert *v2 = BM_edge_other_vert(emid->e, v); + if (bp->offset_type == BEVEL_AMT_PERCENT) { + interp_v3_v3v3(meetco, v->co, v2->co, bp->offset / 100.0f); + } + else { + float dir[3]; + sub_v3_v3v3(dir, v2->co, v->co); + normalize_v3(dir); + madd_v3_v3v3fl(meetco, v->co, dir, bp->offset); + } + if (r_sinratio) { + *r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1); + } + return true; + } if (ok1 && ok2) { mid_v3_v3v3(meetco, meet1, meet2); if (r_sinratio) { @@ -2953,7 +2976,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) } else if (not_in_plane > 0) { if (bp->loop_slide && not_in_plane == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) { - if (offset_on_edge_between(e, e2, enip, bv->v, co, &r)) { + if (offset_on_edge_between(bp, e, e2, enip, bv->v, co, &r)) { eon = enip; } } @@ -2964,7 +2987,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) else { /* n_in_plane > 0 and n_not_in_plane == 0. */ if (bp->loop_slide && in_plane == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) { - if (offset_on_edge_between(e, e2, eip, bv->v, co, &r)) { + if (offset_on_edge_between(bp, e, e2, eip, bv->v, co, &r)) { eon = eip; } } @@ -7195,7 +7218,7 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb) if (bp->offset_type == BEVEL_AMT_PERCENT || bp->offset_type == BEVEL_AMT_ABSOLUTE) { if (ea->is_bev && ebother != NULL && ebother->prev->is_bev) { if (bp->offset_type == BEVEL_AMT_PERCENT) { - return bp->offset > 50.0f ? 50.0f : 100.f; + return 50.0f; } /* This is only right sometimes. The exact answer is very hard to calculate. */ float blen = BM_edge_calc_length(eb->e); -- cgit v1.2.3 From 1c653a0315b04269a2e7385efad6a033ddad2420 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sat, 24 Oct 2020 17:36:38 -0400 Subject: Fix T81999, Boolean Exact+Self Difference fails. A cell with winding number > 1 for the second operand was incorrectly included in the output. --- source/blender/blenlib/intern/mesh_boolean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 169687cf9d1..bad0b84d10f 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -2068,7 +2068,7 @@ static bool apply_bool_op(BoolOpType bool_optype, const Array &winding) return true; } for (int i = 1; i < nw; ++i) { - if (winding[i] == 1) { + if (winding[i] >= 1) { return false; } } -- cgit v1.2.3 From 05129bc821fd386b211e3e5ac981f97eb81d79e7 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sat, 24 Oct 2020 17:44:59 -0400 Subject: Fix T81999, Boolean Exact+Self Difference fails. A cell with winding number > 1 for the second operand was incorrectly included in the output. --- source/blender/blenlib/intern/mesh_boolean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 169687cf9d1..bad0b84d10f 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -2068,7 +2068,7 @@ static bool apply_bool_op(BoolOpType bool_optype, const Array &winding) return true; } for (int i = 1; i < nw; ++i) { - if (winding[i] == 1) { + if (winding[i] >= 1) { return false; } } -- cgit v1.2.3 From 76fd84f20949ec3d09afc30001e8d9d6a43601ea Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sat, 24 Oct 2020 23:32:11 -0500 Subject: Cleanup: Use LISTBASE_FOREACH in curve code This is a followup to rBa308607a533, using the macro in a few places that were missed. --- source/blender/blenkernel/intern/curve.c | 13 ++++----- source/blender/editors/curve/editcurve_query.c | 4 +-- source/blender/editors/curve/editcurve_select.c | 33 ++++++++-------------- source/blender/editors/object/object_hook.c | 8 ++---- .../blender/editors/space_view3d/view3d_buttons.c | 11 ++------ source/blender/makesrna/intern/rna_curve.c | 8 ++---- 6 files changed, 25 insertions(+), 52 deletions(-) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 82548112096..fa45a4ba836 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -438,7 +438,6 @@ ListBase *BKE_curve_editNurbs_get(Curve *cu) short BKE_curve_type_get(const Curve *cu) { - Nurb *nu; int type = cu->type; if (cu->vfont) { @@ -448,7 +447,7 @@ short BKE_curve_type_get(const Curve *cu) if (!cu->type) { type = OB_CURVE; - for (nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { if (nu->pntsv > 1) { type = OB_SURF; } @@ -5276,8 +5275,7 @@ void BKE_curve_transform_ex(Curve *cu, } if (do_keys && cu->key) { - KeyBlock *kb; - for (kb = cu->key->block.first; kb; kb = kb->next) { + LISTBASE_FOREACH (KeyBlock *, kb, &cu->key->block) { float *fp = kb->data; int n = kb->totelem; @@ -5437,9 +5435,8 @@ bool BKE_curve_material_index_validate(Curve *cu) } } else { - Nurb *nu; const int max_idx = max_ii(0, cu->totcol - 1); - for (nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { if (nu->mat_nr > max_idx) { nu->mat_nr = 0; is_valid = false; @@ -5505,12 +5502,12 @@ void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int void BKE_curve_smooth_flag_set(Curve *cu, const bool use_smooth) { if (use_smooth) { - for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { nu->flag |= CU_SMOOTH; } } else { - for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { nu->flag &= ~CU_SMOOTH; } } diff --git a/source/blender/editors/curve/editcurve_query.c b/source/blender/editors/curve/editcurve_query.c index 48571ab2a9b..369137cbe25 100644 --- a/source/blender/editors/curve/editcurve_query.c +++ b/source/blender/editors/curve/editcurve_query.c @@ -26,6 +26,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_curve.h" @@ -170,7 +171,6 @@ void ED_curve_nurb_vert_selected_find( /* in nu and (bezt or bp) selected are written if there's 1 sel. */ /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */ ListBase *editnurb = &cu->editnurb->nurbs; - Nurb *nu1; BezTriple *bezt1; BPoint *bp1; int a; @@ -179,7 +179,7 @@ void ED_curve_nurb_vert_selected_find( *r_bezt = NULL; *r_bp = NULL; - for (nu1 = editnurb->first; nu1; nu1 = nu1->next) { + LISTBASE_FOREACH (Nurb *, nu1, editnurb) { if (nu1->type == CU_BEZIER) { bezt1 = nu1->bezt; a = nu1->pntsu; diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index aa4ba332b66..cb0a66bf5a8 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -237,9 +237,7 @@ int ED_curve_select_count(View3D *v3d, struct EditNurb *editnurb) bool ED_curve_select_check(View3D *v3d, struct EditNurb *editnurb) { - Nurb *nu; - - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (ED_curve_nurb_select_check(v3d, nu)) { return true; } @@ -284,13 +282,12 @@ bool ED_curve_deselect_all_multi(struct bContext *C) bool ED_curve_select_swap(EditNurb *editnurb, bool hide_handles) { - Nurb *nu; BPoint *bp; BezTriple *bezt; int a; bool changed = false; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -331,7 +328,6 @@ static void select_adjacent_cp(ListBase *editnurb, const bool cont, const bool selstatus) { - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; @@ -341,7 +337,7 @@ static void select_adjacent_cp(ListBase *editnurb, return; } - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { lastsel = false; if (nu->type == CU_BEZIER) { a = nu->pntsu; @@ -412,7 +408,6 @@ static void select_adjacent_cp(ListBase *editnurb, static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; Curve *cu; @@ -425,7 +420,7 @@ static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap cu = (Curve *)obedit->data; cu->actvert = CU_ACT_NONE; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { a = nu->pntsu; @@ -632,10 +627,9 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; ListBase *nurbs = &editnurb->nurbs; - Nurb *nu; bool changed = false; - for (nu = nurbs->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { if (ED_curve_nurb_select_check(v3d, nu)) { changed |= ED_curve_nurb_select_all(nu); } @@ -887,7 +881,6 @@ void CURVE_OT_select_previous(wmOperatorType *ot) static void curve_select_more(Object *obedit) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp, *tempbp; int a; short sel = 0; @@ -897,7 +890,7 @@ static void curve_select_more(Object *obedit) /* The algorithm is designed to work in planar cases so it */ /* may not be optimal always (example: end of NURBS sphere) */ if (obedit->type == OB_SURF) { - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { BLI_bitmap *selbpoints; a = nu->pntsu * nu->pntsv; bp = nu->bp; @@ -997,7 +990,6 @@ void CURVE_OT_select_more(wmOperatorType *ot) static void curve_select_less(Object *obedit) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int a; @@ -1005,7 +997,7 @@ static void curve_select_less(Object *obedit) bool lastsel = false; if (obedit->type == OB_SURF) { - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { BLI_bitmap *selbpoints; a = nu->pntsu * nu->pntsv; bp = nu->bp; @@ -1077,7 +1069,7 @@ static void curve_select_less(Object *obedit) } } else { - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { lastsel = false; /* check what type of curve/nurb it is */ if (nu->type == CU_BEZIER) { @@ -1210,14 +1202,13 @@ void CURVE_OT_select_less(wmOperatorType *ot) static void curve_select_random(ListBase *editnurb, float randfac, int seed, bool select) { - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; RNG *rng = BLI_rng_new_srandom(seed); - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -1702,8 +1693,7 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op) Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; - Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (!ED_curve_nurb_select_check(v3d, nu)) { continue; } @@ -1736,9 +1726,8 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op) Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; bool changed = false; - Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { switch (optype) { case SIMCURHAND_TYPE: { if (nu->type & type_ref) { diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 5cfe02dbc59..91c9916d227 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -238,12 +238,11 @@ static void select_editlattice_hook(Object *obedit, HookModifierData *hmd) static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, float r_cent[3]) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int *index, a, nr, totvert = 0; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -280,7 +279,7 @@ static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, nr = 0; zero_v3(r_cent); - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -377,12 +376,11 @@ static bool object_hook_index_array(Main *bmain, static void select_editcurve_hook(Object *obedit, HookModifierData *hmd) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int index = 0, a, nr = 0; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 8e03ed6e11d..f67eb73bbd1 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -283,7 +283,6 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float else if (ob->type == OB_CURVE || ob->type == OB_SURF) { TransformMedian_Curve *median = &median_basis.curve; Curve *cu = ob->data; - Nurb *nu; BPoint *bp; BezTriple *bezt; int a; @@ -291,8 +290,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float StructRNA *seltype = NULL; void *selp = NULL; - nu = nurbs->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -343,7 +341,6 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float bp++; } } - nu = nu->next; } if (totcurvedata == 1) { @@ -973,15 +970,13 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float const TransformMedian_Curve *median = &median_basis.curve, *ve_median = &ve_median_basis.curve; Curve *cu = ob->data; - Nurb *nu; BPoint *bp; BezTriple *bezt; int a; ListBase *nurbs = BKE_curve_editNurbs_get(cu); const float scale_w = compute_scale_factor(ve_median->weight, median->weight); - nu = nurbs->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { if (nu->type == CU_BEZIER) { for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) { if (bezt->f2 & SELECT) { @@ -1038,8 +1033,6 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } BKE_nurb_test_2d(nu); BKE_nurb_handles_test(nu, true, false); /* test for bezier too */ - - nu = nu->next; } } else if ((ob->type == OB_LATTICE) && (apply_vcos || median_basis.lattice.weight)) { diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 2d6bf2897e0..2e73fabe103 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -543,11 +543,9 @@ static void rna_Curve_resolution_u_update_data(Main *bmain, Scene *scene, Pointe { Curve *cu = (Curve *)ptr->owner_id; ListBase *nurbs = BKE_curve_nurbs_get(cu); - Nurb *nu = nurbs->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { nu->resolu = cu->resolu; - nu = nu->next; } rna_Curve_update_data(bmain, scene, ptr); @@ -557,11 +555,9 @@ static void rna_Curve_resolution_v_update_data(Main *bmain, Scene *scene, Pointe { Curve *cu = (Curve *)ptr->owner_id; ListBase *nurbs = BKE_curve_nurbs_get(cu); - Nurb *nu = nurbs->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { nu->resolv = cu->resolv; - nu = nu->next; } rna_Curve_update_data(bmain, scene, ptr); -- cgit v1.2.3 From 1d9499bbbc2c01f4de50cf55c8177de3d7bfdd9b Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sat, 24 Oct 2020 23:58:32 -0500 Subject: UI Code Quality: Cleanup ui_but_update_from_old_block This commit contains some improvements to this function to make this function more purposeful and readable. - Split updating information of the old button to a new function. - Remove some 7 year old code disabled with `#if 0`. - Add comments explaining some of the less obvious aspects. Differential Revision: https://developer.blender.org/D9117 --- source/blender/editors/interface/interface.c | 202 ++++++++++++++------------- 1 file changed, 102 insertions(+), 100 deletions(-) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 601ab44c3d6..ea9385cb08f 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -771,6 +771,95 @@ static void ui_but_extra_icons_update_from_old_but(const uiBut *new_but, const u } } +/** + * Update pointers and other information in the old active button based on new information in the + * corresponding new button from the current layout pass. + * + * \param oldbut: The button from the last layout pass that will be moved to the new block. + * \param but: The newly added button with much of the up to date information, to be feed later. + * + * \note #uiBut has ownership of many of its pointers. When the button is freed all these + * pointers are freed as well, so ownership has to be moved out of \a but in order to free it. + */ +static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but) +{ + BLI_assert(oldbut->active); + + /* flags from the buttons we want to refresh, may want to add more here... */ + const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON; + const int drawflag_copy = 0; /* None currently. */ + + /* still stuff needs to be copied */ + oldbut->rect = but->rect; + oldbut->context = but->context; /* set by Layout */ + + /* drawing */ + oldbut->icon = but->icon; + oldbut->iconadd = but->iconadd; + oldbut->alignnr = but->alignnr; + + /* typically the same pointers, but not on undo/redo */ + /* XXX some menu buttons store button itself in but->poin. Ugly */ + if (oldbut->poin != (char *)oldbut) { + SWAP(char *, oldbut->poin, but->poin); + SWAP(void *, oldbut->func_argN, but->func_argN); + } + + /* Move tooltip from new to old. */ + SWAP(uiButToolTipFunc, oldbut->tip_func, but->tip_func); + SWAP(void *, oldbut->tip_argN, but->tip_argN); + + oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy); + oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy); + + ui_but_extra_icons_update_from_old_but(but, oldbut); + SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons); + + if (oldbut->type == UI_BTYPE_SEARCH_MENU) { + uiButSearch *search_oldbut = (uiButSearch *)oldbut, *search_but = (uiButSearch *)but; + + SWAP(uiButSearchArgFreeFn, search_oldbut->arg_free_fn, search_but->arg_free_fn); + SWAP(void *, search_oldbut->arg, search_but->arg); + } + + /* copy hardmin for list rows to prevent 'sticking' highlight to mouse position + * when scrolling without moving mouse (see T28432) */ + if (ELEM(oldbut->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) { + oldbut->hardmax = but->hardmax; + } + + if (oldbut->type == UI_BTYPE_PROGRESS_BAR) { + uiButProgressbar *progress_oldbut = (uiButProgressbar *)oldbut; + uiButProgressbar *progress_but = (uiButProgressbar *)but; + progress_oldbut->progress = progress_but->progress; + } + + /* move/copy string from the new button to the old */ + /* needed for alt+mouse wheel over enums */ + if (but->str != but->strdata) { + if (oldbut->str != oldbut->strdata) { + SWAP(char *, but->str, oldbut->str); + } + else { + oldbut->str = but->str; + but->str = but->strdata; + } + } + else { + if (oldbut->str != oldbut->strdata) { + MEM_freeN(oldbut->str); + oldbut->str = oldbut->strdata; + } + BLI_strncpy(oldbut->strdata, but->strdata, sizeof(oldbut->strdata)); + } + + if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + SWAP(void *, but->dragpoin, oldbut->dragpoin); + } + + /* note: if layout hasn't been applied yet, it uses old button pointers... */ +} + /** * \return true when \a but_p is set (only done for active buttons). */ @@ -779,138 +868,51 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBut **but_p, uiBut **but_old_p) { - const int drawflag_copy = 0; /* None currently. */ - uiBlock *oldblock = block->oldblock; - uiBut *oldbut = NULL, *but = *but_p; - bool found_active = false; + uiBut *but = *but_p; #if 0 - /* simple/stupid - search every time */ - oldbut = ui_but_find_old(oldblock, but); - (void)but_old_p; + /* Simple method - search every time. Keep this for easy testing of the "fast path." */ + uiBut *oldbut = ui_but_find_old(oldblock, but); + UNUSED_VARS(but_old_p); #else BLI_assert(*but_old_p == NULL || BLI_findindex(&oldblock->buttons, *but_old_p) != -1); - /* Fast-path - avoid loop-in-loop, calling #ui_but_find_old - * as long as old/new buttons are aligned. */ + /* As long as old and new buttons are aligned, avoid loop-in-loop (calling #ui_but_find_old). */ + uiBut *oldbut; if (LIKELY(*but_old_p && ui_but_equals_old(but, *but_old_p))) { oldbut = *but_old_p; } else { - /* fallback to block search */ + /* Fallback to block search. */ oldbut = ui_but_find_old(oldblock, but); } (*but_old_p) = oldbut ? oldbut->next : NULL; #endif + bool found_active = false; + if (!oldbut) { - return found_active; + return false; } if (oldbut->active) { - /* flags from the buttons we want to refresh, may want to add more here... */ - const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON; - - found_active = true; - -#if 0 - but->flag = oldbut->flag; - but->active = oldbut->active; - but->pos = oldbut->pos; - but->ofs = oldbut->ofs; - but->editstr = oldbut->editstr; - but->editval = oldbut->editval; - but->editvec = oldbut->editvec; - but->selsta = oldbut->selsta; - but->selend = oldbut->selend; - but->softmin = oldbut->softmin; - but->softmax = oldbut->softmax; - oldbut->active = NULL; -#endif - - /* move button over from oldblock to new block */ + /* Move button over from oldblock to new block. */ BLI_remlink(&oldblock->buttons, oldbut); BLI_insertlinkafter(&block->buttons, but, oldbut); oldbut->block = block; *but_p = oldbut; - /* still stuff needs to be copied */ - oldbut->rect = but->rect; - oldbut->context = but->context; /* set by Layout */ - - /* drawing */ - oldbut->icon = but->icon; - oldbut->iconadd = but->iconadd; - oldbut->alignnr = but->alignnr; - - /* typically the same pointers, but not on undo/redo */ - /* XXX some menu buttons store button itself in but->poin. Ugly */ - if (oldbut->poin != (char *)oldbut) { - SWAP(char *, oldbut->poin, but->poin); - SWAP(void *, oldbut->func_argN, but->func_argN); - } - - /* Move tooltip from new to old. */ - SWAP(uiButToolTipFunc, oldbut->tip_func, but->tip_func); - SWAP(void *, oldbut->tip_argN, but->tip_argN); - - oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy); - oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy); - - ui_but_extra_icons_update_from_old_but(but, oldbut); - SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons); - - if (oldbut->type == UI_BTYPE_SEARCH_MENU) { - uiButSearch *search_oldbut = (uiButSearch *)oldbut, *search_but = (uiButSearch *)but; - - SWAP(uiButSearchArgFreeFn, search_oldbut->arg_free_fn, search_but->arg_free_fn); - SWAP(void *, search_oldbut->arg, search_but->arg); - } - - /* copy hardmin for list rows to prevent 'sticking' highlight to mouse position - * when scrolling without moving mouse (see T28432) */ - if (ELEM(oldbut->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) { - oldbut->hardmax = but->hardmax; - } - - if (oldbut->type == UI_BTYPE_PROGRESS_BAR) { - uiButProgressbar *progress_oldbut = (uiButProgressbar *)oldbut; - uiButProgressbar *progress_but = (uiButProgressbar *)but; - progress_oldbut->progress = progress_but->progress; - } + ui_but_update_old_active_from_new(oldbut, but); if (!BLI_listbase_is_empty(&block->butstore)) { UI_butstore_register_update(block, oldbut, but); } - /* move/copy string from the new button to the old */ - /* needed for alt+mouse wheel over enums */ - if (but->str != but->strdata) { - if (oldbut->str != oldbut->strdata) { - SWAP(char *, but->str, oldbut->str); - } - else { - oldbut->str = but->str; - but->str = but->strdata; - } - } - else { - if (oldbut->str != oldbut->strdata) { - MEM_freeN(oldbut->str); - oldbut->str = oldbut->strdata; - } - BLI_strncpy(oldbut->strdata, but->strdata, sizeof(oldbut->strdata)); - } - - if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) { - SWAP(void *, but->dragpoin, oldbut->dragpoin); - } - BLI_remlink(&block->buttons, but); ui_but_free(C, but); - /* note: if layout hasn't been applied yet, it uses old button pointers... */ + found_active = true; } else { const int flag_copy = UI_BUT_DRAG_MULTI; -- cgit v1.2.3 From c15bd1c4e658f2a19cf74a0f7aaa892c883a7fb1 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Sun, 25 Oct 2020 22:48:49 +0100 Subject: Sculpt: Face Set Edit delete Geometry operation This adds an operation mode to the Face Set Edit tool which deletes the geometry of a Face Set by clicking on it. The operator also checks for the mesh having a single Face Set to avoid deleting the entire object by accident. This is also disabled for Multires to avoid modifying the limit surface without control (it is not an important limitation as base meshes for multires are usually final, but maybe it can be supported in the future). Reviewed By: sergey Differential Revision: https://developer.blender.org/D8938 --- .../keyconfig/keymap_data/blender_default.py | 4 +- .../blender/editors/sculpt_paint/sculpt_face_set.c | 215 +++++++++++++++++---- 2 files changed, 176 insertions(+), 43 deletions(-) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index c462bf12825..97acdfd311c 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -6490,10 +6490,8 @@ def km_3d_view_tool_sculpt_face_set_edit(params): "3D View Tool: Sculpt, Face Set Edit", {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, {"items": [ - ("sculpt.face_set_edit", {"type": params.tool_mouse, "value": 'ANY'}, + ("sculpt.face_set_edit", {"type": params.tool_mouse, "value": 'PRESS'}, None), - ("sculpt.face_set_edit", {"type": params.tool_tweak, "value": 'ANY'}, - None) ]}, ) diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index af6a06caf69..3c87407b2db 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -1018,6 +1018,7 @@ void SCULPT_OT_face_sets_randomize_colors(wmOperatorType *ot) typedef enum eSculptFaceSetEditMode { SCULPT_FACE_SET_EDIT_GROW = 0, SCULPT_FACE_SET_EDIT_SHRINK = 1, + SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY = 2, } eSculptFaceSetEditMode; static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = { @@ -1035,6 +1036,13 @@ static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = { "Shrink Face Set", "Shrinks the Face Sets boundary by one face based on mesh topology", }, + { + SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY, + "DELETE_GEOMETRY", + 0, + "Delete Geometry", + "Deletes the faces that are assigned to the Face Set", + }, {0, NULL, 0, NULL, NULL}, }; @@ -1096,6 +1104,78 @@ static void sculpt_face_set_shrink(Object *ob, } } +static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool check_visible_only) +{ + + int first_face_set = SCULPT_FACE_SET_NONE; + if (check_visible_only) { + for (int f = 0; f < ss->totfaces; f++) { + if (face_sets[f] > 0) { + first_face_set = face_sets[f]; + break; + } + } + } + else { + first_face_set = abs(face_sets[0]); + } + + if (first_face_set == SCULPT_FACE_SET_NONE) { + return true; + } + + for (int f = 0; f < ss->totfaces; f++) { + const int face_set_id = check_visible_only ? face_sets[f] : abs(face_sets[f]); + if (face_set_id != first_face_set) { + return false; + } + } + return true; +} + +static void sculpt_face_set_delete_geometry(Object *ob, + SculptSession *ss, + const int active_face_set_id, + const bool modify_hidden) +{ + + Mesh *mesh = ob->data; + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); + BMesh *bm = BM_mesh_create(&allocsize, + &((struct BMeshCreateParams){ + .use_toolflags = true, + })); + + BM_mesh_bm_from_me(bm, + mesh, + (&(struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + + BM_mesh_elem_table_init(bm, BM_FACE); + BM_mesh_elem_table_ensure(bm, BM_FACE); + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + BMIter iter; + BMFace *f; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + const int face_index = BM_elem_index_get(f); + const int face_set_id = modify_hidden ? abs(ss->face_sets[face_index]) : + ss->face_sets[face_index]; + BM_elem_flag_set(f, BM_ELEM_TAG, face_set_id == active_face_set_id); + } + BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES); + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + + BM_mesh_bm_to_me(NULL, + bm, + ob->data, + (&(struct BMeshToMeshParams){ + .calc_object_remap = false, + })); + + BM_mesh_free(bm); +} + static void sculpt_face_set_apply_edit(Object *ob, const int active_face_set_id, const int mode, @@ -1103,80 +1183,135 @@ static void sculpt_face_set_apply_edit(Object *ob, { SculptSession *ss = ob->sculpt; - int *prev_face_sets = MEM_dupallocN(ss->face_sets); - switch (mode) { - case SCULPT_FACE_SET_EDIT_GROW: + case SCULPT_FACE_SET_EDIT_GROW: { + int *prev_face_sets = MEM_dupallocN(ss->face_sets); sculpt_face_set_grow(ob, ss, prev_face_sets, active_face_set_id, modify_hidden); + MEM_SAFE_FREE(prev_face_sets); break; - case SCULPT_FACE_SET_EDIT_SHRINK: + } + case SCULPT_FACE_SET_EDIT_SHRINK: { + int *prev_face_sets = MEM_dupallocN(ss->face_sets); sculpt_face_set_shrink(ob, ss, prev_face_sets, active_face_set_id, modify_hidden); + MEM_SAFE_FREE(prev_face_sets); + break; + } + case SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY: + sculpt_face_set_delete_geometry(ob, ss, active_face_set_id, modify_hidden); break; } - - MEM_SAFE_FREE(prev_face_sets); } -static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static bool sculpt_face_set_edit_is_operation_valid(SculptSession *ss, + const eSculptFaceSetEditMode mode, + const bool modify_hidden) { - Object *ob = CTX_data_active_object(C); - SculptSession *ss = ob->sculpt; - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - - const int mode = RNA_enum_get(op->ptr, "mode"); - - /* Dyntopo not supported. */ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { + /* Dyntopo is not supported. */ return OPERATOR_CANCELLED; } - /* Ignore other events to avoid repeated operations. */ - if (event->val != KM_PRESS) { - return OPERATOR_CANCELLED; + if (mode == SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY) { + if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) { + /* Modification of base mesh geometry requires special remapping of multires displacement, + * which does not happen here. + * Disable delete operation. It can be supported in the future by doing similar displacement + * data remapping as what happens in the mesh edit mode. */ + return false; + } + if (check_single_face_set(ss, ss->face_sets, !modify_hidden)) { + /* Cancel the operator if the mesh only contains one Face Set to avoid deleting the + * entire object. */ + return false; + } } + return true; +} - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); +static void sculpt_face_set_edit_modify_geometry(bContext *C, + Object *ob, + const int active_face_set, + const eSculptFaceSetEditMode mode, + const bool modify_hidden) +{ + ED_sculpt_undo_geometry_begin(ob, "edit face set delete geometry"); + sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden); + ED_sculpt_undo_geometry_end(ob); + BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); +} - /* Update the current active Face Set and Vertex as the operator can be used directly from the - * tool without brush cursor. */ - SculptCursorGeometryInfo sgi; - float mouse[2]; - mouse[0] = event->mval[0]; - mouse[1] = event->mval[1]; - SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); +static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **nodes, int totnode) +{ + SculptSession *ss = ob->sculpt; + PBVH *pbvh = ss->pbvh; + + /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */ + SCULPT_visibility_sync_all_face_sets_to_vertices(ob); + + for (int i = 0; i < totnode; i++) { + BKE_pbvh_node_mark_update_visibility(nodes[i]); + } + + BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility); + + if (BKE_pbvh_type(pbvh) == PBVH_FACES) { + BKE_mesh_flush_hidden_from_verts(ob->data); + } +} +static void sculpt_face_set_edit_modify_face_sets(Object *ob, + const int active_face_set, + const eSculptFaceSetEditMode mode, + const bool modify_hidden) +{ PBVH *pbvh = ob->sculpt->pbvh; PBVHNode **nodes; int totnode; BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); if (!nodes) { - return OPERATOR_CANCELLED; + return; } - SCULPT_undo_push_begin("face set edit"); SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS); - - const int active_face_set = SCULPT_active_face_set_get(ss); - const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden"); - sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden); - SCULPT_undo_push_end(); + face_set_edit_do_post_visibility_updates(ob, nodes, totnode); + MEM_freeN(nodes); +} - /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */ - SCULPT_visibility_sync_all_face_sets_to_vertices(ob); +static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - for (int i = 0; i < totnode; i++) { - BKE_pbvh_node_mark_update_visibility(nodes[i]); + const int mode = RNA_enum_get(op->ptr, "mode"); + const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden"); + + if (!sculpt_face_set_edit_is_operation_valid(ss, mode, modify_hidden)) { + return OPERATOR_CANCELLED; } - BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); - MEM_SAFE_FREE(nodes); + /* Update the current active Face Set and Vertex as the operator can be used directly from the + * tool without brush cursor. */ + SculptCursorGeometryInfo sgi; + const float mouse[2] = {event->mval[0], event->mval[1]}; + SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); + const int active_face_set = SCULPT_active_face_set_get(ss); - if (BKE_pbvh_type(pbvh) == PBVH_FACES) { - BKE_mesh_flush_hidden_from_verts(ob->data); + switch (mode) { + case SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY: + sculpt_face_set_edit_modify_geometry(C, ob, active_face_set, mode, modify_hidden); + break; + case SCULPT_FACE_SET_EDIT_GROW: + case SCULPT_FACE_SET_EDIT_SHRINK: + sculpt_face_set_edit_modify_face_sets(ob, active_face_set, mode, modify_hidden); + break; } SCULPT_tag_update_overlays(C); -- cgit v1.2.3 From 0eee384a8dd26062b6a479d004dcd2554940a14b Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Fri, 23 Oct 2020 01:07:20 +0200 Subject: Sculpt: Option to limit the action of line gestures to the segment This adds a tool property for sculpt line gesture tools (line and project) to limits its effect to the segment of the gesture instead of using the infinite line to bisect the mesh in two parts. To achieve that, the line gesture now has two extra side planes that can be enabled/disabled for getting the nodes from the PBVH and to test the vertices. Reviewed By: sergey Differential Revision: https://developer.blender.org/D9307 --- .../startup/bl_ui/space_toolsystem_toolbar.py | 6 + source/blender/editors/sculpt_paint/paint_mask.c | 132 ++++++++++++++++----- 2 files changed, 106 insertions(+), 32 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index b3f4757d10a..a923bb305d9 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -1259,6 +1259,7 @@ class _defs_sculpt: def draw_settings(_context, layout, tool): props = tool.operator_properties("paint.mask_line_gesture") layout.prop(props, "use_front_faces_only", expand=False) + layout.prop(props, "use_limit_to_segment", expand=False) return dict( idname="builtin.line_mask", @@ -1331,12 +1332,17 @@ class _defs_sculpt: @ToolDef.from_fn def project_line(): + def draw_settings(_context, layout, tool): + props = tool.operator_properties("sculpt.project_line_gesture") + layout.prop(props, "use_limit_to_segment", expand=False) + return dict( idname="builtin.line_project", label="Line Project", icon="ops.sculpt.line_project", widget=None, keymap=(), + draw_settings=draw_settings, ) @ToolDef.from_fn diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 2193a31f19b..605cdfcbe9b 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -246,8 +246,16 @@ typedef struct LassoGestureData { } LassoGestureData; typedef struct LineGestureData { + /* Plane aligned to the gesture line. */ float true_plane[4]; float plane[4]; + + /* Planes to limit the action to the length of the gesture segment at both sides of the affected + * area. */ + float side_plane[2][4]; + float true_side_plane[2][4]; + bool use_side_planes; + bool flip; } LineGestureData; @@ -320,6 +328,13 @@ static void sculpt_gesture_operator_properties(wmOperatorType *ot) false, "Front Faces Only", "Affect only faces facing towards the view"); + + RNA_def_boolean(ot->srna, + "use_limit_to_segment", + false, + "Limit to Segment", + "Apply the gesture action only to the area that is contained within the " + "segement without extending its effect to the entire line"); } static void sculpt_gesture_context_init_common(bContext *C, @@ -332,6 +347,7 @@ static void sculpt_gesture_context_init_common(bContext *C, /* Operator properties. */ sgcontext->front_faces_only = RNA_boolean_get(op->ptr, "use_front_faces_only"); + sgcontext->line.use_side_planes = RNA_boolean_get(op->ptr, "use_limit_to_segment"); /* SculptSession */ sgcontext->ss = ob->sculpt; @@ -448,6 +464,50 @@ static SculptGestureContext *sculpt_gesture_init_from_box(bContext *C, wmOperato return sgcontext; } +static void sculpt_gesture_line_plane_from_tri(float *r_plane, + SculptGestureContext *sgcontext, + const bool flip, + const float p1[3], + const float p2[3], + const float p3[3]) +{ + float normal[3]; + normal_tri_v3(normal, p1, p2, p3); + mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->imat, normal); + if (flip) { + mul_v3_fl(normal, -1.0f); + } + float plane_point_object_space[3]; + mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->imat, p1); + plane_from_point_normal_v3(r_plane, plane_point_object_space, normal); +} + +/* Creates 4 points in the plane defined by the line and 2 extra points with an offset relative to + * this plane. */ +static void sculpt_gesture_line_calculate_plane_points(SculptGestureContext *sgcontext, + float line_points[2][2], + float r_plane_points[4][3], + float r_offset_plane_points[2][3]) +{ + float depth_point[3]; + add_v3_v3v3(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], r_plane_points[0]); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[1], r_plane_points[3]); + + madd_v3_v3v3fl(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal, 10.0f); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], r_plane_points[1]); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[1], r_plane_points[2]); + + float normal[3]; + normal_tri_v3(normal, r_plane_points[0], r_plane_points[1], r_plane_points[2]); + add_v3_v3v3(r_offset_plane_points[0], r_plane_points[0], normal); + add_v3_v3v3(r_offset_plane_points[1], r_plane_points[3], normal); +} + static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperator *op) { SculptGestureContext *sgcontext = MEM_callocN(sizeof(SculptGestureContext), @@ -464,36 +524,33 @@ static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperat sgcontext->line.flip = RNA_boolean_get(op->ptr, "flip"); - float depth_point[3]; - float plane_points[3][3]; - - /* Calculate a triangle in the line's plane. */ - add_v3_v3v3(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal); - ED_view3d_win_to_3d( - sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], plane_points[0]); - - madd_v3_v3v3fl(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal, 10.0f); - ED_view3d_win_to_3d( - sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], plane_points[1]); - ED_view3d_win_to_3d( - sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[1], plane_points[2]); - - /* Calculate final line plane and normal using the triangle. */ - float normal[3]; - normal_tri_v3(normal, plane_points[0], plane_points[1], plane_points[2]); - if (!sgcontext->vc.rv3d->is_persp) { - mul_v3_fl(normal, -1.0f); - } - - /* Apply flip. */ - if (sgcontext->line.flip) { - mul_v3_fl(normal, -1.0f); - } - - mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->imat, normal); - float plane_point_object_space[3]; - mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->imat, plane_points[0]); - plane_from_point_normal_v3(sgcontext->line.true_plane, plane_point_object_space, normal); + float plane_points[4][3]; + float offset_plane_points[2][3]; + sculpt_gesture_line_calculate_plane_points( + sgcontext, line_points, plane_points, offset_plane_points); + + /* Calculate line plane and normal. */ + const bool flip = sgcontext->line.flip ^ !sgcontext->vc.rv3d->is_persp; + sculpt_gesture_line_plane_from_tri(sgcontext->line.true_plane, + sgcontext, + flip, + plane_points[0], + plane_points[1], + plane_points[2]); + + /* Calculate the side planes. */ + sculpt_gesture_line_plane_from_tri(sgcontext->line.true_side_plane[0], + sgcontext, + false, + plane_points[1], + plane_points[0], + offset_plane_points[0]); + sculpt_gesture_line_plane_from_tri(sgcontext->line.true_side_plane[1], + sgcontext, + false, + plane_points[3], + plane_points[2], + offset_plane_points[1]); return sgcontext; } @@ -544,14 +601,20 @@ static void sculpt_gesture_flip_for_symmetry_pass(SculptGestureContext *sgcontex flip_v3_v3(sgcontext->view_normal, sgcontext->true_view_normal, symmpass); flip_v3_v3(sgcontext->view_origin, sgcontext->true_view_origin, symmpass); flip_plane(sgcontext->line.plane, sgcontext->line.true_plane, symmpass); + flip_plane(sgcontext->line.side_plane[0], sgcontext->line.true_side_plane[0], symmpass); + flip_plane(sgcontext->line.side_plane[1], sgcontext->line.true_side_plane[1], symmpass); } static void sculpt_gesture_update_effected_nodes_by_line_plane(SculptGestureContext *sgcontext) { SculptSession *ss = sgcontext->ss; - float clip_planes[1][4]; + float clip_planes[3][4]; copy_v4_v4(clip_planes[0], sgcontext->line.plane); - PBVHFrustumPlanes frustum = {.planes = clip_planes, .num_planes = 1}; + copy_v4_v4(clip_planes[1], sgcontext->line.side_plane[0]); + copy_v4_v4(clip_planes[2], sgcontext->line.side_plane[1]); + + const int num_planes = sgcontext->line.use_side_planes ? 3 : 1; + PBVHFrustumPlanes frustum = {.planes = clip_planes, .num_planes = num_planes}; BKE_pbvh_search_gather(ss->pbvh, BKE_pbvh_node_frustum_contain_AABB, &frustum, @@ -630,6 +693,11 @@ static bool sculpt_gesture_is_vertex_effected(SculptGestureContext *sgcontext, P case SCULPT_GESTURE_SHAPE_LASSO: return sculpt_gesture_is_effected_lasso(sgcontext, vd->co); case SCULPT_GESTURE_SHAPE_LINE: + if (sgcontext->line.use_side_planes) { + return plane_point_side_v3(sgcontext->line.plane, vd->co) > 0.0f && + plane_point_side_v3(sgcontext->line.side_plane[0], vd->co) > 0.0f && + plane_point_side_v3(sgcontext->line.side_plane[1], vd->co) > 0.0f; + } return plane_point_side_v3(sgcontext->line.plane, vd->co) > 0.0f; } return false; -- cgit v1.2.3 From c53b6067fadb91403474eeac6bcf17cdad1c5bb3 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Thu, 22 Oct 2020 22:06:59 +0200 Subject: Sculpt: Implement plane deformation falloff for Grab The plane deformation falloff was introduced in the first version of the cloth brush, but due to the lack of all the new features and fixes in the solver it was causing a lot of artifacts for deformation brushes. In order to avoid that, the cloth brush was always using radial falloff for the grab brush. Now the plane falloff is properly implemented using the deformation constraints. Reviewed By: sergey Differential Revision: https://developer.blender.org/D9320 --- source/blender/editors/sculpt_paint/sculpt_cloth.c | 63 +++++++++++++--------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 1a1200bb6c2..ef926330ece 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -326,6 +326,9 @@ static void do_cloth_brush_build_constraints_task_cb_ex( * positions. */ const bool cloth_is_deform_brush = ss->cache != NULL && brush != NULL && SCULPT_is_cloth_deform_brush(brush); + + const bool use_falloff_plane = brush->cloth_force_falloff_type == + BRUSH_CLOTH_FORCE_FALLOFF_PLANE; float radius_squared = 0.0f; if (cloth_is_deform_brush) { radius_squared = ss->cache->initial_radius * ss->cache->initial_radius; @@ -380,12 +383,21 @@ static void do_cloth_brush_build_constraints_task_cb_ex( if (brush && brush->sculpt_tool == SCULPT_TOOL_CLOTH) { /* The cloth brush works by applying forces in most of its modes, but some of them require * deformation coordinates to make the simulation stable. */ - if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB && len_squared < radius_squared) { - /* When the grab brush brush is used as part of the cloth brush, deformation constraints - * are created with different strengths and only inside the radius of the brush. */ - const float fade = BKE_brush_curve_strength(brush, sqrtf(len_squared), ss->cache->radius); - cloth_brush_add_deformation_constraint( - data->cloth_sim, node_index, vd.index, fade * CLOTH_DEFORMATION_GRAB_STRENGTH); + if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) { + if (use_falloff_plane) { + /* With plane falloff the strength of the constraints is set when applying the + * deformation forces. */ + cloth_brush_add_deformation_constraint( + data->cloth_sim, node_index, vd.index, CLOTH_DEFORMATION_GRAB_STRENGTH); + } + else if (len_squared < radius_squared) { + /* With radial falloff deformation constraints are created with different strengths and + * only inside the radius of the brush. */ + const float fade = BKE_brush_curve_strength( + brush, sqrtf(len_squared), ss->cache->radius); + cloth_brush_add_deformation_constraint( + data->cloth_sim, node_index, vd.index, fade * CLOTH_DEFORMATION_GRAB_STRENGTH); + } } else if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK) { /* Cloth Snake Hook creates deformation constraint with fixed strength because the strength @@ -436,9 +448,8 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, const float *grab_delta = data->grab_delta; float(*imat)[4] = data->mat; - const bool use_falloff_plane = !SCULPT_is_cloth_deform_brush(brush) && - brush->cloth_force_falloff_type == - BRUSH_CLOTH_FORCE_FALLOFF_PLANE; + const bool use_falloff_plane = brush->cloth_force_falloff_type == + BRUSH_CLOTH_FORCE_FALLOFF_PLANE; PBVHVertexIter vd; const float bstrength = ss->cache->bstrength; @@ -470,12 +481,6 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, madd_v3_v3fl(gravity, ss->cache->gravity_direction, -data->sd->gravity_factor); } - /* Original data for deform brushes. */ - SculptOrigVertData orig_data; - if (SCULPT_is_cloth_deform_brush(brush)) { - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]); - } - BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { float force[3]; @@ -486,8 +491,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, float current_vertex_location[3]; if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - copy_v3_v3(current_vertex_location, orig_data.co); + copy_v3_v3(current_vertex_location, ss->cache->cloth_sim->init_pos[vd.index]); } else { copy_v3_v3(current_vertex_location, vd.co); @@ -504,7 +508,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, float dist = sqrtf(test.dist); if (use_falloff_plane) { - dist = dist_to_plane_v3(vd.co, deform_plane); + dist = dist_to_plane_v3(current_vertex_location, deform_plane); } const float fade = sim_factor * bstrength * @@ -539,9 +543,15 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, break; case BRUSH_CLOTH_DEFORM_GRAB: madd_v3_v3v3fl(cloth_sim->deformation_pos[vd.index], - orig_data.co, + cloth_sim->init_pos[vd.index], ss->cache->grab_delta_symmetry, fade); + if (use_falloff_plane) { + cloth_sim->deformation_strength[vd.index] = clamp_f(fade, 0.0f, 1.0f); + } + else { + cloth_sim->deformation_strength[vd.index] = 1.0f; + } zero_v3(force); break; case BRUSH_CLOTH_DEFORM_SNAKE_HOOK: @@ -965,8 +975,8 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod } } - if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK) { - /* Set the deformation strength to 0. Snake hook will initialize the strength in the required + if (ELEM(brush->cloth_deform_type, BRUSH_CLOTH_DEFORM_SNAKE_HOOK, BRUSH_CLOTH_DEFORM_GRAB)) { + /* Set the deformation strength to 0. Brushes will initialize the strength in the required * area. */ const int totverts = SCULPT_vertex_count_get(ss); for (int i = 0; i < totverts; i++) { @@ -1228,9 +1238,14 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr, const float outline_col[3], float outline_alpha) { - float local_mat_inv[4][4]; - invert_m4_m4(local_mat_inv, ss->cache->stroke_local_mat); - GPU_matrix_mul(ss->cache->stroke_local_mat); + float local_mat[4][4]; + copy_m4_m4(local_mat, ss->cache->stroke_local_mat); + + if (ss->cache->brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) { + add_v3_v3v3(local_mat[3], ss->cache->true_location, ss->cache->grab_delta); + } + + GPU_matrix_mul(local_mat); const float dist = ss->cache->radius; const float arrow_x = ss->cache->radius * 0.2f; -- cgit v1.2.3 From 31629c1363cc8d004eacae9bd43623826af649a6 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Fri, 23 Oct 2020 02:12:34 +0200 Subject: Fix T81904: Cloth brush simulation failing with local area and mirror When using local area, all nodes need to build their constraints first before activating them for simulation. THis ensures that nodes get their structural constraints from the initial location of each symmetry pass. Reviewed By: sergey Maniphest Tasks: T81904 Differential Revision: https://developer.blender.org/D9303 --- source/blender/editors/sculpt_paint/sculpt_cloth.c | 37 ++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 1a1200bb6c2..67129d5da50 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -1127,14 +1127,27 @@ void SCULPT_cloth_sim_activate_nodes(SculptClothSimulation *cloth_sim, } } +static void sculpt_cloth_ensure_constraints_in_simulation_area(Sculpt *sd, + Object *ob, + PBVHNode **nodes, + int totnode) +{ + SculptSession *ss = ob->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + const float radius = ss->cache->initial_radius; + const float limit = radius + (radius * brush->cloth_sim_limit); + float sim_location[3]; + cloth_brush_simulation_location_get(ss, brush, sim_location); + SCULPT_cloth_brush_ensure_nodes_constraints( + sd, ob, nodes, totnode, ss->cache->cloth_sim, sim_location, limit); +} + /* Main Brush Function. */ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - /* In the first brush step of each symmetry pass, build the constraints for the vertices in all - * nodes inside the simulation's limits. */ /* Brushes that use anchored strokes and restore the mesh can't rely on symmetry passes and steps * count as it is always the first step, so the simulation needs to be created when it does not * exist for this stroke. */ @@ -1151,14 +1164,26 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode SCULPT_is_cloth_deform_brush(brush)); SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim); } + + if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) { + /* When using simulation a fixed local simulation area, constraints are created only using + * the initial stroke position and initial radius (per symmetry pass) instead of per node. + * This allows to skip unnecessary constraints that will never be simulated, making the + * solver faster. When the simulation starts for a node, the node gets activated and all its + * constraints are considered final. As the same node can be included inside the brush radius + * from multiple symmetry passes, the cloth brush can't activate the node for simulation yet + * as this will cause the ensure constraints function to skip the node in the next symmetry + * passes. It needs to build the constraints here and skip simulating the first step, so all + * passes can add their constraints to all affected nodes. */ + sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes, totnode); + } + /* The first step of a symmetry pass is never simulated as deformation modes need valid delta + * for brush tip alignement. */ return; } /* Ensure the constraints for the nodes. */ - const float radius = ss->cache->initial_radius; - const float limit = radius + (radius * brush->cloth_sim_limit); - SCULPT_cloth_brush_ensure_nodes_constraints( - sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, limit); + sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes, totnode); /* Store the initial state in the simulation. */ SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim); -- cgit v1.2.3 From 8d1978a8e0131ab59e94e7e37e063db305166711 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Mon, 26 Oct 2020 00:28:54 +0100 Subject: Fix T81250: Crash after undoing with prefetching Main DB and it's structs can point to different address after undoing. In this case problem was that bmain was not updated. Same fix was done for scene as well. Reviewed By: sergey Differential Revision: https://developer.blender.org/D9240 --- source/blender/sequencer/intern/prefetch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/sequencer/intern/prefetch.c b/source/blender/sequencer/intern/prefetch.c index 013abb716d4..65b2b6c02cf 100644 --- a/source/blender/sequencer/intern/prefetch.c +++ b/source/blender/sequencer/intern/prefetch.c @@ -319,6 +319,7 @@ static void seq_prefetch_update_scene(Scene *scene) return; } + pfjob->scene = scene; seq_prefetch_free_depsgraph(pfjob); seq_prefetch_init_depsgraph(pfjob); } @@ -499,15 +500,14 @@ static PrefetchJob *seq_prefetch_start(const SeqRenderData *context, float cfra) BLI_mutex_init(&pfjob->prefetch_suspend_mutex); BLI_condition_init(&pfjob->prefetch_suspend_cond); - pfjob->bmain = context->bmain; pfjob->bmain_eval = BKE_main_new(); - pfjob->scene = context->scene; seq_prefetch_init_depsgraph(pfjob); } } seq_prefetch_update_scene(context->scene); seq_prefetch_update_context(context); + pfjob->bmain = context->bmain; pfjob->cfra = cfra; pfjob->num_frames_prefetched = 1; -- cgit v1.2.3 From 3deb4f4cb8ba4558adbb24597fb799252449a799 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Mon, 26 Oct 2020 00:30:27 +0100 Subject: Fix T81426: Infinite loop building VSE relations It is possible to create scene strips pointing to each other. This is sanitized when rendering, but in dependency graph such setup will cause infinite loop. This patch fixes loop in dependency graph, but same problem exists in audaspace Reviewed By: sergey Differential Revision: https://developer.blender.org/D9262 --- source/blender/depsgraph/intern/builder/deg_builder_relations.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 86a365a4901..ec5cbc5c605 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -2667,6 +2667,9 @@ void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene) if (scene->ed == nullptr) { return; } + if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_SEQUENCER)) { + return; + } build_scene_audio(scene); ComponentKey scene_audio_key(&scene->id, NodeType::AUDIO); /* Make sure dependencies from sequences data goes to the sequencer evaluation. */ -- cgit v1.2.3 From 8eb7344731f2e8cc910b03beb13722a31fc46f61 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Mon, 26 Oct 2020 00:31:49 +0100 Subject: Fix Recursion when rendering scene strip Recursion happens in case when scene strip point to it's own scene indirectly by using SEQ_SCENE_STRIPS option. Reviewed By: sergey Differential Revision: https://developer.blender.org/D9264 --- source/blender/sequencer/intern/sequencer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index c8dfb6b886f..068d836d1e6 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -6045,6 +6045,12 @@ static Sequence *sequencer_check_scene_recursion(Scene *scene, ListBase *seqbase return seq; } + if (seq->type == SEQ_TYPE_SCENE && (seq->flag & SEQ_SCENE_STRIPS)) { + if (sequencer_check_scene_recursion(scene, &seq->scene->ed->seqbase)) { + return seq; + } + } + if (seq->type == SEQ_TYPE_META && sequencer_check_scene_recursion(scene, &seq->seqbase)) { return seq; } -- cgit v1.2.3 From 3baf65975cc294cdf562e0dca822be0e060b22db Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Mon, 26 Oct 2020 00:47:06 +0100 Subject: Split BKE_sequencer.h intern/extern definitions Intern definitions are moved to sequencer/intern/sequencer.h BKE_sequencer.h was also cleaned up a bit to make sure that functions and structs are in correct category. Reviewed By: sergey Differential Revision: https://developer.blender.org/D9259 --- source/blender/sequencer/BKE_sequencer.h | 481 +++++++++++--------------- source/blender/sequencer/CMakeLists.txt | 2 + source/blender/sequencer/intern/effects.c | 2 + source/blender/sequencer/intern/image_cache.c | 2 + source/blender/sequencer/intern/modifier.c | 2 + source/blender/sequencer/intern/prefetch.c | 2 + source/blender/sequencer/intern/sequencer.c | 2 + source/blender/sequencer/intern/sequencer.h | 190 ++++++++++ 8 files changed, 400 insertions(+), 283 deletions(-) create mode 100644 source/blender/sequencer/intern/sequencer.h diff --git a/source/blender/sequencer/BKE_sequencer.h b/source/blender/sequencer/BKE_sequencer.h index 04be46f0ccf..90b1d611842 100644 --- a/source/blender/sequencer/BKE_sequencer.h +++ b/source/blender/sequencer/BKE_sequencer.h @@ -20,7 +20,7 @@ #pragma once /** \file - * \ingroup bke + * \ingroup sequencer */ #ifdef __cplusplus @@ -39,20 +39,37 @@ struct Scene; struct Sequence; struct SequenceModifierData; struct Stereo3dFormat; -struct StripColorBalance; struct StripElem; struct TextVars; struct bContext; struct bSound; - struct SeqIndexBuildContext; -#define EARLY_NO_INPUT -1 -#define EARLY_DO_EFFECT 0 -#define EARLY_USE_INPUT_1 1 -#define EARLY_USE_INPUT_2 2 +/* Wipe effect */ +enum { + DO_SINGLE_WIPE, + DO_DOUBLE_WIPE, + /* DO_BOX_WIPE, */ /* UNUSED */ + /* DO_CROSS_WIPE, */ /* UNUSED */ + DO_IRIS_WIPE, + DO_CLOCK_WIPE, +}; -/* sequence iterator */ +/* RNA enums, just to be more readable */ +enum { + SEQ_SIDE_NONE = 0, + SEQ_SIDE_LEFT, + SEQ_SIDE_RIGHT, + SEQ_SIDE_BOTH, + SEQ_SIDE_NO_CHANGE, +}; + +/* ********************************************************************** + * sequencer.c + * + * Sequencer iterators + * ********************************************************************** + */ typedef struct SeqIterator { struct Sequence **array; @@ -62,12 +79,6 @@ typedef struct SeqIterator { int valid; } SeqIterator; -void BKE_sequence_iterator_begin(struct Editing *ed, - SeqIterator *iter, - const bool use_current_sequences); -void BKE_sequence_iterator_next(SeqIterator *iter); -void BKE_sequence_iterator_end(SeqIterator *iter); - #define SEQ_ALL_BEGIN(ed, _seq) \ { \ SeqIterator iter_macro; \ @@ -90,6 +101,19 @@ void BKE_sequence_iterator_end(SeqIterator *iter); #define SEQ_CURRENT_END SEQ_ALL_END +void BKE_sequence_iterator_begin(struct Editing *ed, + SeqIterator *iter, + const bool use_current_sequences); +void BKE_sequence_iterator_next(SeqIterator *iter); +void BKE_sequence_iterator_end(SeqIterator *iter); + +/* ********************************************************************** + * sequencer.c + * + * Sequencer render functions + * ********************************************************************** + */ + typedef enum eSeqTaskId { SEQ_TASK_MAIN_RENDER, SEQ_TASK_PREFETCH_RENDER, @@ -118,6 +142,12 @@ typedef struct SeqRenderData { // bool gpu_full_samples; } SeqRenderData; +struct ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int chanshown); +struct ImBuf *BKE_sequencer_give_ibuf_direct(const SeqRenderData *context, + float cfra, + struct Sequence *seq); +void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq); +void BKE_sequence_init_colorspace(struct Sequence *seq); void BKE_sequencer_new_render_data(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, @@ -127,132 +157,24 @@ void BKE_sequencer_new_render_data(struct Main *bmain, int for_render, SeqRenderData *r_context); -int BKE_sequencer_cmp_time_startdisp(const void *a, const void *b); - -/* Wipe effect */ -enum { - DO_SINGLE_WIPE, - DO_DOUBLE_WIPE, - /* DO_BOX_WIPE, */ /* UNUSED */ - /* DO_CROSS_WIPE, */ /* UNUSED */ - DO_IRIS_WIPE, - DO_CLOCK_WIPE, -}; - -struct SeqEffectHandle { - bool multithreaded; - bool supports_mask; - - /* constructors & destructor */ - /* init is _only_ called on first creation */ - void (*init)(struct Sequence *seq); - - /* number of input strips needed - * (called directly after construction) */ - int (*num_inputs)(void); - - /* load is called first time after readblenfile in - * get_sequence_effect automatically */ - void (*load)(struct Sequence *seqconst); - - /* duplicate */ - void (*copy)(struct Sequence *dst, struct Sequence *src, const int flag); - - /* destruct */ - void (*free)(struct Sequence *seq, const bool do_id_user); - - /* returns: -1: no input needed, - * 0: no early out, - * 1: out = ibuf1, - * 2: out = ibuf2 */ - int (*early_out)(struct Sequence *seq, float facf0, float facf1); - - /* stores the y-range of the effect IPO */ - void (*store_icu_yrange)(struct Sequence *seq, short adrcode, float *ymin, float *ymax); - - /* stores the default facf0 and facf1 if no IPO is present */ - void (*get_default_fac)(struct Sequence *seq, float cfra, float *facf0, float *facf1); - - /* execute the effect - * sequence effects are only required to either support - * float-rects or byte-rects - * (mixed cases are handled one layer up...) */ - - struct ImBuf *(*execute)(const SeqRenderData *context, - struct Sequence *seq, - float cfra, - float facf0, - float facf1, - struct ImBuf *ibuf1, - struct ImBuf *ibuf2, - struct ImBuf *ibuf3); - - struct ImBuf *(*init_execution)(const SeqRenderData *context, - struct ImBuf *ibuf1, - struct ImBuf *ibuf2, - struct ImBuf *ibuf3); - - void (*execute_slice)(const SeqRenderData *context, - struct Sequence *seq, - float cfra, - float facf0, - float facf1, - struct ImBuf *ibuf1, - struct ImBuf *ibuf2, - struct ImBuf *ibuf3, - int start_line, - int total_lines, - struct ImBuf *out); -}; - -/* ********************* prototypes *************** */ - /* ********************************************************************** * sequencer.c * - * sequencer render functions + * Sequencer color space functions * ********************************************************************** */ -double BKE_sequencer_rendersize_to_scale_factor(int size); -struct ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int chanshown); -struct ImBuf *BKE_sequencer_give_ibuf_direct(const SeqRenderData *context, - float cfra, - struct Sequence *seq); -struct ImBuf *BKE_sequencer_give_ibuf_seqbase(const SeqRenderData *context, - float cfra, - int chan_shown, - struct ListBase *seqbasep); -struct ImBuf *BKE_sequencer_effect_execute_threaded(struct SeqEffectHandle *sh, - const SeqRenderData *context, - struct Sequence *seq, - float cfra, - float facf0, - float facf1, - struct ImBuf *ibuf1, - struct ImBuf *ibuf2, - struct ImBuf *ibuf3); - -/* ********************************************************************** - * sequencer.c - * - * sequencer color space functions - * ********************************************************************** */ - -void BKE_sequencer_imbuf_to_sequencer_space(struct Scene *scene, - struct ImBuf *ibuf, - bool make_float); void BKE_sequencer_imbuf_from_sequencer_space(struct Scene *scene, struct ImBuf *ibuf); void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4]); /* ********************************************************************** - * sequencer scene functions + * sequencer.c + * + * Sequencer scene functions * ********************************************************************** */ struct Editing *BKE_sequencer_editing_get(struct Scene *scene, bool alloc); struct Editing *BKE_sequencer_editing_ensure(struct Scene *scene); void BKE_sequencer_editing_free(struct Scene *scene, const bool do_id_user); - void BKE_sequencer_sort(struct Scene *scene); - struct Sequence *BKE_sequencer_from_elem(ListBase *seqbase, struct StripElem *se); struct Sequence *BKE_sequencer_active_get(struct Scene *scene); int BKE_sequencer_active_get_pair(struct Scene *scene, @@ -260,7 +182,6 @@ int BKE_sequencer_active_get_pair(struct Scene *scene, struct Sequence **seq_other); void BKE_sequencer_active_set(struct Scene *scene, struct Sequence *seq); struct Mask *BKE_sequencer_mask_get(struct Scene *scene); - /* apply functions recursively */ int BKE_sequencer_base_recursive_apply(struct ListBase *seqbase, int (*apply_fn)(struct Sequence *seq, void *), @@ -268,16 +189,14 @@ int BKE_sequencer_base_recursive_apply(struct ListBase *seqbase, int BKE_sequencer_recursive_apply(struct Sequence *seq, int (*apply_fn)(struct Sequence *, void *), void *arg); - +float BKE_sequence_get_fps(struct Scene *scene, struct Sequence *seq); +int BKE_sequencer_find_next_prev_edit(struct Scene *scene, + int cfra, + const short side, + const bool do_skip_mute, + const bool do_center, + const bool do_unselected); /* maintenance functions, mostly for RNA */ -/* extern */ - -void BKE_sequencer_free_clipboard(void); - -void BKE_sequencer_base_clipboard_pointers_free(struct ListBase *seqbase); -void BKE_sequencer_base_clipboard_pointers_store(struct Main *bmain, struct ListBase *seqbase); -void BKE_sequencer_base_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain); - void BKE_sequence_free(struct Scene *scene, struct Sequence *seq, const bool do_clean_animdata); void BKE_sequence_free_anim(struct Sequence *seq); const char *BKE_sequence_give_name(struct Sequence *seq); @@ -294,22 +213,11 @@ void BKE_sequence_movie_reload_if_needed(struct Main *bmain, bool *r_was_reloaded, bool *r_can_produce_frames); int BKE_sequencer_evaluate_frame(struct Scene *scene, int cfra); -int BKE_sequencer_get_shown_sequences(struct ListBase *seqbasep, - int cfra, - int chanshown, - struct Sequence **seq_arr_out); - struct StripElem *BKE_sequencer_give_stripelem(struct Sequence *seq, int cfra); - -/* intern */ void BKE_sequencer_update_changed_seq_and_deps(struct Scene *scene, struct Sequence *changed_seq, int len_change, int ibuf_change); -bool BKE_sequencer_input_have_to_preprocess(const SeqRenderData *context, - struct Sequence *seq, - float cfra); - bool BKE_sequencer_proxy_rebuild_context(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, @@ -321,45 +229,19 @@ void BKE_sequencer_proxy_rebuild(struct SeqIndexBuildContext *context, short *do_update, float *progress); void BKE_sequencer_proxy_rebuild_finish(struct SeqIndexBuildContext *context, bool stop); - void BKE_sequencer_proxy_set(struct Sequence *seq, bool value); +bool BKE_sequencer_check_scene_recursion(struct Scene *scene, struct ReportList *reports); +bool BKE_sequencer_render_loop_check(struct Sequence *seq_main, struct Sequence *seq); +int BKE_sequencer_cmp_time_startdisp(const void *a, const void *b); +double BKE_sequencer_rendersize_to_scale_factor(int size); + /* ********************************************************************** - * seqcache.c + * image_cache.c * * Sequencer memory cache management functions * ********************************************************************** */ -#define SEQ_CACHE_COST_MAX 10.0f - -struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, - struct Sequence *seq, - float cfra, - int type, - bool skip_disk_cache); -void BKE_sequencer_cache_put(const SeqRenderData *context, - struct Sequence *seq, - float cfra, - int type, - struct ImBuf *i, - float cost, - bool skip_disk_cache); -bool BKE_sequencer_cache_put_if_possible(const SeqRenderData *context, - struct Sequence *seq, - float cfra, - int type, - struct ImBuf *nval, - float cost, - bool skip_disk_cache); -bool BKE_sequencer_cache_recycle_item(struct Scene *scene); -void BKE_sequencer_cache_free_temp_cache(struct Scene *scene, short id, int cfra); -void BKE_sequencer_cache_destruct(struct Scene *scene); -void BKE_sequencer_cache_cleanup_all(struct Main *bmain); void BKE_sequencer_cache_cleanup(struct Scene *scene); -void BKE_sequencer_cache_cleanup_sequence(struct Scene *scene, - struct Sequence *seq, - struct Sequence *seq_changed, - int invalidate_types, - bool force_seq_changed_range); void BKE_sequencer_cache_iterate(struct Scene *scene, void *userdata, bool callback_init(void *userdata, size_t item_count), @@ -368,48 +250,21 @@ void BKE_sequencer_cache_iterate(struct Scene *scene, int cfra, int cache_type, float cost)); -bool BKE_sequencer_cache_is_full(struct Scene *scene); /* ********************************************************************** - * seqprefetch.c + * prefetch.c * * Sequencer frame prefetching * ********************************************************************** */ -void BKE_sequencer_prefetch_start(const SeqRenderData *context, float cfra, float cost); +#define SEQ_CACHE_COST_MAX 10.0f void BKE_sequencer_prefetch_stop_all(void); void BKE_sequencer_prefetch_stop(struct Scene *scene); -void BKE_sequencer_prefetch_free(struct Scene *scene); bool BKE_sequencer_prefetch_need_redraw(struct Main *bmain, struct Scene *scene); -bool BKE_sequencer_prefetch_job_is_running(struct Scene *scene); -void BKE_sequencer_prefetch_get_time_range(struct Scene *scene, int *start, int *end); -SeqRenderData *BKE_sequencer_prefetch_get_original_context(const SeqRenderData *context); -struct Sequence *BKE_sequencer_prefetch_get_original_sequence(struct Sequence *seq, - struct Scene *scene); /* ********************************************************************** - * seqeffects.c + * sequencer.c * - * Sequencer effect strip management functions - * ********************************************************************** - */ - -/* intern */ -struct SeqEffectHandle BKE_sequence_get_blend(struct Sequence *seq); -void BKE_sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, bool force); -float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context, - struct Sequence *seq, - float cfra, - int input); - -/* extern */ -struct SeqEffectHandle BKE_sequence_get_effect(struct Sequence *seq); -int BKE_sequence_effect_get_num_inputs(int seq_type); -int BKE_sequence_effect_get_supports_mask(int seq_type); -void BKE_sequencer_text_font_unload(struct TextVars *data, const bool do_id_user); -void BKE_sequencer_text_font_load(struct TextVars *data, const bool do_id_user); - -/* ********************************************************************** * Sequencer editing functions * ********************************************************************** */ @@ -426,13 +281,8 @@ bool BKE_sequence_single_check(struct Sequence *seq); void BKE_sequence_single_fix(struct Sequence *seq); bool BKE_sequence_test_overlap(struct ListBase *seqbasep, struct Sequence *test); void BKE_sequence_translate(struct Scene *scene, struct Sequence *seq, int delta); -void BKE_sequence_sound_init(struct Scene *scene, struct Sequence *seq); const struct Sequence *BKE_sequencer_foreground_frame_get(const struct Scene *scene, int frame); struct ListBase *BKE_sequence_seqbase(struct ListBase *seqbase, struct Sequence *seq); -struct Sequence *BKE_sequence_metastrip(ListBase *seqbase /* = ed->seqbase */, - struct Sequence *meta /* = NULL */, - struct Sequence *seq); - void BKE_sequencer_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); void BKE_sequencer_dupe_animdata(struct Scene *scene, const char *name_src, const char *name_dst); bool BKE_sequence_base_shuffle_ex(struct ListBase *seqbasep, @@ -454,26 +304,11 @@ struct Sequence *BKE_sequence_dupli_recursive(const struct Scene *scene_src, struct Sequence *seq, int dupe_flag); int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str); - -bool BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur); -void BKE_sequence_invalidate_cache_raw(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_invalidate_cache_preprocessed(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_invalidate_cache_composite(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_invalidate_dependent(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_invalidate_scene_strips(struct Main *bmain, struct Scene *scene_target); -void BKE_sequence_invalidate_movieclip_strips(struct Main *bmain, struct MovieClip *clip_target); -void BKE_sequence_invalidate_cache_in_range(struct Scene *scene, - struct Sequence *seq, - struct Sequence *range_mask, - int invalidate_types); - void BKE_sequencer_update_sound_bounds_all(struct Scene *scene); void BKE_sequencer_update_sound_bounds(struct Scene *scene, struct Sequence *seq); void BKE_sequencer_update_muting(struct Editing *ed); void BKE_sequencer_update_sound(struct Scene *scene, struct bSound *sound); - void BKE_sequencer_refresh_sound_length(struct Main *bmain, struct Scene *scene); - void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); void BKE_sequence_base_dupli_recursive(const struct Scene *scene_src, struct Scene *scene_dst, @@ -482,12 +317,39 @@ void BKE_sequence_base_dupli_recursive(const struct Scene *scene_src, int dupe_flag, const int flag); bool BKE_sequence_is_valid_check(struct Sequence *seq); - -void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce); - struct Sequence *BKE_sequence_get_by_name(struct ListBase *seqbase, const char *name, bool recursive); +void BKE_sequencer_flag_for_removal(struct Scene *scene, + struct ListBase *seqbase, + struct Sequence *seq); +void BKE_sequencer_remove_flagged_sequences(struct Scene *scene, struct ListBase *seqbase); + +/* ********************************************************************** + * sequencer.c + * + * Cache invalidation + * ********************************************************************** + */ + +void BKE_sequence_invalidate_cache_raw(struct Scene *scene, struct Sequence *seq); +void BKE_sequence_invalidate_cache_preprocessed(struct Scene *scene, struct Sequence *seq); +void BKE_sequence_invalidate_cache_composite(struct Scene *scene, struct Sequence *seq); +void BKE_sequence_invalidate_dependent(struct Scene *scene, struct Sequence *seq); +void BKE_sequence_invalidate_scene_strips(struct Main *bmain, struct Scene *scene_target); +void BKE_sequence_invalidate_movieclip_strips(struct Main *bmain, struct MovieClip *clip_target); +void BKE_sequence_invalidate_cache_in_range(struct Scene *scene, + struct Sequence *seq, + struct Sequence *range_mask, + int invalidate_types); +void BKE_sequencer_all_free_anim_ibufs(struct Scene *scene, int cfra); + +/* ********************************************************************** + * sequencer.c + * + * Add strips + * ********************************************************************** + */ /* api for adding new sequence strips */ typedef struct SeqLoadInfo { @@ -529,31 +391,6 @@ typedef struct SeqLoadInfo { typedef struct Sequence *(*SeqLoadFn)(struct bContext *, ListBase *, struct SeqLoadInfo *); struct Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine, int type); - -/* Generate new UUID for the given sequence. */ -void BKE_sequence_session_uuid_generate(struct Sequence *sequence); - -void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq); -void BKE_sequence_init_colorspace(struct Sequence *seq); - -float BKE_sequence_get_fps(struct Scene *scene, struct Sequence *seq); -float BKE_sequencer_give_stripelem_index(struct Sequence *seq, float cfra); - -/* RNA enums, just to be more readable */ -enum { - SEQ_SIDE_NONE = 0, - SEQ_SIDE_LEFT, - SEQ_SIDE_RIGHT, - SEQ_SIDE_BOTH, - SEQ_SIDE_NO_CHANGE, -}; -int BKE_sequencer_find_next_prev_edit(struct Scene *scene, - int cfra, - const short side, - const bool do_skip_mute, - const bool do_center, - const bool do_unselected); - struct Sequence *BKE_sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); @@ -564,11 +401,13 @@ struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); -/* copy/paste */ -extern ListBase seqbase_clipboard; -extern int seqbase_clipboard_frame; +/* ********************************************************************** + * modifier.c + * + * Modifiers + * ********************************************************************** + */ -/* modifiers */ typedef struct SequenceModifierTypeInfo { /* default name for the modifier */ char name[64]; /* MAX_NAME */ @@ -596,7 +435,6 @@ typedef struct SequenceModifierTypeInfo { } SequenceModifierTypeInfo; const struct SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type); - struct SequenceModifierData *BKE_sequence_modifier_new(struct Sequence *seq, const char *name, int type); @@ -611,34 +449,111 @@ struct ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, struct ImBuf *ibuf, int cfra); void BKE_sequence_modifier_list_copy(struct Sequence *seqn, struct Sequence *seq); - int BKE_sequence_supports_modifiers(struct Sequence *seq); -/* internal filters */ -struct ImBuf *BKE_sequencer_render_mask_input(const SeqRenderData *context, - int mask_input_type, - struct Sequence *mask_sequence, - struct Mask *mask_id, - int cfra, - int fra_offset, - bool make_float); -void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, - struct ImBuf *ibuf, - float mul, - bool make_float, - struct ImBuf *mask_input); +/* ********************************************************************** + * seqeffects.c + * + * Sequencer effect strip management functions + * ********************************************************************** + */ -void BKE_sequencer_all_free_anim_ibufs(struct Scene *scene, int cfra); -bool BKE_sequencer_check_scene_recursion(struct Scene *scene, struct ReportList *reports); -bool BKE_sequencer_render_loop_check(struct Sequence *seq_main, struct Sequence *seq); -void BKE_sequencer_flag_for_removal(struct Scene *scene, - struct ListBase *seqbase, - struct Sequence *seq); -void BKE_sequencer_remove_flagged_sequences(struct Scene *scene, struct ListBase *seqbase); +struct SeqEffectHandle { + bool multithreaded; + bool supports_mask; + + /* constructors & destructor */ + /* init is _only_ called on first creation */ + void (*init)(struct Sequence *seq); + + /* number of input strips needed + * (called directly after construction) */ + int (*num_inputs)(void); + + /* load is called first time after readblenfile in + * get_sequence_effect automatically */ + void (*load)(struct Sequence *seqconst); + + /* duplicate */ + void (*copy)(struct Sequence *dst, struct Sequence *src, const int flag); + + /* destruct */ + void (*free)(struct Sequence *seq, const bool do_id_user); + + /* returns: -1: no input needed, + * 0: no early out, + * 1: out = ibuf1, + * 2: out = ibuf2 */ + int (*early_out)(struct Sequence *seq, float facf0, float facf1); + + /* stores the y-range of the effect IPO */ + void (*store_icu_yrange)(struct Sequence *seq, short adrcode, float *ymin, float *ymax); + + /* stores the default facf0 and facf1 if no IPO is present */ + void (*get_default_fac)(struct Sequence *seq, float cfra, float *facf0, float *facf1); + + /* execute the effect + * sequence effects are only required to either support + * float-rects or byte-rects + * (mixed cases are handled one layer up...) */ + + struct ImBuf *(*execute)(const SeqRenderData *context, + struct Sequence *seq, + float cfra, + float facf0, + float facf1, + struct ImBuf *ibuf1, + struct ImBuf *ibuf2, + struct ImBuf *ibuf3); + + struct ImBuf *(*init_execution)(const SeqRenderData *context, + struct ImBuf *ibuf1, + struct ImBuf *ibuf2, + struct ImBuf *ibuf3); + + void (*execute_slice)(const SeqRenderData *context, + struct Sequence *seq, + float cfra, + float facf0, + float facf1, + struct ImBuf *ibuf1, + struct ImBuf *ibuf2, + struct ImBuf *ibuf3, + int start_line, + int total_lines, + struct ImBuf *out); +}; + +struct SeqEffectHandle BKE_sequence_get_effect(struct Sequence *seq); +int BKE_sequence_effect_get_num_inputs(int seq_type); +void BKE_sequencer_text_font_unload(struct TextVars *data, const bool do_id_user); +void BKE_sequencer_text_font_load(struct TextVars *data, const bool do_id_user); + +/* ********************************************************************** + * sequencer.c + * + * Clipboard + * ********************************************************************** + */ + +extern ListBase seqbase_clipboard; +extern int seqbase_clipboard_frame; +void BKE_sequencer_base_clipboard_pointers_store(struct Main *bmain, struct ListBase *seqbase); +void BKE_sequencer_base_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain); +void BKE_sequencer_free_clipboard(void); + +/* ********************************************************************** + * sequencer.c + * + * Depsgraph + * ********************************************************************** + */ /* A debug and development function which checks whether sequences have unique UUIDs. * Errors will be reported to the console. */ void BKE_sequencer_check_uuids_unique_and_report(const struct Scene *scene); +/* Generate new UUID for the given sequence. */ +void BKE_sequence_session_uuid_generate(struct Sequence *sequence); #ifdef __cplusplus } diff --git a/source/blender/sequencer/CMakeLists.txt b/source/blender/sequencer/CMakeLists.txt index 866eba9ca41..84684987ca7 100644 --- a/source/blender/sequencer/CMakeLists.txt +++ b/source/blender/sequencer/CMakeLists.txt @@ -20,6 +20,7 @@ set(INC . + intern ../blenkernel ../blenlib ../blentranslation @@ -42,6 +43,7 @@ set(SRC BKE_sequencer.h intern/sequencer.c + intern/sequencer.h intern/image_cache.c intern/effects.c intern/modifier.c diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c index b4bc2d25155..a05a69a522f 100644 --- a/source/blender/sequencer/intern/effects.c +++ b/source/blender/sequencer/intern/effects.c @@ -61,6 +61,8 @@ #include "BLF_api.h" +#include "sequencer.h" + static struct SeqEffectHandle get_sequence_effect_impl(int seq_type); static void slice_get_byte_buffers(const SeqRenderData *context, diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c index 7d2858050be..ea59625065b 100644 --- a/source/blender/sequencer/intern/image_cache.c +++ b/source/blender/sequencer/intern/image_cache.c @@ -49,6 +49,8 @@ #include "BKE_scene.h" #include "BKE_sequencer.h" +#include "sequencer.h" + /** * Sequencer Cache Design Notes * ============================ diff --git a/source/blender/sequencer/intern/modifier.c b/source/blender/sequencer/intern/modifier.c index a38fe252731..d31be56b036 100644 --- a/source/blender/sequencer/intern/modifier.c +++ b/source/blender/sequencer/intern/modifier.c @@ -45,6 +45,8 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "sequencer.h" + static SequenceModifierTypeInfo *modifiersTypes[NUM_SEQUENCE_MODIFIER_TYPES]; static bool modifierTypesInit = false; diff --git a/source/blender/sequencer/intern/prefetch.c b/source/blender/sequencer/intern/prefetch.c index 65b2b6c02cf..c22fb3c4ad8 100644 --- a/source/blender/sequencer/intern/prefetch.c +++ b/source/blender/sequencer/intern/prefetch.c @@ -54,6 +54,8 @@ #include "DEG_depsgraph_debug.h" #include "DEG_depsgraph_query.h" +#include "sequencer.h" + typedef struct PrefetchJob { struct PrefetchJob *next, *prev; diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index 068d836d1e6..acbdc28c6fd 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -96,6 +96,8 @@ #include "RE_engine.h" +#include "sequencer.h" + #ifdef WITH_AUDASPACE # include #endif diff --git a/source/blender/sequencer/intern/sequencer.h b/source/blender/sequencer/intern/sequencer.h new file mode 100644 index 00000000000..55e19f80fcd --- /dev/null +++ b/source/blender/sequencer/intern/sequencer.h @@ -0,0 +1,190 @@ +/* + * 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. + * + * The Original Code is Copyright (C) 2004 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup sequencer + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Editing; +struct ImBuf; +struct Main; +struct Mask; +struct Scene; +struct Sequence; +struct StripColorBalance; +struct StripElem; + +#define EARLY_NO_INPUT -1 +#define EARLY_DO_EFFECT 0 +#define EARLY_USE_INPUT_1 1 +#define EARLY_USE_INPUT_2 2 + +/* ********************************************************************** + * sequencer.c + * + * sequencer render functions + * ********************************************************************** */ + +struct ImBuf *BKE_sequencer_give_ibuf_seqbase(const SeqRenderData *context, + float cfra, + int chan_shown, + struct ListBase *seqbasep); +struct ImBuf *BKE_sequencer_effect_execute_threaded(struct SeqEffectHandle *sh, + const SeqRenderData *context, + struct Sequence *seq, + float cfra, + float facf0, + float facf1, + struct ImBuf *ibuf1, + struct ImBuf *ibuf2, + struct ImBuf *ibuf3); +struct ImBuf *BKE_sequencer_render_mask_input(const SeqRenderData *context, + int mask_input_type, + struct Sequence *mask_sequence, + struct Mask *mask_id, + int cfra, + int fra_offset, + bool make_float); +void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, + struct ImBuf *ibuf, + float mul, + bool make_float, + struct ImBuf *mask_input); + +/* ********************************************************************** + * sequencer.c + * + * sequencer color space functions + * ********************************************************************** */ + +void BKE_sequencer_imbuf_to_sequencer_space(struct Scene *scene, + struct ImBuf *ibuf, + bool make_float); + +/* ********************************************************************** + * sequencer.c + * + * sequencer scene functions + * ********************************************************************** */ + +void BKE_sequencer_base_clipboard_pointers_free(struct ListBase *seqbase); +int BKE_sequencer_get_shown_sequences(struct ListBase *seqbasep, + int cfra, + int chanshown, + struct Sequence **seq_arr_out); +bool BKE_sequencer_input_have_to_preprocess(const SeqRenderData *context, + struct Sequence *seq, + float cfra); +float BKE_sequencer_give_stripelem_index(struct Sequence *seq, float cfra); + +/* ********************************************************************** + * image_cache.c + * + * Sequencer memory cache management functions + * ********************************************************************** */ + +struct ImBuf *BKE_sequencer_cache_get(const SeqRenderData *context, + struct Sequence *seq, + float cfra, + int type, + bool skip_disk_cache); +void BKE_sequencer_cache_put(const SeqRenderData *context, + struct Sequence *seq, + float cfra, + int type, + struct ImBuf *i, + float cost, + bool skip_disk_cache); +bool BKE_sequencer_cache_put_if_possible(const SeqRenderData *context, + struct Sequence *seq, + float cfra, + int type, + struct ImBuf *nval, + float cost, + bool skip_disk_cache); +bool BKE_sequencer_cache_recycle_item(struct Scene *scene); +void BKE_sequencer_cache_free_temp_cache(struct Scene *scene, short id, int cfra); +void BKE_sequencer_cache_destruct(struct Scene *scene); +void BKE_sequencer_cache_cleanup_all(struct Main *bmain); +void BKE_sequencer_cache_cleanup_sequence(struct Scene *scene, + struct Sequence *seq, + struct Sequence *seq_changed, + int invalidate_types, + bool force_seq_changed_range); +bool BKE_sequencer_cache_is_full(struct Scene *scene); + +/* ********************************************************************** + * prefetch.c + * + * Sequencer frame prefetching + * ********************************************************************** */ + +void BKE_sequencer_prefetch_start(const SeqRenderData *context, float cfra, float cost); +void BKE_sequencer_prefetch_free(struct Scene *scene); +bool BKE_sequencer_prefetch_job_is_running(struct Scene *scene); +void BKE_sequencer_prefetch_get_time_range(struct Scene *scene, int *start, int *end); +SeqRenderData *BKE_sequencer_prefetch_get_original_context(const SeqRenderData *context); +struct Sequence *BKE_sequencer_prefetch_get_original_sequence(struct Sequence *seq, + struct Scene *scene); + +/* ********************************************************************** + * seqeffects.c + * + * Sequencer effect strip management functions + * ********************************************************************** + */ + +struct SeqEffectHandle BKE_sequence_get_blend(struct Sequence *seq); +void BKE_sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, bool force); +float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context, + struct Sequence *seq, + float cfra, + int input); + +/* ********************************************************************** + * sequencer.c + * + * Sequencer editing functions + * ********************************************************************** + */ + +void BKE_sequence_sound_init(struct Scene *scene, struct Sequence *seq); +struct Sequence *BKE_sequence_metastrip(ListBase *seqbase /* = ed->seqbase */, + struct Sequence *meta /* = NULL */, + struct Sequence *seq); + +/* ********************************************************************** + * sequencer.c + * + * Unused + * ********************************************************************** + */ +bool BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur); +void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce); +int BKE_sequence_effect_get_supports_mask(int seq_type); + +#ifdef __cplusplus +} +#endif -- cgit v1.2.3 From e9d21136ce2228a11b788f3202ae929d8fd6d927 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 25 Oct 2020 23:08:29 -0500 Subject: UI: Fix Symmetry options in weight paint panels The now redundant "X" checkbox is removed since it's also present in the Symmetry panel above. The Topology Mirror is moved into the Symmetry panel also. This was needed because `Mesh.use_x_mirror` has recently been turned into different functionality, and its old functionality now lives under `Mesh.use_mirror_vertex_group_x`. Something went wrong in the UI in This transition. Differential Revision: https://developer.blender.org/D9287 --- release/scripts/startup/bl_ui/space_view3d_toolbar.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index e808c8779c6..83134ea393a 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -957,12 +957,16 @@ class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel): layout = self.layout tool_settings = context.tool_settings wpaint = tool_settings.weight_paint - draw_vpaint_symmetry(layout, wpaint, context.object.data) + mesh = context.object.data + draw_vpaint_symmetry(layout, wpaint, mesh) col = layout.column() row = col.row(align=True) - row.prop(context.object.data, 'use_mirror_vertex_group_x') + row.prop(mesh, 'use_mirror_vertex_group_x') + row = layout.row(align=True) + row.active = mesh.use_mirror_vertex_group_x + row.prop(mesh, "use_mirror_topology") class VIEW3D_PT_tools_weightpaint_symmetry_for_topbar(Panel): bl_space_type = 'TOPBAR' @@ -995,14 +999,6 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel): col.prop(wpaint, "use_group_restrict") - obj = context.weight_paint_object - if obj.type == 'MESH': - mesh = obj.data - col.prop(mesh, "use_mirror_x") - row = col.row() - row.active = mesh.use_mirror_x - row.prop(mesh, "use_mirror_topology") - # ********** default tools for vertex-paint **************** -- cgit v1.2.3 From 6c7f30a6f66c9deab015147dd923b5fd18bac97c Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 25 Oct 2020 23:23:38 -0500 Subject: UI: Use property split in vertex paint symmetry panels Set property split in the higher level panel functions so that it carries over to buttons added after. Also discard the redundant "Symmetry" to make sure there is enough space for the checkbox label. --- .../scripts/startup/bl_ui/space_view3d_toolbar.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 83134ea393a..701c98ce489 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -124,11 +124,7 @@ class View3DPanel: # Used by vertex & weight paint def draw_vpaint_symmetry(layout, vpaint, mesh): - col = layout.column() - col.use_property_split = True - col.use_property_decorate = False - row = col.row(heading="Mirror", align=True) row.prop(mesh, "use_mirror_x", text="X", toggle=True) row.prop(mesh, "use_mirror_y", text="Y", toggle=True) @@ -955,16 +951,18 @@ class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + tool_settings = context.tool_settings wpaint = tool_settings.weight_paint mesh = context.object.data - draw_vpaint_symmetry(layout, wpaint, mesh) - col = layout.column() - row = col.row(align=True) - row.prop(mesh, 'use_mirror_vertex_group_x') + draw_vpaint_symmetry(layout, wpaint, mesh) - row = layout.row(align=True) + col = layout.column(align=True) + col.prop(mesh, 'use_mirror_vertex_group_x', text="Vertex Group X") + row = col.row() row.active = mesh.use_mirror_vertex_group_x row.prop(mesh, "use_mirror_topology") @@ -1033,8 +1031,12 @@ class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + tool_settings = context.tool_settings vpaint = tool_settings.vertex_paint + draw_vpaint_symmetry(layout, vpaint, context.object.data) -- cgit v1.2.3 From 4d3a386af2b1da5e4a153426db66f22dcf326e8b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 26 Oct 2020 15:59:08 +1100 Subject: Cleanup: spelling --- source/blender/blenfont/BLF_api.h | 6 +++--- source/blender/blenfont/intern/blf_font.c | 6 +++--- source/blender/blenkernel/intern/fcurve.c | 6 +++--- source/blender/editors/interface/interface_panel.c | 16 ++++++++-------- source/blender/editors/sculpt_paint/sculpt_cloth.c | 22 +++++++++++----------- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 03877957f42..1f39257a4c2 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -74,7 +74,7 @@ void BLF_color4f(int fontid, float r, float g, float b, float a); void BLF_color4fv(int fontid, const float rgba[4]); void BLF_color3f(int fontid, float r, float g, float b); void BLF_color3fv_alpha(int fontid, const float rgb[3], float alpha); -/* also available: UI_FontThemeColor(fontid, colorid) */ +/* Also available: `UI_FontThemeColor(fontid, colorid)`. */ /* Set a 4x4 matrix to be multiplied before draw the text. * Remember that you need call BLF_enable(BLF_MATRIX) @@ -89,8 +89,8 @@ void BLF_color3fv_alpha(int fontid, const float rgb[3], float alpha); */ void BLF_matrix(int fontid, const float m[16]); -/* Batch drawcalls together as long as - * the modelview matrix and the font remain unchanged. */ +/* Batch draw-calls together as long as + * the model-view matrix and the font remain unchanged. */ void BLF_batch_draw_begin(void); void BLF_batch_draw_flush(void); void BLF_batch_draw_end(void); diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 1501ee07b66..189cbaf152d 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -75,9 +75,9 @@ static SpinLock blf_glyph_cache_mutex; * \{ */ /** - * Drawcalls are precious! make them count! - * Since most of the Text elems are not covered by other UI elements, we can - * group some strings together and render them in one drawcall. This behavior + * Draw-calls are precious! make them count! + * Since most of the Text elements are not covered by other UI elements, we can + * group some strings together and render them in one draw-call. This behavior * is on demand only, between #BLF_batch_draw_begin() and #BLF_batch_draw_end(). */ static void blf_batch_draw_init(void) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index dcf4c78dfd8..c4055c0f611 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1646,7 +1646,7 @@ static float fcurve_eval_keyframes_extrapolate( return endpoint_bezt->vec[1][1] - (fac * dx); } - /* Use the gradient of the second handle (later) of neighbour to calculate the gradient and thus + /* Use the gradient of the second handle (later) of neighbor to calculate the gradient and thus * the value of the curve at evaluation time. */ int handle = direction_to_neighbor > 0 ? 0 : 2; float dx = endpoint_bezt->vec[1][0] - evaltime; @@ -1922,7 +1922,7 @@ static float fcurve_eval_keyframes_interpolate(FCurve *fcu, BezTriple *bezts, fl return 0.0f; } -/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes. */ +/* Calculate F-Curve value for 'evaltime' using #BezTriple keyframes. */ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime) { if (evaltime <= bezts->vec[1][0]) { @@ -1937,7 +1937,7 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime return fcurve_eval_keyframes_interpolate(fcu, bezts, evaltime); } -/* Calculate F-Curve value for 'evaltime' using FPoint samples. */ +/* Calculate F-Curve value for 'evaltime' using #FPoint samples. */ static float fcurve_eval_samples(FCurve *fcu, FPoint *fpts, float evaltime) { FPoint *prevfpt, *lastfpt, *fpt; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 2a95a34e5e7..7fa45545a16 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -313,7 +313,7 @@ Panel *UI_panel_add_instanced(const bContext *C, Panel *new_panel = panel_add_instanced(region, panels, panel_type, custom_data); - /* Do this after #panel_add_instatnced so all subpanels are added. */ + /* Do this after #panel_add_instatnced so all sub-panels are added. */ panel_set_expansion_from_list_data(C, new_panel); return new_panel; @@ -325,7 +325,7 @@ Panel *UI_panel_add_instanced(const bContext *C, */ void UI_list_panel_unique_str(Panel *panel, char *r_name) { - /* The panel sortorder will be unique for a specific panel type because the instanced + /* The panel sort-order will be unique for a specific panel type because the instanced * panel list is regenerated for every change in the data order / length. */ snprintf(r_name, INSTANCED_PANEL_UNIQUE_STR_LEN, "%d", panel->sortorder); } @@ -805,7 +805,7 @@ static float panel_region_offset_x_get(const ARegion *region) /** * Starting from the "block size" set in #UI_panel_end, calculate the full size - * of the panel including the subpanel headers and buttons. + * of the panel including the sub-panel headers and buttons. */ static void panel_calculate_size_recursive(ARegion *region, Panel *panel) { @@ -854,7 +854,7 @@ static void panel_calculate_size_recursive(ARegion *region, Panel *panel) void UI_panel_end(Panel *panel, int width, int height) { /* Store the size of the buttons layout in the panel. The actual panel size - * (including subpanels) is calculated in #UI_panels_end. */ + * (including sub-panels) is calculated in #UI_panels_end. */ panel->blocksizex = width; panel->blocksizey = height; } @@ -916,13 +916,13 @@ static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, const bool use_animation) { /* This has to run on inactive panels that may not have a type, - * but we can prevent running on headerless panels in some cases. */ + * but we can prevent running on header-less panels in some cases. */ if (panel->type == NULL || !(panel->type->flag & PNL_NO_HEADER)) { SET_FLAG_FROM_TEST(panel->runtime_flag, use_search_closed, PANEL_USE_CLOSED_FROM_SEARCH); } LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { - /* Don't check if the subpanel is active, otherwise the + /* Don't check if the sub-panel is active, otherwise the * expansion won't be reset when the parent is closed. */ panel_set_expansion_from_seach_filter_recursive( C, child_panel, use_search_closed, use_animation); @@ -964,8 +964,8 @@ static void panel_remove_invisible_layouts_recursive(Panel *panel, const Panel * } } else if (UI_panel_is_closed(panel)) { - /* If subpanels have no search results but the parent panel does, then the parent panel open - * and the subpanels will close. In that case there must be a way to hide the buttons in the + /* If sub-panels have no search results but the parent panel does, then the parent panel open + * and the sub-panels will close. In that case there must be a way to hide the buttons in the * panel but keep the header buttons. */ LISTBASE_FOREACH (uiButtonGroup *, button_group, &block->button_groups) { if (button_group->flag & UI_BUTTON_GROUP_PANEL_HEADER) { diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index bcc73650195..20b164fa80c 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -139,14 +139,14 @@ static float cloth_brush_simulation_falloff_get(const Brush *brush, const float falloff = radius + (radius * brush->cloth_sim_limit * brush->cloth_sim_falloff); if (distance > limit) { - /* Outiside the limits. */ + /* Outside the limits. */ return 0.0f; } if (distance < falloff) { /* Before the falloff area. */ return 1.0f; } - /* Do a smoothstep transition inside the falloff area. */ + /* Do a smooth-step transition inside the falloff area. */ float p = 1.0f - ((distance - falloff) / (limit - falloff)); return 3.0f * p * p - 2.0f * p * p * p; } @@ -214,7 +214,7 @@ static void cloth_brush_add_length_constraint(SculptSession *ss, /* Reallocation if the array capacity is exceeded. */ cloth_brush_reallocate_constraints(cloth_sim); - /* Add the constraint to the GSet to avoid creating it again. */ + /* Add the constraint to the #GSet to avoid creating it again. */ BLI_edgeset_add(cloth_sim->created_length_constraints, v1, v2); } @@ -334,7 +334,7 @@ static void do_cloth_brush_build_constraints_task_cb_ex( radius_squared = ss->cache->initial_radius * ss->cache->initial_radius; } - /* Only limit the contraint creation to a radius when the simulation is local. */ + /* Only limit the constraint creation to a radius when the simulation is local. */ const float cloth_sim_radius_squared = brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL ? data->cloth_sim_radius * data->cloth_sim_radius : @@ -459,7 +459,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, ss, &test, data->brush->falloff_shape); const int thread_id = BLI_task_parallel_thread_id(tls); - /* For Pich Perpendicular Deform Type. */ + /* For Pinch Perpendicular Deform Type. */ float x_object_space[3]; float z_object_space[3]; if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR) { @@ -930,7 +930,7 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod BKE_curvemapping_init(brush->curve); - /* Init the grab delta. */ + /* Initialize the grab delta. */ copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry); normalize_v3(grab_delta); @@ -940,7 +940,7 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod return; } - /* Calcuate push offset. */ + /* Calculate push offset. */ if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PUSH) { mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius); @@ -954,7 +954,7 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_PLANE) { SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co); - /* Init stroke local space matrix. */ + /* Initialize stroke local space matrix. */ cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry); mat[0][3] = 0.0f; cross_v3_v3v3(mat[1], area_no, mat[0]); @@ -1068,7 +1068,7 @@ void SCULPT_cloth_brush_ensure_nodes_constraints( PBVHNode **nodes, int totnode, SculptClothSimulation *cloth_sim, - /* Cannot be const, because it is assigned to a non-const variable. + /* Cannot be `const`, because it is assigned to a `non-const` variable. * NOLINTNEXTLINE: readability-non-const-parameter. */ float initial_location[3], const float radius) @@ -1188,7 +1188,7 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes, totnode); } /* The first step of a symmetry pass is never simulated as deformation modes need valid delta - * for brush tip alignement. */ + * for brush tip alignment. */ return; } @@ -1314,7 +1314,7 @@ static EnumPropertyItem prop_cloth_filter_type[] = { "SCALE", 0, "Scale", - "Scales the mesh as a softbody using the origin of the object as scale"}, + "Scales the mesh as a soft-body using the origin of the object as scale"}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From aa77689f77b412e88bbe66fb466d2fa453701719 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 26 Oct 2020 15:59:24 +1100 Subject: Keymap: enable repeat for text editing paste operations --- release/scripts/presets/keyconfig/keymap_data/blender_default.py | 8 ++++---- .../presets/keyconfig/keymap_data/industry_compatible_data.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 97acdfd311c..ac81a706858 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -2336,10 +2336,10 @@ def km_text(params): ("text.run_script", {"type": 'P', "value": 'PRESS', "alt": True}, None), ("text.cut", {"type": 'X', "value": 'PRESS', "ctrl": True}, None), ("text.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None), - ("text.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None), + ("text.paste", {"type": 'V', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("text.cut", {"type": 'DEL', "value": 'PRESS', "shift": True}, None), ("text.copy", {"type": 'INSERT', "value": 'PRESS', "ctrl": True}, None), - ("text.paste", {"type": 'INSERT', "value": 'PRESS', "shift": True}, None), + ("text.paste", {"type": 'INSERT', "value": 'PRESS', "shift": True, "repeat": True}, None), ("text.duplicate_line", {"type": 'D', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("text.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, None), ("text.select_line", {"type": 'A', "value": 'PRESS', "shift": True, "ctrl": True}, None), @@ -2669,7 +2669,7 @@ def km_console(_params): {"properties": [("interactive", True)]}), ("console.copy_as_script", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True}, None), ("console.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None), - ("console.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None), + ("console.paste", {"type": 'V', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("console.select_set", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), ("console.select_word", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None), ("console.insert", {"type": 'TAB', "value": 'PRESS', "ctrl": True, "repeat": True}, @@ -4861,7 +4861,7 @@ def km_font(params): ("font.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, None), ("font.text_copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None), ("font.text_cut", {"type": 'X', "value": 'PRESS', "ctrl": True}, None), - ("font.text_paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None), + ("font.text_paste", {"type": 'V', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("font.line_break", {"type": 'RET', "value": 'PRESS', "repeat": True}, None), ("font.text_insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True, "repeat": True}, None), ("font.text_insert", {"type": 'BACK_SPACE', "value": 'PRESS', "alt": True, "repeat": True}, diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index 666dbb30365..c79a59145cf 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -1603,10 +1603,10 @@ def km_text(params): ("text.run_script", {"type": 'P', "value": 'PRESS', "alt": True}, None), ("text.cut", {"type": 'X', "value": 'PRESS', "ctrl": True}, None), ("text.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None), - ("text.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None), + ("text.paste", {"type": 'V', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("text.cut", {"type": 'DEL', "value": 'PRESS', "shift": True}, None), ("text.copy", {"type": 'INSERT', "value": 'PRESS', "ctrl": True}, None), - ("text.paste", {"type": 'INSERT', "value": 'PRESS', "shift": True}, None), + ("text.paste", {"type": 'INSERT', "value": 'PRESS', "shift": True, "repeat": True}, None), ("text.duplicate_line", {"type": 'D', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("text.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, None), ("text.select_line", {"type": 'A', "value": 'PRESS', "shift": True, "ctrl": True}, None), @@ -1906,7 +1906,7 @@ def km_console(params): {"properties": [("interactive", True)]}), ("console.copy_as_script", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True}, None), ("console.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None), - ("console.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None), + ("console.paste", {"type": 'V', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("console.select_set", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), ("console.select_word", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None), ("console.insert", {"type": 'TAB', "value": 'PRESS', "ctrl": True, "repeat": True}, @@ -3752,7 +3752,7 @@ def km_font(params): ("font.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, None), ("font.text_copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None), ("font.text_cut", {"type": 'X', "value": 'PRESS', "ctrl": True}, None), - ("font.text_paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None), + ("font.text_paste", {"type": 'V', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("font.line_break", {"type": 'RET', "value": 'PRESS'}, None), ("font.text_insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None), ("font.text_insert", {"type": 'BACK_SPACE', "value": 'PRESS', "alt": True}, -- cgit v1.2.3 From e4facbbea54019abe257787a7e9e8594a6ce3609 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 26 Oct 2020 17:07:58 +1100 Subject: Modifiers: include the object & modifier when logging errors Without this, there was no way of finding out which object, modifier combination caused the error, making the logs not very useful for debugging. --- source/blender/blenkernel/BKE_DerivedMesh.h | 1 + source/blender/blenkernel/BKE_modifier.h | 6 ++- source/blender/blenkernel/BKE_pointcache.h | 2 +- source/blender/blenkernel/intern/DerivedMesh.c | 15 +++++--- source/blender/blenkernel/intern/cloth.c | 22 +++++------ source/blender/blenkernel/intern/crazyspace.c | 4 +- source/blender/blenkernel/intern/modifier.c | 13 ++++++- source/blender/blenkernel/intern/pointcache.c | 35 ++++++++++------- source/blender/editors/armature/meshlaplacian.c | 3 +- source/blender/modifiers/intern/MOD_array.c | 4 +- source/blender/modifiers/intern/MOD_bevel.c | 2 +- source/blender/modifiers/intern/MOD_boolean.c | 18 ++++----- .../modifiers/intern/MOD_correctivesmooth.c | 10 ++--- source/blender/modifiers/intern/MOD_datatransfer.c | 9 +++-- source/blender/modifiers/intern/MOD_decimate.c | 2 +- .../blender/modifiers/intern/MOD_laplaciandeform.c | 15 +++++--- .../blender/modifiers/intern/MOD_laplaciansmooth.c | 2 +- .../blender/modifiers/intern/MOD_mesh_to_volume.cc | 4 +- source/blender/modifiers/intern/MOD_meshcache.c | 8 ++-- source/blender/modifiers/intern/MOD_meshdeform.c | 10 ++--- .../modifiers/intern/MOD_meshsequencecache.c | 4 +- source/blender/modifiers/intern/MOD_multires.c | 4 +- source/blender/modifiers/intern/MOD_normal_edit.c | 15 ++++++-- source/blender/modifiers/intern/MOD_skin.c | 42 +++++++++++++++------ .../modifiers/intern/MOD_solidify_nonmanifold.c | 21 ++++++++--- source/blender/modifiers/intern/MOD_subsurf.c | 4 +- .../blender/modifiers/intern/MOD_surfacedeform.c | 44 +++++++++++----------- .../modifiers/intern/MOD_volume_displace.cc | 2 +- .../blender/modifiers/intern/MOD_volume_to_mesh.cc | 8 ++-- .../blender/modifiers/intern/MOD_weighted_normal.c | 3 +- 30 files changed, 202 insertions(+), 130 deletions(-) diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index b517ecfa599..092eec578c9 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -364,6 +364,7 @@ struct Mesh *editbmesh_get_eval_cage_and_final(struct Depsgraph *depsgraph, float (*editbmesh_vert_coords_alloc(struct BMEditMesh *em, int *r_vert_len))[3]; bool editbmesh_modifier_is_enabled(struct Scene *scene, + const struct Object *ob, struct ModifierData *md, bool has_prev_mesh); void makeDerivedMesh(struct Depsgraph *depsgraph, diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index b2015c4e6d7..10528a651e5 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -427,8 +427,10 @@ bool BKE_modifier_is_non_geometrical(ModifierData *md); bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode); -void BKE_modifier_set_error(struct ModifierData *md, const char *format, ...) - ATTR_PRINTF_FORMAT(2, 3); +void BKE_modifier_set_error(const struct Object *ob, + struct ModifierData *md, + const char *format, + ...) ATTR_PRINTF_FORMAT(3, 4); bool BKE_modifier_is_preview(struct ModifierData *md); void BKE_modifiers_foreach_ID_link(struct Object *ob, IDWalkFunc walk, void *userData); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index f8e04b75b3d..a45b134f825 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -167,7 +167,7 @@ typedef struct PTCacheID { * (the cfra parameter is just for using same function pointer with totwrite). */ int (*totpoint)(void *calldata, int cfra); /* report error if number of points does not match */ - void (*error)(void *calldata, const char *message); + void (*error)(const struct ID *owner_id, void *calldata, const char *message); /* number of points written for current cache frame */ int (*totwrite)(void *calldata, int cfra); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index d551eaf04e4..7b2e1be7b5d 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1021,7 +1021,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && have_non_onlydeform_modifiers_appled) { - BKE_modifier_set_error(md, "Modifier requires original data, bad stack position"); + BKE_modifier_set_error(ob, md, "Modifier requires original data, bad stack position"); continue; } @@ -1047,10 +1047,10 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if (unsupported) { if (sculpt_dyntopo) { - BKE_modifier_set_error(md, "Not supported in dyntopo"); + BKE_modifier_set_error(ob, md, "Not supported in dyntopo"); } else { - BKE_modifier_set_error(md, "Not supported in sculpt mode"); + BKE_modifier_set_error(ob, md, "Not supported in sculpt mode"); } continue; } @@ -1378,7 +1378,10 @@ float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3] return cos; } -bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev_mesh) +bool editbmesh_modifier_is_enabled(Scene *scene, + const Object *ob, + ModifierData *md, + bool has_prev_mesh) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; @@ -1388,7 +1391,7 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev } if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && has_prev_mesh) { - BKE_modifier_set_error(md, "Modifier requires original data, bad stack position"); + BKE_modifier_set_error(ob, md, "Modifier requires original data, bad stack position"); return false; } @@ -1522,7 +1525,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!editbmesh_modifier_is_enabled(scene, md, mesh_final != NULL)) { + if (!editbmesh_modifier_is_enabled(scene, ob, md, mesh_final != NULL)) { continue; } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 403722b80cf..e9df562a15f 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -55,7 +55,7 @@ /* Prototypes for internal functions. */ static void cloth_to_object(Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]); -static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh); +static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mesh); static bool cloth_from_object( Object *ob, ClothModifierData *clmd, Mesh *mesh, float framenr, int first); static void cloth_update_springs(ClothModifierData *clmd); @@ -234,13 +234,13 @@ static bool do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int if (clmd->clothObject == NULL) { if (!cloth_from_object(ob, clmd, result, framenr, 1)) { BKE_ptcache_invalidate(cache); - BKE_modifier_set_error(&(clmd->modifier), "Can't initialize cloth"); + BKE_modifier_set_error(ob, &(clmd->modifier), "Can't initialize cloth"); return false; } if (clmd->clothObject == NULL) { BKE_ptcache_invalidate(cache); - BKE_modifier_set_error(&(clmd->modifier), "Null cloth object"); + BKE_modifier_set_error(ob, &(clmd->modifier), "Null cloth object"); return false; } @@ -742,7 +742,7 @@ static bool cloth_from_object( clmd->clothObject->edgeset = NULL; } else { - BKE_modifier_set_error(&(clmd->modifier), "Out of memory on allocating clmd->clothObject"); + BKE_modifier_set_error(ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject"); return false; } @@ -751,7 +751,7 @@ static bool cloth_from_object( return false; } - cloth_from_mesh(clmd, mesh); + cloth_from_mesh(clmd, ob, mesh); /* create springs */ clmd->clothObject->springs = NULL; @@ -814,7 +814,7 @@ static bool cloth_from_object( if (!cloth_build_springs(clmd, mesh)) { cloth_free_modifier(clmd); - BKE_modifier_set_error(&(clmd->modifier), "Cannot build springs"); + BKE_modifier_set_error(ob, &(clmd->modifier), "Cannot build springs"); return false; } @@ -831,7 +831,7 @@ static bool cloth_from_object( return true; } -static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh) +static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mesh) { const MLoop *mloop = mesh->mloop; const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh); @@ -844,8 +844,8 @@ static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh) "clothVertex"); if (clmd->clothObject->verts == NULL) { cloth_free_modifier(clmd); - BKE_modifier_set_error(&(clmd->modifier), - "Out of memory on allocating clmd->clothObject->verts"); + BKE_modifier_set_error( + ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts"); printf("cloth_free_modifier clmd->clothObject->verts\n"); return; } @@ -861,8 +861,8 @@ static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh) clmd->clothObject->tri = MEM_mallocN(sizeof(MVertTri) * looptri_num, "clothLoopTris"); if (clmd->clothObject->tri == NULL) { cloth_free_modifier(clmd); - BKE_modifier_set_error(&(clmd->modifier), - "Out of memory on allocating clmd->clothObject->looptri"); + BKE_modifier_set_error( + ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject->looptri"); printf("cloth_free_modifier clmd->clothObject->looptri\n"); return; } diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 01c05c62b70..4e1ec9ba35e 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -273,7 +273,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra for (i = 0; md && i <= cageIndex; i++, md = md->next) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!editbmesh_modifier_is_enabled(scene, md, me != NULL)) { + if (!editbmesh_modifier_is_enabled(scene, ob, md, me != NULL)) { continue; } @@ -302,7 +302,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra } for (; md && i <= cageIndex; md = md->next, i++) { - if (editbmesh_modifier_is_enabled(scene, md, me != NULL) && + if (editbmesh_modifier_is_enabled(scene, ob, md, me != NULL) && BKE_modifier_is_correctable_deformed(md)) { numleft++; } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 0aa85f0ad50..d79a03dce6e 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -389,7 +389,7 @@ bool BKE_modifier_is_non_geometrical(ModifierData *md) return (mti->type == eModifierTypeType_NonGeometrical); } -void BKE_modifier_set_error(ModifierData *md, const char *_format, ...) +void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *_format, ...) { char buffer[512]; va_list ap; @@ -406,7 +406,16 @@ void BKE_modifier_set_error(ModifierData *md, const char *_format, ...) md->error = BLI_strdup(buffer); - CLOG_STR_ERROR(&LOG, md->error); +#ifndef NDEBUG + if ((md->mode & eModifierMode_Virtual) == 0) { + /* Ensure correct object is passed in. */ + const Object *ob_orig = (Object *)DEG_get_original_id((ID *)&ob->id); + const ModifierData *md_orig = md->orig_modifier_data ? md->orig_modifier_data : md; + BLI_assert(BLI_findindex(&ob_orig->modifiers, md_orig) != -1); + } +#endif + + CLOG_ERROR(&LOG, "Object: \"%s\", Modifier: \"%s\", %s", ob->id.name + 2, md->name, md->error); } /* used for buttons, to find out if the 'draw deformed in editmode' option is diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 7c8527a8702..415250b184b 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -256,7 +256,9 @@ static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra)) SoftBody *soft = soft_v; return soft->totpoint; } -static void ptcache_softbody_error(void *UNUSED(soft_v), const char *UNUSED(message)) +static void ptcache_softbody_error(const ID *UNUSED(owner_id), + void *UNUSED(soft_v), + const char *UNUSED(message)) { /* ignored for now */ } @@ -471,7 +473,9 @@ static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra)) return psys->totpart; } -static void ptcache_particle_error(void *UNUSED(psys_v), const char *UNUSED(message)) +static void ptcache_particle_error(const ID *UNUSED(owner_id), + void *UNUSED(psys_v), + const char *UNUSED(message)) { /* ignored for now */ } @@ -642,10 +646,11 @@ static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra)) return clmd->clothObject ? clmd->clothObject->mvert_num : 0; } -static void ptcache_cloth_error(void *cloth_v, const char *message) +static void ptcache_cloth_error(const ID *owner_id, void *cloth_v, const char *message) { ClothModifierData *clmd = cloth_v; - BKE_modifier_set_error(&clmd->modifier, "%s", message); + BLI_assert(GS(owner_id->name) == ID_OB); + BKE_modifier_set_error((Object *)owner_id, &clmd->modifier, "%s", message); } static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra)) @@ -659,7 +664,9 @@ static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra)) return surface->data->total_points; } -static void ptcache_dynamicpaint_error(void *UNUSED(sd), const char *UNUSED(message)) +static void ptcache_dynamicpaint_error(const ID *UNUSED(owner_id), + void *UNUSED(sd), + const char *UNUSED(message)) { /* ignored for now */ } @@ -853,7 +860,9 @@ static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra)) return rbw->numbodies; } -static void ptcache_rigidbody_error(void *UNUSED(rb_v), const char *UNUSED(message)) +static void ptcache_rigidbody_error(const struct ID *UNUSED(owner_id), + void *UNUSED(rb_v), + const char *UNUSED(message)) { /* ignored for now */ } @@ -2098,19 +2107,19 @@ static int ptcache_read_stream(PTCacheID *pid, int cfra) } if (!ptcache_file_header_begin_read(pf)) { - pid->error(pid->calldata, "Failed to read point cache file"); + pid->error(pid->owner_id, pid->calldata, "Failed to read point cache file"); error = 1; } else if (pf->type != pid->type) { - pid->error(pid->calldata, "Point cache file has wrong type"); + pid->error(pid->owner_id, pid->calldata, "Point cache file has wrong type"); error = 1; } else if (!pid->read_header(pf)) { - pid->error(pid->calldata, "Failed to read point cache file header"); + pid->error(pid->owner_id, pid->calldata, "Failed to read point cache file header"); error = 1; } else if (pf->totpoint != pid->totpoint(pid->calldata, cfra)) { - pid->error(pid->calldata, "Number of points in cache does not match mesh"); + pid->error(pid->owner_id, pid->calldata, "Number of points in cache does not match mesh"); error = 1; } @@ -2119,7 +2128,7 @@ static int ptcache_read_stream(PTCacheID *pid, int cfra) /* We have stream reading here. */ if (!pid->read_stream(pf, pid->calldata)) { - pid->error(pid->calldata, "Failed to read point cache file data"); + pid->error(pid->owner_id, pid->calldata, "Failed to read point cache file data"); error = 1; } } @@ -2155,7 +2164,7 @@ static int ptcache_read(PTCacheID *pid, int cfra) int pid_totpoint = pid->totpoint(pid->calldata, cfra); if (totpoint != pid_totpoint) { - pid->error(pid->calldata, "Number of points in cache does not match mesh"); + pid->error(pid->owner_id, pid->calldata, "Number of points in cache does not match mesh"); totpoint = MIN2(totpoint, pid_totpoint); } } @@ -2211,7 +2220,7 @@ static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) int pid_totpoint = pid->totpoint(pid->calldata, (int)cfra); if (totpoint != pid_totpoint) { - pid->error(pid->calldata, "Number of points in cache does not match mesh"); + pid->error(pid->owner_id, pid->calldata, "Number of points in cache does not match mesh"); totpoint = MIN2(totpoint, pid_totpoint); } } diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index e51e5ec5cef..3c0b6dacbf6 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -1547,7 +1547,8 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind } } else { - BKE_modifier_set_error(&mmd->modifier, "Failed to find bind solution (increase precision?)"); + BKE_modifier_set_error( + mmd->object, &mmd->modifier, "Failed to find bind solution (increase precision?)"); error("Mesh Deform: failed to find bind solution."); break; } diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 7e21300f3c2..6ca50a34ebf 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -508,6 +508,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, if (offset_is_too_small) { BKE_modifier_set_error( + ctx->object, &amd->modifier, "The offset is too small, we cannot generate the amount of geometry it would require"); } @@ -518,7 +519,8 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, else if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts + (size_t)end_cap_nverts) > max_num_vertices) { count = 1; - BKE_modifier_set_error(&amd->modifier, + BKE_modifier_set_error(ctx->object, + &amd->modifier, "The amount of copies is too high, we cannot generate the amount of " "geometry it would require"); } diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index b84c8a186b5..04ddac338e5 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -208,7 +208,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * Object *ob = ctx->object; if (harden_normals && (ob->type == OB_MESH) && !(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) { - BKE_modifier_set_error(md, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error(ob, md, "Enable 'Auto Smooth' in Object Data Properties"); harden_normals = false; } diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index 7700c8bbff9..5d28aea54b5 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -189,7 +189,7 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data)) return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0; } -static bool BMD_error_messages(ModifierData *md, Collection *col) +static bool BMD_error_messages(const Object *ob, ModifierData *md, Collection *col) { BooleanModifierData *bmd = (BooleanModifierData *)md; @@ -202,21 +202,21 @@ static bool BMD_error_messages(ModifierData *md, Collection *col) #ifndef WITH_GMP /* If compiled without GMP, return a error. */ if (use_exact) { - BKE_modifier_set_error(md, "Compiled without GMP, using fast solver"); + BKE_modifier_set_error(ob, md, "Compiled without GMP, using fast solver"); error_returns_result = false; } #endif /* If intersect is selected using fast solver, return a error. */ if (operand_collection && operation_intersect && !use_exact) { - BKE_modifier_set_error(md, "Cannot execute, intersect only available using exact solver"); + BKE_modifier_set_error(ob, md, "Cannot execute, intersect only available using exact solver"); error_returns_result = true; } /* If the selected collection is empty and using fast solver, return a error. */ if (operand_collection) { if (!use_exact && BKE_collection_is_empty(col)) { - BKE_modifier_set_error(md, "Cannot execute, fast solver and empty collection"); + BKE_modifier_set_error(ob, md, "Cannot execute, fast solver and empty collection"); error_returns_result = true; } @@ -225,7 +225,7 @@ static bool BMD_error_messages(ModifierData *md, Collection *col) FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (col, operand_ob) { if (operand_ob->type != OB_MESH) { BKE_modifier_set_error( - md, "Cannot execute, the selected collection contains non mesh objects"); + ob, md, "Cannot execute, the selected collection contains non mesh objects"); error_returns_result = true; } } @@ -587,7 +587,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return result; } - BMD_error_messages(md, NULL); + BMD_error_messages(ctx->object, md, NULL); Object *operand_ob = bmd->object; @@ -615,7 +615,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* if new mesh returned, return it; otherwise there was * an error, so delete the modifier object */ if (result == NULL) { - BKE_modifier_set_error(md, "Cannot execute boolean operation"); + BKE_modifier_set_error(object, md, "Cannot execute boolean operation"); } } } @@ -626,7 +626,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } /* Return result for certain errors. */ - if (BMD_error_messages(md, col) == confirm_return) { + if (BMD_error_messages(ctx->object, md, col) == confirm_return) { return result; } @@ -669,7 +669,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* if new mesh returned, return it; otherwise there was * an error, so delete the modifier object */ if (result == NULL) { - BKE_modifier_set_error(md, "Cannot execute boolean operation"); + BKE_modifier_set_error(object, md, "Cannot execute boolean operation"); } } } diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index eaf8c44a9be..5884ec0aa17 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -615,7 +615,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, csmd_orig->bind_coords_num = csmd->bind_coords_num; } else { - BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph"); } } @@ -625,7 +625,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, } if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) && (csmd->bind_coords == NULL)) { - BKE_modifier_set_error(md, "Bind data required"); + BKE_modifier_set_error(ob, md, "Bind data required"); goto error; } @@ -633,14 +633,14 @@ static void correctivesmooth_modifier_do(ModifierData *md, if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { if (csmd->bind_coords_num != numVerts) { BKE_modifier_set_error( - md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts); + ob, md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts); goto error; } } else { /* MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO */ if (ob->type != OB_MESH) { - BKE_modifier_set_error(md, "Object is not a mesh"); + BKE_modifier_set_error(ob, md, "Object is not a mesh"); goto error; } else { @@ -648,7 +648,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, if (me_numVerts != numVerts) { BKE_modifier_set_error( - md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts); + ob, md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts); goto error; } } diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 17d716b731c..9b6a21c840d 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -232,16 +232,19 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if (BKE_reports_contain(&reports, RPT_ERROR)) { const char *report_str = BKE_reports_string(&reports, RPT_ERROR); - BKE_modifier_set_error(md, "%s", report_str); + BKE_modifier_set_error(ctx->object, md, "%s", report_str); MEM_freeN((void *)report_str); } else if ((dtmd->data_types & DT_TYPE_LNOR) && !(me->flag & ME_AUTOSMOOTH)) { - BKE_modifier_set_error((ModifierData *)dtmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error( + ctx->object, (ModifierData *)dtmd, "Enable 'Auto Smooth' in Object Data Properties"); } else if (result->totvert > HIGH_POLY_WARNING || ((Mesh *)(ob_source->data))->totvert > HIGH_POLY_WARNING) { BKE_modifier_set_error( - md, "Source or destination object has a high polygon count, computation might be slow"); + ctx->object, + md, + "Source or destination object has a high polygon count, computation might be slow"); } return result; diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 2532afc933e..10ed4f8d80b 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -140,7 +140,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } if (dmd->face_count <= 3) { - BKE_modifier_set_error(md, "Modifier requires more than 3 input faces"); + BKE_modifier_set_error(ctx->object, md, "Modifier requires more than 3 input faces"); return mesh; } diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index 8eb9e97573d..d3dc8c93c02 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -684,14 +684,15 @@ static void LaplacianDeformModifier_do( else { if (sysdif == LAPDEFORM_SYSTEM_CHANGE_VERTEXES) { BKE_modifier_set_error( - &lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts); + ob, &lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_EDGES) { BKE_modifier_set_error( - &lmd->modifier, "Edges changed from %d to %d", sys->total_edges, mesh->totedge); + ob, &lmd->modifier, "Edges changed from %d to %d", sys->total_edges, mesh->totedge); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) { - BKE_modifier_set_error(&lmd->modifier, + BKE_modifier_set_error(ob, + &lmd->modifier, "Vertex group '%s' is not valid, or maybe empty", sys->anchor_grp_name); } @@ -704,8 +705,10 @@ static void LaplacianDeformModifier_do( } else { if (!isValidVertexGroup(lmd, ob, mesh)) { - BKE_modifier_set_error( - &lmd->modifier, "Vertex group '%s' is not valid, or maybe empty", lmd->anchor_grp_name); + BKE_modifier_set_error(ob, + &lmd->modifier, + "Vertex group '%s' is not valid, or maybe empty", + lmd->anchor_grp_name); lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND; } else if (lmd->total_verts > 0 && lmd->total_verts == numVerts) { @@ -725,7 +728,7 @@ static void LaplacianDeformModifier_do( } } if (sys && sys->is_matrix_computed && !sys->has_solution) { - BKE_modifier_set_error(&lmd->modifier, "The system did not find a solution"); + BKE_modifier_set_error(ob, &lmd->modifier, "The system did not find a solution"); } } diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index f7a8faf7a1c..d51f95bd18d 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -82,7 +82,7 @@ struct BLaplacianSystem { typedef struct BLaplacianSystem LaplacianSystem; static void required_data_mask(Object *ob, ModifierData *md, CustomData_MeshMasks *r_cddata_masks); -static bool is_disabled(const struct Scene *UNUSED(scene), ModifierData *md, bool useRenderParams); +static bool is_disabled(const struct Scene *scene, ModifierData *md, bool useRenderParams); static float compute_volume(const float center[3], float (*vertexCos)[3], const MPoly *mpoly, diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc index cc16da0fa80..426bba05d76 100644 --- a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc +++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc @@ -273,8 +273,8 @@ static Volume *modifyVolume(ModifierData *md, const ModifierEvalContext *ctx, Vo return volume; #else - UNUSED_VARS(md, ctx); - BKE_modifier_set_error(md, "Compiled without OpenVDB"); + UNUSED_VARS(md); + BKE_modifier_set_error(ctx->object, md, "Compiled without OpenVDB"); return input_volume; #endif } diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index 5d5b8b847d5..b808d738fe8 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -171,13 +171,13 @@ static void meshcache_do(MeshCacheModifierData *mcmd, /* we could support any object type */ if (UNLIKELY(ob->type != OB_MESH)) { - BKE_modifier_set_error(&mcmd->modifier, "'Integrate' only valid for Mesh objects"); + BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' only valid for Mesh objects"); } else if (UNLIKELY(me->totvert != numVerts)) { - BKE_modifier_set_error(&mcmd->modifier, "'Integrate' original mesh vertex mismatch"); + BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' original mesh vertex mismatch"); } else if (UNLIKELY(me->totpoly == 0)) { - BKE_modifier_set_error(&mcmd->modifier, "'Integrate' requires faces"); + BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' requires faces"); } else { /* the moons align! */ @@ -216,7 +216,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, /* -------------------------------------------------------------------- */ /* Apply the transformation matrix (if needed) */ if (UNLIKELY(err_str)) { - BKE_modifier_set_error(&mcmd->modifier, "%s", err_str); + BKE_modifier_set_error(ob, &mcmd->modifier, "%s", err_str); } else if (ok) { bool use_matrix = false; diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index e2c8db07623..0e530312238 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -373,7 +373,7 @@ static void meshdeformModifier_do(ModifierData *md, Object *ob_target = mmd->object; cagemesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); if (cagemesh == NULL) { - BKE_modifier_set_error(md, "Cannot get mesh from cage object"); + BKE_modifier_set_error(ctx->object, md, "Cannot get mesh from cage object"); return; } @@ -388,7 +388,7 @@ static void meshdeformModifier_do(ModifierData *md, if (!mmd->bindcagecos) { /* progress bar redraw can make this recursive .. */ if (!DEG_is_active(ctx->depsgraph)) { - BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph"); goto finally; } if (!recursive_bind_sentinel) { @@ -405,16 +405,16 @@ static void meshdeformModifier_do(ModifierData *md, totcagevert = BKE_mesh_wrapper_vert_len(cagemesh); if (mmd->totvert != totvert) { - BKE_modifier_set_error(md, "Vertices changed from %d to %d", mmd->totvert, totvert); + BKE_modifier_set_error(ob, md, "Vertices changed from %d to %d", mmd->totvert, totvert); goto finally; } else if (mmd->totcagevert != totcagevert) { BKE_modifier_set_error( - md, "Cage vertices changed from %d to %d", mmd->totcagevert, totcagevert); + ob, md, "Cage vertices changed from %d to %d", mmd->totcagevert, totcagevert); goto finally; } else if (mmd->bindcagecos == NULL) { - BKE_modifier_set_error(md, "Bind data missing"); + BKE_modifier_set_error(ob, md, "Bind data missing"); goto finally; } diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 70732636d02..73106b2e816 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -127,7 +127,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BKE_cachefile_reader_open(cache_file, &mcmd->reader, ctx->object, mcmd->object_path); if (!mcmd->reader) { BKE_modifier_set_error( - md, "Could not create Alembic reader for file %s", cache_file->filepath); + ctx->object, md, "Could not create Alembic reader for file %s", cache_file->filepath); return mesh; } } @@ -170,7 +170,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } if (err_str) { - BKE_modifier_set_error(md, "%s", err_str); + BKE_modifier_set_error(ctx->object, md, "%s", err_str); } if (!ELEM(result, NULL, mesh) && (mesh != org_mesh)) { diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index e3a8d651183..0798f02cc10 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -216,7 +216,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * { Mesh *result = mesh; #if !defined(WITH_OPENSUBDIV) - BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv"); return result; #endif MultiresModifierData *mmd = (MultiresModifierData *)md; @@ -300,7 +300,7 @@ static void deformMatrices(ModifierData *md, { #if !defined(WITH_OPENSUBDIV) - BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv"); return; #endif diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 1be74a8fed2..0ec564d2e2d 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -476,7 +476,15 @@ static bool is_valid_target(NormalEditModifierData *enmd) if ((enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) && enmd->target) { return true; } - BKE_modifier_set_error((ModifierData *)enmd, "Invalid target settings"); + return false; +} + +static bool is_valid_target_with_error(const Object *ob, NormalEditModifierData *enmd) +{ + if (is_valid_target(enmd)) { + return true; + } + BKE_modifier_set_error(ob, (ModifierData *)enmd, "Invalid target settings"); return false; } @@ -491,7 +499,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, (enmd->mix_limit == (float)M_PI)); /* Do not run that modifier at all if autosmooth is disabled! */ - if (!is_valid_target(enmd) || mesh->totloop == 0) { + if (!is_valid_target_with_error(ctx->object, enmd) || mesh->totloop == 0) { return mesh; } @@ -506,7 +514,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) #endif { - BKE_modifier_set_error((ModifierData *)enmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error( + ob, (ModifierData *)enmd, "Enable 'Auto Smooth' in Object Data Properties"); return mesh; } diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 20445a7006a..203736fb9ff 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -1760,13 +1760,19 @@ static bool skin_output_branch_hulls( return result; } +typedef enum eSkinErrorFlag { + SKIN_ERROR_NO_VALID_ROOT = (1 << 0), + SKIN_ERROR_HULL = (1 << 1), +} eSkinErrorFlag; + static BMesh *build_skin(SkinNode *skin_nodes, int totvert, const MeshElemMap *emap, const MEdge *medge, int totedge, const MDeformVert *input_dvert, - SkinModifierData *smd) + SkinModifierData *smd, + eSkinErrorFlag *r_error) { SkinOutput so; int v; @@ -1802,7 +1808,7 @@ static BMesh *build_skin(SkinNode *skin_nodes, skin_update_merged_vertices(skin_nodes, totvert); if (!skin_output_branch_hulls(&so, skin_nodes, totvert, emap, medge)) { - BKE_modifier_set_error(&smd->modifier, "Hull error"); + *r_error |= SKIN_ERROR_HULL; } /* Merge triangles here in the hope of providing better target @@ -1848,7 +1854,7 @@ static void skin_set_orig_indices(Mesh *mesh) * 2) Generate node frames * 3) Output vertices and polygons from frames, connections, and hulls */ -static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd) +static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_error) { Mesh *result; MVertSkin *nodes; @@ -1878,16 +1884,14 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd) MEM_freeN(emat); emat = NULL; - bm = build_skin(skin_nodes, totvert, emap, medge, totedge, dvert, smd); + bm = build_skin(skin_nodes, totvert, emap, medge, totedge, dvert, smd, r_error); MEM_freeN(skin_nodes); MEM_freeN(emap); MEM_freeN(emapmem); if (!has_valid_root) { - BKE_modifier_set_error( - &smd->modifier, - "No valid root vertex found (you need one per mesh island you want to skin)"); + *r_error |= SKIN_ERROR_NO_VALID_ROOT; } if (!bm) { @@ -1904,7 +1908,7 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd) return result; } -static Mesh *final_skin(SkinModifierData *smd, Mesh *mesh) +static Mesh *final_skin(SkinModifierData *smd, Mesh *mesh, eSkinErrorFlag *r_error) { Mesh *result; @@ -1914,7 +1918,7 @@ static Mesh *final_skin(SkinModifierData *smd, Mesh *mesh) } mesh = subdivide_base(mesh); - result = base_skin(mesh, smd); + result = base_skin(mesh, smd, r_error); BKE_id_free(NULL, mesh); return result; @@ -1934,11 +1938,25 @@ static void initData(ModifierData *md) md->mode |= eModifierMode_Editmode; } -static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { - Mesh *result; + eSkinErrorFlag error = 0; + Mesh *result = final_skin((SkinModifierData *)md, mesh, &error); + + if (error & SKIN_ERROR_NO_VALID_ROOT) { + error &= ~SKIN_ERROR_NO_VALID_ROOT; + BKE_modifier_set_error( + ctx->object, + md, + "No valid root vertex found (you need one per mesh island you want to skin)"); + } + if (error & SKIN_ERROR_HULL) { + error &= ~SKIN_ERROR_HULL; + BKE_modifier_set_error(ctx->object, md, "Hull error"); + } + BLI_assert(error == 0); - if (!(result = final_skin((SkinModifierData *)md, mesh))) { + if (result == NULL) { return mesh; } return result; diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index 47adb7ba0bd..8acf07f9181 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -2501,16 +2501,25 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(face_edges); } if (edge_index != numNewEdges) { - BKE_modifier_set_error( - md, "Internal Error: edges array wrong size: %u instead of %u", numNewEdges, edge_index); + BKE_modifier_set_error(ctx->object, + md, + "Internal Error: edges array wrong size: %u instead of %u", + numNewEdges, + edge_index); } if (poly_index != numNewPolys) { - BKE_modifier_set_error( - md, "Internal Error: polys array wrong size: %u instead of %u", numNewPolys, poly_index); + BKE_modifier_set_error(ctx->object, + md, + "Internal Error: polys array wrong size: %u instead of %u", + numNewPolys, + poly_index); } if (loop_index != numNewLoops) { - BKE_modifier_set_error( - md, "Internal Error: loops array wrong size: %u instead of %u", numNewLoops, loop_index); + BKE_modifier_set_error(ctx->object, + md, + "Internal Error: loops array wrong size: %u instead of %u", + numNewLoops, + loop_index); } BLI_assert(edge_index == numNewEdges); BLI_assert(poly_index == numNewPolys); diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index c30dd9f8765..1aa015682dd 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -254,7 +254,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * { Mesh *result = mesh; #if !defined(WITH_OPENSUBDIV) - BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv"); return result; #endif SubsurfModifierData *smd = (SubsurfModifierData *)md; @@ -309,7 +309,7 @@ static void deformMatrices(ModifierData *md, int num_verts) { #if !defined(WITH_OPENSUBDIV) - BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv"); return; #endif diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index aef7df3282f..0c91c1a7715 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -1009,7 +1009,8 @@ static void bindVert(void *__restrict userdata, freeBindData(bwdata); } -static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, +static bool surfacedeformBind(Object *ob, + SurfaceDeformModifierData *smd_orig, SurfaceDeformModifierData *smd_eval, float (*vertexCos)[3], uint numverts, @@ -1030,20 +1031,20 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, vert_edges = MEM_calloc_arrayN(tnumverts, sizeof(*vert_edges), "SDefVertEdgeMap"); if (vert_edges == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); return false; } adj_array = MEM_malloc_arrayN(tnumedges, 2 * sizeof(*adj_array), "SDefVertEdge"); if (adj_array == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); MEM_freeN(vert_edges); return false; } edge_polys = MEM_calloc_arrayN(tnumedges, sizeof(*edge_polys), "SDefEdgeFaceMap"); if (edge_polys == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); MEM_freeN(vert_edges); MEM_freeN(adj_array); return false; @@ -1051,14 +1052,14 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, smd_orig->verts = MEM_malloc_arrayN(numverts, sizeof(*smd_orig->verts), "SDefBindVerts"); if (smd_orig->verts == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); return false; } BKE_bvhtree_from_mesh_get(&treeData, target, BVHTREE_FROM_LOOPTRI, 2); if (treeData.tree == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); MEM_freeN(smd_orig->verts); smd_orig->verts = NULL; @@ -1069,8 +1070,8 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys); if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { - BKE_modifier_set_error((ModifierData *)smd_eval, - "Target has edges with more than two polygons"); + BKE_modifier_set_error( + ob, (ModifierData *)smd_eval, "Target has edges with more than two polygons"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); free_bvhtree_from_mesh(&treeData); MEM_freeN(smd_orig->verts); @@ -1097,7 +1098,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, }; if (data.targetCos == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); return false; } @@ -1116,20 +1117,20 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, MEM_freeN(data.targetCos); if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { - BKE_modifier_set_error((ModifierData *)smd_eval, - "Target has edges with more than two polygons"); + BKE_modifier_set_error( + ob, (ModifierData *)smd_eval, "Target has edges with more than two polygons"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains concave polygons"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains concave polygons"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains overlapping vertices"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains overlapping vertices"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_GENERIC_ERR) { @@ -1137,7 +1138,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, * to explain this with a reasonably sized message. * Though it shouldn't really matter all that much, * because this is very unlikely to occur */ - BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains invalid polygons"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains invalid polygons"); freeData((ModifierData *)smd_orig); } @@ -1234,7 +1235,7 @@ static void surfacedeformModifier_do(ModifierData *md, if (!(smd->flags & MOD_SDEF_BIND)) { if (smd->verts != NULL) { if (!DEG_is_active(ctx->depsgraph)) { - BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph"); return; } ModifierData *md_orig = BKE_modifier_get_original(md); @@ -1246,7 +1247,7 @@ static void surfacedeformModifier_do(ModifierData *md, Object *ob_target = smd->target; target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); if (!target) { - BKE_modifier_set_error(md, "No valid target mesh"); + BKE_modifier_set_error(ob, md, "No valid target mesh"); return; } @@ -1256,7 +1257,7 @@ static void surfacedeformModifier_do(ModifierData *md, /* If not bound, execute bind. */ if (smd->verts == NULL) { if (!DEG_is_active(ctx->depsgraph)) { - BKE_modifier_set_error(md, "Attempt to unbind from inactive dependency graph"); + BKE_modifier_set_error(ob, md, "Attempt to unbind from inactive dependency graph"); return; } @@ -1270,7 +1271,7 @@ static void surfacedeformModifier_do(ModifierData *md, /* Avoid converting edit-mesh data, binding is an exception. */ BKE_mesh_wrapper_ensure_mdata(target); - if (!surfacedeformBind(smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target)) { + if (!surfacedeformBind(ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target)) { smd->flags &= ~MOD_SDEF_BIND; } /* Early abort, this is binding 'call', no need to perform whole evaluation. */ @@ -1279,11 +1280,12 @@ static void surfacedeformModifier_do(ModifierData *md, /* Poly count checks */ if (smd->numverts != numverts) { - BKE_modifier_set_error(md, "Vertices changed from %u to %u", smd->numverts, numverts); + BKE_modifier_set_error(ob, md, "Vertices changed from %u to %u", smd->numverts, numverts); return; } if (smd->numpoly != tnumpoly) { - BKE_modifier_set_error(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); + BKE_modifier_set_error( + ob, md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); return; } diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc index 22bf5cd4893..7293945312a 100644 --- a/source/blender/modifiers/intern/MOD_volume_displace.cc +++ b/source/blender/modifiers/intern/MOD_volume_displace.cc @@ -307,7 +307,7 @@ static Volume *modifyVolume(ModifierData *md, const ModifierEvalContext *ctx, Vo return volume; #else UNUSED_VARS(md, ctx); - BKE_modifier_set_error(md, "Compiled without OpenVDB"); + BKE_modifier_set_error(ctx->object, md, "Compiled without OpenVDB"); return volume; #endif } diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc index ea292155d3c..bbd1bdb6955 100644 --- a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc +++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc @@ -281,7 +281,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * VolumeGrid *volume_grid = BKE_volume_grid_find(volume, vmmd->grid_name); if (volume_grid == nullptr) { - BKE_modifier_set_error(md, "Cannot find '%s' grid", vmmd->grid_name); + BKE_modifier_set_error(vmmd->object, md, "Cannot find '%s' grid", vmmd->grid_name); return input_mesh; } @@ -290,7 +290,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * const VolumeGridType grid_type = BKE_volume_grid_type(volume_grid); VolumeToMeshOp to_mesh_op{*grid, *vmmd, *ctx}; if (!BKE_volume_grid_type_operation(grid_type, to_mesh_op)) { - BKE_modifier_set_error(md, "Expected a scalar grid"); + BKE_modifier_set_error(ctx->object, md, "Expected a scalar grid"); return input_mesh; } @@ -301,8 +301,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } return mesh; #else - UNUSED_VARS(md, ctx); - BKE_modifier_set_error(md, "Compiled without OpenVDB"); + UNUSED_VARS(md); + BKE_modifier_set_error(ctx->object, md, "Compiled without OpenVDB"); return input_mesh; #endif } diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index 65bb009fc58..bd15d909834 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -574,7 +574,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) #endif { - BKE_modifier_set_error((ModifierData *)wnmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error( + ctx->object, (ModifierData *)wnmd, "Enable 'Auto Smooth' in Object Data Properties"); return mesh; } -- cgit v1.2.3 From 81462f86bc5fd8d8a51bdfb39f111570f7c3124e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 26 Oct 2020 09:15:48 +0100 Subject: Fix T81984: Crash in sculpt undo with mask extract after dyntopo toggle More operators missing the mandatory undo flag... --- source/blender/editors/mesh/editmesh_mask_extract.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 0a9aa724764..96abd2226db 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -346,7 +346,7 @@ void MESH_OT_paint_mask_extract(wmOperatorType *ot) ot->invoke = paint_mask_extract_invoke; ot->exec = paint_mask_extract_exec; - ot->flag = OPTYPE_REGISTER; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_float( ot->srna, @@ -430,7 +430,7 @@ void MESH_OT_face_set_extract(wmOperatorType *ot) ot->invoke = face_set_extract_invoke; ot->modal = face_set_extract_modal; - ot->flag = OPTYPE_REGISTER; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; geometry_extract_props(ot->srna); } @@ -598,7 +598,7 @@ void MESH_OT_paint_mask_slice(wmOperatorType *ot) ot->poll = geometry_extract_poll; ot->exec = paint_mask_slice_exec; - ot->flag = OPTYPE_REGISTER; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_float( ot->srna, -- cgit v1.2.3 From 4b7abde11df9bd6ed759a28286ce3a05147e08c8 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 26 Oct 2020 09:50:18 +0100 Subject: Fix T81963: Random rare crashes in override code. Finaly managed to reproduce, we not only have to ensure pose data is up to date for the override armature, but also for the reference linked data. --- source/blender/blenkernel/intern/lib_override.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index e008058ae39..3adda80b445 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1357,10 +1357,15 @@ bool BKE_lib_override_library_operations_create(Main *bmain, ID *local) * ensure this is valid, but in some situations (like hidden collections etc.) this won't * be the case, so we need to take care of this ourselves. */ Object *ob_local = (Object *)local; + Object *ob_reference = (Object *)local->override_library->reference; if (ob_local->data != NULL && ob_local->type == OB_ARMATURE && ob_local->pose != NULL && ob_local->pose->flag & POSE_RECALC) { BKE_pose_rebuild(bmain, ob_local, ob_local->data, true); } + if (ob_reference->data != NULL && ob_reference->type == OB_ARMATURE && + ob_reference->pose != NULL && ob_reference->pose->flag & POSE_RECALC) { + BKE_pose_rebuild(bmain, ob_reference, ob_reference->data, true); + } } PointerRNA rnaptr_local, rnaptr_reference; -- cgit v1.2.3 From 2ddecfffc3d3a3a1db4ae45e8665caa2a85ab43a Mon Sep 17 00:00:00 2001 From: Ankit Meel Date: Mon, 26 Oct 2020 15:02:20 +0530 Subject: Fix T81077 id_management test on macOS This looks like a optimizer bug where it makes wrong assumptions. The code inside lib_id_delete:264 on rBafd13710b897cc1c11b `for (id = last_remapped_id->next; id; id = id->next) {..}` is not executed in release/relwithdebinfo builds. This can be "fixed" by several ways: - Adding a line that prints the `last_remapped_id->name` right before the said for-loop starts. - Turning off optimization for the whole function `id_delete`: `#pragma clang optimize off/on` Ray Molenkamp - Marking `last_remapped_id` volatile. Julian Eisel - Marking `tagged_deleted_ids` volatile. But it adds a warning when calling `BLI_addtail`: discards volatile qualifier. Discovered by accident. Fix T81077 Reviewed By: mont29 Maniphest Tasks: T81077 Differential Revision: https://developer.blender.org/D9315 --- source/blender/blenkernel/intern/lib_id_delete.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index 1e45a3c1163..25c48479ef9 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -261,7 +261,9 @@ static void id_delete(Main *bmain, const bool do_tagged_deletion) bool keep_looping = true; while (keep_looping) { ID *id, *id_next; - ID *last_remapped_id = tagged_deleted_ids.last; + /* Marked volatile to avoid a macOS Clang optimization bug. See T81077. + * #last_remapped_id.next is assumed to be NULL by optimizer which is wrong. */ + volatile ID *last_remapped_id = tagged_deleted_ids.last; keep_looping = false; /* First tag and remove from Main all datablocks directly from target lib. -- cgit v1.2.3 From 042143440d7668d3e357805ffdd20b1a4d2e2975 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 26 Oct 2020 11:01:18 +0100 Subject: LatticeDeform: Performance This patch improves the single core performance of the lattice deform. 1. Prefetching deform vert during initialization. This data is constant for each innerloop. This reduces the complexity of the inner loop what makes more CPU resources free for other optimizations. 2. Prefetching the Lattice instance. It was constant. Although performance wise this isn't noticeable it is always good to free some space in the branch prediction tables. 3. Remove branching in all loops by not exiting when the effect of the loop isn't there. The checks in the inner loops detected if this loop didn't have any effect on the final result and then continue to the next loop. This made the branch prediction unpredictable and a lot of mis predictions were done. For smaller inner loops it is always better to remove unpredictable if statements by using branchless code patterns. 4. Use SSE2 instruction when available. This gives 50% performance increase measured on a Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz with GCC 9.3. Also check other compilers. Before: ``` performance_no_dvert_10000 (4 ms) performance_no_dvert_100000 (30 ms) performance_no_dvert_1000000 (268 ms) performance_no_dvert_10000000 (2637 ms) ``` After: ``` performance_no_dvert_10000 (3 ms) performance_no_dvert_100000 (21 ms) performance_no_dvert_1000000 (180 ms) performance_no_dvert_10000000 (1756 ms) ``` Reviewed By: Campbell Barton Differential Revision: https://developer.blender.org/D9087 --- source/blender/blenkernel/CMakeLists.txt | 1 + source/blender/blenkernel/intern/lattice_deform.c | 151 ++++++++++----------- .../blenkernel/intern/lattice_deform_test.cc | 138 +++++++++++++++++++ 3 files changed, 214 insertions(+), 76 deletions(-) create mode 100644 source/blender/blenkernel/intern/lattice_deform_test.cc diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 0fbc8c4c229..f6df3f1bb62 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -718,6 +718,7 @@ if(WITH_GTESTS) set(TEST_SRC intern/armature_test.cc intern/fcurve_test.cc + intern/lattice_deform_test.cc ) set(TEST_INC ../editors/include diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c index 919093f3630..43965813b84 100644 --- a/source/blender/blenkernel/intern/lattice_deform.c +++ b/source/blender/blenkernel/intern/lattice_deform.c @@ -49,14 +49,24 @@ #include "BKE_deform.h" +#ifdef __SSE2__ +# include +#endif + /* -------------------------------------------------------------------- */ /** \name Lattice Deform API * \{ */ typedef struct LatticeDeformData { - const Object *object; - float *latticedata; + /* Convert from object space to deform space */ float latmat[4][4]; + /* Cached reference to the lattice to use for evaluation. When in edit mode this attribute + * is set to the edit mode lattice. */ + const Lattice *lt; + /* Preprocessed lattice points (converted to deform space). */ + float *latticedata; + /* Prefetched DeformWeights of the lattice. */ + float *lattice_weights; } LatticeDeformData; LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Object *ob) @@ -72,6 +82,7 @@ LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Ob float fu, fv, fw; int u, v, w; float *latticedata; + float *lattice_weights = NULL; float latmat[4][4]; LatticeDeformData *lattice_deform_data; @@ -80,8 +91,10 @@ LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Ob } bp = lt->def; - fp = latticedata = MEM_mallocN(sizeof(float[3]) * lt->pntsu * lt->pntsv * lt->pntsw, - "latticedata"); + const int32_t num_points = lt->pntsu * lt->pntsv * lt->pntsw; + /* We allocate one additional float for SSE2 optimizations. Without this + * the SSE2 instructions for the last item would read in unallocated memory. */ + fp = latticedata = MEM_mallocN(sizeof(float[3]) * num_points + sizeof(float), "latticedata"); /* for example with a particle system: (ob == NULL) */ if (ob == NULL) { @@ -100,6 +113,20 @@ LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Ob invert_m4_m4(imat, latmat); } + /* Prefetch latice deform group weights. */ + int defgrp_index = -1; + const MDeformVert *dvert = BKE_lattice_deform_verts_get(oblatt); + if (lt->vgroup[0] && dvert) { + defgrp_index = BKE_object_defgroup_name_index(ob, lt->vgroup); + + if (defgrp_index != -1) { + lattice_weights = MEM_malloc_arrayN(sizeof(float), num_points, "lattice_weights"); + for (int index = 0; index < num_points; index++) { + lattice_weights[index] = BKE_defvert_find_weight(dvert + index, defgrp_index); + } + } + } + for (w = 0, fw = lt->fw; w < lt->pntsw; w++, fw += lt->dw) { for (v = 0, fv = lt->fv; v < lt->pntsv; v++, fv += lt->dv) { for (u = 0, fu = lt->fu; u < lt->pntsu; u++, bp++, co += 3, fp += 3, fu += lt->du) { @@ -121,7 +148,8 @@ LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Ob lattice_deform_data = MEM_mallocN(sizeof(LatticeDeformData), "Lattice Deform Data"); lattice_deform_data->latticedata = latticedata; - lattice_deform_data->object = oblatt; + lattice_deform_data->lattice_weights = lattice_weights; + lattice_deform_data->lt = lt; copy_m4_m4(lattice_deform_data->latmat, latmat); return lattice_deform_data; @@ -131,30 +159,21 @@ void BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data, float co[3], float weight) { - const Object *ob = lattice_deform_data->object; - Lattice *lt = ob->data; + float *latticedata = lattice_deform_data->latticedata; + float *lattice_weights = lattice_deform_data->lattice_weights; + BLI_assert(latticedata); + const Lattice *lt = lattice_deform_data->lt; float u, v, w, tu[4], tv[4], tw[4]; float vec[3]; int idx_w, idx_v, idx_u; int ui, vi, wi, uu, vv, ww; /* vgroup influence */ - int defgrp_index = -1; float co_prev[3], weight_blend = 0.0f; - const MDeformVert *dvert = BKE_lattice_deform_verts_get(ob); - float *__restrict latticedata = lattice_deform_data->latticedata; - - if (lt->editlatt) { - lt = lt->editlatt->latt; - } - if (latticedata == NULL) { - return; - } - - if (lt->vgroup[0] && dvert) { - defgrp_index = BKE_object_defgroup_name_index(ob, lt->vgroup); - copy_v3_v3(co_prev, co); - } + copy_v3_v3(co_prev, co); +#ifdef __SSE2__ + __m128 co_vec = _mm_loadu_ps(co_prev); +#endif /* co is in local coords, treat with latmat */ mul_v3_m4v3(vec, lattice_deform_data->latmat, co); @@ -197,67 +216,47 @@ void BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data, wi = 0; } - for (ww = wi - 1; ww <= wi + 2; ww++) { - w = tw[ww - wi + 1]; + const int w_stride = lt->pntsu * lt->pntsv; + const int idx_w_max = (lt->pntsw - 1) * lt->pntsu * lt->pntsv; + const int v_stride = lt->pntsu; + const int idx_v_max = (lt->pntsv - 1) * lt->pntsu; + const int idx_u_max = (lt->pntsu - 1); - if (w != 0.0f) { - if (ww > 0) { - if (ww < lt->pntsw) { - idx_w = ww * lt->pntsu * lt->pntsv; - } - else { - idx_w = (lt->pntsw - 1) * lt->pntsu * lt->pntsv; + for (ww = wi - 1; ww <= wi + 2; ww++) { + w = weight * tw[ww - wi + 1]; + idx_w = CLAMPIS(ww * w_stride, 0, idx_w_max); + for (vv = vi - 1; vv <= vi + 2; vv++) { + v = w * tv[vv - vi + 1]; + idx_v = CLAMPIS(vv * v_stride, 0, idx_v_max); + for (uu = ui - 1; uu <= ui + 2; uu++) { + u = v * tu[uu - ui + 1]; + idx_u = CLAMPIS(uu, 0, idx_u_max); + const int idx = idx_w + idx_v + idx_u; +#ifdef __SSE2__ + { + __m128 weight_vec = _mm_set1_ps(u); + /* This will load one extra element, this is ok because + * we ignore that part of register anyway. + */ + __m128 lattice_vec = _mm_loadu_ps(&latticedata[idx * 3]); + co_vec = _mm_add_ps(co_vec, _mm_mul_ps(lattice_vec, weight_vec)); } - } - else { - idx_w = 0; - } - - for (vv = vi - 1; vv <= vi + 2; vv++) { - v = w * tv[vv - vi + 1]; - - if (v != 0.0f) { - if (vv > 0) { - if (vv < lt->pntsv) { - idx_v = idx_w + vv * lt->pntsu; - } - else { - idx_v = idx_w + (lt->pntsv - 1) * lt->pntsu; - } - } - else { - idx_v = idx_w; - } - - for (uu = ui - 1; uu <= ui + 2; uu++) { - u = weight * v * tu[uu - ui + 1]; - - if (u != 0.0f) { - if (uu > 0) { - if (uu < lt->pntsu) { - idx_u = idx_v + uu; - } - else { - idx_u = idx_v + (lt->pntsu - 1); - } - } - else { - idx_u = idx_v; - } - - madd_v3_v3fl(co, &latticedata[idx_u * 3], u); - - if (defgrp_index != -1) { - weight_blend += (u * BKE_defvert_find_weight(dvert + idx_u, defgrp_index)); - } - } - } +#else + madd_v3_v3fl(co, &latticedata[idx * 3], u); +#endif + if (lattice_weights) { + weight_blend += (u * lattice_weights[idx]); } } } } +#ifdef __SSE2__ + { + copy_v3_v3(co, (float *)&co_vec); + } +#endif - if (defgrp_index != -1) { + if (lattice_weights) { interp_v3_v3v3(co, co_prev, co, weight_blend); } } diff --git a/source/blender/blenkernel/intern/lattice_deform_test.cc b/source/blender/blenkernel/intern/lattice_deform_test.cc new file mode 100644 index 00000000000..33a4cc1d871 --- /dev/null +++ b/source/blender/blenkernel/intern/lattice_deform_test.cc @@ -0,0 +1,138 @@ +/* + * 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. + * + * The Original Code is Copyright (C) 2020 by Blender Foundation. + */ +#include "testing/testing.h" + +#include "BKE_idtype.h" +#include "BKE_lattice.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_lattice_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" + +#include "BLI_rand.hh" + +namespace blender::bke::tests { + +struct LatticeDeformTestContext { + Lattice lattice; + Object ob_lattice; + Mesh mesh; + Object ob_mesh; + float (*coords)[3]; + LatticeDeformData *ldd; +}; + +static void test_lattice_deform_init(LatticeDeformTestContext *ctx, + RandomNumberGenerator *rng, + int32_t num_items) +{ + /* Generate random input data between -5 and 5. */ + ctx->coords = (float(*)[3])MEM_malloc_arrayN(sizeof(float[3]), num_items, __func__); + for (uint32_t index = 0; index < num_items; index++) { + ctx->coords[index][0] = (rng->get_float() - 0.5f) * 10; + ctx->coords[index][1] = (rng->get_float() - 0.5f) * 10; + ctx->coords[index][2] = (rng->get_float() - 0.5f) * 10; + } + IDType_ID_LT.init_data(&ctx->lattice.id); + IDType_ID_OB.init_data(&ctx->ob_lattice.id); + ctx->ob_lattice.type = OB_LATTICE; + ctx->ob_lattice.data = &ctx->lattice; + IDType_ID_OB.init_data(&ctx->ob_mesh.id); + IDType_ID_ME.init_data(&ctx->mesh.id); + ctx->ob_mesh.type = OB_MESH; + ctx->ob_mesh.data = &ctx->mesh; + + ctx->ldd = BKE_lattice_deform_data_create(&ctx->ob_lattice, &ctx->ob_mesh); +} + +static void test_lattice_deform(LatticeDeformTestContext *ctx, int32_t num_items) +{ + for (int i = 0; i < num_items; i++) { + float *co = &ctx->coords[i][0]; + BKE_lattice_deform_data_eval_co(ctx->ldd, co, 1.0f); + } +} + +static void test_lattice_deform_free(LatticeDeformTestContext *ctx) +{ + BKE_lattice_deform_data_destroy(ctx->ldd); + MEM_freeN(ctx->coords); + IDType_ID_LT.free_data(&ctx->lattice.id); + IDType_ID_OB.free_data(&ctx->ob_lattice.id); + IDType_ID_OB.free_data(&ctx->ob_mesh.id); + IDType_ID_ME.free_data(&ctx->mesh.id); +} + +TEST(lattice_deform_performance, performance_no_dvert_1) +{ + const int32_t num_items = 1; + LatticeDeformTestContext ctx = {0}; + RandomNumberGenerator rng; + test_lattice_deform_init(&ctx, &rng, num_items); + test_lattice_deform(&ctx, num_items); + test_lattice_deform_free(&ctx); +} +TEST(lattice_deform_performance, performance_no_dvert_1000) +{ + const int32_t num_items = 1000; + LatticeDeformTestContext ctx = {0}; + RandomNumberGenerator rng; + test_lattice_deform_init(&ctx, &rng, num_items); + test_lattice_deform(&ctx, num_items); + test_lattice_deform_free(&ctx); +} +TEST(lattice_deform_performance, performance_no_dvert_10000) +{ + const int32_t num_items = 10000; + LatticeDeformTestContext ctx = {0}; + RandomNumberGenerator rng; + test_lattice_deform_init(&ctx, &rng, num_items); + test_lattice_deform(&ctx, num_items); + test_lattice_deform_free(&ctx); +} +TEST(lattice_deform_performance, performance_no_dvert_100000) +{ + const int32_t num_items = 100000; + LatticeDeformTestContext ctx = {0}; + RandomNumberGenerator rng; + test_lattice_deform_init(&ctx, &rng, num_items); + test_lattice_deform(&ctx, num_items); + test_lattice_deform_free(&ctx); +} +TEST(lattice_deform_performance, performance_no_dvert_1000000) +{ + const int32_t num_items = 1000000; + LatticeDeformTestContext ctx = {0}; + RandomNumberGenerator rng; + test_lattice_deform_init(&ctx, &rng, num_items); + test_lattice_deform(&ctx, num_items); + test_lattice_deform_free(&ctx); +} +TEST(lattice_deform_performance, performance_no_dvert_10000000) +{ + const int32_t num_items = 10000000; + LatticeDeformTestContext ctx = {0}; + RandomNumberGenerator rng; + test_lattice_deform_init(&ctx, &rng, num_items); + test_lattice_deform(&ctx, num_items); + test_lattice_deform_free(&ctx); +} + +} // namespace blender::bke::tests \ No newline at end of file -- cgit v1.2.3 From cf6c0760464faf0308ca8d3b52fc0a7aaf91a214 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Mon, 26 Oct 2020 21:03:25 +1100 Subject: Fix T82077: Tools popup error in the image editor Add check for an image space type. Ref D9347 --- .../modules/bl_keymap_utils/keymap_from_toolbar.py | 29 ++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py b/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py index e18cca7fe25..ebc5370a7af 100644 --- a/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py +++ b/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py @@ -192,16 +192,25 @@ def generate(context, space_type, use_fallback_keys=True, use_reset=True): # PAINT_OT_brush_select mode = context.active_object.mode # See: BKE_paint_get_tool_prop_id_from_paintmode - attr = { - 'SCULPT': "sculpt_tool", - 'VERTEX_PAINT': "vertex_tool", - 'WEIGHT_PAINT': "weight_tool", - 'TEXTURE_PAINT': "image_tool", - 'PAINT_GPENCIL': "gpencil_tool", - 'VERTEX_GPENCIL': "gpencil_vertex_tool", - 'SCULPT_GPENCIL': "gpencil_sculpt_tool", - 'WEIGHT_GPENCIL': "gpencil_weight_tool", - }.get(mode, None) + if space_type == 'IMAGE_EDITOR': + if context.space_data.ui_mode == 'PAINT': + attr = "image_tool" + else: + attr = None + elif space_type == 'VIEW_3D': + attr = { + 'SCULPT': "sculpt_tool", + 'VERTEX_PAINT': "vertex_tool", + 'WEIGHT_PAINT': "weight_tool", + 'TEXTURE_PAINT': "image_tool", + 'PAINT_GPENCIL': "gpencil_tool", + 'VERTEX_GPENCIL': "gpencil_vertex_tool", + 'SCULPT_GPENCIL': "gpencil_sculpt_tool", + 'WEIGHT_GPENCIL': "gpencil_weight_tool", + }.get(mode, None) + else: + attr = None + if attr is not None: setattr(kmi_hack_brush_select_properties, attr, item.data_block) kmi_found = wm.keyconfigs.find_item_from_operator( -- cgit v1.2.3 From fff08e81ea74c66858c550109d33a59603d20c32 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 22 Oct 2020 15:14:28 +0200 Subject: Pose: Add a 'pose_ensure' new utils that only rebuilds if needed. Avoids having to spread the check logic everywhere in the code. --- source/blender/blenkernel/BKE_armature.h | 4 ++++ source/blender/blenkernel/intern/armature.c | 22 +++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 4e8775aefb3..db44a771095 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -180,6 +180,10 @@ void BKE_pose_rebuild(struct Main *bmain, struct Object *ob, struct bArmature *arm, const bool do_id_user); +void BKE_pose_ensure(struct Main *bmain, + struct Object *ob, + struct bArmature *arm, + const bool do_id_user); void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_pose_where_is_bone(struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 7b8ed47c513..bad2ed53436 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2573,6 +2573,20 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_ } } +/** + * Ensures object's pose is rebuilt if needed. + * + * \param bmain: May be NULL, only used to tag depsgraph as being dirty... + */ +void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user) +{ + BLI_assert(!ELEM(NULL, arm, ob)); + if (ob->type == OB_ARMATURE && ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC))) { + BLI_assert(GS(arm->id.name) == ID_AR); + BKE_pose_rebuild(bmain, ob, arm, do_id_user); + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -2711,11 +2725,9 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob) if (ELEM(NULL, arm, scene)) { return; } - if ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC)) { - /* WARNING! passing NULL bmain here means we won't tag depsgraph's as dirty - - * hopefully this is OK. */ - BKE_pose_rebuild(NULL, ob, arm, true); - } + /* WARNING! passing NULL bmain here means we won't tag depsgraph's as dirty - + * hopefully this is OK. */ + BKE_pose_ensure(NULL, ob, arm, true); ctime = BKE_scene_frame_get(scene); /* not accurate... */ -- cgit v1.2.3 From 25c3a2e42dadc737d076d4b97b7ea778929ecf40 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 26 Oct 2020 11:24:58 +0100 Subject: Proper, cleaner fix for T81963: Random rare crashes in override code. Use new `BKE_pose_ensure` utils, and do so for reference linked object too everywhere. --- source/blender/blenkernel/intern/lib_override.c | 57 ++++++++++++++++--------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 3adda80b445..f19ab96588e 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1230,13 +1230,16 @@ bool BKE_lib_override_library_status_check_local(Main *bmain, ID *local) BLI_assert(GS(local->name) == GS(reference->name)); if (GS(local->name) == ID_OB) { - /* Our beloved pose's bone cross-data pointers... Usually, depsgraph evaluation would ensure - * this is valid, but in some cases (like hidden collections etc.) this won't be the case, so - * we need to take care of this ourselves. */ + /* Our beloved pose's bone cross-data pointers.. Usually, depsgraph evaluation would + * ensure this is valid, but in some situations (like hidden collections etc.) this won't + * be the case, so we need to take care of this ourselves. */ Object *ob_local = (Object *)local; - if (ob_local->data != NULL && ob_local->type == OB_ARMATURE && ob_local->pose != NULL && - ob_local->pose->flag & POSE_RECALC) { - BKE_pose_rebuild(bmain, ob_local, ob_local->data, true); + if (ob_local->type == OB_ARMATURE) { + Object *ob_reference = (Object *)local->override_library->reference; + BLI_assert(ob_local->data != NULL); + BLI_assert(ob_reference->data != NULL); + BKE_pose_ensure(bmain, ob_local, ob_local->data, true); + BKE_pose_ensure(bmain, ob_reference, ob_reference->data, true); } } @@ -1296,13 +1299,16 @@ bool BKE_lib_override_library_status_check_reference(Main *bmain, ID *local) } if (GS(local->name) == ID_OB) { - /* Our beloved pose's bone cross-data pointers... Usually, depsgraph evaluation would ensure - * this is valid, but in some cases (like hidden collections etc.) this won't be the case, so - * we need to take care of this ourselves. */ + /* Our beloved pose's bone cross-data pointers.. Usually, depsgraph evaluation would + * ensure this is valid, but in some situations (like hidden collections etc.) this won't + * be the case, so we need to take care of this ourselves. */ Object *ob_local = (Object *)local; - if (ob_local->data != NULL && ob_local->type == OB_ARMATURE && ob_local->pose != NULL && - ob_local->pose->flag & POSE_RECALC) { - BKE_pose_rebuild(bmain, ob_local, ob_local->data, true); + if (ob_local->type == OB_ARMATURE) { + Object *ob_reference = (Object *)local->override_library->reference; + BLI_assert(ob_local->data != NULL); + BLI_assert(ob_reference->data != NULL); + BKE_pose_ensure(bmain, ob_local, ob_local->data, true); + BKE_pose_ensure(bmain, ob_reference, ob_reference->data, true); } } @@ -1353,18 +1359,16 @@ bool BKE_lib_override_library_operations_create(Main *bmain, ID *local) } if (GS(local->name) == ID_OB) { - /* Our beloved pose's bone cross-data pointers... Usually, depsgraph evaluation would + /* Our beloved pose's bone cross-data pointers.. Usually, depsgraph evaluation would * ensure this is valid, but in some situations (like hidden collections etc.) this won't * be the case, so we need to take care of this ourselves. */ Object *ob_local = (Object *)local; - Object *ob_reference = (Object *)local->override_library->reference; - if (ob_local->data != NULL && ob_local->type == OB_ARMATURE && ob_local->pose != NULL && - ob_local->pose->flag & POSE_RECALC) { - BKE_pose_rebuild(bmain, ob_local, ob_local->data, true); - } - if (ob_reference->data != NULL && ob_reference->type == OB_ARMATURE && - ob_reference->pose != NULL && ob_reference->pose->flag & POSE_RECALC) { - BKE_pose_rebuild(bmain, ob_reference, ob_reference->data, true); + if (ob_local->type == OB_ARMATURE) { + Object *ob_reference = (Object *)local->override_library->reference; + BLI_assert(ob_local->data != NULL); + BLI_assert(ob_reference->data != NULL); + BKE_pose_ensure(bmain, ob_local, ob_local->data, true); + BKE_pose_ensure(bmain, ob_reference, ob_reference->data, true); } } @@ -1422,6 +1426,17 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for BKE_lib_override_library_main_tag(bmain, IDOVERRIDE_LIBRARY_TAG_UNUSED, true); } + /* Usual pose bones issue, need to be done outside of the threaded process or we may run into + * concurency issues here. + * Note that calling #BKE_pose_ensure again in thread in + * #BKE_lib_override_library_operations_create is not a problem then.. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + if (ob->type == OB_ARMATURE) { + BLI_assert(ob->data != NULL); + BKE_pose_ensure(bmain, ob, ob->data, true); + } + } + TaskPool *task_pool = BLI_task_pool_create(bmain, TASK_PRIORITY_HIGH); FOREACH_MAIN_ID_BEGIN (bmain, id) { -- cgit v1.2.3 From 47f5a635daade324b4ca4bd720380a16e1cf2c9c Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 26 Oct 2020 12:25:46 +0100 Subject: Geometry Nodes: add utility method to check if a geometry has a mesh --- source/blender/blenkernel/BKE_geometry.hh | 1 + source/blender/blenkernel/intern/geometry.cc | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/source/blender/blenkernel/BKE_geometry.hh b/source/blender/blenkernel/BKE_geometry.hh index e2532d639c4..a90a1f433f2 100644 --- a/source/blender/blenkernel/BKE_geometry.hh +++ b/source/blender/blenkernel/BKE_geometry.hh @@ -62,6 +62,7 @@ class Geometry { void user_remove(); bool is_mutable() const; + bool mesh_available() const; void mesh_set_and_keep_ownership(Mesh *mesh); void mesh_set_and_transfer_ownership(Mesh *mesh); void mesh_reset(); diff --git a/source/blender/blenkernel/intern/geometry.cc b/source/blender/blenkernel/intern/geometry.cc index 014197ed423..58ec71108da 100644 --- a/source/blender/blenkernel/intern/geometry.cc +++ b/source/blender/blenkernel/intern/geometry.cc @@ -57,6 +57,14 @@ bool Geometry::is_mutable() const return users_ <= 1; } +/** + * Returns true when this geometry has a mesh component. + */ +bool Geometry::mesh_available() const +{ + return mesh_ != nullptr; +} + /** * Replace the mesh in the geometry. The caller remains the owner of the given mesh and is * responsible for freeing it eventually. -- cgit v1.2.3 From 4ae2d6206aa88546d246e42bb8c86b9a841eca37 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 26 Oct 2020 12:27:51 +0100 Subject: Geometry Nodes: initial Transform node Most of this code has been written by @HooglyBoogly. I just changed the exec funtion so that it does not have to make a copy of the mesh. --- release/scripts/startup/nodeitems_builtins.py | 1 + source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.c | 1 + source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_geometry.h | 1 + source/blender/nodes/NOD_static_types.h | 1 + .../blender/nodes/geometry/node_geometry_util.hh | 1 + .../nodes/geometry/nodes/node_geo_transform.cc | 75 ++++++++++++++++++++++ 8 files changed, 82 insertions(+) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_transform.cc diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index d95ec5d840d..82a957fb118 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -488,6 +488,7 @@ geometry_node_categories = [ GeometryNodeCategory("GEO_MESH", "Mesh", items=[ NodeItem("GeometryNodeTriangulate"), NodeItem("GeometryNodeEdgeSplit"), + NodeItem("GeometryNodeTransform"), ]), GeometryNodeCategory("GEO_MATH", "Misc", items=[ NodeItem("ShaderNodeMapRange"), diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index da4bcb8a00e..0ae31989a05 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1342,6 +1342,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_TRIANGULATE 1000 #define GEO_NODE_EDGE_SPLIT 1001 +#define GEO_NODE_TRANSFORM 1002 /** \} */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index cf06e55814f..f7b5e92d11b 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -4661,6 +4661,7 @@ static void registerGeometryNodes(void) register_node_type_geo_triangulate(); register_node_type_geo_edge_split(); + register_node_type_geo_transform(); } static void registerFunctionNodes(void) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 9058ee965a5..ffaabecb406 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -139,6 +139,7 @@ set(SRC geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_edge_split.cc + geometry/nodes/node_geo_transform.cc geometry/nodes/node_geo_triangulate.cc geometry/node_geometry_exec.cc geometry/node_geometry_tree.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 2b561c419a3..27d8f3a898c 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -28,6 +28,7 @@ void register_node_type_geo_group(void); void register_node_type_geo_triangulate(void); void register_node_type_geo_edge_split(void); +void register_node_type_geo_transform(void); #ifdef __cplusplus } diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index cd75e8a1ff0..5cfc9148f34 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -268,6 +268,7 @@ DefNode(FunctionNode, FN_NODE_RANDOM_FLOAT, 0, "RANDOM_FLOAT", DefNode(GeometryNode, GEO_NODE_TRIANGULATE, 0, "TRIANGULATE", Triangulate, "Triangulate", "") DefNode(GeometryNode, GEO_NODE_EDGE_SPLIT, 0, "EDGE_SPLIT", EdgeSplit, "Edge Split", "") +DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "") /* undefine macros */ diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index e0b170dd6c8..bb26763642b 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -18,6 +18,7 @@ #include +#include "BLI_float3.hh" #include "BLI_utildefines.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc new file mode 100644 index 00000000000..d0ac41b3641 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc @@ -0,0 +1,75 @@ +/* + * 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. + */ + +#include "BKE_mesh.h" +#include "BLI_math_matrix.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_transform_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_VECTOR, N_("Translation"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_TRANSLATION}, + {SOCK_VECTOR, N_("Rotation"), 0.0f, 0.0f, 0.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_EULER}, + {SOCK_VECTOR, N_("Scale"), 1.0f, 1.0f, 1.0f, 1.0f, -FLT_MAX, FLT_MAX, PROP_XYZ}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_transform_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +namespace blender::nodes { +static void geo_transform_exec(bNode *UNUSED(node), GValueByName &inputs, GValueByName &outputs) +{ + GeometryPtr geometry = inputs.extract("Geometry"); + + if (!geometry.has_value() || !geometry->mesh_available()) { + outputs.move_in("Geometry", std::move(geometry)); + return; + } + + bke::make_geometry_mutable(geometry); + + Mesh *mesh = geometry->mesh_get_for_write(); + + const float3 translation = inputs.extract("Translation"); + const float3 rotation = inputs.extract("Rotation"); + const float3 scale = inputs.extract("Scale"); + + /* Use only translation if rotation and scale are zero. */ + if (translation.length() > 0.0f && rotation.length() == 0.0f && scale.length() == 0.0f) { + BKE_mesh_translate(mesh, translation, true); + } + else { + float mat[4][4]; + loc_eul_size_to_mat4(mat, translation, rotation, scale); + BKE_mesh_transform(mesh, mat, true); + } + + outputs.move_in("Geometry", std::move(geometry)); +} +} // namespace blender::nodes + +void register_node_type_geo_transform() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_TRANSFORM, "Transform", 0, 0); + node_type_socket_templates(&ntype, geo_node_transform_in, geo_node_transform_out); + ntype.geometry_node_execute = blender::nodes::geo_transform_exec; + nodeRegisterType(&ntype); +} -- cgit v1.2.3 From c48e4b7a44b5771e3bb801d3fa3feae82022720b Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 26 Oct 2020 13:27:02 +0100 Subject: Geometry Nodes: improve node tree evaluation This change reduces the number of unnecessary copies of data and avoids computing the same value more than once. --- source/blender/modifiers/intern/MOD_nodes.cc | 153 +++++++++++++++++---------- source/blender/nodes/NOD_geometry_exec.hh | 9 +- 2 files changed, 103 insertions(+), 59 deletions(-) diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 38712054f22..6d7fe559eab 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -121,110 +121,98 @@ using namespace blender::bke; class GeometryNodesEvaluator { private: LinearAllocator<> allocator_; - const DerivedNodeTree &tree_; - Map group_input_data_; + Map value_by_input_; Vector group_outputs_; MultiFunctionByNode &mf_by_node_; const DataTypeConversions &conversions_; public: - GeometryNodesEvaluator(const DerivedNodeTree &tree, - Map group_input_data, + GeometryNodesEvaluator(const Map &group_input_data, Vector group_outputs, MultiFunctionByNode &mf_by_node) - : tree_(tree), - group_input_data_(std::move(group_input_data)), - group_outputs_(std::move(group_outputs)), + : group_outputs_(std::move(group_outputs)), mf_by_node_(mf_by_node), conversions_(get_implicit_type_conversions()) { + for (auto item : group_input_data.items()) { + this->forward_to_inputs(*item.key, item.value); + } } Vector execute() { Vector results; for (const DInputSocket *group_output : group_outputs_) { - const CPPType &type = *socket_cpp_type_get(*group_output->typeinfo()); - void *result_buffer = allocator_.allocate(type.size(), type.alignment()); - this->compute_input_socket(*group_output, result_buffer); - results.append(GMutablePointer{type, result_buffer}); + GMutablePointer result = this->get_input_value(*group_output); + results.append(result); } - for (GMutablePointer value : group_input_data_.values()) { - value.type()->destruct(value.get()); + for (GMutablePointer value : value_by_input_.values()) { + value.destruct(); } return results; } private: - void compute_input_socket(const DInputSocket &socket_to_compute, void *r_value) + GMutablePointer get_input_value(const DInputSocket &socket_to_compute) { + std::optional value = value_by_input_.pop_try(&socket_to_compute); + if (value.has_value()) { + /* This input has been computed before, return it directly. */ + return *value; + } + Span from_sockets = socket_to_compute.linked_sockets(); Span from_group_inputs = socket_to_compute.linked_group_inputs(); const int total_inputs = from_sockets.size() + from_group_inputs.size(); BLI_assert(total_inputs <= 1); + const CPPType &type = *socket_cpp_type_get(*socket_to_compute.typeinfo()); + if (total_inputs == 0) { + /* The input is not connected, use the value from the socket itself. */ bNodeSocket &bsocket = *socket_to_compute.bsocket(); - socket_cpp_value_get(bsocket, r_value); - return; + void *buffer = allocator_.allocate(type.size(), type.alignment()); + socket_cpp_value_get(bsocket, buffer); + return GMutablePointer{type, buffer}; } if (from_group_inputs.size() == 1) { + /* The input gets its value from the input of a group that is not further connected. */ bNodeSocket &bsocket = *from_group_inputs[0]->bsocket(); - socket_cpp_value_get(bsocket, r_value); - return; + void *buffer = allocator_.allocate(type.size(), type.alignment()); + socket_cpp_value_get(bsocket, buffer); + return GMutablePointer{type, buffer}; } + /* Compute the socket now. */ const DOutputSocket &from_socket = *from_sockets[0]; - const CPPType &from_type = *socket_cpp_type_get(*from_socket.typeinfo()); - const CPPType &to_type = *socket_cpp_type_get(*socket_to_compute.typeinfo()); - if (from_type == to_type) { - this->compute_output_socket(from_socket, r_value); - } - else { - /* The type of both sockets don't match, so a conversion is necessary. */ - if (conversions_.is_convertible(from_type, to_type)) { - void *from_value = allocator_.allocate(from_type.size(), from_type.alignment()); - this->compute_output_socket(from_socket, from_value); - conversions_.convert(from_type, to_type, from_value, r_value); - from_type.destruct(from_value); - } - else { - /* Use a default value when the types cannot be converted. */ - to_type.copy_to_uninitialized(to_type.default_value(), r_value); - } - } + this->compute_output_and_forward(from_socket); + return value_by_input_.pop(&socket_to_compute); } - void compute_output_socket(const DOutputSocket &socket_to_compute, void *r_value) + void compute_output_and_forward(const DOutputSocket &socket_to_compute) { - const GMutablePointer *group_input = group_input_data_.lookup_ptr(&socket_to_compute); - if (group_input != nullptr) { - const CPPType &type = *group_input->type(); - type.copy_to_uninitialized(group_input->get(), r_value); - return; - } - const DNode &node = socket_to_compute.node(); - GValueByName node_inputs{allocator_}; - /* Compute all inputs for the node. */ + /* Prepare inputs required to execute the node. */ + GValueByName node_inputs{allocator_}; for (const DInputSocket *input_socket : node.inputs()) { - const CPPType &type = *socket_cpp_type_get(*input_socket->typeinfo()); - void *buffer = allocator_.allocate(type.size(), type.alignment()); - compute_input_socket(*input_socket, buffer); - node_inputs.move_in(input_socket->identifier(), GMutablePointer{type, buffer}); - type.destruct(buffer); + if (input_socket->is_available()) { + GMutablePointer value = this->get_input_value(*input_socket); + node_inputs.transfer_ownership_in(input_socket->identifier(), value); + } } - /* Execute the node itself. */ + /* Execute the node. */ GValueByName node_outputs{allocator_}; this->execute_node(node, node_inputs, node_outputs); - /* Pass relevant value to the caller. */ - bNodeSocket *bsocket_to_compute = socket_to_compute.bsocket(); - const CPPType &type_to_compute = *socket_cpp_type_get(*bsocket_to_compute->typeinfo); - GMutablePointer computed_value = node_outputs.extract(bsocket_to_compute->identifier); - type_to_compute.relocate_to_uninitialized(computed_value.get(), r_value); + /* Forward computed outputs to linked input sockets. */ + for (const DOutputSocket *output_socket : node.outputs()) { + if (output_socket->is_available()) { + GMutablePointer value = node_outputs.extract(output_socket->identifier()); + this->forward_to_inputs(*output_socket, value); + } + } } void execute_node(const DNode &node, GValueByName &node_inputs, GValueByName &node_outputs) @@ -266,6 +254,55 @@ class GeometryNodesEvaluator { value.destruct(); } } + + void forward_to_inputs(const DOutputSocket &from_socket, GMutablePointer value_to_forward) + { + Span linked_sockets = from_socket.linked_sockets(); + + Vector to_sockets_with_same_type; + Vector to_sockets_with_different_type; + for (const DInputSocket *linked_socket : linked_sockets) { + if (from_socket.typeinfo() == linked_socket->typeinfo()) { + to_sockets_with_same_type.append(linked_socket); + } + else { + to_sockets_with_different_type.append(linked_socket); + } + } + + const CPPType &from_type = *value_to_forward.type(); + + for (const DInputSocket *to_socket : to_sockets_with_different_type) { + const CPPType &to_type = *socket_cpp_type_get(*to_socket->typeinfo()); + void *buffer = allocator_.allocate(to_type.size(), to_type.alignment()); + conversions_.convert(from_type, to_type, value_to_forward.get(), buffer); + value_by_input_.add_new(to_socket, GMutablePointer{to_type, buffer}); + } + + if (to_sockets_with_same_type.size() == 0) { + /* This value is not further used, so destruct it. */ + value_to_forward.destruct(); + } + else if (to_sockets_with_same_type.size() == 1) { + /* This value is only used on one input socket, no need to copy it. */ + const DInputSocket *to_socket = to_sockets_with_same_type[0]; + value_by_input_.add_new(to_socket, value_to_forward); + } + else { + /* Multiple inputs use the value, make a copy for every input except for one. */ + const DInputSocket *first_to_socket = to_sockets_with_same_type[0]; + Span other_to_sockets = to_sockets_with_same_type.as_span().drop_front( + 1); + const CPPType &type = *value_to_forward.type(); + + value_by_input_.add_new(first_to_socket, value_to_forward); + for (const DInputSocket *to_socket : other_to_sockets) { + void *buffer = allocator_.allocate(type.size(), type.alignment()); + type.copy_to_uninitialized(value_to_forward.get(), buffer); + value_by_input_.add_new(to_socket, GMutablePointer{type, buffer}); + } + } + } }; /** @@ -292,7 +329,7 @@ static GeometryPtr compute_geometry(const DerivedNodeTree &tree, Vector group_outputs; group_outputs.append(&socket_to_compute); - GeometryNodesEvaluator evaluator{tree, group_inputs, group_outputs, mf_by_node}; + GeometryNodesEvaluator evaluator{group_inputs, group_outputs, mf_by_node}; Vector results = evaluator.execute(); BLI_assert(results.size() == 1); GMutablePointer result = results[0]; diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index fe6dc732898..70e2af6c7fb 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -55,7 +55,14 @@ class GValueByName { } } - /* Add a value to the container. */ + /* Add a value to the container. The container is responsible for destructing the value that is + * passed in. */ + void transfer_ownership_in(StringRef name, GMutablePointer value) + { + values_.add_new(name, value); + } + + /* Add a value to the container. The caller remains responsible for destructing the value. */ void move_in(StringRef name, GMutablePointer value) { const CPPType &type = *value.type(); -- cgit v1.2.3 From a5dda5996e6f7bc41ef8b9ca66ee3c76734b62c1 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 26 Oct 2020 13:29:03 +0100 Subject: Geometry Nodes: connect group input and output by default --- release/scripts/startup/bl_operators/geometry_nodes.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/release/scripts/startup/bl_operators/geometry_nodes.py b/release/scripts/startup/bl_operators/geometry_nodes.py index 7643c49f33e..b915827f0e6 100644 --- a/release/scripts/startup/bl_operators/geometry_nodes.py +++ b/release/scripts/startup/bl_operators/geometry_nodes.py @@ -39,6 +39,9 @@ class NewGeometryNodeTree(bpy.types.Operator): input_node.location.x = -200 - input_node.width output_node.location.x = 200 + + group.links.new(output_node.inputs[0], input_node.outputs[0]) + context.space_data.node_tree = group return {'FINISHED'} -- cgit v1.2.3 From e04491073d91434a5c3a93ec36d94efd3b540eec Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 26 Oct 2020 14:16:26 +0100 Subject: Geometry Nodes: support evaluation with more than one group input Group inputs are not yet exposed in the modifier. For now I just added a simple float setting that will be passed to every float input of the group. Inputs of other types have some default value. --- source/blender/makesdna/DNA_modifier_types.h | 4 ++ source/blender/makesrna/intern/rna_modifier.c | 4 ++ source/blender/modifiers/intern/MOD_nodes.cc | 87 +++++++++++++++++---------- 3 files changed, 63 insertions(+), 32 deletions(-) diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 414c21fd428..a077e3c3f43 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -2222,6 +2222,10 @@ enum { typedef struct NodesModifierData { ModifierData modifier; struct bNodeTree *node_group; + + /* This property exists only temporary for testing purposes. */ + float test_float_input; + char _pad[4]; } NodesModifierData; typedef struct MeshToVolumeModifierData { diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 7715a35af76..af5892d8933 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -6941,6 +6941,10 @@ static void rna_def_modifier_nodes(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + prop = RNA_def_property(srna, "test_float_input", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Float Input", "Temporary float input for testing purposes"); + RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + RNA_define_lib_overridable(false); } # endif diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 6d7fe559eab..5a368f7087f 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -257,42 +257,41 @@ class GeometryNodesEvaluator { void forward_to_inputs(const DOutputSocket &from_socket, GMutablePointer value_to_forward) { - Span linked_sockets = from_socket.linked_sockets(); - - Vector to_sockets_with_same_type; - Vector to_sockets_with_different_type; - for (const DInputSocket *linked_socket : linked_sockets) { - if (from_socket.typeinfo() == linked_socket->typeinfo()) { - to_sockets_with_same_type.append(linked_socket); - } - else { - to_sockets_with_different_type.append(linked_socket); - } - } + Span to_sockets_all = from_socket.linked_sockets(); const CPPType &from_type = *value_to_forward.type(); - for (const DInputSocket *to_socket : to_sockets_with_different_type) { + Vector to_sockets_same_type; + for (const DInputSocket *to_socket : to_sockets_all) { const CPPType &to_type = *socket_cpp_type_get(*to_socket->typeinfo()); - void *buffer = allocator_.allocate(to_type.size(), to_type.alignment()); - conversions_.convert(from_type, to_type, value_to_forward.get(), buffer); - value_by_input_.add_new(to_socket, GMutablePointer{to_type, buffer}); + if (from_type == to_type) { + to_sockets_same_type.append(to_socket); + } + else { + void *buffer = allocator_.allocate(to_type.size(), to_type.alignment()); + if (conversions_.is_convertible(from_type, to_type)) { + conversions_.convert(from_type, to_type, value_to_forward.get(), buffer); + } + else { + to_type.copy_to_uninitialized(to_type.default_value(), buffer); + } + value_by_input_.add_new(to_socket, GMutablePointer{to_type, buffer}); + } } - if (to_sockets_with_same_type.size() == 0) { + if (to_sockets_same_type.size() == 0) { /* This value is not further used, so destruct it. */ value_to_forward.destruct(); } - else if (to_sockets_with_same_type.size() == 1) { + else if (to_sockets_same_type.size() == 1) { /* This value is only used on one input socket, no need to copy it. */ - const DInputSocket *to_socket = to_sockets_with_same_type[0]; + const DInputSocket *to_socket = to_sockets_same_type[0]; value_by_input_.add_new(to_socket, value_to_forward); } else { /* Multiple inputs use the value, make a copy for every input except for one. */ - const DInputSocket *first_to_socket = to_sockets_with_same_type[0]; - Span other_to_sockets = to_sockets_with_same_type.as_span().drop_front( - 1); + const DInputSocket *first_to_socket = to_sockets_same_type[0]; + Span other_to_sockets = to_sockets_same_type.as_span().drop_front(1); const CPPType &type = *value_to_forward.type(); value_by_input_.add_new(first_to_socket, value_to_forward); @@ -311,20 +310,43 @@ class GeometryNodesEvaluator { * often than necessary. It's going to be replaced soon. */ static GeometryPtr compute_geometry(const DerivedNodeTree &tree, - const DOutputSocket *group_input, - GeometryPtr group_input_geometry, - const DInputSocket &socket_to_compute) + Span group_input_sockets, + const DInputSocket &socket_to_compute, + GeometryPtr input_geometry, + NodesModifierData *nmd) { ResourceCollector resources; + LinearAllocator<> &allocator = resources.linear_allocator(); MultiFunctionByNode mf_by_node = get_multi_function_per_node(tree, resources); - /* Use this buffer so that it is not destructed when the scope ends. The evaluator is responsible - * for destructing it. */ - TypedBuffer buffer; - new (buffer.ptr()) GeometryPtr(std::move(group_input_geometry)); - Map group_inputs; - group_inputs.add_new(group_input, GMutablePointer{buffer.ptr()}); + + if (group_input_sockets.size() > 0) { + Span remaining_input_sockets = group_input_sockets; + + /* If the group expects a geometry as first input, use the geometry that has been passed to + * modifier. */ + const DOutputSocket *first_input_socket = group_input_sockets[0]; + if (first_input_socket->bsocket()->type == SOCK_GEOMETRY) { + GeometryPtr *geometry_in = allocator.construct(std::move(input_geometry)); + group_inputs.add_new(first_input_socket, geometry_in); + remaining_input_sockets = remaining_input_sockets.drop_front(1); + } + + /* Initialize remaining group inputs. */ + for (const DOutputSocket *socket : remaining_input_sockets) { + const CPPType &type = *socket_cpp_type_get(*socket->typeinfo()); + if (type.is()) { + float *value_in = allocator.construct(nmd->test_float_input); + group_inputs.add_new(socket, value_in); + } + else { + void *value_in = allocator.allocate(type.size(), type.alignment()); + type.copy_to_uninitialized(type.default_value(), value_in); + group_inputs.add_new(socket, {type, value_in}); + } + } + } Vector group_outputs; group_outputs.append(&socket_to_compute); @@ -377,7 +399,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) input_geometry->mesh_set_and_keep_ownership(mesh); GeometryPtr new_geometry = compute_geometry( - tree, group_inputs[0], std::move(input_geometry), *group_outputs[0]); + tree, group_inputs, *group_outputs[0], std::move(input_geometry), nmd); make_geometry_mutable(new_geometry); Mesh *new_mesh = new_geometry->mesh_release(); if (new_mesh == nullptr) { @@ -397,6 +419,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropDecorate(layout, false); uiItemR(layout, ptr, "node_group", 0, NULL, ICON_MESH_DATA); + uiItemR(layout, ptr, "test_float_input", 0, NULL, ICON_NONE); modifier_panel_end(layout, ptr); } -- cgit v1.2.3