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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2015-06-04 13:05:11 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2015-06-04 13:05:11 +0300
commit343c4fb54a514b55a9d0e01fc1275fa66bf1fbca (patch)
tree78ab1fd1f77af1c467e98cc31e940845e0737aee
parent44276743cfb31996f90a19c6d98839bea3cc1ce4 (diff)
parentcf7a5e93f8d89d8b5382b07834dd0e9fc694254b (diff)
Merge branch 'master' into gooseberry
Conflicts: intern/cycles/kernel/svm/svm.h
-rw-r--r--build_files/scons/tools/Blender.py2
-rw-r--r--extern/bullet2/src/Bullet-C-Api.h1
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp6
-rw-r--r--intern/cycles/app/cycles_standalone.cpp21
-rw-r--r--intern/cycles/app/cycles_xml.cpp24
-rw-r--r--intern/cycles/blender/blender_shader.cpp2
-rw-r--r--intern/cycles/device/device.cpp6
-rw-r--r--intern/cycles/device/device_cuda.cpp4
-rw-r--r--intern/cycles/device/device_opencl.cpp11
-rw-r--r--intern/cycles/kernel/svm/svm.h292
-rw-r--r--intern/cycles/kernel/svm/svm_types.h10
-rw-r--r--intern/cycles/render/graph.h2
-rw-r--r--intern/cycles/render/mesh.cpp17
-rw-r--r--intern/cycles/render/nodes.h73
-rw-r--r--intern/cycles/render/object.cpp31
-rw-r--r--intern/cycles/render/object.h6
-rw-r--r--intern/cycles/render/session.cpp2
-rw-r--r--intern/cycles/render/shader.cpp41
-rw-r--r--intern/cycles/render/shader.h8
-rw-r--r--intern/cycles/util/util_atomic.h6
-rw-r--r--intern/cycles/util/util_view.cpp1
-rw-r--r--release/scripts/freestyle/modules/freestyle/functions.py6
-rw-r--r--release/scripts/freestyle/modules/freestyle/predicates.py53
-rw-r--r--release/scripts/freestyle/modules/freestyle/shaders.py8
-rw-r--r--release/scripts/freestyle/modules/freestyle/utils.py110
-rw-r--r--release/scripts/modules/addon_utils.py28
-rw-r--r--release/scripts/modules/bl_i18n_utils/bl_extract_messages.py10
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils.py17
-rw-r--r--release/scripts/modules/nodeitems_utils.py6
-rw-r--r--release/scripts/startup/bl_operators/object_align.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py6
-rw-r--r--source/blender/blenfont/intern/blf_font.c37
-rw-r--r--source/blender/blenfont/intern/blf_internal.h3
-rw-r--r--source/blender/blenfont/intern/blf_thumbs.c18
-rw-r--r--source/blender/blenkernel/BKE_object.h8
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h2
-rw-r--r--source/blender/blenkernel/intern/appdir.c1
-rw-r--r--source/blender/blenkernel/intern/library.c2
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c9
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c4
-rw-r--r--source/blender/blenkernel/intern/object.c42
-rw-r--r--source/blender/blenkernel/intern/pointcache.c2
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c2
-rw-r--r--source/blender/blenlib/BLI_stack.h1
-rw-r--r--source/blender/blenlib/intern/path_util.c52
-rw-r--r--source/blender/blenlib/intern/stack.c35
-rw-r--r--source/blender/blenlib/intern/threads.c4
-rw-r--r--source/blender/blenloader/intern/readblenentry.c24
-rw-r--r--source/blender/blenloader/intern/readfile.c21
-rw-r--r--source/blender/blenloader/intern/versioning_250.c2
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c3
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c452
-rw-r--r--source/blender/collada/GeometryExporter.cpp4
-rw-r--r--source/blender/editors/curve/editfont.c2
-rw-r--r--source/blender/editors/include/UI_interface.h4
-rw-r--r--source/blender/editors/interface/interface.c53
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c14
-rw-r--r--source/blender/editors/interface/interface_handlers.c48
-rw-r--r--source/blender/editors/interface/interface_layout.c3
-rw-r--r--source/blender/editors/interface/interface_ops.c8
-rw-r--r--source/blender/editors/interface/interface_panel.c37
-rw-r--r--source/blender/editors/interface/interface_regions.c52
-rw-r--r--source/blender/editors/interface/interface_style.c2
-rw-r--r--source/blender/editors/interface/interface_templates.c32
-rw-r--r--source/blender/editors/interface/interface_widgets.c142
-rw-r--r--source/blender/editors/interface/resources.c5
-rw-r--r--source/blender/editors/interface/view2d.c16
-rw-r--r--source/blender/editors/interface/view2d_ops.c79
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c53
-rw-r--r--source/blender/editors/mesh/mesh_data.c2
-rw-r--r--source/blender/editors/object/object_modifier.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c20
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c2
-rw-r--r--source/blender/editors/space_file/file_draw.c2
-rw-r--r--source/blender/editors/space_node/node_templates.c19
-rw-r--r--source/blender/editors/space_view3d/drawobject.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c62
-rw-r--r--source/blender/editors/transform/transform.c8
-rw-r--r--source/blender/editors/transform/transform_manipulator.c2
-rw-r--r--source/blender/editors/transform/transform_ops.c4
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp49
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp5
-rw-r--r--source/blender/imbuf/IMB_thumbs.h7
-rw-r--r--source/blender/imbuf/intern/colormanagement.c42
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp15
-rw-r--r--source/blender/imbuf/intern/stereoimbuf.c4
-rw-r--r--source/blender/imbuf/intern/targa.c2
-rw-r--r--source/blender/imbuf/intern/thumbs.c108
-rw-r--r--source/blender/imbuf/intern/thumbs_font.c42
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c2
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c6
-rw-r--r--source/blender/python/intern/bpy_util.c18
-rw-r--r--source/blender/render/intern/raytrace/rayobject_instance.cpp2
-rw-r--r--source/blender/windowmanager/WM_api.h12
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c23
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c99
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c19
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c41
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c11
-rw-r--r--source/blender/windowmanager/intern/wm_window.c6
-rw-r--r--source/blender/windowmanager/wm_event_system.h11
-rw-r--r--source/creator/CMakeLists.txt4
-rw-r--r--source/creator/creator.c4
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.h13
-rw-r--r--source/gameengine/GameLogic/SCA_PropertySensor.cpp9
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp48
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.cpp8
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.cpp3
-rw-r--r--source/gameengine/Ketsji/KX_WorldInfo.cpp12
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp6
-rw-r--r--tests/gtests/blenlib/BLI_stack_test.cc54
112 files changed, 2064 insertions, 841 deletions
diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py
index 03ca5e9c0ae..eeaa0d27379 100644
--- a/build_files/scons/tools/Blender.py
+++ b/build_files/scons/tools/Blender.py
@@ -664,7 +664,7 @@ def WinPyBundle(target=None, source=None, env=None):
py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.tar.gz'
py_target = env.subst(env['BF_INSTALLDIR']).lstrip("#")
- py_target = os.path.join(py_target, VERSION, 'python', 'lib')
+ py_target = os.path.join(py_target, VERSION, 'python')
def printexception(func,path,ex):
if os.path.exists(path): #do not report if path does not exist. eg on a fresh build.
print str(func) + ' failed on ' + str(path)
diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h
index 2eabf3840e1..5d00f7e3ac3 100644
--- a/extern/bullet2/src/Bullet-C-Api.h
+++ b/extern/bullet2/src/Bullet-C-Api.h
@@ -171,6 +171,7 @@ extern "C" {
/* Convex Hull */
PL_DECLARE_HANDLE(plConvexHull);
plConvexHull plConvexHullCompute(float (*coords)[3], int count);
+ void plConvexHullDelete(plConvexHull hull);
int plConvexHullNumVertices(plConvexHull hull);
int plConvexHullNumFaces(plConvexHull hull);
void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], int *original_index);
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp
index 21f0aa93220..e1f69afe101 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp
@@ -413,6 +413,12 @@ plConvexHull plConvexHullCompute(float (*coords)[3], int count)
return reinterpret_cast<plConvexHull>(computer);
}
+void plConvexHullDelete(plConvexHull hull)
+{
+ btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull));
+ delete computer;
+}
+
int plConvexHullNumVertices(plConvexHull hull)
{
btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull));
diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp
index 8f39c5126f5..3980ca547c2 100644
--- a/intern/cycles/app/cycles_standalone.cpp
+++ b/intern/cycles/app/cycles_standalone.cpp
@@ -21,6 +21,7 @@
#include "device.h"
#include "scene.h"
#include "session.h"
+#include "integrator.h"
#include "util_args.h"
#include "util_foreach.h"
@@ -296,6 +297,7 @@ static void keyboard(unsigned char key)
else if(key == 'i')
options.interactive = !(options.interactive);
+ /* Navigation */
else if(options.interactive && (key == 'w' || key == 'a' || key == 's' || key == 'd')) {
Transform matrix = options.session->scene->camera->matrix;
float3 translate;
@@ -318,6 +320,25 @@ static void keyboard(unsigned char key)
options.session->reset(session_buffer_params(), options.session_params.samples);
}
+
+ /* Set Max Bounces */
+ else if(options.interactive && (key == '0' || key == '1' || key == '2' || key == '3')) {
+ int bounce;
+ switch(key) {
+ case '0': bounce = 0; break;
+ case '1': bounce = 1; break;
+ case '2': bounce = 2; break;
+ case '3': bounce = 3; break;
+ default: bounce = 0; break;
+ }
+
+ options.session->scene->integrator->max_bounce = bounce;
+
+ /* Update and Reset */
+ options.session->scene->integrator->need_update = true;
+
+ options.session->reset(session_buffer_params(), options.session_params.samples);
+ }
}
#endif
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 06fc6a33953..d53ab67621e 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -394,6 +394,10 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
for(pugi::xml_node node = graph_node.first_child(); node; node = node.next_sibling()) {
ShaderNode *snode = NULL;
+ /* ToDo: Add missing nodes
+ * RGBCurvesNode, VectorCurvesNode, RGBRampNode and ConvertNode (RGB -> BW).
+ */
+
if(string_iequals(node.name(), "image_texture")) {
ImageTextureNode *img = new ImageTextureNode();
@@ -404,6 +408,8 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
xml_read_enum(&img->projection, ImageTextureNode::projection_enum, node, "projection");
xml_read_float(&img->projection_blend, node, "projection_blend");
+ /* ToDo: Interpolation */
+
snode = img;
}
else if(string_iequals(node.name(), "environment_texture")) {
@@ -516,6 +522,11 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
xml_read_float3(&normal->direction, node, "direction");
snode = normal;
}
+ else if(string_iequals(node.name(), "bump")) {
+ BumpNode *bump = new BumpNode();
+ xml_read_bool(&bump->invert, node, "invert");
+ snode = bump;
+ }
else if(string_iequals(node.name(), "mapping")) {
snode = new MappingNode();
}
@@ -570,6 +581,9 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
else if(string_iequals(node.name(), "background")) {
snode = new BackgroundNode();
}
+ else if(string_iequals(node.name(), "holdout")) {
+ snode = new HoldoutNode();
+ }
else if(string_iequals(node.name(), "absorption_volume")) {
snode = new AbsorptionVolumeNode();
}
@@ -578,7 +592,14 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
}
else if(string_iequals(node.name(), "subsurface_scattering")) {
SubsurfaceScatteringNode *sss = new SubsurfaceScatteringNode();
- //xml_read_enum(&sss->falloff, SubsurfaceScatteringNode::falloff_enum, node, "falloff");
+
+ string falloff;
+ xml_read_string(&falloff, node, "falloff");
+ if(falloff == "cubic")
+ sss->closure = CLOSURE_BSSRDF_CUBIC_ID;
+ else
+ sss->closure = CLOSURE_BSSRDF_GAUSSIAN_ID;
+
snode = sss;
}
else if(string_iequals(node.name(), "geometry")) {
@@ -622,6 +643,7 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
snode = new InvertNode();
}
else if(string_iequals(node.name(), "mix")) {
+ /* ToDo: Tag Mix case for optimization */
MixNode *mix = new MixNode();
xml_read_enum(&mix->type, MixNode::type_enum, node, "type");
xml_read_bool(&mix->use_clamp, node, "use_clamp");
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 9f48600161d..6c54149164d 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -926,7 +926,7 @@ static void add_nodes(Scene *scene,
output_map[b_output->ptr.data] = proxy->outputs[0];
}
- if (b_group_ntree) {
+ if(b_group_ntree) {
add_nodes(scene,
b_engine,
b_data,
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index d69244a07bd..0a4802c2c90 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -94,7 +94,7 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int d
}
if(GLEW_VERSION_1_5) {
- if (!vertex_buffer)
+ if(!vertex_buffer)
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
@@ -110,7 +110,7 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int d
vp = vbuffer;
}
- if (vp) {
+ if(vp) {
/* texture coordinate - vertex pair */
vp[0] = 0.0f;
vp[1] = 0.0f;
@@ -132,7 +132,7 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int d
vp[14] = dx;
vp[15] = (float)height + dy;
- if (vertex_buffer)
+ if(vertex_buffer)
glUnmapBuffer(GL_ARRAY_BUFFER);
}
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 8d690466c07..80a2dda22c4 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -919,7 +919,7 @@ public:
draw_params.bind_display_space_shader_cb();
}
- if (!vertex_buffer)
+ if(!vertex_buffer)
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
@@ -928,7 +928,7 @@ public:
vpointer = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
- if (vpointer) {
+ if(vpointer) {
/* texture coordinate - vertex pair */
vpointer[0] = 0.0f;
vpointer[1] = 0.0f;
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 72224d3f027..87d4ee91919 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -640,8 +640,11 @@ public:
clGetProgramBuildInfo(*kernel_program, cdDevice, CL_PROGRAM_BUILD_LOG, ret_val_size, &build_log[0], NULL);
build_log[ret_val_size] = '\0';
- fprintf(stderr, "OpenCL kernel build output:\n");
- fprintf(stderr, "%s\n", &build_log[0]);
+ /* Skip meaningless empty output from the NVidia compiler. */
+ if(!(ret_val_size == 2 && build_log[0] == '\n')) {
+ fprintf(stderr, "OpenCL kernel build output:\n");
+ fprintf(stderr, "%s\n", &build_log[0]);
+ }
}
if(ciErr != CL_SUCCESS) {
@@ -676,6 +679,10 @@ public:
double starttime = time_dt();
printf("Compiling OpenCL kernel ...\n");
+ /* TODO(sergey): Report which kernel is being compiled
+ * as well (megakernel or which of split kernels etc..).
+ */
+ printf("Build flags: %s\n", custom_kernel_build_options.c_str());
if(!build_kernel(kernel_program, custom_kernel_build_options, debug_src))
return false;
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index db83d2ec024..e9b36dd1f39 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -184,7 +184,7 @@ CCL_NAMESPACE_END
CCL_NAMESPACE_BEGIN
#define NODES_GROUP(group) ((group) <= __NODES_MAX_GROUP__)
-#define NODES_FEATURE(feature) (__NODES_FEATURES__ & (feature) != 0)
+#define NODES_FEATURE(feature) ((__NODES_FEATURES__ & (feature)) != 0)
/* Main Interpreter Loop */
ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderType type, int path_flag)
@@ -213,17 +213,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_CLOSURE_BACKGROUND:
svm_node_closure_background(sd, stack, node);
break;
- case NODE_CLOSURE_HOLDOUT:
- svm_node_closure_holdout(sd, stack, node);
- break;
- case NODE_CLOSURE_AMBIENT_OCCLUSION:
- svm_node_closure_ambient_occlusion(sd, stack, node);
- break;
-#if NODES_FEATURE(NODE_FEATURE_VOLUME)
- case NODE_CLOSURE_VOLUME:
- svm_node_closure_volume(kg, sd, stack, node, path_flag);
- break;
-#endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
case NODE_CLOSURE_SET_WEIGHT:
svm_node_closure_set_weight(sd, node.y, node.z, node.w);
break;
@@ -236,7 +225,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_MIX_CLOSURE:
svm_node_mix_closure(sd, stack, node);
break;
-#endif /* NODES_GROUP(NODE_GROUP_LEVEL_0) */
case NODE_JUMP_IF_ZERO:
if(stack_load_float(stack, node.z) == 0.0f)
offset += node.y;
@@ -245,13 +233,137 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
if(stack_load_float(stack, node.z) == 1.0f)
offset += node.y;
break;
-#ifdef __TEXTURES__
+ case NODE_GEOMETRY:
+ svm_node_geometry(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_CONVERT:
+ svm_node_convert(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_TEX_COORD:
+ svm_node_tex_coord(kg, sd, path_flag, stack, node, &offset);
+ break;
+ case NODE_VALUE_F:
+ svm_node_value_f(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_VALUE_V:
+ svm_node_value_v(kg, sd, stack, node.y, &offset);
+ break;
+ case NODE_ATTR:
+ svm_node_attr(kg, sd, stack, node);
+ break;
+# if NODES_FEATURE(NODE_FEATURE_BUMP)
+ case NODE_GEOMETRY_BUMP_DX:
+ svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_GEOMETRY_BUMP_DY:
+ svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_SET_DISPLACEMENT:
+ svm_node_set_displacement(sd, stack, node.y);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
+# ifdef __TEXTURES__
case NODE_TEX_IMAGE:
svm_node_tex_image(kg, sd, stack, node);
break;
case NODE_TEX_IMAGE_BOX:
svm_node_tex_image_box(kg, sd, stack, node);
break;
+ case NODE_TEX_NOISE:
+ svm_node_tex_noise(kg, sd, stack, node, &offset);
+ break;
+# endif /* __TEXTURES__ */
+# ifdef __EXTRA_NODES__
+# if NODES_FEATURE(NODE_FEATURE_BUMP)
+ case NODE_SET_BUMP:
+ svm_node_set_bump(kg, sd, stack, node);
+ break;
+ case NODE_ATTR_BUMP_DX:
+ svm_node_attr_bump_dx(kg, sd, stack, node);
+ break;
+ case NODE_ATTR_BUMP_DY:
+ svm_node_attr_bump_dy(kg, sd, stack, node);
+ break;
+ case NODE_TEX_COORD_BUMP_DX:
+ svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node, &offset);
+ break;
+ case NODE_TEX_COORD_BUMP_DY:
+ svm_node_tex_coord_bump_dy(kg, sd, path_flag, stack, node, &offset);
+ break;
+ case NODE_CLOSURE_SET_NORMAL:
+ svm_node_set_normal(kg, sd, stack, node.y, node.z);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
+ case NODE_HSV:
+ svm_node_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+# endif /* __EXTRA_NODES__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_0) */
+
+#if NODES_GROUP(NODE_GROUP_LEVEL_1)
+ case NODE_CLOSURE_HOLDOUT:
+ svm_node_closure_holdout(sd, stack, node);
+ break;
+ case NODE_CLOSURE_AMBIENT_OCCLUSION:
+ svm_node_closure_ambient_occlusion(sd, stack, node);
+ break;
+ case NODE_FRESNEL:
+ svm_node_fresnel(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_LAYER_WEIGHT:
+ svm_node_layer_weight(sd, stack, node);
+ break;
+# if NODES_FEATURE(NODE_FEATURE_VOLUME)
+ case NODE_CLOSURE_VOLUME:
+ svm_node_closure_volume(kg, sd, stack, node, path_flag);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
+# ifdef __EXTRA_NODES__
+ case NODE_MATH:
+ svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+ case NODE_VECTOR_MATH:
+ svm_node_vector_math(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+ case NODE_RGB_RAMP:
+ svm_node_rgb_ramp(kg, sd, stack, node, &offset);
+ break;
+ case NODE_GAMMA:
+ svm_node_gamma(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_BRIGHTCONTRAST:
+ svm_node_brightness(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_LIGHT_PATH:
+ svm_node_light_path(sd, stack, node.y, node.z, path_flag);
+ break;
+ case NODE_OBJECT_INFO:
+ svm_node_object_info(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_PARTICLE_INFO:
+ svm_node_particle_info(kg, sd, stack, node.y, node.z);
+ break;
+# ifdef __HAIR__
+# if NODES_FEATURE(NODE_FEATURE_HAIR)
+ case NODE_HAIR_INFO:
+ svm_node_hair_info(kg, sd, stack, node.y, node.z);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_HAIR) */
+# endif /* __HAIR__ */
+# endif /* __EXTRA_NODES__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_1) */
+
+#if NODES_GROUP(NODE_GROUP_LEVEL_2)
+ case NODE_MAPPING:
+ svm_node_mapping(kg, sd, stack, node.y, node.z, &offset);
+ break;
+ case NODE_MIN_MAX:
+ svm_node_min_max(kg, sd, stack, node.y, node.z, &offset);
+ break;
+ case NODE_CAMERA:
+ svm_node_camera(kg, sd, stack, node.y, node.z, node.w);
+ break;
+# ifdef __TEXTURES__
case NODE_TEX_ENVIRONMENT:
svm_node_tex_environment(kg, sd, stack, node);
break;
@@ -261,9 +373,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_TEX_GRADIENT:
svm_node_tex_gradient(sd, stack, node);
break;
- case NODE_TEX_NOISE:
- svm_node_tex_noise(kg, sd, stack, node, &offset);
- break;
case NODE_TEX_VORONOI:
svm_node_tex_voronoi(kg, sd, stack, node, &offset);
break;
@@ -282,57 +391,37 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_TEX_BRICK:
svm_node_tex_brick(kg, sd, stack, node, &offset);
break;
-#endif /* __TEXTURES__ */
- case NODE_CAMERA:
- svm_node_camera(kg, sd, stack, node.y, node.z, node.w);
- break;
- case NODE_GEOMETRY:
- svm_node_geometry(kg, sd, stack, node.y, node.z);
- break;
-#ifdef __EXTRA_NODES__
- case NODE_GEOMETRY_BUMP_DX:
- svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z);
- break;
- case NODE_GEOMETRY_BUMP_DY:
- svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
- break;
- case NODE_LIGHT_PATH:
- svm_node_light_path(sd, stack, node.y, node.z, path_flag);
- break;
- case NODE_OBJECT_INFO:
- svm_node_object_info(kg, sd, stack, node.y, node.z);
+ case NODE_TEX_VOXEL:
+ svm_node_tex_voxel(kg, sd, stack, node, &offset);
break;
- case NODE_PARTICLE_INFO:
- svm_node_particle_info(kg, sd, stack, node.y, node.z);
+# endif /* __TEXTURES__ */
+# ifdef __EXTRA_NODES__
+ case NODE_NORMAL:
+ svm_node_normal(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
-#ifdef __HAIR__
-# if NODES_FEATURE(NODE_FEATURE_HAIR)
- case NODE_HAIR_INFO:
- svm_node_hair_info(kg, sd, stack, node.y, node.z);
+ case NODE_LIGHT_FALLOFF:
+ svm_node_light_falloff(sd, stack, node);
break;
-# endif /* NODES_FEATURE(NODE_FEATURE_HAIR) */
-#endif /* __HAIR__ */
+# endif /* __EXTRA_NODES__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_2) */
-#endif /* __EXTRA_NODES__ */
- case NODE_CONVERT:
- svm_node_convert(sd, stack, node.y, node.z, node.w);
+#if NODES_GROUP(NODE_GROUP_LEVEL_3)
+ case NODE_RGB_CURVES:
+ svm_node_rgb_curves(kg, sd, stack, node, &offset);
break;
- case NODE_VALUE_F:
- svm_node_value_f(kg, sd, stack, node.y, node.z);
+ case NODE_VECTOR_CURVES:
+ svm_node_vector_curves(kg, sd, stack, node, &offset);
break;
- case NODE_VALUE_V:
- svm_node_value_v(kg, sd, stack, node.y, &offset);
+ case NODE_TANGENT:
+ svm_node_tangent(kg, sd, stack, node);
+ break;
+ case NODE_NORMAL_MAP:
+ svm_node_normal_map(kg, sd, stack, node);
break;
-#ifdef __EXTRA_NODES__
+# ifdef __EXTRA_NODES__
case NODE_INVERT:
svm_node_invert(sd, stack, node.y, node.z, node.w);
break;
- case NODE_GAMMA:
- svm_node_gamma(sd, stack, node.y, node.z, node.w);
- break;
- case NODE_BRIGHTCONTRAST:
- svm_node_brightness(sd, stack, node.y, node.z, node.w);
- break;
case NODE_MIX:
svm_node_mix(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
@@ -348,28 +437,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_COMBINE_HSV:
svm_node_combine_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
- case NODE_HSV:
- svm_node_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
-#endif /* __EXTRA_NODES__ */
- case NODE_ATTR:
- svm_node_attr(kg, sd, stack, node);
- break;
-#ifdef __EXTRA_NODES__
- case NODE_ATTR_BUMP_DX:
- svm_node_attr_bump_dx(kg, sd, stack, node);
- break;
- case NODE_ATTR_BUMP_DY:
- svm_node_attr_bump_dy(kg, sd, stack, node);
- break;
-#endif /* __EXTRA_NODES__ */
- case NODE_FRESNEL:
- svm_node_fresnel(sd, stack, node.y, node.z, node.w);
- break;
- case NODE_LAYER_WEIGHT:
- svm_node_layer_weight(sd, stack, node);
+ case NODE_VECTOR_TRANSFORM:
+ svm_node_vector_transform(kg, sd, stack, node);
break;
-#ifdef __EXTRA_NODES__
case NODE_WIREFRAME:
svm_node_wireframe(kg, sd, stack, node);
break;
@@ -379,68 +449,12 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_BLACKBODY:
svm_node_blackbody(kg, sd, stack, node.y, node.z);
break;
- case NODE_SET_DISPLACEMENT:
- svm_node_set_displacement(sd, stack, node.y);
- break;
- case NODE_SET_BUMP:
- svm_node_set_bump(kg, sd, stack, node);
- break;
- case NODE_MATH:
- svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
- case NODE_VECTOR_MATH:
- svm_node_vector_math(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
- case NODE_VECTOR_TRANSFORM:
- svm_node_vector_transform(kg, sd, stack, node);
- break;
- case NODE_NORMAL:
- svm_node_normal(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
-#endif /* __EXTRA_NODES__ */
- case NODE_MAPPING:
- svm_node_mapping(kg, sd, stack, node.y, node.z, &offset);
- break;
- case NODE_MIN_MAX:
- svm_node_min_max(kg, sd, stack, node.y, node.z, &offset);
- break;
- case NODE_TEX_COORD:
- svm_node_tex_coord(kg, sd, path_flag, stack, node, &offset);
- break;
-#ifdef __EXTRA_NODES__
- case NODE_TEX_COORD_BUMP_DX:
- svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node, &offset);
- break;
- case NODE_TEX_COORD_BUMP_DY:
- svm_node_tex_coord_bump_dy(kg, sd, path_flag, stack, node, &offset);
- break;
- case NODE_CLOSURE_SET_NORMAL:
- svm_node_set_normal(kg, sd, stack, node.y, node.z );
- break;
- case NODE_RGB_RAMP:
- svm_node_rgb_ramp(kg, sd, stack, node, &offset);
- break;
- case NODE_RGB_CURVES:
- svm_node_rgb_curves(kg, sd, stack, node, &offset);
- break;
- case NODE_VECTOR_CURVES:
- svm_node_vector_curves(kg, sd, stack, node, &offset);
- break;
- case NODE_LIGHT_FALLOFF:
- svm_node_light_falloff(sd, stack, node);
- break;
-#endif /* __EXTRA_NODES__ */
- case NODE_TANGENT:
- svm_node_tangent(kg, sd, stack, node);
- break;
- case NODE_NORMAL_MAP:
- svm_node_normal_map(kg, sd, stack, node);
- break;
- case NODE_TEX_VOXEL:
- svm_node_tex_voxel(kg, sd, stack, node, &offset);
- break;
+# endif /* __EXTRA_NODES__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_3) */
case NODE_END:
+ return;
default:
+ kernel_assert(!"Unknown node type was passed to the SVM machine");
return;
}
}
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index eff6cd2c223..641d30a5737 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -39,11 +39,17 @@ CCL_NAMESPACE_BEGIN
#define NODE_GROUP_LEVEL_0 0
#define NODE_GROUP_LEVEL_1 1
#define NODE_GROUP_LEVEL_2 2
-#define NODE_GROUP_LEVEL_MAX NODE_GROUP_LEVEL_2
+#define NODE_GROUP_LEVEL_3 3
+#define NODE_GROUP_LEVEL_MAX NODE_GROUP_LEVEL_3
#define NODE_FEATURE_VOLUME (1 << 0)
#define NODE_FEATURE_HAIR (1 << 1)
-#define NODE_FEATURE_ALL (NODE_FEATURE_VOLUME|NODE_FEATURE_HAIR)
+#define NODE_FEATURE_BUMP (1 << 2)
+/* TODO(sergey): Consider using something like ((uint)(-1)).
+ * Need to ceck carefully operand types around usage of this
+ * define first.
+ */
+#define NODE_FEATURE_ALL (NODE_FEATURE_VOLUME|NODE_FEATURE_HAIR|NODE_FEATURE_BUMP)
typedef enum NodeType {
NODE_END = 0,
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 1a17909bddc..93341b56d99 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -225,7 +225,7 @@ public:
* so it's possible to disable huge nodes inside of the required
* nodes group.
*/
- virtual int get_feature() { return 0; }
+ virtual int get_feature() { return bump == SHADER_BUMP_NONE ? 0 : NODE_FEATURE_BUMP; }
};
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 884186c5914..4f99bfc1520 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -1231,6 +1231,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
/* Update images needed for true displacement. */
bool need_displacement_images = false;
+ bool old_need_object_flags_update = false;
foreach(Mesh *mesh, scene->meshes) {
if(mesh->need_update &&
mesh->displacement_method != Mesh::DISPLACE_BUMP)
@@ -1242,6 +1243,12 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
if(need_displacement_images) {
VLOG(1) << "Updating images used for true displacement.";
device_update_displacement_images(device, dscene, scene, progress);
+ old_need_object_flags_update = scene->object_manager->need_flags_update;
+ scene->object_manager->device_update_flags(device,
+ dscene,
+ scene,
+ progress,
+ false);
}
/* device update */
@@ -1327,6 +1334,16 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
}
need_update = false;
+
+ if(need_displacement_images) {
+ /* Re-tag flags for update, so they're re-evaluated
+ * for meshes with correct bounding boxes.
+ *
+ * This wouldn't cause wrong results, just true
+ * displacement might be less optimal ot calculate.
+ */
+ scene->object_manager->need_flags_update = old_need_object_flags_update;
+ }
}
void MeshManager::device_free(Device *device, DeviceScene *dscene)
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 56d21716f3b..4961cd4aebb 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -105,6 +105,7 @@ public:
~EnvironmentTextureNode();
ShaderNode *clone() const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
ImageManager *image_manager;
int is_float;
@@ -124,6 +125,8 @@ class SkyTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(SkyTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
float3 sun_direction;
float turbidity;
float ground_albedo;
@@ -141,6 +144,8 @@ class GradientTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(GradientTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring type;
static ShaderEnum type_enum;
};
@@ -154,6 +159,8 @@ class VoronoiTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(VoronoiTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring coloring;
static ShaderEnum coloring_enum;
@@ -163,6 +170,8 @@ class MusgraveTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(MusgraveTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring type;
static ShaderEnum type_enum;
@@ -172,6 +181,8 @@ class WaveTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(WaveTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
ustring type;
static ShaderEnum type_enum;
};
@@ -180,12 +191,16 @@ class MagicTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(MagicTextureNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
int depth;
};
class CheckerTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(CheckerTextureNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
};
class BrickTextureNode : public TextureNode {
@@ -194,6 +209,8 @@ public:
float offset, squash;
int offset_frequency, squash_frequency;
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
};
class PointDensityTextureNode : public ShaderNode {
@@ -222,6 +239,7 @@ public:
class MappingNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MappingNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
TextureMapping tex_mapping;
};
@@ -344,6 +362,7 @@ public:
class HoldoutNode : public ShaderNode {
public:
SHADER_NODE_CLASS(HoldoutNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class AmbientOcclusionNode : public ShaderNode {
@@ -351,6 +370,7 @@ public:
SHADER_NODE_CLASS(AmbientOcclusionNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class VolumeNode : public ShaderNode {
@@ -358,6 +378,7 @@ public:
SHADER_NODE_CLASS(VolumeNode)
void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2);
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ClosureType closure;
};
@@ -405,6 +426,7 @@ public:
SHADER_NODE_CLASS(UVMapNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ustring attribute;
bool from_dupli;
@@ -413,6 +435,7 @@ public:
class LightPathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(LightPathNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class LightFalloffNode : public ShaderNode {
@@ -424,12 +447,14 @@ public:
class ObjectInfoNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ObjectInfoNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class ParticleInfoNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ParticleInfoNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class HairInfoNode : public ShaderNode {
@@ -438,7 +463,10 @@ public:
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
- virtual int get_feature() { return NODE_FEATURE_HAIR; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ virtual int get_feature() {
+ return ShaderNode::get_feature() | NODE_FEATURE_HAIR;
+ }
};
class ValueNode : public ShaderNode {
@@ -473,12 +501,16 @@ public:
class InvertNode : public ShaderNode {
public:
SHADER_NODE_CLASS(InvertNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class MixNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
bool use_clamp;
ustring type;
@@ -488,41 +520,55 @@ public:
class CombineRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineRGBNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class CombineHSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineHSVNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class CombineXYZNode : public ShaderNode {
public:
SHADER_NODE_CLASS(CombineXYZNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class GammaNode : public ShaderNode {
public:
SHADER_NODE_CLASS(GammaNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class BrightContrastNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BrightContrastNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class SeparateRGBNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateRGBNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class SeparateHSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateHSVNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class SeparateXYZNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SeparateXYZNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class HSVNode : public ShaderNode {
@@ -549,18 +595,21 @@ class FresnelNode : public ShaderNode {
public:
SHADER_NODE_CLASS(FresnelNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class LayerWeightNode : public ShaderNode {
public:
SHADER_NODE_CLASS(LayerWeightNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class WireframeNode : public ShaderNode {
public:
SHADER_NODE_CLASS(WireframeNode)
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
bool use_pixel_size;
};
@@ -568,16 +617,21 @@ public:
class WavelengthNode : public ShaderNode {
public:
SHADER_NODE_CLASS(WavelengthNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class BlackbodyNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BlackbodyNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
class MathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MathNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
bool use_clamp;
@@ -588,6 +642,7 @@ public:
class NormalNode : public ShaderNode {
public:
SHADER_NODE_CLASS(NormalNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
float3 direction;
};
@@ -595,6 +650,7 @@ public:
class VectorMathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorMathNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ustring type;
static ShaderEnum type_enum;
@@ -604,6 +660,8 @@ class VectorTransformNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorTransformNode)
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
ustring type;
ustring convert_from;
ustring convert_to;
@@ -616,6 +674,10 @@ class BumpNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BumpNode)
bool has_spatial_varying() { return true; }
+ virtual int get_feature() {
+ /* TODO(sergey): Check for incoming links. */
+ return NODE_FEATURE_BUMP;
+ }
bool invert;
};
@@ -623,12 +685,18 @@ public:
class RGBCurvesNode : public ShaderNode {
public:
SHADER_NODE_CLASS(RGBCurvesNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
float4 curves[RAMP_TABLE_SIZE];
};
class VectorCurvesNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorCurvesNode)
+
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
float4 curves[RAMP_TABLE_SIZE];
};
@@ -637,6 +705,7 @@ public:
SHADER_NODE_CLASS(RGBRampNode)
float4 ramp[RAMP_TABLE_SIZE];
bool interpolate;
+ virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
class SetNormalNode : public ShaderNode {
@@ -665,6 +734,7 @@ public:
SHADER_NODE_CLASS(NormalMapNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
ustring space;
static ShaderEnum space_enum;
@@ -677,6 +747,7 @@ public:
SHADER_NODE_CLASS(TangentNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+ virtual int get_group() { return NODE_GROUP_LEVEL_3; }
ustring direction_type;
static ShaderEnum direction_type_enum;
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index da9bc23ccc4..ae72d728c8c 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -410,7 +410,8 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
void ObjectManager::device_update_flags(Device *device,
DeviceScene *dscene,
Scene *scene,
- Progress& /*progress*/)
+ Progress& /*progress*/,
+ bool bounds_valid)
{
if(!need_update && !need_flags_update)
return;
@@ -425,9 +426,13 @@ void ObjectManager::device_update_flags(Device *device,
uint *object_flag = dscene->object_flag.get_data();
vector<Object *> volume_objects;
+ bool has_volume_objects = false;
foreach(Object *object, scene->objects) {
if(object->mesh->has_volume) {
- volume_objects.push_back(object);
+ if(bounds_valid) {
+ volume_objects.push_back(object);
+ }
+ has_volume_objects = true;
}
}
@@ -440,15 +445,23 @@ void ObjectManager::device_update_flags(Device *device,
object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME;
}
- foreach(Object *volume_object, volume_objects) {
- if(object == volume_object) {
- continue;
- }
- if(object->bounds.intersects(volume_object->bounds)) {
- object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
- break;
+ if(bounds_valid) {
+ foreach(Object *volume_object, volume_objects) {
+ if(object == volume_object) {
+ continue;
+ }
+ if(object->bounds.intersects(volume_object->bounds)) {
+ object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
+ break;
+ }
}
}
+ else if(has_volume_objects) {
+ /* Not really valid, but can't make more reliable in the case
+ * of bounds not being up to date.
+ */
+ object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
+ }
++object_index;
}
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index acc08a0e204..379d1748cdd 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -77,7 +77,11 @@ public:
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress);
- void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_update_flags(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& progress,
+ bool bounds_valid = true);
void device_free(Device *device, DeviceScene *dscene);
void tag_update(Scene *scene);
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index b880a62f4de..a9a03e54cf7 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -608,7 +608,7 @@ DeviceRequestedFeatures Session::get_requested_device_features()
requested_features.experimental = params.experimental;
if(!params.background) {
requested_features.max_closure = 64;
- requested_features.max_nodes_group = NODE_GROUP_LEVEL_2;
+ requested_features.max_nodes_group = NODE_GROUP_LEVEL_MAX;
requested_features.nodes_features = NODE_FEATURE_ALL;
}
else {
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 667279360c3..31be2a3d3f4 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -481,21 +481,42 @@ void ShaderManager::add_default(Scene *scene)
}
}
-void ShaderManager::get_requested_features(Scene *scene, int& max_group, int& features)
+/* NOTE: Expects max_group and features to be initialized in the callee. */
+void ShaderManager::get_requested_graph_features(ShaderGraph *graph,
+ int& max_group,
+ int& features)
+{
+ foreach(ShaderNode *node, graph->nodes) {
+ max_group = max(max_group, node->get_group());
+ features |= node->get_feature();
+ if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
+ BsdfNode *bsdf_node = static_cast<BsdfNode*>(node);
+ if(CLOSURE_IS_VOLUME(bsdf_node->closure)) {
+ features |= NODE_FEATURE_VOLUME;
+ }
+ }
+ }
+}
+
+void ShaderManager::get_requested_features(Scene *scene,
+ int& max_group,
+ int& features)
{
max_group = NODE_GROUP_LEVEL_0;
features = 0;
for(int i = 0; i < scene->shaders.size(); i++) {
Shader *shader = scene->shaders[i];
- foreach(ShaderNode *node, shader->graph->nodes) {
- max_group = min(max_group, node->get_group());
- features |= node->get_feature();
- if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
- BsdfNode *bsdf_node = static_cast<BsdfNode*>(node);
- if(CLOSURE_IS_VOLUME(bsdf_node->closure)) {
- features |= NODE_FEATURE_VOLUME;
- }
- }
+ /* Gather requested features from all the nodes from the graph nodes. */
+ get_requested_graph_features(shader->graph, max_group, features);
+ /* Gather requested features from the graph itself. */
+ if(shader->graph_bump) {
+ get_requested_graph_features(shader->graph_bump,
+ max_group,
+ features);
+ }
+ ShaderNode *output_node = shader->graph->output();
+ if(output_node->input("Displacement")->link != NULL) {
+ features |= NODE_FEATURE_BUMP;
}
}
}
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index 27b239601d0..64d45635ef1 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -166,7 +166,9 @@ public:
static void add_default(Scene *scene);
/* Selective nodes compilation. */
- void get_requested_features(Scene *scene, int& max_group, int& features);
+ void get_requested_features(Scene *scene,
+ int& max_group,
+ int& features);
protected:
ShaderManager();
@@ -178,6 +180,10 @@ protected:
static vector<float> beckmann_table;
size_t beckmann_table_offset;
+
+ void get_requested_graph_features(ShaderGraph *graph,
+ int& max_group,
+ int& features);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_atomic.h b/intern/cycles/util/util_atomic.h
index 85a82d38275..1d1e2963348 100644
--- a/intern/cycles/util/util_atomic.h
+++ b/intern/cycles/util/util_atomic.h
@@ -53,9 +53,9 @@ ccl_device_inline void atomic_add_float(volatile ccl_global float *source,
do {
prev_value.float_value = *source;
new_value.float_value = prev_value.float_value + operand;
- } while (atomic_cmpxchg((volatile ccl_global unsigned int *)source,
- prev_value.int_value,
- new_value.int_value) != prev_value.int_value);
+ } while(atomic_cmpxchg((volatile ccl_global unsigned int *)source,
+ prev_value.int_value,
+ new_value.int_value) != prev_value.int_value);
}
#endif /* __KERNEL_OPENCL__ */
diff --git a/intern/cycles/util/util_view.cpp b/intern/cycles/util/util_view.cpp
index 0c11316417b..9b5cd22fb4a 100644
--- a/intern/cycles/util/util_view.cpp
+++ b/intern/cycles/util/util_view.cpp
@@ -110,6 +110,7 @@ void view_display_help()
view_display_text(x1+20, y2-230, "Left mouse: Move camera");
view_display_text(x1+20, y2-250, "Right mouse: Rotate camera");
view_display_text(x1+20, y2-270, "W/A/S/D: Move camera");
+ view_display_text(x1+20, y2-290, "0/1/2/3: Set max bounces");
glColor3f(1.0f, 1.0f, 1.0f);
}
diff --git a/release/scripts/freestyle/modules/freestyle/functions.py b/release/scripts/freestyle/modules/freestyle/functions.py
index 48d9b2e2b39..426d344e8ab 100644
--- a/release/scripts/freestyle/modules/freestyle/functions.py
+++ b/release/scripts/freestyle/modules/freestyle/functions.py
@@ -189,11 +189,13 @@ class CurveMaterialF0D(UnaryFunction0DMaterial):
priority is used to pick one of the two materials at material
boundaries.
- Note: expects instances of CurvePoint to be iterated over
+ Notes: expects instances of CurvePoint to be iterated over
+ can return None if no fedge can be found
"""
def __call__(self, inter):
fe = inter.object.fedge
- assert(fe is not None), "CurveMaterialF0D: fe is None"
+ if fe is None:
+ return None
if fe.is_smooth:
return fe.material
else:
diff --git a/release/scripts/freestyle/modules/freestyle/predicates.py b/release/scripts/freestyle/modules/freestyle/predicates.py
index 2439cb0cf97..5cbe577b956 100644
--- a/release/scripts/freestyle/modules/freestyle/predicates.py
+++ b/release/scripts/freestyle/modules/freestyle/predicates.py
@@ -43,6 +43,7 @@ __all__ = (
"FalseUP0D",
"FalseUP1D",
"Length2DBP1D",
+ "MaterialBP1D",
"NotBP1D",
"NotUP1D",
"ObjectNamesUP1D",
@@ -150,12 +151,13 @@ from freestyle.functions import (
pyViewMapGradientNormF1D,
)
+from freestyle.utils import material_from_fedge
+
import random
# -- Unary predicates for 0D elements (vertices) -- #
-
class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D):
def __init__(self, a):
UnaryPredicate0D.__init__(self)
@@ -234,9 +236,10 @@ class AndUP1D(UnaryPredicate1D):
def __init__(self, *predicates):
UnaryPredicate1D.__init__(self)
self.predicates = predicates
- # there are cases in which only one predicate is supplied (in the parameter editor)
- if len(self.predicates) < 1:
- raise ValueError("Expected one or more UnaryPredicate1D, got ", len(predicates))
+ correct_types = all(isinstance(p, UnaryPredicate1D) for p in self.predicates)
+ if not (correct_types and predicates):
+ raise TypeError("%s: Expected one or more UnaryPredicate1D, got %r" %
+ (self.__class__.__name__, self.predicates))
def __call__(self, inter):
return all(pred(inter) for pred in self.predicates)
@@ -246,9 +249,10 @@ class OrUP1D(UnaryPredicate1D):
def __init__(self, *predicates):
UnaryPredicate1D.__init__(self)
self.predicates = predicates
- # there are cases in which only one predicate is supplied (in the parameter editor)
- if len(self.predicates) < 1:
- raise ValueError("Expected one or more UnaryPredicate1D, got ", len(predicates))
+ correct_types = all(isinstance(p, UnaryPredicate1D) for p in self.predicates)
+ if not (correct_types and predicates):
+ raise TypeError("%s: Expected one or more UnaryPredicate1D, got %r" %
+ (self.__class__.__name__, self.predicates))
def __call__(self, inter):
return any(pred(inter) for pred in self.predicates)
@@ -257,10 +261,10 @@ class OrUP1D(UnaryPredicate1D):
class NotUP1D(UnaryPredicate1D):
def __init__(self, pred):
UnaryPredicate1D.__init__(self)
- self.__pred = pred
+ self.predicate = pred
def __call__(self, inter):
- return not self.__pred(inter)
+ return not self.predicate(inter)
class ObjectNamesUP1D(UnaryPredicate1D):
@@ -563,32 +567,36 @@ class pyClosedCurveUP1D(UnaryPredicate1D):
class AndBP1D(BinaryPredicate1D):
def __init__(self, *predicates):
BinaryPredicate1D.__init__(self)
- self._predicates = predicates
- if len(predicates) < 2:
- raise ValueError("Expected two or more BinaryPredicate1D, got ", len(predictates))
+ self.predicates = tuple(predicates)
+ correct_types = all(isinstance(p, BinaryPredicate1D) for p in self.predicates)
+ if not (correct_types and predicates):
+ raise TypeError("%s: Expected one or more BinaryPredicate1D, got %r" %
+ (self.__class__.__name__, self.predicates))
def __call__(self, i1, i2):
- return all(pred(i1, i2) for pred in self._predicates)
+ return all(pred(i1, i2) for pred in self.predicates)
class OrBP1D(BinaryPredicate1D):
def __init__(self, *predicates):
BinaryPredicate1D.__init__(self)
- self._predicates = predicates
- if len(predicates) < 2:
- raise ValueError("Expected two or more BinaryPredicate1D, got ", len(predictates))
+ self.predicates = tuple(predicates)
+ correct_types = all(isinstance(p, BinaryPredicate1D) for p in self.predicates)
+ if not (correct_types and predicates):
+ raise TypeError("%s: Expected one or more BinaryPredicate1D, got %r" %
+ (self.__class__.__name__, self.predicates))
def __call__(self, i1, i2):
- return any(pred(i1, i2) for pred in self._predicates)
+ return any(pred(i1, i2) for pred in self.predicates)
class NotBP1D(BinaryPredicate1D):
def __init__(self, predicate):
BinaryPredicate1D.__init__(self)
- self._predicate = predicate
+ self.predicate = predicate
def __call__(self, i1, i2):
- return (not self._predicate(i1, i2))
+ return (not self.predicate(i1, i2))
class pyZBP1D(BinaryPredicate1D):
@@ -663,3 +671,10 @@ class pyShuffleBP1D(BinaryPredicate1D):
def __call__(self, inter1, inter2):
return (random.uniform(0, 1) < random.uniform(0, 1))
+
+class MaterialBP1D(BinaryPredicate1D):
+ """Checks whether the two supplied ViewEdges have the same material."""
+ def __call__(self, i1, i2):
+ fedges = (fe for ve in (i1, i2) for fe in (ve.first_fedge, ve.last_fedge))
+ materials = {material_from_fedge(fe) for fe in fedges}
+ return len(materials) < 2
diff --git a/release/scripts/freestyle/modules/freestyle/shaders.py b/release/scripts/freestyle/modules/freestyle/shaders.py
index 61365e8dd87..127db3fcd4b 100644
--- a/release/scripts/freestyle/modules/freestyle/shaders.py
+++ b/release/scripts/freestyle/modules/freestyle/shaders.py
@@ -138,7 +138,7 @@ from freestyle.predicates import (
from freestyle.utils import (
bound,
- bounding_box,
+ BoundingBox,
phase_to_direction,
)
@@ -865,7 +865,7 @@ class pyBluePrintCirclesShader(StrokeShader):
def shade(self, stroke):
# get minimum and maximum coordinates
- p_min, p_max = bounding_box(stroke)
+ p_min, p_max = BoundingBox.from_sequence(svert.point for svert in stroke).corners
stroke.resample(32 * self.__turns)
sv_nb = len(stroke) // self.__turns
@@ -917,7 +917,7 @@ class pyBluePrintEllipsesShader(StrokeShader):
self.__random_radius = random_radius
def shade(self, stroke):
- p_min, p_max = bounding_box(stroke)
+ p_min, p_max = BoundingBox.from_sequence(svert.point for svert in stroke).corners
stroke.resample(32 * self.__turns)
sv_nb = len(stroke) // self.__turns
@@ -964,7 +964,7 @@ class pyBluePrintSquaresShader(StrokeShader):
return
# get minimum and maximum coordinates
- p_min, p_max = bounding_box(stroke)
+ p_min, p_max = BoundingBox.from_sequence(svert.point for svert in stroke).corners
stroke.resample(32 * self.__turns)
num_segments = len(stroke) // self.__turns
diff --git a/release/scripts/freestyle/modules/freestyle/utils.py b/release/scripts/freestyle/modules/freestyle/utils.py
index 224734d5bfb..41d2297f723 100644
--- a/release/scripts/freestyle/modules/freestyle/utils.py
+++ b/release/scripts/freestyle/modules/freestyle/utils.py
@@ -22,24 +22,29 @@ writing.
"""
__all__ = (
- "ContextFunctions",
"bound",
- "bounding_box",
+ "BoundingBox",
+ "ContextFunctions",
"find_matching_vertex",
- "getCurrentScene",
"get_chain_length",
+ "get_object_name",
+ "get_strokes",
"get_test_stroke",
+ "getCurrentScene",
"integrate",
+ "is_poly_clockwise",
"iter_distance_along_stroke",
"iter_distance_from_camera",
"iter_distance_from_object",
"iter_material_value",
"iter_t2d_along_stroke",
+ "material_from_fedge",
"pairwise",
"phase_to_direction",
"rgb_to_bw",
"stroke_curvature",
"stroke_normal",
+ "StrokeCollector",
"tripplewise",
)
@@ -55,6 +60,7 @@ from _freestyle import (
from freestyle.types import (
Interface0DIterator,
Stroke,
+ StrokeShader,
StrokeVertexIterator,
)
@@ -79,12 +85,38 @@ def bound(lower, x, higher):
return (lower if x <= lower else higher if x >= higher else x)
-def bounding_box(stroke):
- """
- Returns the maximum and minimum coordinates (the bounding box) of the stroke's vertices
- """
- x, y = zip(*(svert.point for svert in stroke))
- return (Vector((min(x), min(y))), Vector((max(x), max(y))))
+def get_strokes():
+ """Get all strokes that are currently available"""
+ return tuple(map(Operators().get_stroke_from_index, range(Operators().get_strokes_size())))
+
+
+def is_poly_clockwise(stroke):
+ """True if the stroke is orientated in a clockwise way, False otherwise"""
+ v = sum((v2.point.x - v1.point.x) * (v1.point.y + v2.point.y) for v1, v2 in pairwise(stroke))
+ v1, v2 = stroke[0], stroke[-1]
+ if (v1.point - v2.point).length > 1e-3:
+ v += (v2.point.x - v1.point.x) * (v1.point.y + v2.point.y)
+ return v > 0
+
+
+def get_object_name(stroke):
+ """Returns the name of the object that this stroke is drawn on."""
+ fedge = stroke[0].fedge
+ if fedge is None:
+ return None
+ return fedge.viewedge.viewshape.name
+
+
+def material_from_fedge(fe):
+ "get the diffuse rgba color from an FEdge"
+ if fe is None:
+ return None
+ if fe.is_smooth:
+ material = fe.material
+ else:
+ right, left = fe.material_right, fe.material_left
+ material = right if (right.priority > left.priority) else left
+ return material
# -- General helper functions -- #
@@ -106,6 +138,54 @@ def phase_to_direction(length):
# lower bound (e.g., thickness, range and certain values)
BoundedProperty = namedtuple("BoundedProperty", ["min", "max", "delta"])
+
+class BoundingBox:
+ """Object representing a bounding box consisting out of 2 2D vectors"""
+
+ __slots__ = (
+ "minimum",
+ "maximum",
+ "size",
+ "corners",
+ )
+
+ def __init__(self, minimum: Vector, maximum: Vector):
+ self.minimum = minimum
+ self.maximum = maximum
+ if len(minimum) != len(maximum):
+ raise TypeError("Expected two vectors of size 2, got", minimum, maximum)
+ self.size = len(minimum)
+ self.corners = (minimum, maximum)
+
+ def __repr__(self):
+ return "BoundingBox(%r, %r)" % (self.minimum, self.maximum)
+
+ @classmethod
+ def from_sequence(cls, sequence):
+ """BoundingBox from sequence of 2D or 3D Vector objects"""
+ x, y = zip(*sequence)
+ mini = Vector((min(x), min(y)))
+ maxi = Vector((max(x), max(y)))
+ return cls(mini, maxi)
+
+ def inside(self, other):
+ """True if self inside other, False otherwise"""
+ if self.size != other.size:
+ raise TypeError("Expected two BoundingBox of the same size, got", self, other)
+ return (self.minimum.x >= other.minimum.x and self.minimum.y >= other.minimum.y and
+ self.maximum.x <= other.maximum.x and self.maximum.y <= other.maximum.y)
+
+
+class StrokeCollector(StrokeShader):
+ "Collects and Stores stroke objects"
+ def __init__(self):
+ StrokeShader.__init__(self)
+ self.strokes = []
+
+ def shade(self, stroke):
+ self.strokes.append(stroke)
+
+
# -- helper functions for chaining -- #
def get_chain_length(ve, orientation):
@@ -147,6 +227,7 @@ def find_matching_vertex(id, it):
"""Finds the matching vertex, or returns None."""
return next((ve for ve in it if ve.id == id), None)
+
# -- helper functions for iterating -- #
def pairwise(iterable, types={Stroke, StrokeVertexIterator}):
@@ -210,7 +291,7 @@ def iter_distance_from_object(stroke, location, range_min, range_max, normfac):
def iter_material_value(stroke, func, attribute):
- "Yields a specific material attribute from the vertex' underlying material."
+ """Yields a specific material attribute from the vertex' underlying material."""
it = Interface0DIterator(stroke)
for svert in it:
material = func(it)
@@ -252,8 +333,9 @@ def iter_material_value(stroke, func, attribute):
raise ValueError("unexpected material attribute: " + attribute)
yield (svert, value)
+
def iter_distance_along_stroke(stroke):
- "Yields the absolute distance along the stroke up to the current vertex."
+ """Yields the absolute distance along the stroke up to the current vertex."""
distance = 0.0
# the positions need to be copied, because they are changed in the calling function
points = tuple(svert.point.copy() for svert in stroke)
@@ -295,6 +377,7 @@ def stroke_curvature(it):
yield abs(K)
+
def stroke_normal(stroke):
"""
Compute the 2D normal at the stroke vertex pointed by the iterator
@@ -304,7 +387,7 @@ def stroke_normal(stroke):
The returned normals are dynamic: they update when the
vertex position (and therefore the vertex normal) changes.
- for use in geometry modifiers it is advised to
+ for use in geometry modifiers it is advised to
cast this generator function to a tuple or list
"""
n = len(stroke) - 1
@@ -323,12 +406,13 @@ def stroke_normal(stroke):
n2 = Vector((e2[1], -e2[0])).normalized()
yield (n1 + n2).normalized()
+
def get_test_stroke():
"""Returns a static stroke object for testing """
from freestyle.types import Stroke, Interface0DIterator, StrokeVertexIterator, SVertex, Id, StrokeVertex
# points for our fake stroke
points = (Vector((1.0, 5.0, 3.0)), Vector((1.0, 2.0, 9.0)),
- Vector((6.0, 2.0, 3.0)), Vector((7.0, 2.0, 3.0)),
+ Vector((6.0, 2.0, 3.0)), Vector((7.0, 2.0, 3.0)),
Vector((2.0, 6.0, 3.0)), Vector((2.0, 8.0, 3.0)))
ids = (Id(0, 0), Id(1, 1), Id(2, 2), Id(3, 3), Id(4, 4), Id(5, 5))
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index 8c86f31022c..11aeebb8a43 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -416,19 +416,21 @@ def reset_all(reload_scripts=False):
disable(mod_name)
-def module_bl_info(mod, info_basis={"name": "",
- "author": "",
- "version": (),
- "blender": (),
- "location": "",
- "description": "",
- "wiki_url": "",
- "support": 'COMMUNITY',
- "category": "",
- "warning": "",
- "show_expanded": False,
- }
- ):
+def module_bl_info(mod, info_basis=None):
+ if info_basis is None:
+ info_basis = {
+ "name": "",
+ "author": "",
+ "version": (),
+ "blender": (),
+ "location": "",
+ "description": "",
+ "wiki_url": "",
+ "support": 'COMMUNITY',
+ "category": "",
+ "warning": "",
+ "show_expanded": False,
+ }
addon_info = getattr(mod, "bl_info", {})
diff --git a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
index 580753482c2..43a09a1acbd 100644
--- a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
+++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
@@ -925,18 +925,18 @@ def main():
return
import sys
- back_argv = sys.argv
+ import argparse
+
# Get rid of Blender args!
- sys.argv = sys.argv[sys.argv.index("--") + 1:]
+ argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
- import argparse
parser = argparse.ArgumentParser(description="Process UI messages from inside Blender.")
parser.add_argument('-c', '--no_checks', default=True, action="store_false", help="No checks over UI messages.")
parser.add_argument('-m', '--no_messages', default=True, action="store_false", help="No export of UI messages.")
parser.add_argument('-o', '--output', default=None, help="Output POT file path.")
parser.add_argument('-s', '--settings', default=None,
help="Override (some) default settings. Either a JSon file name, or a JSon string.")
- args = parser.parse_args()
+ args = parser.parse_args(argv)
settings = settings_i18n.I18nSettings()
settings.from_json(args.settings)
@@ -946,8 +946,6 @@ def main():
dump_messages(do_messages=args.no_messages, do_checks=args.no_checks, settings=settings)
- sys.argv = back_argv
-
if __name__ == "__main__":
print("\n\n *** Running {} *** \n".format(__file__))
diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py
index 524fef909e8..d472621029e 100644
--- a/release/scripts/modules/bl_i18n_utils/utils.py
+++ b/release/scripts/modules/bl_i18n_utils/utils.py
@@ -162,7 +162,7 @@ def get_po_files_from_dir(root_dir, langs=set()):
yield uid, po_file
-def enable_addons(addons={}, support={}, disable=False, check_only=False):
+def enable_addons(addons=None, support=None, disable=False, check_only=False):
"""
Enable (or disable) addons based either on a set of names, or a set of 'support' types.
Returns the list of all affected addons (as fake modules)!
@@ -170,6 +170,11 @@ def enable_addons(addons={}, support={}, disable=False, check_only=False):
"""
import addon_utils
+ if addons is None:
+ addons = {}
+ if support is None:
+ support = {}
+
userpref = bpy.context.user_preferences
used_ext = {ext.module for ext in userpref.addons}
@@ -212,13 +217,13 @@ class I18nMessage:
__slots__ = ("msgctxt_lines", "msgid_lines", "msgstr_lines", "comment_lines", "is_fuzzy", "is_commented",
"settings")
- def __init__(self, msgctxt_lines=[], msgid_lines=[], msgstr_lines=[], comment_lines=[],
+ def __init__(self, msgctxt_lines=None, msgid_lines=None, msgstr_lines=None, comment_lines=None,
is_commented=False, is_fuzzy=False, settings=settings):
self.settings = settings
- self.msgctxt_lines = msgctxt_lines
- self.msgid_lines = msgid_lines
- self.msgstr_lines = msgstr_lines
- self.comment_lines = comment_lines
+ self.msgctxt_lines = msgctxt_lines or []
+ self.msgid_lines = msgid_lines or []
+ self.msgstr_lines = msgstr_lines or []
+ self.comment_lines = comment_lines or []
self.is_fuzzy = is_fuzzy
self.is_commented = is_commented
diff --git a/release/scripts/modules/nodeitems_utils.py b/release/scripts/modules/nodeitems_utils.py
index ff2100916fc..2f69ea84386 100644
--- a/release/scripts/modules/nodeitems_utils.py
+++ b/release/scripts/modules/nodeitems_utils.py
@@ -43,7 +43,11 @@ class NodeCategory:
class NodeItem:
- def __init__(self, nodetype, label=None, settings={}, poll=None):
+ def __init__(self, nodetype, label=None, settings=None, poll=None):
+
+ if settings is None:
+ settings = {}
+
self.nodetype = nodetype
self._label = label
self.settings = settings
diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py
index 7fb0924add5..3c84e5dc553 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -72,7 +72,6 @@ def GlobalBB_HQ(obj):
me = obj.to_mesh(scene=bpy.context.scene, apply_modifiers=True, settings='PREVIEW')
verts = me.vertices
- bpy.data.meshes.remove(me)
val = matrix_world * verts[-1].co
@@ -113,6 +112,8 @@ def GlobalBB_HQ(obj):
if val > up:
up = val
+ bpy.data.meshes.remove(me)
+
return Vector((left, front, up)), Vector((right, back, down))
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index f315c947009..d1f7c0f5e40 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -133,7 +133,7 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal
else:
row = col.row(align=True)
panel.prop_unified_color(row, context, brush, "color", text="")
- if brush.image_tool == 'FILL':
+ if brush.image_tool == 'FILL' and not projpaint:
col.prop(brush, "fill_threshold")
else:
panel.prop_unified_color(row, context, brush, "secondary_color", text="")
@@ -216,7 +216,9 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal
col = layout.column(align=True)
col.prop(brush, "use_accumulate")
- col.prop(brush, "use_alpha")
+ if projpaint:
+ col.prop(brush, "use_alpha")
+
col.prop(brush, "use_gradient")
col.separator()
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 1391e18748c..2057b0f6bbf 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -286,10 +286,9 @@ void blf_font_buffer(FontBLF *font, const char *str)
(unsigned char)(buf_info->col[2] * 255),
(unsigned char)(buf_info->col[3] * 255)};
- unsigned char *cbuf;
int chx, chy;
int y, x;
- float a, *fbuf;
+ float a;
BLF_KERNING_VARS(font, has_kerning, kern_mode);
@@ -349,8 +348,12 @@ void blf_font_buffer(FontBLF *font, const char *str)
a = *(g->bitmap + x + (yb * g->pitch)) / 255.0f;
if (a > 0.0f) {
+ const size_t buf_ofs = (
+ ((size_t)(chx + x) + ((size_t)(pen_y + y) * (size_t)buf_info->w)) *
+ (size_t)buf_info->ch);
+ float *fbuf = buf_info->fbuf + buf_ofs;
float alphatest;
- fbuf = buf_info->fbuf + buf_info->ch * ((chx + x) + ((pen_y + y) * buf_info->w));
+
if (a >= 1.0f) {
fbuf[0] = b_col_float[0];
fbuf[1] = b_col_float[1];
@@ -380,8 +383,12 @@ void blf_font_buffer(FontBLF *font, const char *str)
a = *(g->bitmap + x + (yb * g->pitch)) / 255.0f;
if (a > 0.0f) {
+ const size_t buf_ofs = (
+ ((size_t)(chx + x) + ((size_t)(pen_y + y) * (size_t)buf_info->w)) *
+ (size_t)buf_info->ch);
+ unsigned char *cbuf = buf_info->cbuf + buf_ofs;
int alphatest;
- cbuf = buf_info->cbuf + buf_info->ch * ((chx + x) + ((pen_y + y) * buf_info->w));
+
if (a >= 1.0f) {
cbuf[0] = b_col_char[0];
cbuf[1] = b_col_char[1];
@@ -667,6 +674,28 @@ float blf_font_fixed_width(FontBLF *font)
return g->advance;
}
+int blf_font_count_missing_chars(FontBLF *font, const char *str, const size_t len, int *r_tot_chars)
+{
+ int missing = 0;
+ size_t i = 0;
+
+ *r_tot_chars = 0;
+ while (i < len) {
+ unsigned int c;
+
+ if ((c = str[i]) < 0x80) {
+ i++;
+ }
+ else if ((c = BLI_str_utf8_as_unicode_step(str, &i)) != BLI_UTF8_ERR) {
+ if (FT_Get_Char_Index((font)->face, c) == 0) {
+ missing++;
+ }
+ }
+ (*r_tot_chars)++;
+ }
+ return missing;
+}
+
void blf_font_free(FontBLF *font)
{
GlyphCacheBLF *gc;
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 39b3e3397be..85410a4d856 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -62,6 +62,9 @@ void blf_font_width_and_height(struct FontBLF *font, const char *str, size_t len
float blf_font_width(struct FontBLF *font, const char *str, size_t len);
float blf_font_height(struct FontBLF *font, const char *str, size_t len);
float blf_font_fixed_width(struct FontBLF *font);
+
+int blf_font_count_missing_chars(struct FontBLF *font, const char *str, const size_t len, int *r_tot_chars);
+
void blf_font_free(struct FontBLF *font);
struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font, unsigned int size, unsigned int dpi);
diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c
index 7c0a43e09ee..4b7a568b8b0 100644
--- a/source/blender/blenfont/intern/blf_thumbs.c
+++ b/source/blender/blenfont/intern/blf_thumbs.c
@@ -90,6 +90,10 @@ void BLF_thumb_preview(
font_size_curr = font_size;
for (i = 0; i < draw_str_lines; i++) {
+ const char *draw_str_i18n = BLF_translate_do(BLF_I18NCONTEXT_DEFAULT, draw_str[i]);
+ const size_t draw_str_i18n_len = strlen(draw_str_i18n);
+ int draw_str_i18n_nbr = 0;
+
blf_font_size(font, (unsigned int)MAX2(font_size_min, font_size_curr), dpi);
/* decrease font size each time */
@@ -98,7 +102,19 @@ void BLF_thumb_preview(
font->pos[1] -= font->glyph_cache->ascender * 1.1f;
- blf_font_buffer(font, BLF_translate_do(BLF_I18NCONTEXT_DEFAULT, draw_str[i]));
+ /* We fallback to default english strings in case not enough chars are available in current font for given
+ * translated string (useful in non-latin i18n context, like chinese, since many fonts will then show
+ * nothing but ugly 'missing char' in their preview).
+ * Does not handle all cases, but much better than nothing.
+ */
+ if (blf_font_count_missing_chars(
+ font, draw_str_i18n, draw_str_i18n_len, &draw_str_i18n_nbr) > (draw_str_i18n_nbr / 2))
+ {
+ blf_font_buffer(font, draw_str[i]);
+ }
+ else {
+ blf_font_buffer(font, draw_str_i18n);
+ }
}
blf_font_free(font);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 7502db21132..0465a354f9f 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -53,11 +53,11 @@ void BKE_object_workob_clear(struct Object *workob);
void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob);
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src);
-struct SoftBody *copy_softbody(struct SoftBody *sb, bool copy_caches);
+struct SoftBody *copy_softbody(const struct SoftBody *sb, bool copy_caches);
struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb);
struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys);
-void BKE_object_copy_particlesystems(struct Object *obn, struct Object *ob);
-void BKE_object_copy_softbody(struct Object *obn, struct Object *ob);
+void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src);
+void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src);
void BKE_object_free_particlesystems(struct Object *ob);
void BKE_object_free_softbody(struct Object *ob);
void BKE_object_free_bulletsoftbody(struct Object *ob);
@@ -73,7 +73,7 @@ void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *
bool BKE_object_support_modifier_type_check(struct Object *ob, int modifier_type);
-void BKE_object_link_modifiers(struct Object *ob, struct Object *from);
+void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src);
void BKE_object_free_modifiers(struct Object *ob);
void BKE_object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob);
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 4584568d4b9..3d67b91d767 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -301,7 +301,7 @@ struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches);
void BKE_ptcache_free_mem(struct ListBase *mem_cache);
void BKE_ptcache_free(struct PointCache *cache);
void BKE_ptcache_free_list(struct ListBase *ptcaches);
-struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, struct ListBase *ptcaches_old, bool copy_data);
+struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, bool copy_data);
/********************** Baking *********************/
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index 3f69618b591..b1b32e75f59 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -632,6 +632,7 @@ bool BKE_appdir_program_python_search(
)
{
is_found = true;
+ break;
}
}
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index d98dd186977..c850216f5ef 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -1626,7 +1626,7 @@ void rename_id(ID *id, const char *name)
void name_uiprefix_id(char *name, const ID *id)
{
name[0] = id->lib ? 'L' : ' ';
- name[1] = id->flag & LIB_FAKEUSER ? 'F' : (id->us == 0) ? '0' : ' ';
+ name[1] = (id->flag & LIB_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' ');
name[2] = ' ';
strcpy(name + 3, id->name + 2);
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index 080a8cead7b..e8418e876bb 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -1233,14 +1233,9 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen
copy_v3_v3(new_ml->bb->vec[6], tempmax);
/* add new_ml to mainb[] */
- if (process->totelem == process->mem) {
- MetaElem **newelem;
+ if (UNLIKELY(process->totelem == process->mem)) {
process->mem = process->mem * 2 + 10;
- newelem = MEM_mallocN(sizeof(MetaElem *) * process->mem, "metaballs");
-
- memcpy(newelem, process->mainb, sizeof(MetaElem *) * process->totelem);
- if (process->mainb) MEM_freeN(process->mainb);
- process->mainb = newelem;
+ process->mainb = MEM_reallocN(process->mainb, sizeof(MetaElem *) * process->mem);
}
process->mainb[process->totelem++] = new_ml;
}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 302d85e8128..d17ca751c5e 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -372,6 +372,10 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space, const float lnor[3],
/* If vec_ref or vec_other are too much aligned with lnor, we can't build lnor space,
* tag it as invalid and abort. */
lnor_space->ref_alpha = lnor_space->ref_beta = 0.0f;
+
+ if (edge_vectors) {
+ BLI_stack_clear(edge_vectors);
+ }
return;
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index ba62404e88f..5595d824ed0 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -252,7 +252,7 @@ bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
return true;
}
-void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
+void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src)
{
ModifierData *md;
BKE_object_free_modifiers(ob_dst);
@@ -268,8 +268,6 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
if (ELEM(md->type,
eModifierType_Hook,
- eModifierType_Softbody,
- eModifierType_ParticleInstance,
eModifierType_Collision))
{
continue;
@@ -277,10 +275,15 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
if (!BKE_object_support_modifier_type_check(ob_dst, md->type))
continue;
-
- if (md->type == eModifierType_Skin) {
- /* ensure skin-node customdata exists */
- BKE_mesh_ensure_skin_customdata(ob_dst->data);
+
+ switch (md->type) {
+ case eModifierType_Softbody:
+ BKE_object_copy_softbody(ob_dst, ob_src);
+ break;
+ case eModifierType_Skin:
+ /* ensure skin-node customdata exists */
+ BKE_mesh_ensure_skin_customdata(ob_dst->data);
+ break;
}
nmd = modifier_new(md->type);
@@ -297,7 +300,6 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
}
BKE_object_copy_particlesystems(ob_dst, ob_src);
- BKE_object_copy_softbody(ob_dst, ob_src);
/* TODO: smoke?, cloth? */
}
@@ -1243,7 +1245,7 @@ struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene)
#endif /* WITH_GAMEENGINE */
-SoftBody *copy_softbody(SoftBody *sb, bool copy_caches)
+SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches)
{
SoftBody *sbn;
@@ -1363,24 +1365,24 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys)
return psysn;
}
-void BKE_object_copy_particlesystems(Object *obn, Object *ob)
+void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src)
{
ParticleSystem *psys, *npsys;
ModifierData *md;
- if (obn->type != OB_MESH) {
+ if (ob_dst->type != OB_MESH) {
/* currently only mesh objects can have soft body */
return;
}
- BLI_listbase_clear(&obn->particlesystem);
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ BLI_listbase_clear(&ob_dst->particlesystem);
+ for (psys = ob_src->particlesystem.first; psys; psys = psys->next) {
npsys = BKE_object_copy_particlesystem(psys);
- BLI_addtail(&obn->particlesystem, npsys);
+ BLI_addtail(&ob_dst->particlesystem, npsys);
/* need to update particle modifiers too */
- for (md = obn->modifiers.first; md; md = md->next) {
+ for (md = ob_dst->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_ParticleSystem) {
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
if (psmd->psys == psys)
@@ -1408,10 +1410,12 @@ void BKE_object_copy_particlesystems(Object *obn, Object *ob)
}
}
-void BKE_object_copy_softbody(Object *obn, Object *ob)
+void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src)
{
- if (ob->soft)
- obn->soft = copy_softbody(ob->soft, false);
+ if (ob_src->soft) {
+ ob_dst->softflag = ob_src->softflag;
+ ob_dst->soft = copy_softbody(ob_src->soft, false);
+ }
}
static void copy_object_pose(Object *obn, Object *ob)
@@ -2151,7 +2155,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
}
/* vec: 4 items! */
- if (where_on_path(par, ctime, vec, dir, cu->flag & CU_FOLLOW ? quat : NULL, &radius, NULL)) {
+ if (where_on_path(par, ctime, vec, dir, (cu->flag & CU_FOLLOW) ? quat : NULL, &radius, NULL)) {
if (cu->flag & CU_FOLLOW) {
#if 0
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 01bc4a1c237..4711a5900f0 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -3063,7 +3063,7 @@ static PointCache *ptcache_copy(PointCache *cache, bool copy_data)
}
/* returns first point cache */
-PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old, bool copy_data)
+PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcaches_old, bool copy_data)
{
PointCache *cache = ptcaches_old->first;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index f73b556e412..16f218d5fb6 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -4074,7 +4074,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
SubsurfFlags flags)
{
int useSimple = (smd->subdivType == ME_SIMPLE_SUBSURF) ? CCG_SIMPLE_SUBDIV : 0;
- CCGFlags useAging = smd->flags & eSubsurfModifierFlag_DebugIncr ? CCG_USE_AGING : 0;
+ CCGFlags useAging = (smd->flags & eSubsurfModifierFlag_DebugIncr) ? CCG_USE_AGING : 0;
int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
CCGDerivedMesh *result;
diff --git a/source/blender/blenlib/BLI_stack.h b/source/blender/blenlib/BLI_stack.h
index a8c4478c450..6d41e5feb88 100644
--- a/source/blender/blenlib/BLI_stack.h
+++ b/source/blender/blenlib/BLI_stack.h
@@ -48,6 +48,7 @@ void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL();
void *BLI_stack_peek(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BLI_stack_discard(BLI_Stack *stack) ATTR_NONNULL();
+void BLI_stack_clear(BLI_Stack *stack) ATTR_NONNULL();
size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index b079478f397..9cf360a77e3 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -57,6 +57,7 @@
# include <shlobj.h>
# include "BLI_winstuff.h"
# include "MEM_guardedalloc.h"
+# include "BLI_alloca.h"
#else
# include "unistd.h"
#endif /* WIN32 */
@@ -1033,31 +1034,36 @@ bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen)
type = BLI_exists(name);
if ((type == 0) || S_ISDIR(type)) {
- char filename[FILE_MAX];
- char ext[FILE_MAX];
- const char *extensions = getenv("PATHEXT");
- if (extensions) {
- const char *temp;
- do {
- strcpy(filename, name);
- temp = strchr(extensions, ';');
- if (temp) {
- strncpy(ext, extensions, temp - extensions);
- ext[temp - extensions] = 0;
- extensions = temp + 1;
- strcat(filename, ext);
- }
- else {
- strcat(filename, extensions);
- }
+ /* typically 3-5, ".EXE", ".BAT"... etc */
+ const int ext_max = 12;
+ const char *ext = getenv("PATHEXT");
+ if (ext) {
+ const int name_len = strlen(name);
+ char *filename = alloca(name_len + ext_max);
+ char *filename_ext;
+ const char *ext_next;
+
+ /* null terminated in the loop */
+ memcpy(filename, name, name_len);
+ filename_ext = filename + name_len;
- type = BLI_exists(filename);
- if (type && (!S_ISDIR(type))) {
- retval = true;
- BLI_strncpy(name, filename, maxlen);
- break;
+ do {
+ int ext_len;
+ ext_next = strchr(ext, ';');
+ ext_len = ext_next ? ((ext_next++) - ext) : strlen(ext);
+
+ if (LIKELY(ext_len < ext_max)) {
+ memcpy(filename_ext, ext, ext_len);
+ filename_ext[ext_len] = '\0';
+
+ type = BLI_exists(filename);
+ if (type && (!S_ISDIR(type))) {
+ retval = true;
+ BLI_strncpy(name, filename, maxlen);
+ break;
+ }
}
- } while (temp);
+ } while ((ext = ext_next));
}
}
else {
diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c
index 2d3a2f77a3e..3c9e1a52cda 100644
--- a/source/blender/blenlib/intern/stack.c
+++ b/source/blender/blenlib/intern/stack.c
@@ -216,6 +216,41 @@ void BLI_stack_discard(BLI_Stack *stack)
}
}
+/**
+ * Discards all elements without freeing.
+ */
+void BLI_stack_clear(BLI_Stack *stack)
+{
+#ifdef USE_TOTELEM
+ if (UNLIKELY(stack->totelem == 0)) {
+ return;
+ }
+ stack->totelem = 0;
+#else
+ if (UNLIKELY(stack->chunk_curr == NULL)) {
+ return;
+ }
+#endif
+
+ stack->chunk_index = stack->chunk_elem_max - 1;
+
+ if (stack->chunk_free) {
+ if (stack->chunk_curr) {
+ /* move all used chunks into tail of free list */
+ struct StackChunk *chunk_free_last = stack->chunk_free;
+ while (chunk_free_last->next) {
+ chunk_free_last = chunk_free_last->next;
+ }
+ chunk_free_last->next = stack->chunk_curr;
+ stack->chunk_curr = NULL;
+ }
+ }
+ else {
+ stack->chunk_free = stack->chunk_curr;
+ stack->chunk_curr = NULL;
+ }
+}
+
size_t BLI_stack_count(const BLI_Stack *stack)
{
#ifdef USE_TOTELEM
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index a404f46a6e2..50295954192 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -199,6 +199,7 @@ void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot)
}
}
+ BLI_spin_lock(&_malloc_lock);
if (thread_levels == 0) {
MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread);
@@ -211,6 +212,7 @@ void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot)
}
thread_levels++;
+ BLI_spin_unlock(&_malloc_lock);
}
/* amount of available threads */
@@ -329,9 +331,11 @@ void BLI_end_threads(ListBase *threadbase)
BLI_freelistN(threadbase);
}
+ BLI_spin_lock(&_malloc_lock);
thread_levels--;
if (thread_levels == 0)
MEM_set_lock_callback(NULL, NULL);
+ BLI_spin_unlock(&_malloc_lock);
}
/* System Information */
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index 95440158277..20ec27a1f4b 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -176,26 +176,38 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to
prv = BLO_library_read_struct(fd, bhead, "PreviewImage");
if (prv) {
memcpy(new_prv, prv, sizeof(PreviewImage));
- if (prv->rect[0]) {
+ if (prv->rect[0] && prv->w[0] && prv->h[0]) {
unsigned int *rect = NULL;
- new_prv->rect[0] = MEM_callocN(new_prv->w[0] * new_prv->h[0] * sizeof(unsigned int), "prvrect");
+ size_t len = new_prv->w[0] * new_prv->h[0] * sizeof(unsigned int);
+ new_prv->rect[0] = MEM_callocN(len, __func__);
bhead = blo_nextbhead(fd, bhead);
rect = (unsigned int *)(bhead + 1);
- memcpy(new_prv->rect[0], rect, bhead->len);
+ BLI_assert(len == bhead->len);
+ memcpy(new_prv->rect[0], rect, len);
}
else {
+ /* This should not be needed, but can happen in 'broken' .blend files,
+ * better handle this gracefully than crashing. */
+ BLI_assert(prv->rect[0] == NULL && prv->w[0] == 0 && prv->h[0] == 0);
new_prv->rect[0] = NULL;
+ new_prv->w[0] = new_prv->h[0] = 0;
}
- if (prv->rect[1]) {
+ if (prv->rect[1] && prv->w[1] && prv->h[1]) {
unsigned int *rect = NULL;
- new_prv->rect[1] = MEM_callocN(new_prv->w[1] * new_prv->h[1] * sizeof(unsigned int), "prvrect");
+ size_t len = new_prv->w[1] * new_prv->h[1] * sizeof(unsigned int);
+ new_prv->rect[1] = MEM_callocN(len, __func__);
bhead = blo_nextbhead(fd, bhead);
rect = (unsigned int *)(bhead + 1);
- memcpy(new_prv->rect[1], rect, bhead->len);
+ BLI_assert(len == bhead->len);
+ memcpy(new_prv->rect[1], rect, len);
}
else {
+ /* This should not be needed, but can happen in 'broken' .blend files,
+ * better handle this gracefully than crashing. */
+ BLI_assert(prv->rect[1] == NULL && prv->w[1] == 0 && prv->h[1] == 0);
new_prv->rect[1] = NULL;
+ new_prv->w[1] = new_prv->h[1] = 0;
}
MEM_freeN(prv);
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index c7d0cf99904..1edd694f935 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1539,6 +1539,10 @@ void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
for (ima = oldmain->image.first; ima; ima = ima->id.next) {
ImagePackedFile *imapf;
+
+ if (ima->packedfile)
+ insert_packedmap(fd, ima->packedfile);
+
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next)
if (imapf->packedfile)
insert_packedmap(fd, imapf->packedfile);
@@ -1577,6 +1581,9 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
for (ima = oldmain->image.first; ima; ima = ima->id.next) {
ImagePackedFile *imapf;
+
+ ima->packedfile = newpackedadr(fd, ima->packedfile);
+
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next)
imapf->packedfile = newpackedadr(fd, imapf->packedfile);
}
@@ -2081,7 +2088,7 @@ static void direct_link_cache_library(FileData *fd, CacheLibrary *cachelib)
static PackedFile *direct_link_packedfile(FileData *fd, PackedFile *oldpf)
{
PackedFile *pf = newpackedadr(fd, oldpf);
-
+
if (pf) {
pf->data = newpackedadr(fd, pf->data);
}
@@ -3528,13 +3535,17 @@ static void direct_link_image(FileData *fd, Image *ima)
link_list(fd, &(ima->views));
link_list(fd, &(ima->packedfiles));
- ima->packedfile = NULL;
- for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
- imapf->packedfile = direct_link_packedfile(fd, imapf->packedfile);
+ if (ima->packedfiles.first) {
+ for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
+ imapf->packedfile = direct_link_packedfile(fd, imapf->packedfile);
+ }
+ ima->packedfile = NULL;
+ }
+ else {
+ ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
}
ima->anims.first = ima->anims.last = NULL;
- ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
ima->preview = direct_link_preview_image(fd, ima->preview);
ima->stereo3d_format = newdataadr(fd, ima->stereo3d_format);
ima->ok = 1;
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 274fc474ade..2727f3a3965 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -766,7 +766,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
bSoundActuator *sAct = (bSoundActuator*) act->data;
if (sAct->sound) {
sound = blo_do_versions_newlibadr(fd, lib, sAct->sound);
- sAct->flag = sound->flags & SOUND_FLAGS_3D ? ACT_SND_3D_SOUND : 0;
+ sAct->flag = (sound->flags & SOUND_FLAGS_3D) ? ACT_SND_3D_SOUND : 0;
sAct->pitch = sound->pitch;
sAct->volume = sound->volume;
sAct->sound3D.reference_distance = sound->distance;
diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c
index fe4a0204335..2dfad5a1f47 100644
--- a/source/blender/bmesh/operators/bmo_hull.c
+++ b/source/blender/bmesh/operators/bmo_hull.c
@@ -537,6 +537,9 @@ static void hull_from_bullet(
}
BLI_array_free(fvi);
+
+ plConvexHullDelete(hull);
+
MEM_freeN(hull_verts);
MEM_freeN(coords);
MEM_freeN(input_verts);
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 252c16e8919..5e4b25128f7 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -57,6 +57,9 @@
/* happens far too often, uncomment for development */
// #define BEVEL_ASSERT_PROJECT
+/* will likely remove the code enabled by this soon, when sure that it is not needed */
+// #define PRE_275_ALGORITHM
+
/* for testing */
// #pragma GCC diagnostic error "-Wpadded"
@@ -187,7 +190,7 @@ typedef struct BevelParams {
bool limit_offset; /* should offsets be limited by collisions? */
const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */
int vertex_group; /* vertex group index, maybe set if vertex_only */
- int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */
+ int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */
} BevelParams;
// #pragma GCC diagnostic ignored "-Wpadded"
@@ -484,8 +487,7 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f
}
/**
- * Like #bev_create_quad_tri, but when verts straddle an old edge.
- *
+ * Like bev_create_quad_tri, but when verts straddle an old edge.
* <pre>
* e
* |
@@ -593,10 +595,42 @@ static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_
}
}
+/* co should be approximately on the plane between e1 and e2, which share common vert v
+ * and common face f (which cannot be NULL).
+ * Is it between those edges, sweeping CCW? */
+static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1, EdgeHalf *e2)
+{
+ BMVert *v1, *v2;
+ float dir1[3], dir2[3], dirco[3], no[3];
+ float ang11, ang1co;
+
+ v1 = BM_edge_other_vert(e1->e, v);
+ v2 = BM_edge_other_vert(e2->e, v);
+ sub_v3_v3v3(dir1, v->co, v1->co);
+ sub_v3_v3v3(dir2, v->co, v2->co);
+ sub_v3_v3v3(dirco, v->co, co);
+ normalize_v3(dir1);
+ normalize_v3(dir2);
+ normalize_v3(dirco);
+ ang11 = angle_normalized_v3v3(dir1, dir2);
+ ang1co = angle_normalized_v3v3(dir1, dirco);
+ /* angles are in [0,pi]. need to compare cross product with normal to see if they are reflex */
+ cross_v3_v3v3(no, dir1, dir2);
+ if (dot_v3v3(no, f->no) < 0.0f)
+ ang11 = (float)(M_PI * 2.0) - ang11;
+ cross_v3_v3v3(no, dir1, dirco);
+ if (dot_v3v3(no, f->no) < 0.0f)
+ ang1co = (float)(M_PI * 2.0) - ang1co;
+ return (ang11 - ang1co > -BEVEL_EPSILON_BIG);
+}
+
/*
* Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco.
* e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of
* the bevel vertex, e1 precedes e2 in CCW order.
+ * Except: if edges_between is true, there are edges between e1 and e2 in CCW order so they
+ * don't share a common face. We want the meeting point to be on an existing face so it
+ * should be dropped onto one of the intermediate faces, if possible.
* Offset edge is on right of both edges, where e1 enters v and e2 leave it.
* When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2),
* but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may
@@ -605,16 +639,27 @@ static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_
* record the change in offset_l (or offset_r); later we can tell that a change has happened because
* the offset will differ from its original value in offset_l_spec (or offset_r_spec).
*/
-static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float meetco[3])
+static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool edges_between, float meetco[3])
{
- float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3],
- off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], ang, d;
+ float dir1[3], dir2[3], dir1n[3], dir2p[3], norm_v[3], norm_v1[3], norm_v2[3],
+ norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3],
+ isect2[3], dropco[3], plane[4], ang, d;
BMVert *closer_v;
+ EdgeHalf *e, *e1next, *e2prev;
+ BMFace *ff;
+ int isect_kind;
/* get direction vectors for two offset lines */
sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co);
sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
+ if (edges_between) {
+ e1next = e1->next;
+ e2prev = e2->prev;
+ sub_v3_v3v3(dir1n, BM_edge_other_vert(e1next->e, v)->co, v->co);
+ sub_v3_v3v3(dir2p, v->co, BM_edge_other_vert(e2prev->e, v)->co);
+ }
+
ang = angle_v3v3(dir1, dir2);
if (ang < BEVEL_EPSILON_BIG) {
/* special case: e1 and e2 are parallel; put offset point perp to both, from v.
@@ -654,14 +699,31 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float
* If e1-v-e2 is a reflex angle (viewed from vertex normal side), need to flip.
* Use f->no to figure out which side to look at angle from, as even if
* f is non-planar, will be more accurate than vertex normal */
- cross_v3_v3v3(norm_v, dir2, dir1);
- normalize_v3(norm_v);
- if (dot_v3v3(norm_v, f ? f->no : v->no) < 0.0f)
- negate_v3(norm_v);
+ if (!edges_between) {
+ cross_v3_v3v3(norm_v1, dir2, dir1);
+ normalize_v3(norm_v1);
+ if (dot_v3v3(norm_v1, f ? f->no : v->no) < 0.0f)
+ negate_v3(norm_v1);
+ copy_v3_v3(norm_v2, norm_v1);
+ }
+ else {
+ /* separate faces; get face norms at corners for each separately */
+ cross_v3_v3v3(norm_v1, dir1n, dir1);
+ normalize_v3(norm_v1);
+ f = e1->fnext;
+ if (dot_v3v3(norm_v1, f ? f->no : v->no) < 0.0f)
+ negate_v3(norm_v1);
+ cross_v3_v3v3(norm_v2, dir2, dir2p);
+ normalize_v3(norm_v2);
+ f = e2->fprev;
+ if (dot_v3v3(norm_v2, f ? f->no : v->no) < 0.0f)
+ negate_v3(norm_v2);
+ }
+
/* get vectors perp to each edge, perp to norm_v, and pointing into face */
- cross_v3_v3v3(norm_perp1, dir1, norm_v);
- cross_v3_v3v3(norm_perp2, dir2, norm_v);
+ cross_v3_v3v3(norm_perp1, dir1, norm_v1);
+ cross_v3_v3v3(norm_perp2, dir2, norm_v2);
normalize_v3(norm_perp1);
normalize_v3(norm_perp2);
@@ -673,11 +735,10 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float
madd_v3_v3fl(off2a, norm_perp2, e2->offset_l);
add_v3_v3v3(off2b, off2a, dir2);
- /* intersect the lines; by construction they should be on the same plane and not parallel */
- if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) {
-#ifdef BEVEL_ASSERT_PROJECT
- BLI_assert(!"offset_meet failure");
-#endif
+ /* intersect the lines */
+ isect_kind = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2);
+ if (isect_kind == 0) {
+ /* lines are colinear: we already tested for this, but this used a different epsilon */
copy_v3_v3(meetco, off1a); /* just to do something */
d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
if (fabsf(d - e2->offset_l) > BEVEL_EPSILON)
@@ -697,6 +758,26 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float
copy_v3_v3(meetco, closer_v->co);
e1->offset_r = len_v3v3(meetco, v->co);
}
+ if (edges_between && e1->offset_r > 0.0 && e2->offset_l > 0.0) {
+ /* Try to drop meetco to a face between e1 and e2 */
+ if (isect_kind == 2) {
+ /* lines didn't meet in 3d: get average of meetco and isect2 */
+ mid_v3_v3v3(meetco, meetco, isect2);
+ }
+ for (e = e1; e != e2; e = e->next) {
+ ff = e->fnext;
+ if (!ff)
+ continue;
+ plane_from_point_normal_v3(plane, v->co, ff->no);
+ closest_to_plane_v3(dropco, plane, meetco);
+ if (point_between_edges(dropco, v, ff, e, e->next)) {
+ copy_v3_v3(meetco, dropco);
+ break;
+ }
+ }
+ e1->offset_r = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co);
+ e2->offset_l = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
+ }
}
}
}
@@ -740,6 +821,17 @@ static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetc
return true;
}
+/* Return true if it will look good to put the meeting point where offset_on_edge_between
+ * would put it. This means that neither side sees a reflex angle */
+static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v)
+{
+ float ang;
+ float meet[3];
+
+ return offset_meet_edge(e1, emid, v, meet, &ang) &&
+ offset_meet_edge(emid, e2, v, meet, &ang);
+}
+
/* Calculate the best place for a meeting point for the offsets from edges e1 and e2
* on the in-between edge emid. Viewed from the vertex normal side, the CCW
* order of these edges is e1, emid, e2.
@@ -799,6 +891,7 @@ static void offset_on_edge_between(
e2->offset_l = d;
}
+#ifdef PRE_275_ALGORITHM
/* Calculate the best place for a meeting point for the offsets from edges e1 and e2
* when there is an in-between edge emid, and we prefer to have a point that may not
* be on emid if that does a better job of keeping offsets at the user spec.
@@ -874,6 +967,7 @@ static void offset_in_two_planes(
/* else iret == 1 and the lines are coplanar so meetco has the intersection */
}
}
+#endif
/* Offset by e->offset in plane with normal plane_no, on left if left==true,
* else on right. If no is NULL, choose an arbitrary plane different
@@ -1425,6 +1519,323 @@ static void set_bound_vert_seams(BevVert *bv)
} while ((v = v->next) != bv->vmesh->boundstart);
}
+#ifndef PRE_275_ALGORITHM
+/* Is e between two planes where angle between is 180? */
+static bool eh_on_plane(EdgeHalf *e)
+{
+ float dot;
+
+ if (e->fprev && e->fnext) {
+ dot = dot_v3v3(e->fprev->no, e->fnext->no);
+ if (fabsf(dot) <= BEVEL_EPSILON ||
+ fabsf(dot - 1.0f) <= BEVEL_EPSILON)
+ return true;
+ }
+ return false;
+}
+
+/* Calculate the profiles for all the BoundVerts of VMesh vm */
+static void calculate_vm_profiles(BevelParams *bp, BevVert *bv, VMesh *vm)
+{
+ BoundVert *v;
+
+ v = vm->boundstart;
+ do {
+ set_profile_params(bp, bv, v);
+ calculate_profile(bp, v);
+ } while ((v = v->next) != vm->boundstart);
+}
+
+/* Implements build_boundary for vertex-only case */
+static void build_boundary_vertex_only(BevelParams *bp, BevVert *bv, bool construct)
+{
+ VMesh *vm = bv->vmesh;
+ EdgeHalf *efirst, *e;
+ BoundVert *v;
+ float co[3];
+
+ BLI_assert(bp->vertex_only);
+
+ e = efirst = &bv->edges[0];
+ do {
+ slide_dist(e, bv->v, e->offset_l, co);
+ if (construct) {
+ v = add_new_bound_vert(bp->mem_arena, vm, co);
+ v->efirst = v->elast = e;
+ e->leftv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ } while ((e = e->next) != efirst);
+
+ calculate_vm_profiles(bp, bv, vm);
+
+ if (construct) {
+ set_bound_vert_seams(bv);
+ if (vm->count == 2)
+ vm->mesh_kind = M_NONE;
+ else if (bp->seg == 1)
+ vm->mesh_kind = M_POLY;
+ else
+ vm->mesh_kind = M_ADJ;
+ }
+}
+
+/* Special case of build_boundary when a single edge is beveled.
+ * The 'width adjust' part of build_boundary has been done already, and
+ * efirst is the first beveled edge at vertex bv. */
+static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf *efirst, bool construct)
+{
+ MemArena *mem_arena = bp->mem_arena;
+ VMesh *vm = bv->vmesh;
+ BoundVert *v;
+ EdgeHalf *e;
+ const float *no;
+ float co[3], d;
+
+ e = efirst;
+ if (bv->edgecount == 2) {
+ /* only 2 edges in, so terminate the edge with an artificial vertex on the unbeveled edge */
+ no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL);
+ offset_in_plane(e, no, true, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = v->ebev = e;
+ e->leftv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL);
+ offset_in_plane(e, no, false, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = e;
+ e->rightv = v;
+ }
+ else {
+ adjust_bound_vert(e->rightv, co);
+ }
+ /* make artifical extra point along unbeveled edge, and form triangle */
+ slide_dist(e->next, bv->v, e->offset_l, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = e->next;
+ e->next->leftv = e->next->rightv = v;
+ /* could use M_POLY too, but tri-fan looks nicer)*/
+ vm->mesh_kind = M_TRI_FAN;
+ set_bound_vert_seams(bv);
+ }
+ else {
+ adjust_bound_vert(e->next->leftv, co);
+ }
+ }
+ else {
+ /* More than 2 edges in. Put on-edge verts on all the other edges
+ * and join with the beveled edge to make a poly or adj mesh,
+ * Because e->prev has offset 0, offset_meet will put co on that edge */
+ /* TODO: should do something else if angle between e and e->prev > 180 */
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e->prev;
+ v->elast = v->ebev = e;
+ e->leftv = v;
+ e->prev->leftv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ e = e->next;
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e->prev;
+ v->elast = e;
+ e->leftv = v;
+ e->prev->rightv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ d = len_v3v3(bv->v->co, co);
+ for (e = e->next; e->next != efirst; e = e->next) {
+ slide_dist(e, bv->v, d, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = e;
+ e->leftv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ }
+ }
+ calculate_vm_profiles(bp, bv, vm);
+
+ if (bv->edgecount >= 3) {
+ /* special case: snap profile to plane of adjacent two edges */
+ v = vm->boundstart;
+ BLI_assert(v->ebev != NULL);
+ move_profile_plane(v, v->efirst, v->next->elast);
+ calculate_profile(bp, v);
+ }
+
+ if (construct) {
+ set_bound_vert_seams(bv);
+
+ if (vm->count == 2 && bv->edgecount == 3) {
+ vm->mesh_kind = M_NONE;
+ }
+ else if (vm->count == 3) {
+ vm->mesh_kind = M_TRI_FAN;
+ }
+ else {
+ vm->mesh_kind = M_POLY;
+ }
+ }
+}
+
+/* Make a circular list of BoundVerts for bv, each of which has the coordinates
+ * of a vertex on the boundary of the beveled vertex bv->v.
+ * This may adjust some EdgeHalf widths, and there might have to be
+ * a subsequent pass to make the widths as consistent as possible.
+ * The first time through, construct will be true and we are making the BoundVerts
+ * and setting up the BoundVert and EdgeHalf pointers appropriately.
+ * For a width consistency path, we just recalculate the coordinates of the
+ * BoundVerts. If the other ends have been (re)built already, then we
+ * copy the offsets from there to match, else we use the ideal (user-specified)
+ * widths.
+ * Also, if construct, decide on the mesh pattern that will be used inside the boundary.
+ * Doesn't make the actual BMVerts */
+static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
+{
+ MemArena *mem_arena = bp->mem_arena;
+ EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eother;
+ BoundVert *v;
+ BevVert *bvother;
+ VMesh *vm;
+ float co[3];
+ int nip, nnip;
+
+ /* Current bevel does nothing if only one edge into a vertex */
+ if (bv->edgecount <= 1)
+ return;
+
+ if (bp->vertex_only) {
+ build_boundary_vertex_only(bp, bv, construct);
+ return;
+ }
+
+ vm = bv->vmesh;
+
+ /* Find a beveled edge to be efirst. Then for each edge, try matching widths to other end. */
+ e = efirst = next_bev(bv, NULL);
+ BLI_assert(e->is_bev);
+ do {
+ eother = find_other_end_edge_half(bp, e, &bvother);
+ if (eother && bvother->visited && bp->offset_type != BEVEL_AMT_PERCENT) {
+ /* try to keep bevel even by matching other end offsets */
+ e->offset_l = eother->offset_r;
+ e->offset_r = eother->offset_l;
+ }
+ else {
+ /* reset to user spec */
+ e->offset_l = e->offset_l_spec;
+ e->offset_r = e->offset_r_spec;
+ }
+ } while ((e = e->next) != efirst);
+
+ if (bv->selcount == 1) {
+ /* special case: only one beveled edge in */
+ build_boundary_terminal_edge(bp, bv, efirst, construct);
+ return;
+ }
+
+ /* Here: there is more than one beveled edge.
+ * We make BoundVerts to connect the sides of the beveled edges.
+ * Non-beveled edges in between will just join to the appropriate juncture point. */
+ e = efirst;
+ do {
+ BLI_assert(e->is_bev);
+ /* Make the BoundVert for the right side of e; other side will be made
+ * when the beveled edge to the left of e is handled.
+ * Analyze edges until next beveled edge.
+ * They are either "in plane" (preceding and subsequent faces are coplanar)
+ * or not. The "non-in-plane" edges effect silhouette and we prefer to slide
+ * along one of those if possible. */
+ nip = nnip = 0; /* counts of in-plane / not-in-plane */
+ enip = eip = NULL; /* representatives of each */
+ for (e2 = e->next; !e2->is_bev; e2 = e2->next) {
+ if (eh_on_plane(e2)) {
+ nip++;
+ eip = e2;
+ }
+ else {
+ nnip++;
+ enip = e2;
+ }
+ }
+ if (nip == 0 && nnip == 0) {
+ offset_meet(e, e2, bv->v, e->fnext, false, co);
+ }
+ else if (nnip > 0) {
+ if (nnip == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) {
+ offset_on_edge_between(bp, e, e2, enip, bv->v, co);
+ }
+ else {
+ offset_meet(e, e2, bv->v, NULL, true, co);
+ }
+ }
+ else {
+ /* nip > 0 and nnip == 0 */
+ if (nip == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) {
+ offset_on_edge_between(bp, e, e2, eip, bv->v, co);
+ }
+ else {
+ offset_meet(e, e2, bv->v, NULL, true, co);
+ }
+ }
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e;
+ v->elast = e2;
+ v->ebev = e2;
+ e->rightv = v;
+ e2->leftv = v;
+ for (e3 = e->next; e3 != e2; e3 = e3->next) {
+ e3->leftv = e3->rightv = v;
+ }
+ }
+ else {
+ adjust_bound_vert(e->rightv, co);
+ }
+ e = e2;
+ } while (e != efirst);
+
+ calculate_vm_profiles(bp, bv, vm);
+
+ if (construct) {
+ set_bound_vert_seams(bv);
+
+ if (vm->count == 2) {
+ vm->mesh_kind = M_NONE;
+ }
+ else if (efirst->seg == 1) {
+ vm->mesh_kind = M_POLY;
+ }
+ else {
+ vm->mesh_kind = M_ADJ;
+ }
+ }
+}
+#endif
+
+#ifdef PRE_275_ALGORITHM
+/* This code was used prior to just before the 2.75 Blender release.
+ * It treated multiple non-beveled edges between beveled ones differently */
+
/* Make a circular list of BoundVerts for bv, each of which has the coordinates
* of a vertex on the boundary of the beveled vertex bv->v.
* This may adjust some EdgeHalf widths, and there might have to be
@@ -1519,7 +1930,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
/* handle only left side of beveled edge e here: next iteration should do right side */
if (e->prev->is_bev) {
BLI_assert(e->prev != e); /* see: wire edge special case */
- offset_meet(e->prev, e, bv->v, e->fprev, co);
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co);
if (construct) {
v = add_new_bound_vert(mem_arena, vm, co);
v->efirst = e->prev;
@@ -1556,7 +1967,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
else {
/* neither e->prev nor e->prev->prev are beveled: make on-edge on e->prev */
- offset_meet(e->prev, e, bv->v, e->fprev, co);
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co);
if (construct) {
v = add_new_bound_vert(mem_arena, vm, co);
v->efirst = e->prev;
@@ -1580,7 +1991,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
else if (e->prev->is_bev) {
/* on-edge meet between e->prev and e */
- offset_meet(e->prev, e, bv->v, e->fprev, co);
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co);
if (construct) {
v = add_new_bound_vert(mem_arena, vm, co);
v->efirst = e->prev;
@@ -1657,6 +2068,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
}
+#endif
/* Do a global pass to try to make offsets as even as possible.
* Consider this graph:
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index a0eddadfe78..7c7c57f3305 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -532,8 +532,8 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
// each <source> will get id like meshName + "map-channel-1"
int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
for (int a = 0; a < num_layers; a++) {
-
- if (!this->export_settings->active_uv_only || a == active_uv_index) {
+ int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, a);
+ if (!this->export_settings->active_uv_only || layer_index == active_uv_index) {
MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index b67ae228b25..a4f5c250b0f 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -1366,7 +1366,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
accentcode = 0;
}
else if (event->utf8_buf[0]) {
- BLI_strncpy_wchar_from_utf8(inserted_text, event->utf8_buf, 2);
+ inserted_text[0] = BLI_str_utf8_as_unicode(event->utf8_buf);
ascii = inserted_text[0];
insert_into_textbuf(obedit, ascii);
accentcode = 0;
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index c4967da2610..84651134107 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -326,7 +326,7 @@ void UI_draw_widget_scroll(struct uiWidgetColors *wcol, const struct rcti *rect,
/* Shortening string helper. */
float UI_text_clip_middle_ex(
struct uiFontStyle *fstyle, char *str, float okwidth, const float minwidth,
- const size_t max_len, const char *rpart_sep);
+ const size_t max_len, const char rpart_sep);
/* Callbacks
*
@@ -750,7 +750,7 @@ void UI_panel_category_draw_all(struct ARegion *ar, const
* as screen/ if ED_KEYMAP_UI is set, or internally in popup functions. */
void UI_region_handlers_add(struct ListBase *handlers);
-void UI_popup_handlers_add(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *popup, const bool accept_dbl_click);
+void UI_popup_handlers_add(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *popup, const char flag);
void UI_popup_handlers_remove(struct ListBase *handlers, uiPopupBlockHandle *popup);
void UI_popup_handlers_remove_all(struct bContext *C, struct ListBase *handlers);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 1eadd259295..e045db8fdd2 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -83,11 +83,11 @@
#define B_NOP -1
-/*
- * a full doc with API notes can be found in bf-blender/trunk/blender/doc/guides/interface_API.txt
+/**
+ * a full doc with API notes can be found in 'blender/doc/guides/interface_API.txt'
*
- * uiBlahBlah() external function
- * ui_blah_blah() internal function
+ * `uiBlahBlah()` external function.
+ * `ui_blah_blah()` internal function.
*/
static void ui_but_free(const bContext *C, uiBut *but);
@@ -1100,13 +1100,16 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
return found;
}
-/* this goes in a seemingly weird pattern:
+/**
+ * This goes in a seemingly weird pattern:
*
+ * <pre>
* 4
* 5 6
* 1 2
* 7 8
* 3
+ * </pre>
*
* but it's actually quite logical. It's designed to be 'upwards compatible'
* for muscle memory so that the menu item locations are fixed and don't move
@@ -3098,13 +3101,13 @@ void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3])
/**
* \brief ui_def_but is the function that draws many button types
*
- * \param x,y The lower left hand corner of the button (X axis)
- * \param width,height The size of the button.
+ * \param x, y: The lower left hand corner of the button (X axis)
+ * \param width, height: The size of the button.
*
* for float buttons:
- * - \a a1 Click Step (how much to change the value each click)
- * - \a a2 Number of decimal point values to display. 0 defaults to 3 (0.000)
- * 1,2,3, and a maximum of 4, all greater values will be clamped to 4.
+ * \param a1: Click Step (how much to change the value each click)
+ * \param a2: Number of decimal point values to display. 0 defaults to 3 (0.000)
+ * 1,2,3, and a maximum of 4, all greater values will be clamped to 4.
*/
static uiBut *ui_def_but(
uiBlock *block, int type, int retval, const char *str,
@@ -4321,8 +4324,11 @@ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxle
}
-/* arg is user value, searchfunc and handlefunc both get it as arg */
-/* if active set, button opens with this item visible and selected */
+/**
+ * \param sfunc, bfunc: both get it as \a arg.
+ * \param arg: user value,
+ * \param active: when set, button opens with this item visible and selected.
+ */
void UI_but_func_search_set(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc, void *active)
{
but->search_func = sfunc;
@@ -4391,8 +4397,10 @@ static void operator_enum_call_cb(struct bContext *UNUSED(C), void *but, void *a
}
}
-/* Same parameters as for uiDefSearchBut, with additional operator type and properties, used by callback
- * to call again the right op with the right options (properties values). */
+/**
+ * Same parameters as for uiDefSearchBut, with additional operator type and properties, used by callback
+ * to call again the right op with the right options (properties values).
+ */
uiBut *uiDefSearchButO_ptr(
uiBlock *block, wmOperatorType *ot, IDProperty *properties,
void *arg, int retval, int icon, int maxlen, int x, int y,
@@ -4415,7 +4423,8 @@ uiBut *uiDefSearchButO_ptr(
return but;
}
-/* push a new event onto event queue to activate the given button
+/**
+ * push a new event onto event queue to activate the given button
* (usually a text-field) upon entering a popup
*/
void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but)
@@ -4448,7 +4457,19 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
if (type == BUT_GET_LABEL) {
if (but->str) {
- tmp = BLI_strdup(but->str);
+ const char *str_sep;
+ size_t str_len;
+
+ if ((but->flag & UI_BUT_HAS_SEP_CHAR) &&
+ (str_sep = strrchr(but->str, UI_SEP_CHAR)))
+ {
+ str_len = (str_sep - but->str);
+ }
+ else {
+ str_len = strlen(but->str);
+ }
+
+ tmp = BLI_strdupn(but->str, str_len);
}
else {
type = BUT_GET_RNA_LABEL; /* Fail-safe solution... */
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 44e06bab4ab..4f77185fb8f 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -379,12 +379,11 @@ void UI_OT_eyedropper_color(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
-/* Data Dropper
- *
- * note: datadropper is only internal name to avoid confusion in this file
- */
+/* Data Dropper */
/** \name Eyedropper (ID data-blocks)
+ *
+ * \note: datadropper is only internal name to avoid confusion in this file.
* \{ */
typedef struct DataDropper {
@@ -653,12 +652,11 @@ void UI_OT_eyedropper_id(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
-/* Depth Dropper
- *
- * note: depthdropper is only internal name to avoid confusion in this file
- */
+/* Depth Dropper */
/** \name Eyedropper (Depth)
+ *
+ * \note: depthdropper is only internal name to avoid confusion in this file.
* \{ */
typedef struct DepthDropper {
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 83198ae857e..4ec990bb832 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -198,7 +198,7 @@ static void ui_selectcontext_apply(
#define IS_ALLSELECT_EVENT(event) ((event)->alt != 0)
-/* just show a tinted color so users know its activated */
+/** just show a tinted color so users know its activated */
#define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE
#endif /* USE_ALLSELECT */
@@ -206,15 +206,18 @@ static void ui_selectcontext_apply(
#ifdef USE_DRAG_MULTINUM
-/* how far to drag before we check for gesture direction (in pixels),
+/**
+ * how far to drag before we check for gesture direction (in pixels),
* note: half the height of a button is about right... */
#define DRAG_MULTINUM_THRESHOLD_DRAG_X (UI_UNIT_Y / 4)
-/* how far to drag horizontally before we stop checking which buttons the gesture spans (in pixels),
+/**
+ * how far to drag horizontally before we stop checking which buttons the gesture spans (in pixels),
* locking down the buttons so we can drag freely without worrying about vertical movement. */
#define DRAG_MULTINUM_THRESHOLD_DRAG_Y (UI_UNIT_Y / 4)
-/* how strict to be when detecting a vertical gesture, [0.5 == sloppy], [0.9 == strict], (unsigned dot-product)
+/**
+ * how strict to be when detecting a vertical gesture, [0.5 == sloppy], [0.9 == strict], (unsigned dot-product)
* note: we should be quite strict here, since doing a vertical gesture by accident should be avoided,
* however with some care a user should be able to do a vertical movement without *missing*. */
#define DRAG_MULTINUM_THRESHOLD_VERTICAL (0.75f)
@@ -1626,10 +1629,11 @@ static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data,
ar_prev = CTX_wm_region(C);
CTX_wm_region_set(C, data->region);
- WM_event_add_ui_handler(C, &data->window->modalhandlers,
- ui_handler_region_drag_toggle,
- ui_handler_region_drag_toggle_remove,
- drag_info, false);
+ WM_event_add_ui_handler(
+ C, &data->window->modalhandlers,
+ ui_handler_region_drag_toggle,
+ ui_handler_region_drag_toggle_remove,
+ drag_info, WM_HANDLER_BLOCKING);
CTX_wm_region_set(C, ar_prev);
}
@@ -1942,6 +1946,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
if (data->str) MEM_freeN(data->str);
data->str = data->origstr;
+ data->origstr = NULL;
data->value = data->origvalue;
copy_v3_v3(data->vec, data->origvec);
/* postpone clearing origdata */
@@ -2085,7 +2090,6 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
#endif
if (data->cancel) {
- data->origstr = NULL;
data->origvalue = 0.0;
zero_v3(data->origvec);
}
@@ -2350,15 +2354,17 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
}
-/* ************************ password text ******************************
+/**
+ * Password Text
+ * =============
*
* Functions to convert password strings that should not be displayed
- * to asterisk representation (e.g. mysecretpasswd -> *************)
+ * to asterisk representation (e.g. 'mysecretpasswd' -> '*************')
*
* It converts every UTF-8 character to an asterisk, and also remaps
* the cursor position and selection start/end.
*
- * Note: remaping is used, because password could contain UTF-8 characters.
+ * \note: remaping is used, because password could contain UTF-8 characters.
*
*/
@@ -2558,7 +2564,8 @@ static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data,
ui_but_update(but);
}
-/* this is used for both utf8 and ascii, its meant to be used for single keys,
+/**
+ * This is used for both utf8 and ascii, its meant to be used for single keys,
* notice the buffer is either copied or not, so its not suitable for pasting in
* - campbell */
static bool ui_textedit_type_buf(
@@ -7540,7 +7547,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
if (!(but->block->handle && but->block->handle->popup)) {
if (button_modal_state(state)) {
if (!button_modal_state(data->state))
- WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data, false);
+ WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data, 0);
}
else {
if (button_modal_state(data->state)) {
@@ -8424,13 +8431,14 @@ static void ui_handle_button_return_submenu(bContext *C, const wmEvent *event, u
/* ************************* menu handling *******************************/
-/* function used to prevent loosing the open menu when using nested pulldowns,
+/**
+ * Function used to prevent loosing the open menu when using nested pulldowns,
* when moving mouse towards the pulldown menu over other buttons that could
* steal the highlight from the current button, only checks:
*
* - while mouse moves in triangular area defined old mouse position and
- * left/right side of new menu
- * - only for 1 second
+ * left/right side of new menu.
+ * - only for 1 second.
*/
static void ui_mouse_motion_towards_init_ex(uiPopupBlockHandle *menu, const int xy[2], const bool force)
@@ -9855,12 +9863,12 @@ static void ui_popup_handler_remove(bContext *C, void *userdata)
void UI_region_handlers_add(ListBase *handlers)
{
WM_event_remove_ui_handler(handlers, ui_region_handler, ui_region_handler_remove, NULL, false);
- WM_event_add_ui_handler(NULL, handlers, ui_region_handler, ui_region_handler_remove, NULL, false);
+ WM_event_add_ui_handler(NULL, handlers, ui_region_handler, ui_region_handler_remove, NULL, 0);
}
-void UI_popup_handlers_add(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup, const bool accept_dbl_click)
+void UI_popup_handlers_add(bContext *C, ListBase *handlers, uiPopupBlockHandle *popup, const char flag)
{
- WM_event_add_ui_handler(C, handlers, ui_popup_handler, ui_popup_handler_remove, popup, accept_dbl_click);
+ WM_event_add_ui_handler(C, handlers, ui_popup_handler, ui_popup_handler_remove, popup, flag);
}
void UI_popup_handlers_remove(ListBase *handlers, uiPopupBlockHandle *popup)
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index f6e0273560e..279d72819be 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -2729,7 +2729,8 @@ uiLayout *uiLayoutBox(uiLayout *layout)
return (uiLayout *)ui_layout_box(layout, UI_BTYPE_ROUNDBOX);
}
-/* Check all buttons defined in this layout, and set any button flagged as UI_BUT_LIST_ITEM as active/selected.
+/**
+ * Check all buttons defined in this layout, and set any button flagged as UI_BUT_LIST_ITEM as active/selected.
* Needed to handle correctly text colors of active (selected) list item.
*/
void ui_layout_list_set_labels_active(uiLayout *layout)
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 770bbc12853..88da91acc36 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -763,10 +763,12 @@ static void UI_OT_editsource(wmOperatorType *ot)
}
/* ------------------------------------------------------------------------- */
-/* EditTranslation utility funcs and operator,
- * Note: this includes utility functions and button matching checks.
- * this only works in conjunction with a py operator! */
+/**
+ * EditTranslation utility funcs and operator,
+ * \note: this includes utility functions and button matching checks.
+ * this only works in conjunction with a py operator!
+ */
static void edittranslation_find_po_file(const char *root, const char *uilng, char *path, const size_t maxlen)
{
char tstr[32]; /* Should be more than enough! */
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 4b0585c34b3..665266edb9f 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -210,8 +210,9 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar)
}
-/* XXX Disabled paneltab handling for now. Old 2.4x feature, *DO NOT* confuse it with new tool tabs in 2.70. ;)
- * See also T41704.
+/**
+ * XXX Disabled paneltab handling for now. Old 2.4x feature, *DO NOT* confuse it with new tool tabs in 2.70. ;)
+ * See also T41704.
*/
/* #define UI_USE_PANELTAB */
@@ -568,6 +569,8 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
rcti headrect;
rctf itemrect;
int ofsx;
+ const bool is_closed_x = (panel->flag & PNL_CLOSEDX) ? true : false;
+ const bool is_closed_y = (panel->flag & PNL_CLOSEDY) ? true : false;
if (panel->paneltab) return;
if (panel->type && (panel->type->flag & PNL_NO_HEADER)) return;
@@ -580,7 +583,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
{
float minx = rect->xmin;
- float maxx = rect->xmax;
+ float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax;
float y = headrect.ymax;
glEnable(GL_BLEND);
@@ -595,8 +598,11 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
}
else if (!(panel->runtime_flag & PNL_FIRST)) {
/* draw embossed separator */
- minx += 5.0f / block->aspect;
- maxx -= 5.0f / block->aspect;
+
+ if (is_closed_x == false) {
+ minx += 5.0f / block->aspect;
+ maxx -= 5.0f / block->aspect;
+ }
glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
fdrawline(minx, y, maxx, y);
@@ -623,7 +629,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
}
/* horizontal title */
- if (!(panel->flag & PNL_CLOSEDX)) {
+ if (is_closed_x == false) {
ui_draw_aligned_panel_header(style, block, &headrect, 'h');
/* itemrect smaller */
@@ -639,9 +645,10 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
/* if the panel is minimized vertically:
* (------)
*/
- if (panel->flag & PNL_CLOSEDY) {
+ if (is_closed_y) {
+ /* skip */
}
- else if (panel->flag & PNL_CLOSEDX) {
+ else if (is_closed_x) {
/* draw vertical title */
ui_draw_aligned_panel_header(style, block, &headrect, 'v');
}
@@ -688,9 +695,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
BLI_rctf_scale(&itemrect, 0.35f);
- if (panel->flag & PNL_CLOSEDY)
+ if (is_closed_y)
ui_draw_tria_rect(&itemrect, 'h');
- else if (panel->flag & PNL_CLOSEDX)
+ else if (is_closed_x)
ui_draw_tria_rect(&itemrect, 'h');
else
ui_draw_tria_rect(&itemrect, 'v');
@@ -737,11 +744,13 @@ typedef struct PanelSort {
Panel *pa, *orig;
} PanelSort;
-/* note about sorting;
+/**
+ * \note about sorting;
* the sortorder has a lower value for new panels being added.
* however, that only works to insert a single panel, when more new panels get
* added the coordinates of existing panels and the previously stored to-be-inserted
- * panels do not match for sorting */
+ * panels do not match for sorting
+ */
static int find_leftmost_panel(const void *a1, const void *a2)
{
@@ -1285,7 +1294,7 @@ static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was
C, &win->modalhandlers,
ui_panel_drag_collapse_handler,
ui_panel_drag_collapse_handler_remove,
- dragcol_data, false);
+ dragcol_data, 0);
}
/* this function is supposed to call general window drawing too */
@@ -2098,7 +2107,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
data = MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData");
pa->activedata = data;
- WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, false);
+ WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, 0);
}
if (ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG))
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 3f323de131b..9835f0885b6 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -70,8 +70,9 @@
#include "interface_intern.h"
-#define MENU_TOP 8
+#define MENU_TOP (int)(8 * UI_DPI_FAC)
#define MENU_PADDING (int)(0.2f * UI_UNIT_Y)
+#define MENU_BORDER (int)(0.3f * U.widget_unit)
static int rna_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int direction)
{
@@ -827,8 +828,8 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr
{
/* thumbnail preview */
if (data->preview) {
- int butw = BLI_rcti_size_x(&data->bbox) / data->prv_cols;
- int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / data->prv_rows;
+ int butw = (BLI_rcti_size_x(&data->bbox) - 2 * MENU_BORDER) / data->prv_cols;
+ int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_BORDER) / data->prv_rows;
int row, col;
*r_rect = data->bbox;
@@ -836,10 +837,10 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr
col = itemnr % data->prv_cols;
row = itemnr / data->prv_cols;
- r_rect->xmin += col * butw;
+ r_rect->xmin += MENU_BORDER + (col * butw);
r_rect->xmax = r_rect->xmin + butw;
- r_rect->ymax = data->bbox.ymax - MENU_TOP - (row * buth);
+ r_rect->ymax -= MENU_BORDER + (row * buth);
r_rect->ymin = r_rect->ymax - buth;
}
/* list view */
@@ -1159,25 +1160,27 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
/* compute position */
if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
- const int margin = UI_POPUP_MARGIN;
+ const int margin_x = UI_POPUP_MARGIN;
+ const int margin_y = MENU_TOP;
+ const int search_but_h = BLI_rctf_size_y(&but->rect) + 10;
/* this case is search menu inside other menu */
/* we copy region size */
ar->winrct = butregion->winrct;
/* widget rect, in region coords */
- data->bbox.xmin = margin;
- data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - margin;
+ data->bbox.xmin = margin_x;
+ data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - margin_x;
/* Do not use shadow width for height, gives insane margin with big shadows, and issue T41548 with small ones */
- data->bbox.ymin = 8 * UI_DPI_FAC;
- data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - 8 * UI_DPI_FAC;
+ data->bbox.ymin = margin_y;
+ data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - margin_y;
/* check if button is lower half */
if (but->rect.ymax < BLI_rctf_cent_y(&but->block->rect)) {
- data->bbox.ymin += BLI_rctf_size_y(&but->rect);
+ data->bbox.ymin += search_but_h;
}
else {
- data->bbox.ymax -= BLI_rctf_size_y(&but->rect);
+ data->bbox.ymax -= search_but_h;
}
}
else {
@@ -2617,7 +2620,7 @@ uiPopupBlockHandle *ui_popup_menu_create(
if (!but) {
handle->popup = true;
- UI_popup_handlers_add(C, &window->modalhandlers, handle, false);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
WM_event_add_mousemove(C);
}
@@ -2679,7 +2682,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPUP, pup);
menu->popup = true;
- UI_popup_handlers_add(C, &window->modalhandlers, menu, false);
+ UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
WM_event_add_mousemove(C);
MEM_freeN(pup);
@@ -2805,7 +2808,9 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie)
menu->popup = true;
menu->towardstime = PIL_check_seconds_timer();
- UI_popup_handlers_add(C, &window->modalhandlers, menu, true);
+ UI_popup_handlers_add(
+ C, &window->modalhandlers,
+ menu, WM_HANDLER_ACCEPT_DBL_CLICK);
WM_event_add_mousemove(C);
MEM_freeN(pie);
@@ -2997,7 +3002,7 @@ void UI_popup_block_invoke_ex(bContext *C, uiBlockCreateFunc func, void *arg, co
handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
handle->opcontext = opcontext;
- UI_popup_handlers_add(C, &window->modalhandlers, handle, false);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
WM_event_add_mousemove(C);
}
@@ -3020,7 +3025,7 @@ void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc po
handle->cancel_func = cancel_func;
// handle->opcontext = opcontext;
- UI_popup_handlers_add(C, &window->modalhandlers, handle, false);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
WM_event_add_mousemove(C);
}
@@ -3039,18 +3044,21 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int
handle->cancel_func = confirm_cancel_operator;
handle->opcontext = opcontext;
- UI_popup_handlers_add(C, &window->modalhandlers, handle);
+ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
WM_event_add_mousemove(C);
}
#endif
void UI_popup_block_close(bContext *C, uiBlock *block)
{
- if (block->handle) {
- wmWindow *win = CTX_wm_window(C);
+ wmWindow *win = CTX_wm_window(C);
+
+ /* check window before 'block->handle' incase the
+ * popup execution closed the window and freed the block. see T44688. */
- /* if loading new .blend while popup is open, window will be NULL */
- if (win) {
+ /* if loading new .blend while popup is open, window will be NULL */
+ if (win) {
+ if (block->handle) {
UI_popup_handlers_remove(&win->modalhandlers, block->handle);
ui_popup_block_free(C, block->handle);
}
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 4b683f3fcc2..10575fcbc54 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -64,7 +64,7 @@
/* style + theme + layout-engine = UI */
-/*
+/**
* This is a complete set of layout rules, the 'state' of the Layout
* Engine. Multiple styles are possible, defined via C or Python. Styles
* get a name, and will typically get activated per region type, like
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 7ed3c25768c..e6e8a96dd8d 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -190,10 +190,10 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
/* preview thumbnails */
if (template.prv_rows > 0 && template.prv_cols > 0) {
int w = 4 * U.widget_unit * template.prv_cols;
- int h = 4 * U.widget_unit * template.prv_rows + U.widget_unit;
+ int h = 5 * U.widget_unit * template.prv_rows;
/* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL);
but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y,
template.prv_rows, template.prv_cols, "");
@@ -366,7 +366,8 @@ static const char *template_id_browse_tip(StructRNA *type)
return N_("Browse ID data to be linked");
}
-/* Return a type-based i18n context, needed e.g. by "New" button.
+/**
+ * \return a type-based i18n context, needed e.g. by "New" button.
* In most languages, this adjective takes different form based on gender of type name...
*/
#ifdef WITH_INTERNATIONAL
@@ -692,7 +693,8 @@ void uiTemplateIDPreview(
/************************ ID Chooser Template ***************************/
-/* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use
+/**
+ * This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use
*
* - propname: property identifier for property that ID-pointer gets stored to
* - proptypename: property identifier for property used to determine the type of ID-pointer that can be used
@@ -752,7 +754,8 @@ void uiTemplateAnyID(
/* ---------- */
-/* This is creating/editing RNA-Paths
+/**
+ * This is creating/editing RNA-Paths
*
* - ptr: struct which holds the path property
* - propname: property identifier for property that path gets stored to
@@ -1670,7 +1673,7 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem)
int x, y;
/* XXX hardcoded size to 5 units */
const int w = UI_UNIT_X * 5;
- const int h = args.show_labels ? (int)(6.25f * UI_UNIT_Y) : UI_UNIT_Y * 5;
+ const int h = args.show_labels ? 6 * UI_UNIT_Y : UI_UNIT_Y * 5;
x = (a % 8) * w;
y = (a / 8) * h;
@@ -2483,10 +2486,10 @@ static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
/* see view3d_header.c */
}
-/* TODO:
- * - for now, grouping of layers is determined by dividing up the length of
- * the array of layer bitflags */
-
+/**
+ * \todo for now, grouping of layers is determined by dividing up the length of
+ * the array of layer bitflags
+ */
void uiTemplateLayers(
uiLayout *layout, PointerRNA *ptr, const char *propname,
PointerRNA *used_ptr, const char *used_propname, int active_layer)
@@ -2627,10 +2630,11 @@ void uiTemplateGameStates(
/************************* List Template **************************/
-static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout,
- struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
- struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
- int UNUSED(index), int UNUSED(flt_flag))
+static void uilist_draw_item_default(
+ struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout,
+ struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
+ struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
+ int UNUSED(index), int UNUSED(flt_flag))
{
PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index fb7b319b720..8190df678e2 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -65,9 +65,9 @@
#define ICON_SIZE_FROM_BUTRECT(rect) (0.8f * BLI_rcti_size_y(rect))
/* ************** widget base functions ************** */
-/*
+/**
* - in: roundbox codes for corner types and radius
- * - return: array of [size][2][x,y] points, the edges of the roundbox, + UV coords
+ * - return: array of `[size][2][x, y]` points, the edges of the roundbox, + UV coords
*
* - draw black box with alpha 0 on exact button boundbox
* - for every AA step:
@@ -100,14 +100,14 @@ typedef struct uiWidgetBase {
float inner_v[WIDGET_SIZE_MAX][2];
float inner_uv[WIDGET_SIZE_MAX][2];
- bool inner, outline, emboss, shadedir;
+ bool draw_inner, draw_outline, draw_emboss, draw_shadedir;
uiWidgetTrias tria1;
uiWidgetTrias tria2;
} uiWidgetBase;
-/* uiWidgetType: for time being only for visual appearance,
+/** uiWidgetType: for time being only for visual appearance,
* later, a handling callback can be added too
*/
typedef struct uiWidgetType {
@@ -237,10 +237,10 @@ static void widget_init(uiWidgetBase *wtb)
wtb->tria1.tot = 0;
wtb->tria2.tot = 0;
- wtb->inner = 1;
- wtb->outline = 1;
- wtb->emboss = 1;
- wtb->shadedir = 1;
+ wtb->draw_inner = true;
+ wtb->draw_outline = true;
+ wtb->draw_emboss = true;
+ wtb->draw_shadedir = true;
}
/* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
@@ -647,7 +647,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glEnable(GL_BLEND);
/* backdrop non AA */
- if (wtb->inner) {
+ if (wtb->draw_inner) {
if (wcol->shaded == 0) {
if (wcol->alpha_check) {
float inner_v_half[WIDGET_SIZE_MAX][2];
@@ -713,7 +713,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glShadeModel(GL_SMOOTH);
for (a = 0; a < wtb->totvert; a++, col_pt += 4) {
- round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->shadedir]);
+ round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]);
}
glEnableClientState(GL_VERTEX_ARRAY);
@@ -729,7 +729,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
}
/* for each AA step */
- if (wtb->outline) {
+ if (wtb->draw_outline) {
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
float triangle_strip_emboss[WIDGET_SIZE_MAX * 2][2]; /* only for emboss */
@@ -740,7 +740,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
- if (wtb->emboss) {
+ if (wtb->draw_emboss) {
widget_verts_to_triangle_strip_open(wtb, wtb->halfwayvert, triangle_strip_emboss);
}
@@ -758,7 +758,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
/* emboss bottom shadow */
- if (wtb->emboss) {
+ if (wtb->draw_emboss) {
UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss);
if (emboss[3]) {
@@ -929,7 +929,8 @@ static void ui_text_clip_give_next_off(uiBut *but, const char *str)
but->ofs += bytes;
}
-/* Helper.
+/**
+ * Helper.
* This func assumes things like kerning handling have already been handled!
* Return the length of modified (right-clipped + ellipsis) string.
*/
@@ -969,7 +970,7 @@ static void ui_text_clip_right_ex(
*/
float UI_text_clip_middle_ex(
uiFontStyle *fstyle, char *str, float okwidth, const float minwidth,
- const size_t max_len, const char *rpart_sep)
+ const size_t max_len, const char rpart_sep)
{
float strwidth;
@@ -1002,7 +1003,7 @@ float UI_text_clip_middle_ex(
size_t final_lpart_len;
if (rpart_sep) {
- rpart = strstr(str, rpart_sep);
+ rpart = strrchr(str, rpart_sep);
if (rpart) {
rpart_len = strlen(rpart);
@@ -1084,14 +1085,14 @@ static void ui_text_clip_middle(uiFontStyle *fstyle, uiBut *but, const rcti *rec
const float minwidth = (float)(UI_DPI_ICON_SIZE) / but->block->aspect * 2.0f;
but->ofs = 0;
- but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, NULL);
+ but->strwidth = UI_text_clip_middle_ex(fstyle, but->drawstr, okwidth, minwidth, max_len, '\0');
}
/**
* Like ui_text_clip_middle(), but protect/preserve at all cost the right part of the string after sep.
* Useful for strings with shortcuts (like 'AVeryLongFooBarLabelForMenuEntry|Ctrl O' -> 'AVeryLong...MenuEntry|Ctrl O').
*/
-static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char *rsep)
+static void ui_text_clip_middle_protect_right(uiFontStyle *fstyle, uiBut *but, const rcti *rect, const char rsep)
{
/* No margin for labels! */
const int border = ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_MENU) ? 0 : (int)(UI_TEXT_CLIP_MARGIN + 0.5f);
@@ -1525,17 +1526,14 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* Big previews with optional text label below */
if (but->flag & UI_BUT_ICON_PREVIEW && ui_block_is_menu(but->block)) {
const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE;
- const int icon_size_i = BLI_rcti_size_y(rect);
- float icon_size, text_size;
+ int icon_size = BLI_rcti_size_y(rect);
+ int text_size = 0;
/* This is a bit britle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */
- if (icon_size_i > BLI_rcti_size_x(rect)) {
- icon_size = 0.8f * (float)icon_size_i;
- text_size = 0.2f * (float)icon_size_i;
- }
- else {
- icon_size = (float)icon_size_i;
- text_size = 0.0f;
+ if (icon_size > BLI_rcti_size_x(rect)) {
+ /* button is not square, it has extra height for label */
+ text_size = UI_UNIT_Y;
+ icon_size -= text_size;
}
/* draw icon in rect above the space reserved for the label */
@@ -1544,9 +1542,12 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
widget_draw_preview(icon, alpha, rect);
glDisable(GL_BLEND);
- /* offset rect to draw label in*/
+ /* offset rect to draw label in */
rect->ymin -= text_size;
rect->ymax -= icon_size;
+
+ /* vertically centering text */
+ rect->ymin += UI_UNIT_Y / 2;
}
/* Icons on the left with optional text label on the right */
else if (but->flag & UI_HAS_ICON || show_menu_icon) {
@@ -1607,9 +1608,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
ui_text_clip_right_label(fstyle, but, rect);
}
- else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == UI_BTYPE_BUT)) {
+ else if (but->flag & UI_BUT_HAS_SEP_CHAR) {
/* Clip middle, but protect in all case right part containing the shortcut, if any. */
- ui_text_clip_middle_protect_right(fstyle, but, rect, "|");
+ ui_text_clip_middle_protect_right(fstyle, but, rect, UI_SEP_CHAR);
}
else {
ui_text_clip_middle(fstyle, but, rect);
@@ -1626,17 +1627,6 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* *********************** widget types ************************************* */
-
-/* uiWidgetStateColors
- * char inner_anim[4];
- * char inner_anim_sel[4];
- * char inner_key[4];
- * char inner_key_sel[4];
- * char inner_driven[4];
- * char inner_driven_sel[4];
- * float blend;
- */
-
static struct uiWidgetStateColors wcol_state_colors = {
{115, 190, 76, 255},
{90, 166, 51, 255},
@@ -1647,18 +1637,6 @@ static struct uiWidgetStateColors wcol_state_colors = {
0.5f, 0.0f
};
-/* uiWidgetColors
- * char outline[3];
- * char inner[4];
- * char inner_sel[4];
- * char item[3];
- * char text[3];
- * char text_sel[3];
- *
- * short shaded;
- * float shadetop, shadedown;
- */
-
static struct uiWidgetColors wcol_num = {
{25, 25, 25, 255},
{180, 180, 180, 255},
@@ -2224,7 +2202,7 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
widget_softshadow(rect, roundboxalign, 0.25f * U.widget_unit);
round_box_edges(&wtb, roundboxalign, rect, 0.25f * U.widget_unit);
- wtb.emboss = 0;
+ wtb.draw_emboss = false;
widgetbase_draw(&wtb, wcol);
glDisable(GL_BLEND);
@@ -2762,7 +2740,7 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
else
rad = 0.5f * BLI_rcti_size_x(rect);
- wtb.shadedir = (horizontal) ? 1 : 0;
+ wtb.draw_shadedir = (horizontal) ? true : false;
/* draw back part, colors swapped and shading inverted */
if (horizontal)
@@ -2791,11 +2769,11 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
}
/* draw */
- wtb.emboss = 0; /* only emboss once */
+ wtb.draw_emboss = false; /* only emboss once */
/* exception for progress bar */
if (state & UI_SCROLL_NO_OUTLINE) {
- SWAP(bool, outline, wtb.outline);
+ SWAP(bool, outline, wtb.draw_outline);
}
round_box_edges(&wtb, UI_CNR_ALL, slider, rad);
@@ -2818,7 +2796,7 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
widgetbase_draw(&wtb, wcol);
if (state & UI_SCROLL_NO_OUTLINE) {
- SWAP(bool, outline, wtb.outline);
+ SWAP(bool, outline, wtb.draw_outline);
}
}
}
@@ -2945,7 +2923,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
toffs = offs * 0.75f;
round_box_edges(&wtb, roundboxalign, rect, offs);
- wtb.outline = 0;
+ wtb.draw_outline = false;
widgetbase_draw(&wtb, wcol);
/* draw left/right parts only when not in text editing */
@@ -2970,7 +2948,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
/* left part of slider, always rounded */
rect1.xmax = rect1.xmin + ceil(offs + U.pixelsize);
round_box_edges(&wtb1, roundboxalign & ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT), &rect1, offs);
- wtb1.outline = 0;
+ wtb1.draw_outline = false;
widgetbase_draw(&wtb1, wcol);
/* right part of slider, interpolate roundness */
@@ -2995,8 +2973,8 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
}
/* outline */
- wtb.outline = 1;
- wtb.inner = 0;
+ wtb.draw_outline = true;
+ wtb.draw_inner = false;
widgetbase_draw(&wtb, wcol);
/* add space at either side of the button so text aligns with numbuttons (which have arrow icons) */
@@ -3088,7 +3066,7 @@ static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, i
float rad;
widget_init(&wtb);
- wtb.outline = 0;
+ wtb.draw_outline = false;
/* rounded */
rad = 0.5f * BLI_rcti_size_y(rect);
@@ -3203,7 +3181,7 @@ static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta
widget_init(&wtb);
/* not rounded, no outline */
- wtb.outline = 0;
+ wtb.draw_outline = false;
round_box_edges(&wtb, 0, rect, 0.0f);
widgetbase_draw(&wtb, wcol);
@@ -3217,7 +3195,7 @@ static void widget_menu_radial_itembut(uiBut *but, uiWidgetColors *wcol, rcti *r
widget_init(&wtb);
- wtb.emboss = 0;
+ wtb.draw_emboss = false;
rad = 0.5f * BLI_rcti_size_y(rect);
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
@@ -3240,7 +3218,7 @@ static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta
widget_init(&wtb);
/* rounded, but no outline */
- wtb.outline = 0;
+ wtb.draw_outline = false;
rad = 0.2f * U.widget_unit;
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
@@ -3393,8 +3371,8 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
/* outline */
round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
- wtb.outline = 1;
- wtb.inner = 0;
+ wtb.draw_outline = true;
+ wtb.draw_inner = false;
widgetbase_draw(&wtb, &wt->wcol);
}
@@ -4099,7 +4077,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
const float minwidth = (float)(UI_DPI_ICON_SIZE);
BLI_strncpy(drawstr, name, sizeof(drawstr));
- UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL);
+ UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
glColor4ubv((unsigned char *)wt->wcol.text);
UI_fontstyle_draw(fstyle, rect, drawstr);
@@ -4134,39 +4112,31 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
{
- rcti trect = *rect, bg_rect;
+ rcti trect = *rect;
+ const float text_size = UI_UNIT_Y;
float font_dims[2] = {0.0f, 0.0f};
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
+ /* drawing button background */
wt->state(wt, state);
wt->draw(&wt->wcol, rect, 0, 0);
+ /* draw icon in rect above the space reserved for the label */
+ rect->ymin += text_size;
glEnable(GL_BLEND);
widget_draw_preview(iconid, 1.0f, rect);
+ glDisable(GL_BLEND);
BLF_width_and_height(fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
/* text rect */
trect.xmin += 0;
- trect.xmax = trect.xmin + font_dims[0] + 10;
- trect.ymin += 10;
+ trect.xmax = trect.xmin + font_dims[0] + U.widget_unit / 2;
+ trect.ymin += U.widget_unit / 2;
trect.ymax = trect.ymin + font_dims[1];
if (trect.xmax > rect->xmax - PREVIEW_PAD)
trect.xmax = rect->xmax - PREVIEW_PAD;
- bg_rect = trect;
- bg_rect.xmin = rect->xmin + PREVIEW_PAD;
- bg_rect.ymin = rect->ymin + PREVIEW_PAD;
- bg_rect.xmax = rect->xmax - PREVIEW_PAD;
- bg_rect.ymax += PREVIEW_PAD / 2;
-
- if (bg_rect.xmax > rect->xmax - PREVIEW_PAD)
- bg_rect.xmax = rect->xmax - PREVIEW_PAD;
-
- glColor4ubv((unsigned char *)wt->wcol_theme->inner_sel);
- glRecti(bg_rect.xmin, bg_rect.ymin, bg_rect.xmax, bg_rect.ymax);
- glDisable(GL_BLEND);
-
{
char drawstr[UI_MAX_DRAW_STR];
const float okwidth = (float)BLI_rcti_size_x(&trect);
@@ -4174,7 +4144,7 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
const float minwidth = (float)(UI_DPI_ICON_SIZE);
BLI_strncpy(drawstr, name, sizeof(drawstr));
- UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, NULL);
+ UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');
glColor4ubv((unsigned char *)wt->wcol.text);
UI_fontstyle_draw(fstyle, &trect, drawstr);
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index ed61518de6b..617a3e1bdc6 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -824,8 +824,9 @@ static void ui_theme_space_init_handles_color(ThemeSpace *theme_space)
rgba_char_args_set(theme_space->act_spline, 0xdb, 0x25, 0x12, 255);
}
-/* initialize default theme
- * Note: when you add new colors, created & saved themes need initialized
+/**
+ * initialize default theme
+ * \note: when you add new colors, created & saved themes need initialized
* use function below, init_userdef_do_versions()
*/
void ui_theme_init_default(void)
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 7cdf6078c4f..37b14318c16 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -322,7 +322,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
if (do_init) {
float panelzoom = (style) ? style->panelzoom : 1.0f;
- float scrolw = v2d->scroll & V2D_SCROLL_RIGHT ? V2D_SCROLL_WIDTH : 0.0f;
+ float scrolw = (v2d->scroll & V2D_SCROLL_RIGHT) ? V2D_SCROLL_WIDTH : 0.0f;
v2d->tot.xmin = 0.0f;
v2d->tot.xmax = winx - scrolw;
@@ -363,8 +363,9 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
}
-/* Ensure View2D rects remain in a viable configuration
- * - cur is not allowed to be: larger than max, smaller than min, or outside of tot
+/**
+ * Ensure View2D rects remain in a viable configuration
+ * 'cur' is not allowed to be: larger than max, smaller than min, or outside of 'tot'
*/
// XXX pre2.5 -> this used to be called test_view2d()
static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers)
@@ -844,7 +845,8 @@ void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
}
-/* Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot)
+/**
+ * Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot)
* This does not take into account if zooming the view on an axis will improve the view (if allowed)
*/
void UI_view2d_curRect_reset(View2D *v2d)
@@ -1100,8 +1102,10 @@ void UI_view2d_view_ortho(View2D *v2d)
glLoadIdentity();
}
-/* Set view matrices to only use one axis of 'cur' only
- * - xaxis = if non-zero, only use cur x-axis, otherwise use cur-yaxis (mostly this will be used for x)
+/**
+ * Set view matrices to only use one axis of 'cur' only
+ *
+ * \param xaxis: if non-zero, only use cur x-axis, otherwise use cur-yaxis (mostly this will be used for x)
*/
void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis)
{
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index eafc5c1d24c..6fbe8509188 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -63,12 +63,13 @@ static int view2d_poll(bContext *C)
/* ********************************************************* */
/* VIEW PANNING OPERATOR */
-/* This group of operators come in several forms:
- * 1) Modal 'dragging' with MMB - where movement of mouse dictates amount to pan view by
- * 2) Scrollwheel 'steps' - rolling mousewheel by one step moves view by predefined amount
+/**
+ * This group of operators come in several forms:
+ * -# Modal 'dragging' with MMB - where movement of mouse dictates amount to pan view by
+ * -# Scrollwheel 'steps' - rolling mousewheel by one step moves view by predefined amount
*
- * In order to make sure this works, each operator must define the following RNA-Operator Props:
- * deltax, deltay - define how much to move view by (relative to zoom-correction factor)
+ * In order to make sure this works, each operator must define the following RNA-Operator Props:
+ * - `deltax, deltay` - define how much to move view by (relative to zoom-correction factor)
*/
/* ------------------ Shared 'core' stuff ---------------------- */
@@ -525,15 +526,18 @@ static void VIEW2D_OT_scroll_up(wmOperatorType *ot)
/* ********************************************************* */
/* SINGLE-STEP VIEW ZOOMING OPERATOR */
-/* This group of operators come in several forms:
- * 1) Scrollwheel 'steps' - rolling mousewheel by one step zooms view by predefined amount
- * 2) Scrollwheel 'steps' + alt + ctrl/shift - zooms view on one axis only (ctrl=x, shift=y) // XXX this could be implemented...
- * 3) Pad +/- Keys - pressing each key moves the zooms the view by a predefined amount
+/**
+ * This group of operators come in several forms:
+ * -# Scrollwheel 'steps' - rolling mousewheel by one step zooms view by predefined amount.
+ * -# Scrollwheel 'steps' + alt + ctrl/shift - zooms view on one axis only (ctrl=x, shift=y).
+ * XXX this could be implemented...
+ * -# Pad +/- Keys - pressing each key moves the zooms the view by a predefined amount.
*
* In order to make sure this works, each operator must define the following RNA-Operator Props:
- * zoomfacx, zoomfacy - These two zoom factors allow for non-uniform scaling.
- * It is safe to scale by 0, as these factors are used to determine
- * amount to enlarge 'cur' by
+ *
+ * - zoomfacx, zoomfacy - These two zoom factors allow for non-uniform scaling.
+ * It is safe to scale by 0, as these factors are used to determine.
+ * amount to enlarge 'cur' by.
*/
/* ------------------ 'Shared' stuff ------------------------ */
@@ -872,10 +876,11 @@ static void VIEW2D_OT_zoom_out(wmOperatorType *ot)
/* ********************************************************* */
/* DRAG-ZOOM OPERATOR */
-/* MMB Drag - allows non-uniform scaling by dragging mouse
+/**
+ * MMB Drag - allows non-uniform scaling by dragging mouse
*
- * In order to make sure this works, each operator must define the following RNA-Operator Props:
- * deltax, deltay - amounts to add to each side of the 'cur' rect
+ * In order to make sure this works, each operator must define the following RNA-Operator Props:
+ * - `deltax, deltay` - amounts to add to each side of the 'cur' rect
*/
/* apply transform to view (i.e. adjust 'cur' rect) */
@@ -1192,10 +1197,12 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot)
/* ********************************************************* */
/* BORDER-ZOOM */
-/* The user defines a rect using standard borderselect tools, and we use this rect to
+/**
+ * The user defines a rect using standard borderselect tools, and we use this rect to
* define the new zoom-level of the view in the following ways:
- * 1) LEFTMOUSE - zoom in to view
- * 2) RIGHTMOUSE - zoom out of view
+ *
+ * -# LEFTMOUSE - zoom in to view
+ * -# RIGHTMOUSE - zoom out of view
*
* Currently, these key mappings are hardcoded, but it shouldn't be too important to
* have custom keymappings for this...
@@ -1534,13 +1541,14 @@ static void VIEW2D_OT_smoothview(wmOperatorType *ot)
/* ********************************************************* */
/* SCROLLERS */
-/* Scrollers should behave in the following ways, when clicked on with LMB (and dragged):
- * 1) 'Handles' on end of 'bubble' - when the axis that the scroller represents is zoomable,
- * enlarge 'cur' rect on the relevant side
- * 2) 'Bubble'/'bar' - just drag, and bar should move with mouse (view pans opposite)
+/**
+ * Scrollers should behave in the following ways, when clicked on with LMB (and dragged):
+ * -# 'Handles' on end of 'bubble' - when the axis that the scroller represents is zoomable,
+ * enlarge 'cur' rect on the relevant side.
+ * -# 'Bubble'/'bar' - just drag, and bar should move with mouse (view pans opposite).
*
- * In order to make sure this works, each operator must define the following RNA-Operator Props:
- * deltax, deltay - define how much to move view by (relative to zoom-correction factor)
+ * In order to make sure this works, each operator must define the following RNA-Operator Props:
+ * - `deltax, deltay` - define how much to move view by (relative to zoom-correction factor)
*/
/* customdata for scroller-invoke data */
@@ -1562,10 +1570,12 @@ typedef struct v2dScrollerMove {
} v2dScrollerMove;
-/* View2DScrollers is typedef'd in UI_view2d.h
+/**
+ * #View2DScrollers is typedef'd in UI_view2d.h
* This is a CUT DOWN VERSION of the 'real' version, which is defined in view2d.c, as we only need focus bubble info
- * WARNING: the start of this struct must not change, so that it stays in sync with the 'real' version
- * For now, we don't need to have a separate (internal) header for structs like this...
+ *
+ * \warning: The start of this struct must not change, so that it stays in sync with the 'real' version
+ * For now, we don't need to have a separate (internal) header for structs like this...
*/
struct View2DScrollers {
/* focus bubbles */
@@ -1584,10 +1594,12 @@ enum {
/* ------------------------ */
-/* check if mouse is within scroller handle
- * - mouse = relevant mouse coordinate in region space
- * - sc_min, sc_max = extents of scroller 'groove' (potential available space for scroller)
- * - sh_min, sh_max = positions of scrollbar handles
+/**
+ * Check if mouse is within scroller handle.
+ *
+ * \param mouse: relevant mouse coordinate in region space.
+ * \param sc_min, sc_max: extents of scroller 'groove' (potential available space for scroller).
+ * \param sh_min, sh_max: positions of scrollbar handles.
*/
static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_min, int sh_max)
{
@@ -1791,7 +1803,10 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
-/* handle user input for scrollers - calculations of mouse-movement need to be done here, not in the apply callback! */
+/**
+ * Handle user input for scrollers - calculations of mouse-movement need to be done here,
+ * not in the apply callback!
+ */
static int scroller_activate_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
v2dScrollerMove *vsm = op->customdata;
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 0b9da1efed6..517710405a0 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -777,18 +777,11 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
/* vars from original func */
UvElementMap *element_map;
UvElement *buf;
- UvElement *islandbuf;
- /* island number for faces */
- int *island_number;
bool *winding;
BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
MLoopUV *luv;
- int totverts, totfaces, i, totuv, j, nislands = 0, islandbufsize = 0;
-
- unsigned int *map;
- BMFace **stack;
- int stacksize = 0;
+ int totverts, totfaces, i, totuv, j;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
@@ -798,9 +791,6 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
totverts = bm->totvert;
totuv = 0;
- island_number = MEM_mallocN(sizeof(*stack) * totfaces, "uv_island_number_face");
- winding = MEM_callocN(sizeof(*winding) * totfaces, "winding");
-
/* generate UvElement array */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
@@ -809,26 +799,20 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
}
if (totuv == 0) {
- MEM_freeN(island_number);
return NULL;
}
+
element_map = (UvElementMap *)MEM_callocN(sizeof(*element_map), "UvElementMap");
- if (!element_map) {
- MEM_freeN(island_number);
- return NULL;
- }
element_map->totalUVs = totuv;
element_map->vert = (UvElement **)MEM_callocN(sizeof(*element_map->vert) * totverts, "UvElementVerts");
buf = element_map->buf = (UvElement *)MEM_callocN(sizeof(*element_map->buf) * totuv, "UvElement");
- if (!element_map->vert || !element_map->buf) {
- BM_uv_element_map_free(element_map);
- MEM_freeN(island_number);
- return NULL;
- }
+ winding = MEM_mallocN(sizeof(*winding) * totfaces, "winding");
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, j) {
- island_number[j] = INVALID_ISLAND;
+
+ winding[j] = false;
+
if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa->len);
@@ -900,11 +884,24 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
element_map->vert[i] = newvlist;
}
+ MEM_freeN(winding);
+
if (do_islands) {
+ unsigned int *map;
+ BMFace **stack;
+ int stacksize = 0;
+ UvElement *islandbuf;
+ /* island number for faces */
+ int *island_number = NULL;
+
+ int nislands = 0, islandbufsize = 0;
+
/* map holds the map from current vmap->buf to the new, sorted map */
map = MEM_mallocN(sizeof(*map) * totuv, "uvelement_remap");
stack = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_face_stack");
islandbuf = MEM_callocN(sizeof(*islandbuf) * totuv, "uvelement_island_buffer");
+ island_number = MEM_mallocN(sizeof(*island_number) * totfaces, "uv_island_number_face");
+ copy_vn_i(island_number, totfaces, INVALID_ISLAND);
/* at this point, every UvElement in vert points to a UvElement sharing the same vertex. Now we should sort uv's in islands. */
for (i = 0; i < totuv; i++) {
@@ -953,6 +950,8 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
}
}
+ MEM_freeN(island_number);
+
/* remap */
for (i = 0; i < bm->totvert; i++) {
/* important since we may do selection only. Some of these may be NULL */
@@ -961,14 +960,6 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
}
element_map->islandIndices = MEM_callocN(sizeof(*element_map->islandIndices) * nislands, "UvElementMap_island_indices");
- if (!element_map->islandIndices) {
- MEM_freeN(islandbuf);
- MEM_freeN(stack);
- MEM_freeN(map);
- BM_uv_element_map_free(element_map);
- MEM_freeN(island_number);
- }
-
j = 0;
for (i = 0; i < totuv; i++) {
UvElement *element = element_map->buf[i].next;
@@ -991,8 +982,6 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const boo
MEM_freeN(map);
}
- MEM_freeN(island_number);
- MEM_freeN(winding);
BLI_buffer_free(&tf_uv_buf);
return element_map;
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index b9a9f708af7..a2054a5f43c 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -429,7 +429,7 @@ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set)
/* copy data from active vertex color layer */
if (layernum) {
const int layernum_dst = CustomData_get_active_layer(&em->bm->ldata, CD_MLOOPCOL);
- BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPCOL, layernum, layernum_dst);
+ BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPCOL, layernum_dst, layernum);
}
if (active_set || layernum == 0) {
CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index c88f1257936..ce9693793a4 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -248,7 +248,7 @@ static bool object_has_modifier_cb(Object *ob, void *data)
bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v)
{
ModifierData *md;
- int totlevel = *((int *)totlevel_v);
+ int totlevel = *((char *)totlevel_v);
for (md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Multires) {
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 886e4e5ef8c..30ab00a72c2 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -955,21 +955,30 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewCon
}
}
+static bool ommit_cursor_drawing(Paint *paint, PaintMode mode, Brush *brush)
+{
+ if (paint->flags & PAINT_SHOW_BRUSH) {
+ if (ELEM(mode, PAINT_TEXTURE_2D, PAINT_TEXTURE_PROJECTIVE) && brush->imagepaint_tool == PAINT_TOOL_FILL)
+ return true;
+ }
+ return false;
+}
+
static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
{
Scene *scene = CTX_data_scene(C);
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
ViewContext vc;
- PaintMode mode;
float final_radius;
float translation[2];
float outline_alpha, *outline_col;
float zoomx, zoomy;
-
+
/* check that brush drawing is enabled */
- if (!(paint->flags & PAINT_SHOW_BRUSH))
+ if (ommit_cursor_drawing(paint, mode, brush))
return;
/* can't use stroke vc here because this will be called during
@@ -978,7 +987,6 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
get_imapaint_zoom(C, &zoomx, &zoomy);
zoomx = max_ff(zoomx, zoomy);
- mode = BKE_paintmode_get_active_from_context(C);
/* skip everything and draw brush here */
if (brush->flag & BRUSH_CURVE) {
@@ -1018,8 +1026,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* check if brush is subtracting, use different color then */
/* TODO: no way currently to know state of pen flip or
* invert key modifier without starting a stroke */
- if ((!(ups->draw_inverted) ^
- !(brush->flag & BRUSH_DIR_IN)) &&
+ if (((ups->draw_inverted == 0) ^
+ ((brush->flag & BRUSH_DIR_IN) == 0)) &&
ELEM(brush->sculpt_tool, SCULPT_TOOL_DRAW,
SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
SCULPT_TOOL_PINCH, SCULPT_TOOL_CREASE))
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index a569bf469b3..58f1ebb9eac 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -5085,7 +5085,7 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
ps->blend = brush->blend;
/* only check for inversion for the soften tool, elsewhere, a resident brush inversion flag can cause issues */
if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
- ps->mode = ((ps->mode == BRUSH_STROKE_INVERT) ^ ((brush->flag & BRUSH_DIR_IN) != 0) ?
+ ps->mode = (((ps->mode == BRUSH_STROKE_INVERT) ^ ((brush->flag & BRUSH_DIR_IN) != 0)) ?
BRUSH_STROKE_INVERT : BRUSH_STROKE_NORMAL);
ps->blurkernel = paint_new_blur_kernel(brush, true);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 0e75a344699..ede90b6e1f1 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1200,7 +1200,7 @@ static float brush_strength(const Sculpt *sd, const StrokeCache *cache, const fl
/* Primary strength input; square it to make lower values more sensitive */
const float root_alpha = BKE_brush_alpha_get(scene, brush);
float alpha = root_alpha * root_alpha;
- float dir = brush->flag & BRUSH_DIR_IN ? -1 : 1;
+ float dir = (brush->flag & BRUSH_DIR_IN) ? -1 : 1;
float pressure = BKE_brush_use_alpha_pressure(scene, brush) ? cache->pressure : 1;
float pen_flip = cache->pen_flip ? -1 : 1;
float invert = cache->invert ? -1 : 1;
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 0a9a12efc0b..0e4d8857663 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -310,7 +310,7 @@ static void file_draw_string(int sx, int sy, const char *string, float width, in
fs.align = align;
BLI_strncpy(fname, string, FILE_MAXFILE);
- UI_text_clip_middle_ex(&fs, fname, width, UI_DPI_ICON_SIZE, sizeof(fname), NULL);
+ UI_text_clip_middle_ex(&fs, fname, width, UI_DPI_ICON_SIZE, sizeof(fname), '\0');
/* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict (for buttons it works) */
rect.xmin = sx;
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 8b68ac013c2..a7fd624d2aa 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -24,6 +24,7 @@
* \ingroup edinterface
*/
+#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
@@ -214,8 +215,22 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *
}
else if (!node_from) {
node_from = nodeAddStaticNode(C, ntree, type);
- node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
- node_from->locy = node_to->locy;
+ if (node_prev != NULL) {
+ /* If we're replacing existing node, use it's location. */
+ node_from->locx = node_prev->locx;
+ node_from->locy = node_prev->locy;
+ node_from->offsetx = node_prev->offsetx;
+ node_from->offsety = node_prev->offsety;
+ }
+ else {
+ /* Avoid exact intersection of nodes.
+ * TODO(sergey): Still not ideal, but better than nothing.
+ */
+ int index = BLI_findindex(&node_to->inputs, sock_to);
+ BLI_assert(index != -1);
+ node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
+ node_from->locy = node_to->locy - (node_from->typeinfo->height * index);
+ }
node_link_item_apply(node_from, item);
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index c040045b598..2aa57fe1cad 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -6191,7 +6191,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
PTCacheEditPoint *point;
PTCacheEditKey *key;
ParticleEditSettings *pset = PE_settings(scene);
- int i, k, totpoint = edit->totpoint, timed = pset->flag & PE_FADE_TIME ? pset->fade_frames : 0;
+ int i, k, totpoint = edit->totpoint, timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : 0;
int totkeys = 1;
float sel_col[3];
float nosel_col[3];
@@ -6331,7 +6331,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glColor3fv(nosel_col);
/* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
glBegin(GL_POINTS);
- glVertex3fv(key->flag & PEK_USE_WCO ? key->world_co : key->co);
+ glVertex3fv((key->flag & PEK_USE_WCO) ? key->world_co : key->co);
glEnd();
}
}
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index fb98f8b91a7..1d5c2a3a169 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -26,8 +26,6 @@
/* defines VIEW3D_OT_navigate - walk modal operator */
-//#define NDOF_WALK_DEBUG
-//#define NDOF_WALK_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -58,6 +56,11 @@
#include "view3d_intern.h" /* own include */
+//#define NDOF_WALK_DEBUG
+//#define NDOF_WALK_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */
+
+#define USE_TABLET_SUPPORT
+
/* prototypes */
static float getVelocityZeroTime(const float gravity, const float velocity);
@@ -276,6 +279,14 @@ typedef struct WalkInfo {
/* mouse reverse */
bool is_reversed;
+#ifdef USE_TABLET_SUPPORT
+ /* check if we had a cursor event before */
+ bool is_cursor_first;
+
+ /* tablet devices (we can't relocate the cursor) */
+ bool is_cursor_absolute;
+#endif
+
/* gravity system */
eWalkGravityState gravity_state;
float gravity;
@@ -519,6 +530,12 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);
+#ifdef USE_TABLET_SUPPORT
+ walk->is_cursor_first = true;
+
+ walk->is_cursor_absolute = false;
+#endif
+
walk->active_directions = 0;
#ifdef NDOF_WALK_DRAW_TOOMUCH
@@ -586,10 +603,16 @@ static int walkEnd(bContext *C, WalkInfo *walk)
/* restore the cursor */
WM_cursor_modal_restore(win);
- /* center the mouse */
- WM_cursor_warp(win,
- walk->ar->winrct.xmin + walk->center_mval[0],
- walk->ar->winrct.ymin + walk->center_mval[1]);
+#ifdef USE_TABLET_SUPPORT
+ if (walk->is_cursor_absolute == false)
+#endif
+ {
+ /* center the mouse */
+ WM_cursor_warp(
+ win,
+ walk->ar->winrct.xmin + walk->center_mval[0],
+ walk->ar->winrct.ymin + walk->center_mval[1]);
+ }
if (walk->state == WALK_CONFIRM) {
MEM_freeN(walk);
@@ -617,6 +640,27 @@ static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const
}
else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+#ifdef USE_TABLET_SUPPORT
+ if (walk->is_cursor_first) {
+ /* wait until we get the 'warp' event */
+ if ((walk->center_mval[0] == event->mval[0]) &&
+ (walk->center_mval[1] == event->mval[1]))
+ {
+ walk->is_cursor_first = false;
+ }
+ return;
+ }
+
+ if ((walk->is_cursor_absolute == false) && WM_event_is_absolute(event)) {
+ walk->is_cursor_absolute = true;
+ copy_v2_v2_int(walk->prev_mval, event->mval);
+ copy_v2_v2_int(walk->center_mval, event->mval);
+ /* without this we can't turn 180d */
+ CLAMP_MIN(walk->mouse_speed, 4.0f);
+ }
+#endif /* USE_TABLET_SUPPORT */
+
+
walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
walk->moffset[1] += event->mval[1] - walk->prev_mval[1];
@@ -627,6 +671,12 @@ static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const
{
walk->redraw = true;
+#ifdef USE_TABLET_SUPPORT
+ if (walk->is_cursor_absolute) {
+ /* pass */
+ }
+ else
+#endif
if (wm_event_is_last_mousemove(event)) {
wmWindow *win = CTX_wm_window(C);
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index b629a69fc0b..34314e7ff3d 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -6658,6 +6658,10 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]
/* first get the direction of the original mouse position */
sub_v2_v2v2(dir, imval_fl, mval_fl);
ED_view3d_win_to_delta(t->ar, dir, dir, t->zfac);
+
+ invert_m4_m4(t->obedit->imat, t->obedit->obmat);
+ mul_mat3_m4_v3(t->obedit->imat, dir);
+
normalize_v3(dir);
for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
@@ -7013,6 +7017,10 @@ static void drawVertSlide(TransInfo *t)
mval_ofs[1] = t->mval[1] - t->imval[1];
ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac);
+
+ invert_m4_m4(t->obedit->imat, t->obedit->obmat);
+ mul_mat3_m4_v3(t->obedit->imat, co_dest_3d);
+
add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
glLineWidth(1);
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index fea0984001b..667c0f01c18 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -513,7 +513,7 @@ static int calc_manipulator_stats(const bContext *C)
for (k = 0, ek = point->keys; k < point->totkey; k++, ek++) {
if (ek->flag & PEK_SELECT) {
- calc_tw_center(scene, ek->flag & PEK_USE_WCO ? ek->world_co : ek->co);
+ calc_tw_center(scene, (ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co);
totsel++;
}
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index f77f1d3b518..62fa1b5a989 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -849,7 +849,7 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh;
+ ot->poll = ED_operator_editmesh_region_view3d;
RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
@@ -869,7 +869,7 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh;
+ ot->poll = ED_operator_editmesh_region_view3d;
RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
index 4d0d140474a..a36d446fcb7 100644
--- a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
+++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
@@ -30,6 +30,9 @@
extern "C" {
#endif
+#include "BLI_hash_mm2a.h"
+
+
///////////////////////////////////////////////////////////////////////////////////////////
//-------------------MODULE INITIALIZATION--------------------------------
@@ -478,6 +481,48 @@ static PyGetSetDef BPy_FrsMaterial_getseters[] = {
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
+static PyObject *BPy_FrsMaterial_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
+{
+ const BPy_FrsMaterial *matA = NULL, *matB = NULL;
+ bool result = 0;
+
+ if (!BPy_FrsMaterial_Check(objectA) || !BPy_FrsMaterial_Check(objectB)) {
+ if (comparison_type == Py_NE) {
+ Py_RETURN_TRUE;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
+ }
+
+ matA = (BPy_FrsMaterial *)objectA;
+ matB = (BPy_FrsMaterial *)objectB;
+
+ switch (comparison_type) {
+ case Py_NE:
+ result = (*matA->m) != (*matB->m);
+ break;
+ case Py_EQ:
+ result = (*matA->m) == (*matB->m);
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError, "Material does not support this comparison type");
+ return NULL;
+ }
+
+ if (result == true) {
+ Py_RETURN_TRUE;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
+}
+
+
+static Py_hash_t FrsMaterial_hash(PyObject *self)
+{
+ return (Py_uhash_t)BLI_hash_mm2((const unsigned char *)self, sizeof(*self), 0);
+}
/*-----------------------BPy_FrsMaterial type definition ------------------------------*/
PyTypeObject FrsMaterial_Type = {
@@ -494,7 +539,7 @@ PyTypeObject FrsMaterial_Type = {
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
- 0, /* tp_hash */
+ (hashfunc)FrsMaterial_hash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
@@ -504,7 +549,7 @@ PyTypeObject FrsMaterial_Type = {
FrsMaterial_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
- 0, /* tp_richcompare */
+ (richcmpfunc)BPy_FrsMaterial_richcmpr, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
index 1ef29792d56..9f0660baa9b 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
@@ -188,7 +188,10 @@ static PyObject *CurvePoint_fedge_get(BPy_CurvePoint *self, void *UNUSED(closure
{
SVertex *A = self->cp->A();
Interface0D *B = (Interface0D *)self->cp->B();
- return Any_BPy_Interface1D_from_Interface1D(*(A->getFEdge(*B)));
+ // B can be NULL under certain circumstances
+ if (B)
+ return Any_BPy_Interface1D_from_Interface1D(*(A->getFEdge(*B)));
+ Py_RETURN_NONE;
}
PyDoc_STRVAR(CurvePoint_t2d_doc,
diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h
index 2cb56832a00..f2f75973bcd 100644
--- a/source/blender/imbuf/IMB_thumbs.h
+++ b/source/blender/imbuf/IMB_thumbs.h
@@ -63,6 +63,11 @@ typedef enum ThumbSource {
#define PREVIEW_RENDER_DEFAULT_HEIGHT 128
+/* Note this can also be used as versionning system,
+ * to force refreshing all thumbnails if e.g. we change some thumb generating code or so.
+ * Only used by fonts so far. */
+#define THUMB_DEFAULT_HASH "00000000000000000000000000000000"
+
/* create thumbnail for file and returns new imbuf for thumbnail */
ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *ibuf);
@@ -84,7 +89,7 @@ void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float
/* special function for previewing fonts */
ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y);
-const char *IMB_thumb_load_font_get_language(void);
+bool IMB_thumb_load_font_get_hash(char *r_hash);
#ifdef __cplusplus
}
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index c3c403db9c1..a61204ea850 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -1357,11 +1357,12 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle,
float *fp;
unsigned char *cp;
+ const size_t i_last = ((size_t)width) * height;
size_t i;
/* first convert byte buffer to float, keep in image space */
for (i = 0, fp = linear_buffer, cp = byte_buffer;
- i < ((size_t)width) * height;
+ i != i_last;
i++, fp += channels, cp += channels)
{
if (channels == 3) {
@@ -1470,11 +1471,12 @@ static void *do_display_buffer_apply_thread(void *handle_v)
memcpy(display_buffer, linear_buffer, ((size_t)width) * height * channels * sizeof(float));
if (is_straight_alpha && channels == 4) {
+ const size_t i_last = ((size_t)width) * height;
size_t i;
float *fp;
for (i = 0, fp = display_buffer;
- i < ((size_t)width) * height;
+ i != i_last;
i++, fp += channels)
{
straight_to_premul_v4(fp);
@@ -1787,8 +1789,10 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in
if (processor) {
OCIO_PackedImageDesc *img;
- img = OCIO_createOCIO_PackedImageDesc(buffer, width, height, channels, sizeof(float),
- channels * sizeof(float), channels * sizeof(float) * width);
+ img = OCIO_createOCIO_PackedImageDesc(
+ buffer, width, height, channels, sizeof(float),
+ (size_t)channels * sizeof(float),
+ (size_t)channels * sizeof(float) * width);
if (predivide)
OCIO_processorApply_predivide(processor, img);
@@ -2015,7 +2019,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
const ColorManagedDisplaySettings *display_settings, void **cache_handle)
{
unsigned char *display_buffer;
- int buffer_size;
+ size_t buffer_size;
ColormanageCacheViewSettings cache_view_settings;
ColormanageCacheDisplaySettings cache_display_settings;
ColorManagedViewSettings default_view_settings;
@@ -2113,8 +2117,8 @@ void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *li
float *buffer;
ColormanageProcessor *cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
- buffer = MEM_callocN(channels * width * height * sizeof(float), "display transform temp buffer");
- memcpy(buffer, linear_buffer, channels * width * height * sizeof(float));
+ buffer = MEM_mallocN((size_t)channels * width * height * sizeof(float), "display transform temp buffer");
+ memcpy(buffer, linear_buffer, (size_t)channels * width * height * sizeof(float));
IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide);
@@ -2658,14 +2662,14 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
if (!cm_processor)
channels = 4;
- display_buffer_float = MEM_callocN(channels * width * height * sizeof(float), "display buffer for dither");
+ display_buffer_float = MEM_callocN((size_t)channels * width * height * sizeof(float), "display buffer for dither");
}
if (cm_processor) {
for (y = ymin; y < ymax; y++) {
for (x = xmin; x < xmax; x++) {
- int display_index = (y * display_stride + x) * 4;
- int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels;
+ size_t display_index = ((size_t)y * display_stride + x) * 4;
+ size_t linear_index = ((size_t)(y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels;
float pixel[4];
if (linear_buffer) {
@@ -2694,7 +2698,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
}
if (display_buffer_float) {
- int index = ((y - ymin) * width + (x - xmin)) * channels;
+ size_t index = ((size_t)(y - ymin) * width + (x - xmin)) * channels;
if (channels == 4) {
copy_v4_v4(display_buffer_float + index, pixel);
@@ -2737,8 +2741,8 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
int i;
for (i = ymin; i < ymax; i++) {
- int byte_offset = (linear_stride * i + xmin) * 4;
- int display_offset = (display_stride * i + xmin) * 4;
+ size_t byte_offset = ((size_t)linear_stride * i + xmin) * 4;
+ size_t display_offset = ((size_t)display_stride * i + xmin) * 4;
memcpy(display_buffer + display_offset, byte_buffer + byte_offset, 4 * sizeof(char) * width);
}
@@ -2746,7 +2750,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
}
if (display_buffer_float) {
- int display_index = (ymin * display_stride + xmin) * channels;
+ size_t display_index = ((size_t)ymin * display_stride + xmin) * channels;
IMB_buffer_byte_from_float(display_buffer + display_index, display_buffer_float, channels, dither,
IB_PROFILE_SRGB, IB_PROFILE_SRGB, true, width, height, display_stride, width);
@@ -2833,8 +2837,8 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
if (copy_display_to_byte_buffer && (unsigned char *) ibuf->rect != display_buffer) {
int y;
for (y = ymin; y < ymax; y++) {
- int index = y * buffer_width * 4;
- memcpy((unsigned char *)ibuf->rect + index, display_buffer + index, (xmax - xmin) * 4);
+ size_t index = (size_t)y * buffer_width * 4;
+ memcpy((unsigned char *)ibuf->rect + index, display_buffer + index, (size_t)(xmax - xmin) * 4);
}
}
}
@@ -2970,8 +2974,10 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo
OCIO_PackedImageDesc *img;
/* apply OCIO processor */
- img = OCIO_createOCIO_PackedImageDesc(buffer, width, height, channels, sizeof(float),
- channels * sizeof(float), channels * sizeof(float) * width);
+ img = OCIO_createOCIO_PackedImageDesc(
+ buffer, width, height, channels, sizeof(float),
+ (size_t)channels * sizeof(float),
+ (size_t)channels * sizeof(float) * width);
if (predivide)
OCIO_processorApply_predivide(cm_processor->processor, img);
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 22c854d6e1b..e805d3dc25c 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -638,7 +638,7 @@ typedef struct ExrHandle {
struct ExrHandle *next, *prev;
char name[FILE_MAX];
- IFileStream *ifile_stream;
+ IStream *ifile_stream;
MultiPartInputFile *ifile;
OFileStream *ofile_stream;
@@ -1345,6 +1345,7 @@ void IMB_exr_close(void *handle)
delete data->ofile;
delete data->mpofile;
delete data->ofile_stream;
+ delete data->multiView;
data->ifile = NULL;
data->ifile_stream = NULL;
@@ -1495,7 +1496,7 @@ static ExrPass *imb_exr_get_pass(ListBase *lb, char *passname)
}
/* creates channels, makes a hierarchy and assigns memory to channels */
-static ExrHandle *imb_exr_begin_read_mem(MultiPartInputFile& file, int width, int height)
+static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream, MultiPartInputFile &file, int width, int height)
{
ExrLayer *lay;
ExrPass *pass;
@@ -1504,7 +1505,9 @@ static ExrHandle *imb_exr_begin_read_mem(MultiPartInputFile& file, int width, in
int a;
char layname[EXR_TOT_MAXNAME], passname[EXR_TOT_MAXNAME];
+ data->ifile_stream = &file_stream;
data->ifile = &file;
+
data->width = width;
data->height = height;
@@ -1855,6 +1858,7 @@ static bool imb_exr_is_multi(MultiPartInputFile& file)
struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
+ Mem_IStream *membuf = NULL;
MultiPartInputFile *file = NULL;
if (imb_is_a_openexr(mem) == 0) return(NULL);
@@ -1863,8 +1867,9 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
try
{
- Mem_IStream *membuf = new Mem_IStream(mem, size);
bool is_multi;
+
+ membuf = new Mem_IStream(mem, size);
file = new MultiPartInputFile(*membuf);
Box2i dw = file->header(0).dataWindow();
@@ -1914,7 +1919,7 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
if (is_multi && ((flags & IB_thumbnail) == 0)) { /* only enters with IB_multilayer flag set */
/* constructs channels for reading, allocates memory in channels */
- ExrHandle *handle = imb_exr_begin_read_mem(*file, width, height);
+ ExrHandle *handle = imb_exr_begin_read_mem(*membuf, *file, width, height);
if (handle) {
IMB_exr_read_channels(handle);
ibuf->userdata = handle; /* potential danger, the caller has to check for this! */
@@ -1998,6 +2003,7 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
}
/* file is no longer needed */
+ delete membuf;
delete file;
}
}
@@ -2012,6 +2018,7 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
std::cerr << exc.what() << std::endl;
if (ibuf) IMB_freeImBuf(ibuf);
delete file;
+ delete membuf;
return (0);
}
diff --git a/source/blender/imbuf/intern/stereoimbuf.c b/source/blender/imbuf/intern/stereoimbuf.c
index cf9c6b388ff..f1608f56c0b 100644
--- a/source/blender/imbuf/intern/stereoimbuf.c
+++ b/source/blender/imbuf/intern/stereoimbuf.c
@@ -620,7 +620,7 @@ static void imb_stereo3d_squeeze_rectf(float *rectf, Stereo3dFormat *s3d, const
width, height, width, width);
IMB_scaleImBuf_threaded(ibuf, x, y);
- rectf = MEM_dupallocN(ibuf->rect_float);
+ memcpy(rectf, ibuf->rect_float, x * y * sizeof(float[4]));
IMB_freeImBuf(ibuf);
}
@@ -645,7 +645,7 @@ static void imb_stereo3d_squeeze_rect(int *rect, Stereo3dFormat *s3d, const size
width, height, width, width);
IMB_scaleImBuf_threaded(ibuf, x, y);
- rect = MEM_dupallocN(ibuf->rect);
+ memcpy(rect, ibuf->rect, x * y * sizeof(unsigned int));
IMB_freeImBuf(ibuf);
}
diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c
index 70b71ec4182..40dcdc9d24a 100644
--- a/source/blender/imbuf/intern/targa.c
+++ b/source/blender/imbuf/intern/targa.c
@@ -568,7 +568,7 @@ ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colors
else ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, (tga.pixsize + 0x7) & ~0x7, IB_rect);
if (ibuf == NULL) return NULL;
- ibuf->ftype = TGA;
+ ibuf->ftype = (tga.imgtyp < 4) ? RAWTGA : TGA;
mem = mem + 18 + tga.numid;
cp[0] = 0xff;
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
index 626f02e8ade..7a949b7ffea 100644
--- a/source/blender/imbuf/intern/thumbs.c
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -200,6 +200,17 @@ static void escape_uri_string(const char *string, char *escaped_string, int esca
/** ----- end of adapted code from glib --- */
+static bool thumbhash_from_path(const char *UNUSED(path), ThumbSource source, char *r_hash)
+{
+ switch (source) {
+ case THB_SOURCE_FONT:
+ return IMB_thumb_load_font_get_hash(r_hash);
+ default:
+ r_hash[0] = '\0';
+ return false;
+ }
+}
+
static int uri_from_filename(const char *path, char *uri)
{
char orig_uri[URI_MAX];
@@ -298,7 +309,8 @@ void IMB_thumb_makedirs(void)
/* create thumbnail for file and returns new imbuf for thumbnail */
static ImBuf *thumb_create_ex(
- const char *file_path, const char *uri, const char *thumb, ThumbSize size, ThumbSource source, ImBuf *img)
+ const char *file_path, const char *uri, const char *thumb, const bool use_hash, const char *hash,
+ ThumbSize size, ThumbSource source, ImBuf *img)
{
char desc[URI_MAX + 22];
char tpath[FILE_MAX];
@@ -420,6 +432,9 @@ static ImBuf *thumb_create_ex(
IMB_metadata_change_field(img, "Software", "Blender");
IMB_metadata_change_field(img, "Thumb::URI", uri);
IMB_metadata_change_field(img, "Thumb::MTime", mtime);
+ if (use_hash) {
+ IMB_metadata_change_field(img, "X-Blender::Hash", hash);
+ }
if (ELEM(source, THB_SOURCE_IMAGE, THB_SOURCE_BLEND, THB_SOURCE_FONT)) {
IMB_metadata_change_field(img, "Thumb::Image::Width", cwidth);
IMB_metadata_change_field(img, "Thumb::Image::Height", cheight);
@@ -439,6 +454,25 @@ static ImBuf *thumb_create_ex(
return img;
}
+static ImBuf *thumb_create_or_fail(
+ const char *file_path, const char *uri, const char *thumb, const bool use_hash, const char *hash,
+ ThumbSize size, ThumbSource source)
+{
+ ImBuf *img = thumb_create_ex(file_path, uri, thumb, use_hash, hash, size, source, NULL);
+
+ if (!img) {
+ /* thumb creation failed, write fail thumb */
+ img = thumb_create_ex(file_path, uri, thumb, use_hash, hash, THB_FAIL, source, NULL);
+ if (img) {
+ /* we don't need failed thumb anymore */
+ IMB_freeImBuf(img);
+ img = NULL;
+ }
+ }
+
+ return img;
+}
+
ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *img)
{
char uri[URI_MAX] = "";
@@ -447,7 +481,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
uri_from_filename(path, uri);
thumbname_from_uri(uri, thumb_name, sizeof(thumb_name));
- return thumb_create_ex(path, uri, thumb_name, size, source, img);
+ return thumb_create_ex(path, uri, thumb_name, false, THUMB_DEFAULT_HASH, size, source, img);
}
/* read thumbnail for file and returns new imbuf for thumbnail */
@@ -495,15 +529,10 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source
char uri[URI_MAX];
const char *file_path;
const char *path;
- char path_buff[FILE_MAX];
BLI_stat_t st;
ImBuf *img = NULL;
path = file_path = org_path;
- if (source == THB_SOURCE_FONT) {
- BLI_snprintf(path_buff, sizeof(path_buff), "%s.%s", org_path, IMB_thumb_load_font_get_language());
- path = path_buff;
- }
if (BLI_stat(file_path, &st) == -1) {
return NULL;
@@ -531,45 +560,46 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source
else {
img = IMB_loadiffname(thumb_path, IB_rect | IB_metadata, NULL);
if (img) {
+ bool regenerate = false;
+
char mtime[40];
- if (!IMB_metadata_get_field(img, "Thumb::MTime", mtime, 40)) {
- /* illegal thumb, forget it! */
- IMB_freeImBuf(img);
- img = NULL;
+ char thumb_hash[33];
+ char thumb_hash_curr[33];
+
+ const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash);
+
+ if (IMB_metadata_get_field(img, "Thumb::MTime", mtime, sizeof(mtime))) {
+ regenerate = (st.st_mtime != atol(mtime));
}
else {
- time_t t = atol(mtime);
- if (st.st_mtime != t) {
- /* recreate all thumbs */
- IMB_freeImBuf(img);
- img = NULL;
- IMB_thumb_delete(path, THB_NORMAL);
- IMB_thumb_delete(path, THB_LARGE);
- IMB_thumb_delete(path, THB_FAIL);
- img = thumb_create_ex(file_path, uri, thumb_name, size, source, NULL);
- if (!img) {
- /* thumb creation failed, write fail thumb */
- img = thumb_create_ex(file_path, uri, thumb_name, THB_FAIL, source, NULL);
- if (img) {
- /* we don't need failed thumb anymore */
- IMB_freeImBuf(img);
- img = NULL;
- }
- }
+ /* illegal thumb, regenerate it! */
+ regenerate = true;
+ }
+
+ if (use_hash && !regenerate) {
+ if (IMB_metadata_get_field(img, "X-Blender::Hash", thumb_hash_curr, sizeof(thumb_hash_curr))) {
+ regenerate = !STREQ(thumb_hash, thumb_hash_curr);
+ }
+ else {
+ regenerate = true;
}
}
+
+ if (regenerate) {
+ /* recreate all thumbs */
+ IMB_freeImBuf(img);
+ img = NULL;
+ IMB_thumb_delete(path, THB_NORMAL);
+ IMB_thumb_delete(path, THB_LARGE);
+ IMB_thumb_delete(path, THB_FAIL);
+ img = thumb_create_or_fail(file_path, uri, thumb_name, use_hash, thumb_hash, size, source);
+ }
}
else {
- img = thumb_create_ex(file_path, uri, thumb_name, size, source, NULL);
- if (!img) {
- /* thumb creation failed, write fail thumb */
- img = thumb_create_ex(file_path, uri, thumb_name, THB_FAIL, source, NULL);
- if (img) {
- /* we don't need failed thumb anymore */
- IMB_freeImBuf(img);
- img = NULL;
- }
- }
+ char thumb_hash[33];
+ const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash);
+
+ img = thumb_create_or_fail(file_path, uri, thumb_name, use_hash, thumb_hash, size, source);
}
}
}
diff --git a/source/blender/imbuf/intern/thumbs_font.c b/source/blender/imbuf/intern/thumbs_font.c
index 7c94742a187..4b024f3c51b 100644
--- a/source/blender/imbuf/intern/thumbs_font.c
+++ b/source/blender/imbuf/intern/thumbs_font.c
@@ -25,6 +25,9 @@
*/
#include "BLI_utildefines.h"
+#include "BLI_string.h"
+#include "BLI_fileops.h"
+#include "BLI_hash_md5.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -36,18 +39,18 @@
#include "../../blenfont/BLF_api.h"
#include "../../blenfont/BLF_translation.h" /* 'N_' macro and BLF_lang_get()... */
+static const char *thumb_str[] = {
+ N_("AaBbCc"),
+
+ N_("The quick"),
+ N_("brown fox"),
+ N_("jumps over"),
+ N_("the lazy dog"),
+};
struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y)
{
const int font_size = y / 4;
- const char *thumb_str[] = {
- N_("AaBbCc"),
-
- N_("The quick"),
- N_("brown fox"),
- N_("jumps over"),
- N_("the lazy dog"),
- };
struct ImBuf *ibuf;
float font_color[4];
@@ -72,7 +75,26 @@ struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned
return ibuf;
}
-const char *IMB_thumb_load_font_get_language(void)
+bool IMB_thumb_load_font_get_hash(char *r_hash)
{
- return BLF_lang_get();
+ char buf[1024];
+ char *str = buf;
+ size_t len = 0;
+
+ int draw_str_lines = ARRAY_SIZE(thumb_str);
+ int i;
+
+ unsigned char digest[16];
+
+ len += BLI_strncpy_rlen(str + len, THUMB_DEFAULT_HASH, sizeof(buf) - len);
+
+ for (i = 0; (i < draw_str_lines) && (len < sizeof(buf)); i++) {
+ len += BLI_strncpy_rlen(str + len, BLF_translate_do(BLF_I18NCONTEXT_DEFAULT, thumb_str[i]), sizeof(buf) - len);
+ }
+
+ BLI_hash_md5_buffer(str, len, digest);
+ r_hash[0] = '\0';
+ BLI_hash_md5_to_hexdigest(digest, r_hash);
+
+ return true;
}
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index fa16ebbb5da..82600421736 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -771,7 +771,7 @@ static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
for (i = 0; i < curdupface; i++) {
mf = CDDM_get_tessface(splitdm, i);
- test_index_face(mf, &splitdm->faceData, i, (mf->flag & ME_FACE_SEL ? 4 : 3));
+ test_index_face(mf, &splitdm->faceData, i, ((mf->flag & ME_FACE_SEL) ? 4 : 3));
}
BLI_edgehash_free(edgehash, NULL);
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 4fa86527334..2e431884845 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -148,7 +148,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
unsigned int i, j;
unsigned int i1, i2;
unsigned int step_tot = use_render_params ? ltmd->render_steps : ltmd->steps;
- const bool do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0;
+ const bool do_flip = (ltmd->flag & MOD_SCREW_NORMAL_FLIP) != 0;
const int quad_ord[4] = {
do_flip ? 3 : 0,
@@ -158,9 +158,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
};
const int quad_ord_ofs[4] = {
do_flip ? 2 : 0,
- do_flip ? 1 : 1,
+ 1,
do_flip ? 0 : 2,
- do_flip ? 3 : 3,
+ 3,
};
unsigned int maxVerts = 0, maxEdges = 0, maxPolys = 0;
diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c
index 5846ccd8757..e876adfa58e 100644
--- a/source/blender/python/intern/bpy_util.c
+++ b/source/blender/python/intern/bpy_util.c
@@ -85,7 +85,6 @@ short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool
bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const bool use_location)
{
PyObject *pystring;
- const char *cstring;
if (!PyErr_Occurred())
return 1;
@@ -109,13 +108,12 @@ bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const boo
return 0;
}
- cstring = _PyUnicode_AsString(pystring);
-
if (use_location) {
const char *filename;
int lineno;
PyObject *pystring_format; /* workaround, see below */
+ const char *cstring;
PyC_FileAndNum(&filename, &lineno);
if (filename == NULL) {
@@ -123,19 +121,23 @@ bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const boo
}
#if 0 /* ARG!. workaround for a bug in blenders use of vsnprintf */
- BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", cstring, filename, lineno);
+ BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", _PyUnicode_AsString(pystring), filename, lineno);
#else
- pystring_format = PyUnicode_FromFormat(TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno);
+ pystring_format = PyUnicode_FromFormat(
+ TIP_("%s\nlocation: %s:%d\n"),
+ _PyUnicode_AsString(pystring), filename, lineno);
+
cstring = _PyUnicode_AsString(pystring_format);
BKE_report(reports, RPT_ERROR, cstring);
- Py_DECREF(pystring_format); /* workaround */
-#endif
/* not exactly needed. just for testing */
fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno);
+
+ Py_DECREF(pystring_format); /* workaround */
+#endif
}
else {
- BKE_report(reports, RPT_ERROR, cstring);
+ BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(pystring));
}
diff --git a/source/blender/render/intern/raytrace/rayobject_instance.cpp b/source/blender/render/intern/raytrace/rayobject_instance.cpp
index 01e592cba0c..d080ddcc375 100644
--- a/source/blender/render/intern/raytrace/rayobject_instance.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_instance.cpp
@@ -197,7 +197,7 @@ static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max)
//There must be a faster way than rotating all the 8 vertexs of the BB
for (i = 0; i < 8; i++) {
- for (j = 0; j < 3; j++) t[j] = i & (1 << j) ? M[j] : m[j];
+ for (j = 0; j < 3; j++) t[j] = (i & (1 << j)) ? M[j] : m[j];
mul_m4_v3(obj->target2global, t);
DO_MINMAX(t, min, max);
}
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index e81c913bc6f..9d1a5171b9e 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -159,7 +159,7 @@ typedef void (*wmUIHandlerRemoveFunc)(struct bContext *C, void *userdata);
struct wmEventHandler *WM_event_add_ui_handler(
const struct bContext *C, ListBase *handlers,
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
- void *userdata, const bool accept_dbl_click);
+ void *userdata, const char flag);
void WM_event_remove_ui_handler(
ListBase *handlers,
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
@@ -173,11 +173,21 @@ void WM_event_free_ui_handler_all(
struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op);
void WM_event_remove_handlers(struct bContext *C, ListBase *handlers);
+/* handler flag */
+enum {
+ WM_HANDLER_BLOCKING = (1 << 0), /* after this handler all others are ignored */
+ WM_HANDLER_ACCEPT_DBL_CLICK = (1 << 1), /* handler accepts double key press events */
+
+ /* internal */
+ WM_HANDLER_DO_FREE = (1 << 7), /* handler tagged to be freed in wm_handlers_do() */
+};
+
struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase *dropboxes);
/* mouse */
void WM_event_add_mousemove(struct bContext *C);
bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
+bool WM_event_is_absolute(const struct wmEvent *event);
/* notifiers */
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference);
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 68fd32cb450..d84b65847ca 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -313,21 +313,22 @@ void WM_cursor_time(wmWindow *win, int nr)
}
-/* ******************************************************************
- * Custom Cursor Description:
+/**
+ * Custom Cursor Description
+ * =========================
*
* Each bit represents a pixel, so 1 byte = 8 pixels,
* the bytes go Left to Right. Top to bottom
* the bits in a byte go right to left
* (ie; 0x01, 0x80 represents a line of 16 pix with the first and last pix set.)
*
- * A 0 in the bitmap = bg_color, a 1 fg_color
- * a 0 in the mask = transparent pix.
+ * - A 0 in the bitmap = bg_color, a 1 fg_color
+ * - a 0 in the mask = transparent pix.
*
* Until 32x32 cursors are supported on all platforms, the size of the
* small cursors MUST be 16x16.
*
- * Large cursors have a MAXSIZE of 32x32.
+ * Large cursors have a maximum size of 32x32.
*
* Other than that, the specified size of the cursors is just a guideline,
* However, the char array that defines the BM and MASK must be byte aligned.
@@ -335,18 +336,20 @@ void WM_cursor_time(wmWindow *win, int nr)
* (3 bytes = 17 bits rounded up to nearest whole byte). Pad extra bits
* in mask with 0's.
*
- * Setting big_bm = NULL disables the large version of the cursor.
+ * Setting `big_bm = NULL` disables the large version of the cursor.
*
- * *******************************************************************
+ * ----
*
* There is a nice Python GUI utility that can be used for drawing cursors in
* this format in the Blender source distribution, in
- * blender/source/tools/MakeCursor.py . Start it with $ python MakeCursor.py
- * It will copy its output to the console when you press 'Do it'.
+ * `./source/tools/utils/make_cursor_gui.py` .
*
+ * Start it with the command `python3 make_cursor_gui.py`
+ * It will copy its output to the console when you press 'Do it'.
*/
-/* Because defining a cursor mixes declarations and executable code
+/**
+ * Because defining a cursor mixes declarations and executable code
* each cursor needs it's own scoping block or it would be split up
* over several hundred lines of code. To enforce/document this better
* I define 2 pretty brain-dead macros so it's obvious what the extra "[]"
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index e8e557ae19f..893e05b2093 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -566,10 +566,9 @@ void WM_event_print(const wmEvent *event)
RNA_enum_identifier(event_type_items, event->type, &type_id);
RNA_enum_identifier(event_value_items, event->val, &val_id);
- printf("wmEvent type:%d / %s, val:%d / %s, \n"
- " shift:%d, ctrl:%d, alt:%d, oskey:%d, keymodifier:%d, \n"
- " mouse:(%d,%d), ascii:'%c', utf8:'%.*s', "
- " keymap_idname:%s, pointer:%p\n",
+ printf("wmEvent type:%d / %s, val:%d / %s,\n"
+ " shift:%d, ctrl:%d, alt:%d, oskey:%d, keymodifier:%d,\n"
+ " mouse:(%d,%d), ascii:'%c', utf8:'%.*s', keymap_idname:%s, pointer:%p\n",
event->type, type_id, event->val, val_id,
event->shift, event->ctrl, event->alt, event->oskey, event->keymodifier,
event->x, event->y, event->ascii,
@@ -579,17 +578,19 @@ void WM_event_print(const wmEvent *event)
if (ISNDOF(event->type)) {
const wmNDOFMotionData *ndof = event->customdata;
if (event->type == NDOF_MOTION) {
- printf(" ndof: rot: (%.4f %.4f %.4f),\n"
- " tx: (%.4f %.4f %.4f),\n"
- " dt: %.4f, progress: %d\n",
- UNPACK3(ndof->rvec),
- UNPACK3(ndof->tvec),
- ndof->dt, ndof->progress);
+ printf(" ndof: rot: (%.4f %.4f %.4f), tx: (%.4f %.4f %.4f), dt: %.4f, progress: %d\n",
+ UNPACK3(ndof->rvec), UNPACK3(ndof->tvec), ndof->dt, ndof->progress);
}
else {
/* ndof buttons printed already */
}
}
+
+ if (event->tablet_data) {
+ const wmTabletData *wmtab = event->tablet_data;
+ printf(" tablet: active: %d, pressure %.4f, tilt: (%.4f %.4f)\n",
+ wmtab->Active, wmtab->Pressure, wmtab->Xtilt, wmtab->Ytilt);
+ }
}
else {
printf("wmEvent - NULL\n");
@@ -617,6 +618,11 @@ void WM_report_banner_show(const bContext *C)
wm_reports->reporttimer->customdata = rti;
}
+bool WM_event_is_absolute(const wmEvent *event)
+{
+ return (event->tablet_data != NULL);
+}
+
static void wm_add_reports(const bContext *C, ReportList *reports)
{
/* if the caller owns them, handle this */
@@ -702,7 +708,8 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca
wm_add_reports(C, op->reports);
}
-/* this function is mainly to check that the rules for freeing
+/**
+ * This function is mainly to check that the rules for freeing
* an operator are kept in sync.
*/
static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot)
@@ -821,23 +828,29 @@ int WM_operator_call(bContext *C, wmOperator *op)
return WM_operator_call_ex(C, op, false);
}
-/* this is intended to be used when an invoke operator wants to call exec on its self
+/**
+ * This is intended to be used when an invoke operator wants to call exec on its self
* and is basically like running op->type->exec() directly, no poll checks no freeing,
- * since we assume whoever called invoke will take care of that */
+ * since we assume whoever called invoke will take care of that
+ */
int WM_operator_call_notest(bContext *C, wmOperator *op)
{
return wm_operator_exec_notest(C, op);
}
-/* do this operator again, put here so it can share above code */
+/**
+ * Execute this operator again, put here so it can share above code
+ */
int WM_operator_repeat(bContext *C, wmOperator *op)
{
return wm_operator_exec(C, op, true, true);
}
-/* true if WM_operator_repeat can run
+/**
+ * \return true if #WM_operator_repeat can run
* simple check for now but may become more involved.
- * To be sure the operator can run call WM_operator_poll(C, op->type) also, since this call
- * checks if WM_operator_repeat() can run at all, not that it WILL run at any time. */
+ * To be sure the operator can run call `WM_operator_poll(C, op->type)` also, since this call
+ * checks if WM_operator_repeat() can run at all, not that it WILL run at any time.
+ */
bool WM_operator_repeat_check(const bContext *UNUSED(C), wmOperator *op)
{
if (op->type->exec != NULL) {
@@ -1043,8 +1056,9 @@ bool WM_operator_last_properties_store(wmOperator *UNUSED(op))
#endif
-static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
- PointerRNA *properties, ReportList *reports, const bool poll_only)
+static int wm_operator_invoke(
+ bContext *C, wmOperatorType *ot, wmEvent *event,
+ PointerRNA *properties, ReportList *reports, const bool poll_only)
{
int retval = OPERATOR_PASS_THROUGH;
@@ -1141,7 +1155,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
}
if (wrap) {
- rcti *winrect = NULL;
+ const rcti *winrect = NULL;
ARegion *ar = CTX_wm_region(C);
ScrArea *sa = CTX_wm_area(C);
@@ -1150,7 +1164,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
{
winrect = &ar->winrct;
}
- else if (sa) {
+ else if (sa && BLI_rcti_isect_pt_v(&sa->totrct, &event->x)) {
winrect = &sa->totrct;
}
@@ -1179,12 +1193,15 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
return retval;
}
-/* WM_operator_name_call is the main accessor function
+/**
+ * #WM_operator_name_call is the main accessor function
* this is for python to access since its done the operator lookup
*
- * invokes operator in context */
-static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports,
- const short context, const bool poll_only)
+ * invokes operator in context
+ */
+static int wm_operator_call_internal(
+ bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports,
+ const short context, const bool poll_only)
{
wmEvent *event;
@@ -1324,13 +1341,16 @@ int WM_operator_name_call(bContext *C, const char *opstring, short context, Poin
return 0;
}
-/* Similar to WM_operator_name_call called with WM_OP_EXEC_DEFAULT context.
- * - wmOperatorType is used instead of operator name since python already has the operator type
- * - poll() must be called by python before this runs.
- * - reports can be passed to this function (so python can report them as exceptions)
+/**
+ * Similar to #WM_operator_name_call called with #WM_OP_EXEC_DEFAULT context.
+ *
+ * - #wmOperatorType is used instead of operator name since python already has the operator type.
+ * - `poll()` must be called by python before this runs.
+ * - reports can be passed to this function (so python can report them as exceptions).
*/
-int WM_operator_call_py(bContext *C, wmOperatorType *ot, short context,
- PointerRNA *properties, ReportList *reports, const bool is_undo)
+int WM_operator_call_py(
+ bContext *C, wmOperatorType *ot, short context,
+ PointerRNA *properties, ReportList *reports, const bool is_undo)
{
int retval = OPERATOR_CANCELLED;
@@ -1607,7 +1627,8 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve
}
}
-/* Check whether operator is allowed to run in case interface is locked,
+/**
+ * Check whether operator is allowed to run in case interface is locked,
* If interface is unlocked, will always return truth.
*/
static bool wm_operator_check_locked_interface(bContext *C, wmOperatorType *ot)
@@ -2610,11 +2631,12 @@ void WM_event_fileselect_event(wmWindowManager *wm, void *ophandle, int eventval
/* operator is supposed to have a filled "path" property */
/* optional property: filetype (XXX enum?) */
-/* Idea is to keep a handler alive on window queue, owning the operator.
+/**
+ * The idea here is to keep a handler alive on window queue, owning the operator.
* The filewindow can send event to make it execute, thus ensuring
* executing happens outside of lower level queues, with UI refreshed.
- * Should also allow multiwin solutions */
-
+ * Should also allow multiwin solutions
+ */
void WM_event_add_fileselect(bContext *C, wmOperator *op)
{
wmEventHandler *handler, *handlernext;
@@ -2760,7 +2782,7 @@ void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
wmEventHandler *WM_event_add_ui_handler(
const bContext *C, ListBase *handlers,
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
- void *userdata, const bool accept_dbl_click)
+ void *userdata, const char flag)
{
wmEventHandler *handler = MEM_callocN(sizeof(wmEventHandler), "event ui handler");
handler->ui_handle = ui_handle;
@@ -2777,9 +2799,8 @@ wmEventHandler *WM_event_add_ui_handler(
handler->ui_menu = NULL;
}
- if (accept_dbl_click) {
- handler->flag |= WM_HANDLER_ACCEPT_DBL_CLICK;
- }
+ BLI_assert((flag & WM_HANDLER_DO_FREE) == 0);
+ handler->flag = flag;
BLI_addhead(handlers, handler);
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index 6bc858e861a..f8258d18c1a 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -157,8 +157,8 @@ static void wm_job_main_thread_yield(wmJob *wm_job, bool ending)
BLI_ticket_mutex_lock(wm_job->main_thread_mutex);
}
-/* finds:
- * if type or owner, compare for it, otherwise any matching job
+/**
+ * Finds if type or owner, compare for it, otherwise any matching job.
*/
static wmJob *wm_job_find(wmWindowManager *wm, void *owner, const int job_type)
{
@@ -185,9 +185,12 @@ static wmJob *wm_job_find(wmWindowManager *wm, void *owner, const int job_type)
/* ******************* public API ***************** */
-/* returns current or adds new job, but doesnt run it */
-/* every owner only gets a single job, adding a new one will stop running job and
- * when stopped it starts the new one */
+/**
+ * \return current job or adds new job, but doesnt run it.
+ *
+ * \note every owner only gets a single job,
+ * adding a new one will stop running job and when stopped it starts the new one.
+ */
wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type)
{
wmJob *wm_job = wm_job_find(wm, owner, job_type);
@@ -375,8 +378,10 @@ static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test)
// if (suspend) printf("job suspended: %s\n", test->name);
}
-/* if job running, the same owner gave it a new job */
-/* if different owner starts existing startjob, it suspends itself */
+/**
+ * if job running, the same owner gave it a new job.
+ * if different owner starts existing startjob, it suspends itself
+ */
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
{
if (wm_job->running) {
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index bdb45712f22..d02b42bd8ed 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -577,12 +577,13 @@ void WM_operator_bl_idname(char *to, const char *from)
to[0] = 0;
}
-/* Print a string representation of the operator, with the args that it runs so python can run it again.
+/**
+ * Print a string representation of the operator, with the args that it runs so python can run it again.
*
* When calling from an existing wmOperator, better to use simple version:
- * WM_operator_pystring(C, op);
+ * `WM_operator_pystring(C, op);`
*
- * Note: both op and opptr may be NULL (op is only used for macro operators).
+ * \note Both \a op and \a opptr may be `NULL` (\a op is only used for macro operators).
*/
char *WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args, const bool macro_args,
wmOperatorType *ot, PointerRNA *opptr)
@@ -1722,18 +1723,20 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op,
return OPERATOR_RUNNING_MODAL;
}
-/* Same as WM_operator_props_popup but don't use operator redo.
- * just wraps WM_operator_props_dialog_popup.
+/**
+ * Same as #WM_operator_props_popup but don't use operator redo.
+ * just wraps #WM_operator_props_dialog_popup.
*/
int WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return wm_operator_props_popup_ex(C, op, false, false);
}
-/* Same as WM_operator_props_popup but call the operator first,
+/**
+ * Same as #WM_operator_props_popup but call the operator first,
* This way - the button values correspond to the result of the operator.
- * Without this, first access to a button will make the result jump,
- * see [#32452] */
+ * Without this, first access to a button will make the result jump, see T32452.
+ */
int WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return wm_operator_props_popup_ex(C, op, true, true);
@@ -3166,9 +3169,10 @@ void WM_paint_cursor_end(wmWindowManager *wm, void *handle)
/* **************** Border gesture *************** */
-/* Border gesture has two types:
- * 1) WM_GESTURE_CROSS_RECT: starts a cross, on mouse click it changes to border
- * 2) WM_GESTURE_RECT: starts immediate as a border, on mouse click or release it ends
+/**
+ * Border gesture has two types:
+ * -# #WM_GESTURE_CROSS_RECT: starts a cross, on mouse click it changes to border.
+ * -# #WM_GESTURE_RECT: starts immediate as a border, on mouse click or release it ends.
*
* It stores 4 values (xmin, xmax, ymin, ymax) and event it ended with (event_type)
*/
@@ -4107,12 +4111,15 @@ typedef enum {
RC_PROP_REQUIRE_BOOL = 4,
} RCPropFlags;
-/* attempt to retrieve the rna pointer/property from an rna path;
- * returns 0 for failure, 1 for success, and also 1 if property is not
- * set */
-static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op,
- const char *name, PointerRNA *r_ptr,
- PropertyRNA **r_prop, int req_length, RCPropFlags flags)
+/**
+ * Attempt to retrieve the rna pointer/property from an rna path.
+ *
+ * \return 0 for failure, 1 for success, and also 1 if property is not set.
+ */
+static int radial_control_get_path(
+ PointerRNA *ctx_ptr, wmOperator *op,
+ const char *name, PointerRNA *r_ptr,
+ PropertyRNA **r_prop, int req_length, RCPropFlags flags)
{
PropertyRNA *unused_prop;
int len;
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 4ce2415e310..d081644fa61 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -54,11 +54,12 @@
#include "WM_api.h"
#include "wm_subwindow.h"
-/* wmSubWindow stored in wmWindow... but not exposed outside this C file */
-/* it seems a bit redundant (area regions can store it too, but we keep it
- * because we can store all kind of future opengl fanciness here */
-
-/* we use indices and array because:
+/**
+ * \note #wmSubWindow stored in #wmWindow but not exposed outside this C file,
+ * it seems a bit redundant (area regions can store it too, but we keep it
+ * because we can store all kind of future opengl fanciness here.
+ *
+ * We use indices and array because:
* - index has safety, no pointers from this C file hanging around
* - fast lookups of indices with array, list would give overhead
* - old code used it this way...
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 6d1bf51902c..f704e985f8f 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1117,10 +1117,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
}
-/* This timer system only gives maximum 1 timer event per redraw cycle,
+/**
+ * This timer system only gives maximum 1 timer event per redraw cycle,
* to prevent queues to get overloaded.
- * Timer handlers should check for delta to decide if they just
- * update, or follow real time.
+ * Timer handlers should check for delta to decide if they just update, or follow real time.
* Timer handlers can also set duration to match frames passed
*/
static int wm_window_timer(const bContext *C)
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index 061b869f46c..9127d3ec6f0 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -47,8 +47,8 @@ struct wmWidget;
typedef struct wmEventHandler {
struct wmEventHandler *next, *prev;
- int type; /* WM_HANDLER_DEFAULT, ... */
- int flag; /* WM_HANDLER_BLOCKING, ... */
+ char type; /* WM_HANDLER_DEFAULT, ... */
+ char flag; /* WM_HANDLER_BLOCKING, ... */
/* keymap handler */
wmKeyMap *keymap; /* pointer to builtin/custom keymaps */
@@ -81,13 +81,6 @@ enum {
WM_HANDLER_FILESELECT
};
-/* handler flag */
-enum {
- WM_HANDLER_BLOCKING = (1 << 0), /* after this handler all others are ignored */
- WM_HANDLER_DO_FREE = (1 << 1), /* handler tagged to be freed in wm_handlers_do() */
- WM_HANDLER_ACCEPT_DBL_CLICK = (1 << 2), /* handler accepts double key press events */
-};
-
/* wm_event_system.c */
void wm_event_free_all (wmWindow *win);
void wm_event_free (wmEvent *event);
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 09047206694..c4647a86b93 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -651,9 +651,9 @@ elseif(WIN32)
execute_process(
COMMAND \${CMAKE_COMMAND} -E make_directory
- \"\${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python/lib\"
+ \"\${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python\"
COMMAND \${CMAKE_COMMAND} -E
- chdir \"\${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python/lib\"
+ chdir \"\${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/python\"
\${CMAKE_COMMAND} -E
tar xzfv \"\${PYTHON_ZIP}\"
)
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 8c4ec595eb3..29fad1352fd 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -680,7 +680,11 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
/* If this is a stack overflow then we can't walk the stack, so just show
* where the error happened */
if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) {
+#ifdef NDEBUG
+ TerminateProcess(GetCurrentProcess(), SIGSEGV);
+#else
blender_crash_handler(SIGSEGV);
+#endif
}
return EXCEPTION_EXECUTE_HANDLER;
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index 34b814d7416..c3ce98ed27a 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -111,6 +111,8 @@ typedef struct PyObjectPlus_Proxy {
/* Opposite of BGE_PROXY_REF */
#define BGE_PROXY_FROM_REF(_self) (((PyObjectPlus *)_self)->GetProxy())
+/* Same as 'BGE_PROXY_REF' but doesn't incref. */
+#define BGE_PROXY_FROM_REF_BORROW(_self) _bge_proxy_from_ref_borrow((void *)_self)
// This must be the first line of each
@@ -631,6 +633,17 @@ public:
#ifdef WITH_PYTHON
PyObject *PyUnicode_From_STR_String(const STR_String& str);
+
+inline PyObject *_bge_proxy_from_ref_borrow(void *self_v)
+{
+ PyObject *self_proxy = BGE_PROXY_FROM_REF(self_v);
+ /* this is typically _very_ bad practice,
+ * however we know the proxy is owned by 'self_v' */
+ self_proxy->ob_refcnt--;
+ return self_proxy;
+}
+
#endif
+
#endif /* __PYOBJECTPLUS_H__ */
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
index 6f34f8710c1..6841d2a8ea1 100644
--- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
@@ -265,13 +265,8 @@ bool SCA_PropertySensor::CheckPropertyCondition()
//the concept of Edge and Level triggering has unwanted effect for KX_PROPSENSOR_CHANGED
//see Game Engine bugtracker [ #3809 ]
- if (m_checktype != KX_PROPSENSOR_CHANGED)
- {
- m_recentresult=result;
- } else
- {
- m_recentresult=result;//true;
- }
+ m_recentresult = result;
+
return result;
}
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 14a7324d2b9..e77960b99b1 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -2530,7 +2530,9 @@ int KX_GameObject::pyattr_set_record_animation(void *self_v, const KX_PYATTRIBUT
PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetWorldPosition());
@@ -2552,7 +2554,9 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D
PyObject *KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetLocalPosition());
@@ -2574,7 +2578,9 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D
PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
if (self->GetPhysicsController1())
@@ -2586,7 +2592,9 @@ PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIB
PyObject *KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
+ return Matrix_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3, 3,
+ mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetWorldOrientation());
@@ -2611,7 +2619,9 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT
PyObject *KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
+ return Matrix_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3, 3,
+ mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetLocalOrientation());
@@ -2635,7 +2645,9 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT
PyObject *KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetWorldScaling());
@@ -2657,7 +2669,9 @@ int KX_GameObject::pyattr_set_worldScaling(void *self_v, const KX_PYATTRIBUTE_DE
PyObject *KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->NodeGetLocalScaling());
@@ -2759,7 +2773,9 @@ int KX_GameObject::pyattr_set_worldTransform(void *self_v, const KX_PYATTRIBUTE_
PyObject *KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(GetLinearVelocity(false));
@@ -2781,7 +2797,9 @@ int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRI
PyObject *KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(GetLinearVelocity(true));
@@ -2803,7 +2821,9 @@ int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRI
PyObject *KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(GetAngularVelocity(false));
@@ -2825,7 +2845,9 @@ int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTR
PyObject *KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(GetAngularVelocity(true));
@@ -2946,7 +2968,9 @@ PyObject *KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE
PyObject *KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 4,
+ mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR);
#else
KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
return PyObjectFrom(self->GetObjectColor());
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
index 717d58e0ca7..12abcb250a7 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
@@ -522,7 +522,9 @@ static Mathutils_Callback mathutils_obactu_vector_cb = {
PyObject *KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV);
}
int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -538,7 +540,9 @@ int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *a
PyObject *KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV);
}
int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
index 237f485134a..b42200783e4 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
@@ -87,8 +87,6 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
if (gameOb->GetSGNode())
{
- PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode());
-
MT_Vector3 attachPos,attachDir,attachAxle;
if(!PyVecTo(pylistPos,attachPos)) {
PyErr_SetString(PyExc_AttributeError,
@@ -115,6 +113,7 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
return NULL;
}
+ PHY_IMotionState *motionState = new KX_MotionState(gameOb->GetSGNode());
m_vehicle->AddWheel(motionState,attachPos,attachDir,attachAxle,suspensionRestLength,wheelRadius,hasSteering);
}
diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp
index f6caaf03066..8678b058761 100644
--- a/source/gameengine/Ketsji/KX_WorldInfo.cpp
+++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp
@@ -418,7 +418,9 @@ PyObject *KX_WorldInfo::pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRI
PyObject *KX_WorldInfo::pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_MIST_COLOR);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_MIST_COLOR);
#else
KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
return PyObjectFrom(MT_Vector3(self->m_mistcolor));
@@ -442,7 +444,9 @@ PyObject *KX_WorldInfo::pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_BACK_COLOR);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_BACK_COLOR);
#else
KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
return PyObjectFrom(MT_Vector3(self->m_backgroundcolor));
@@ -465,7 +469,9 @@ int KX_WorldInfo::pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *
PyObject *KX_WorldInfo::pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
- return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_AMBIENT_COLOR);
+ return Vector_CreatePyObject_cb(
+ BGE_PROXY_FROM_REF_BORROW(self_v), 3,
+ mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_AMBIENT_COLOR);
#else
KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
return PyObjectFrom(MT_Vector3(self->m_ambientcolor));
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index edc5b91c4c0..8ea2b4f299d 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -2203,8 +2203,6 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA
MFace *mf;
MVert *mv;
- int flen;
-
if (CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE);
MTFace *tf;
@@ -2214,6 +2212,8 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA
for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) {
if (tf->mode & TF_DYNAMIC) {
+ int flen;
+
if (mf->v4) {
tot_bt_tris += 2;
flen = 4;
@@ -2255,12 +2255,10 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA
fv_pt = quad_verts;
*poly_index_pt++ = origi;
*poly_index_pt++ = origi;
- flen = 4;
}
else {
fv_pt = tri_verts;
*poly_index_pt++ = origi;
- flen = 3;
}
for (; *fv_pt > -1; fv_pt++) {
diff --git a/tests/gtests/blenlib/BLI_stack_test.cc b/tests/gtests/blenlib/BLI_stack_test.cc
index 08701356816..44956a589dc 100644
--- a/tests/gtests/blenlib/BLI_stack_test.cc
+++ b/tests/gtests/blenlib/BLI_stack_test.cc
@@ -11,6 +11,14 @@ extern "C" {
#define SIZE 1024
+/* number of items per chunk. use a small value to expose bugs */
+#define STACK_CHUNK_SIZE 8
+
+/* Ensure block size is set to #STACK_NEW_EX_ARGS */
+#define BLI_stack_new(esize, descr) \
+ BLI_stack_new_ex(esize, descr, esize * STACK_CHUNK_SIZE)
+
+
TEST(stack, Empty)
{
BLI_Stack *stack;
@@ -110,18 +118,60 @@ TEST(stack, Peek)
EXPECT_EQ(BLI_stack_is_empty(stack), true);
}
+/* Check that clearing the stack leaves in it a correct state. */
+TEST(stack, Clear)
+{
+ const int tot_rerun = 4;
+ int rerun;
+
+ /* based on range test */
+ int tot = SIZE;
+ BLI_Stack *stack;
+ int in, out;
+
+ /* use a small chunk size to ensure we test */
+ stack = BLI_stack_new(sizeof(in), __func__);
+
+ for (rerun = 0; rerun < tot_rerun; rerun++) {
+ for (in = 0; in < tot; in++) {
+ BLI_stack_push(stack, (void *)&in);
+ }
+
+ BLI_stack_clear(stack);
+ EXPECT_EQ(BLI_stack_is_empty(stack), true);
+
+ /* and again, this time check its valid */
+ for (in = 0; in < tot; in++) {
+ BLI_stack_push(stack, (void *)&in);
+ }
+
+ for (in = tot - 1; in >= 0; in--) {
+ EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ BLI_stack_pop(stack, (void *)&out);
+ EXPECT_EQ(in, out);
+ }
+
+ EXPECT_EQ(BLI_stack_is_empty(stack), true);
+
+ /* without this, we wont test case when mixed free/used */
+ tot /= 2;
+ }
+
+ BLI_stack_free(stack);
+}
+
TEST(stack, Reuse)
{
const int sizes[] = {3, 11, 81, 400, 999, 12, 1, 9721, 7, 99, 5, 0};
int sizes_test[ARRAY_SIZE(sizes)];
const int *s;
- int in, out, i;
+ int out, i;
int sum, sum_test;
BLI_Stack *stack;
- stack = BLI_stack_new(sizeof(in), __func__);
+ stack = BLI_stack_new(sizeof(i), __func__);
/* add a bunch of numbers, ensure we get same sum out */
sum = 0;