diff options
49 files changed, 575 insertions, 175 deletions
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 0e0dc382ca3..1ec9b00d4ca 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -245,7 +245,7 @@ if(WITH_BOOST) set(Boost_USE_STATIC_LIBS ON) endif() set(Boost_USE_MULTITHREADED ON) - set(__boost_packages filesystem regex system thread date_time) + set(__boost_packages filesystem regex thread date_time) if(WITH_CYCLES_OSL) if(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6")) list(APPEND __boost_packages wave) @@ -261,6 +261,7 @@ if(WITH_BOOST) if(WITH_OPENVDB) list(APPEND __boost_packages iostreams) endif() + list(APPEND __boost_packages system) find_package(Boost 1.48 COMPONENTS ${__boost_packages}) if(NOT Boost_FOUND) # try to find non-multithreaded if -mt not found, this flag diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index b34d4dfe6f1..9834cda43bc 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = Blender # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "V2.7x" +PROJECT_NUMBER = "V2.8x" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/python_api/sphinx_doc_update.py b/doc/python_api/sphinx_doc_update.py new file mode 100755 index 00000000000..c93f1676d52 --- /dev/null +++ b/doc/python_api/sphinx_doc_update.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 + +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Contributor(s): Bastien Montagne +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8 compliant> + +""" +This is a helper script to generate Blender Python API documentation (using Sphinx), and update server data using rsync. + +You'll need to specify your user login and password, obviously. + +Example usage: + + ./sphinx_doc_update.py --mirror ../../../docs/remote_api_backup/ --source ../.. --blender ../../../build_cmake/bin/blender --user foobar --password barfoo + +""" + +import os +import shutil +import subprocess +import sys +import tempfile +import zipfile + + +DEFAULT_RSYNC_SERVER = "www.blender.org" +DEFAULT_RSYNC_ROOT = "/api/" +DEFAULT_SYMLINK_ROOT = "/data/www/vhosts/www.blender.org/api" + + +def argparse_create(): + import argparse + global __doc__ + + # When --help or no args are given, print this help + usage_text = __doc__ + + parser = argparse.ArgumentParser(description=usage_text, + formatter_class=argparse.RawDescriptionHelpFormatter) + + parser.add_argument( + "--mirror", dest="mirror_dir", + metavar='PATH', required=True, + help="Path to local rsync mirror of api doc server") + parser.add_argument( + "--source", dest="source_dir", + metavar='PATH', required=True, + help="Path to Blender git repository") + parser.add_argument( + "--blender", dest="blender", + metavar='PATH', required=True, + help="Path to Blender executable") + parser.add_argument( + "--rsync-server", dest="rsync_server", default=DEFAULT_RSYNC_SERVER, + metavar='RSYNCSERVER', type=str, required=False, + help=("rsync server address")) + parser.add_argument( + "--rsync-root", dest="rsync_root", default=DEFAULT_RSYNC_ROOT, + metavar='RSYNCROOT', type=str, required=False, + help=("Root path of API doc on rsync server")) + parser.add_argument( + "--user", dest="user", + metavar='USER', type=str, required=True, + help=("User to login on rsync server")) + parser.add_argument( + "--password", dest="password", + metavar='PASSWORD', type=str, required=True, + help=("Password to login on rsync server")) + + return parser + + +def main(): + # ---------- + # Parse Args + + args = argparse_create().parse_args() + + rsync_base = "rsync://%s@%s:%s" % (args.user, args.rsync_server, args.rsync_root) + + # I) Update local mirror using rsync. + rsync_mirror_cmd = ("rsync", "--delete-after", "-avzz", rsync_base, args.mirror_dir) + subprocess.run(rsync_mirror_cmd, env=dict(os.environ, RSYNC_PASSWORD=args.password)) + + with tempfile.TemporaryDirectory() as tmp_dir: + # II) Generate doc source in temp dir. + doc_gen_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1", + "--python", "%s/doc/python_api/sphinx_doc_gen.py" % args.source_dir, "--", + "--output", tmp_dir) + subprocess.run(doc_gen_cmd) + + # III) Get Blender version info. + blenver = "" + getver_file = os.path.join(tmp_dir, "blendver.txt") + getver_script = ("" + "import sys, bpy\n" + "with open(sys.argv[-1], 'w') as f:\n" + " f.write('%d_%d%s_release' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n" + " if bpy.app.version_cycle in {'rc', 'release'} else '%d_%d_%d' % bpy.app.version)\n") + get_ver_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1", + "--python-expr", getver_script, "--", getver_file) + subprocess.run(get_ver_cmd) + with open(getver_file) as f: + blenver = f.read() + os.remove(getver_file) + + # IV) Build doc. + curr_dir = os.getcwd() + os.chdir(tmp_dir) + sphinx_cmd = ("sphinx-build", "-b", "html", "sphinx-in", "sphinx-out") + subprocess.run(sphinx_cmd) + shutil.rmtree(os.path.join("sphinx-out", ".doctrees")) + os.chdir(curr_dir) + + # V) Cleanup existing matching dir in server mirror (if any), and copy new doc. + api_name = "blender_python_api_%s" % blenver + api_dir = os.path.join(args.mirror_dir, api_name) + if os.path.exists(api_dir): + shutil.rmtree(api_dir) + os.rename(os.path.join(tmp_dir, "sphinx-out"), api_dir) + + # VI) Create zip archive. + zip_name = "blender_python_reference_%s" % blenver + zip_path = os.path.join(args.mirror_dir, zip_name) + with zipfile.ZipFile(zip_path, 'w') as zf: + for de in os.scandir(api_dir): + zf.write(de.path, arcname=os.path.join(zip_name, de.name)) + os.rename(zip_path, os.path.join(api_dir, "%s.zip" % zip_name)) + + # VII) Create symlinks and html redirects. + #~ os.symlink(os.path.join(DEFAULT_SYMLINK_ROOT, api_name, "contents.html"), os.path.join(api_dir, "index.html")) + os.symlink("./contents.html", os.path.join(api_dir, "index.html")) + if blenver.endswith("release"): + symlink = os.path.join(args.mirror_dir, "blender_python_api_current") + os.remove(symlink) + os.symlink("./%s" % api_name, symlink) + with open(os.path.join(args.mirror_dir, "250PythonDoc/index.html"), 'w') as f: + f.write("<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\"" + "content=\"0;url=../%s/\"></head><body>Redirecting...</body></html>" % api_name) + else: + symlink = os.path.join(args.mirror_dir, "blender_python_api_master") + os.remove(symlink) + os.symlink("./%s" % api_name, symlink) + with open(os.path.join(args.mirror_dir, "blender_python_api/index.html"), 'w') as f: + f.write("<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\"" + "content=\"0;url=../%s/\"></head><body>Redirecting...</body></html>" % api_name) + + # VIII) Upload (first do a dry-run so user can ensure everything is OK). + print("Doc generated in local mirror %s, please check it before uploading " + "(hit [Enter] to continue, [Ctrl-C] to exit):" % api_dir) + sys.stdin.read(1) + + rsync_mirror_cmd = ("rsync", "--dry-run", "--delete-after", "-avzz", args.mirror_dir, rsync_base) + subprocess.run(rsync_mirror_cmd, env=dict(os.environ, RSYNC_PASSWORD=args.password)) + + print("Rsync upload simulated, please check every thing is OK (hit [Enter] to continue, [Ctrl-C] to exit):") + sys.stdin.read(1) + + rsync_mirror_cmd = ("rsync", "--delete-after", "-avzz", args.mirror_dir, rsync_base) + subprocess.run(rsync_mirror_cmd, env=dict(os.environ, RSYNC_PASSWORD=args.password)) + + +if __name__ == "__main__": + main() diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h index efe540a8518..fd97a63efb5 100644 --- a/intern/cycles/kernel/geom/geom_volume.h +++ b/intern/cycles/kernel/geom/geom_volume.h @@ -69,7 +69,7 @@ ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, # if __CUDA_ARCH__ >= 300 CUtexObject tex = kernel_tex_fetch(__bindless_mapping, desc.offset); float f = kernel_tex_image_interp_3d_float(tex, P.x, P.y, P.z); - float4 r = make_float4(f, f, f, 1.0); + float4 r = make_float4(f, f, f, 1.0f); # else float4 r = volume_image_texture_3d(desc.offset, P.x, P.y, P.z); # endif diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index 3775934f293..7b30df04550 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -112,7 +112,7 @@ template<typename T> struct texture_image { ccl_always_inline float4 read(uchar r) { float f = r*(1.0f/255.0f); - return make_float4(f, f, f, 1.0); + return make_float4(f, f, f, 1.0f); } ccl_always_inline float4 read(float r) diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 5d02be1fa2f..378ce650129 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -296,7 +296,7 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, /* float, byte and half */ else { float f = kernel_tex_image_interp_float(tex, x, y); - r = make_float4(f, f, f, 1.0); + r = make_float4(f, f, f, 1.0f); } # endif #endif diff --git a/intern/cycles/kernel/svm/svm_voxel.h b/intern/cycles/kernel/svm/svm_voxel.h index d2cc2c3730e..f54f4e8e888 100644 --- a/intern/cycles/kernel/svm/svm_voxel.h +++ b/intern/cycles/kernel/svm/svm_voxel.h @@ -50,7 +50,7 @@ ccl_device void svm_node_tex_voxel(KernelGlobals *kg, r = kernel_tex_image_interp_3d_float4(tex, co.x, co.y, co.z); else { float f = kernel_tex_image_interp_3d_float(tex, co.x, co.y, co.z); - r = make_float4(f, f, f, 1.0); + r = make_float4(f, f, f, 1.0f); } # else /* __CUDA_ARCH__ >= 300 */ r = volume_image_texture_3d(id, co.x, co.y, co.z); diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 5445fd3c29c..2d297c33446 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -1650,10 +1650,10 @@ void MeshManager::device_update_displacement_images(Device *device, foreach(Mesh *mesh, scene->meshes) { if(mesh->need_update) { foreach(Shader *shader, mesh->used_shaders) { - if(shader->graph_bump == NULL) { + if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) { continue; } - foreach(ShaderNode* node, shader->graph_bump->nodes) { + foreach(ShaderNode* node, shader->graph->nodes) { if(node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) { continue; } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index c916e4a5f5e..dd733f73306 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -798,6 +798,7 @@ class CameraNode : public ShaderNode { public: SHADER_NODE_CLASS(CameraNode) bool has_spatial_varying() { return true; } + virtual int get_group() { return NODE_GROUP_LEVEL_2; } }; class FresnelNode : public ShaderNode { diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 727bc9a01fb..653c0ccb472 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -838,7 +838,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) case KeyRelease: { XKeyEvent *xke = &(xe->xkey); - KeySym key_sym; + KeySym key_sym = XK_VoidSymbol; KeySym key_sym_str; char ascii; #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) @@ -870,26 +870,30 @@ GHOST_SystemX11::processEvent(XEvent *xe) * * To address this, we: * - * - Try to get a 'number' key_sym using XLookupKeysym (with or without shift modifier). + * - Try to get a 'number' key_sym using XLookupKeysym (with virtual shift modifier), + * in a very restrictive set of cases. * - Fallback to XLookupString to get a key_sym from active user-defined keymap. * - * Note that this enforces users to use an ascii-compatible keymap with Blender - but at least it gives - * predictable and consistent results. + * Note that: + * - This effectively 'lock' main number keys to always output number events (except when using alt-gr). + * - This enforces users to use an ascii-compatible keymap with Blender - but at least it gives + * predictable and consistent results. * * Also, note that nothing in XLib sources [1] makes it obvious why those two functions give different * key_sym results... * * [1] http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/KeyBind.c */ - if ((xke->keycode >= 10 && xke->keycode < 20)) { + /* Mode_switch 'modifier' is AltGr - when this one or Shift are enabled, we do not want to apply + * that 'forced number' hack. */ + const unsigned int mode_switch_mask = XkbKeysymToModifiers(xke->display, XK_Mode_switch); + const unsigned int number_hack_forbidden_kmods_mask = mode_switch_mask | ShiftMask; + if ((xke->keycode >= 10 && xke->keycode < 20) && ((xke->state & number_hack_forbidden_kmods_mask) == 0)) { key_sym = XLookupKeysym(xke, ShiftMask); if (!((key_sym >= XK_0) && (key_sym <= XK_9))) { - key_sym = XLookupKeysym(xke, 0); + key_sym = XK_VoidSymbol; } } - else { - key_sym = XLookupKeysym(xke, 0); - } if (!XLookupString(xke, &ascii, 1, &key_sym_str, NULL)) { ascii = '\0'; diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject 9628dc1922be2fb6281bc66f5f7512c2a57c294 +Subproject dc166057192ea882b5cc70484d4c8bacd7cb41b diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png Binary files differindex fa893b4be0d..60956db2576 100644 --- a/release/datafiles/splash.png +++ b/release/datafiles/splash.png diff --git a/release/datafiles/splash_2x.png b/release/datafiles/splash_2x.png Binary files differindex f8dd2bbeaf3..3a5000c6bbc 100644 --- a/release/datafiles/splash_2x.png +++ b/release/datafiles/splash_2x.png diff --git a/release/datafiles/splash_scale.sh b/release/datafiles/splash_scale.sh new file mode 100755 index 00000000000..8a3f2c6d1eb --- /dev/null +++ b/release/datafiles/splash_scale.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Use this script to generate splash.png from splash_2x.png. +# Supposed to give best quality image. +# +# Based on ImageMagic documentation, which is interesting +# to read anyway: +# +# http://www.imagemagick.org/Usage/filter +# http://www.imagemagick.org/Usage/filter/nicolas/ + +convert \ + splash_2x.png \ + -colorspace RGB \ + -filter Cosine \ + -resize 50% \ + -colorspace sRGB \ + splash.png diff --git a/release/datafiles/splash_template.xcf b/release/datafiles/splash_template.xcf Binary files differindex b3141471c51..12719b5c155 100644 --- a/release/datafiles/splash_template.xcf +++ b/release/datafiles/splash_template.xcf diff --git a/release/scripts/addons b/release/scripts/addons -Subproject 407d0ea752b3af73d3f13ba072671bd09eefecb +Subproject 06dad53c80801e0e0919f086040e3d9c31bbd0a diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib -Subproject 9f29e18707917ec5be262431d2e09dbb85332f4 +Subproject 04af69be141a5757fc60b44cc1a5b72db524af3 diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index b9cb7f24ebd..1748d1d3738 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -411,6 +411,20 @@ class VIEW3D_MT_uv_map(Menu): layout.operator("uv.reset") +class VIEW3D_MT_edit_proportional(Menu): + bl_label = "Proportional Editing" + + def draw(self, context): + layout = self.layout + + layout.props_enum(context.tool_settings, "proportional_edit") + + layout.separator() + + layout.label("Falloff:") + layout.props_enum(context.tool_settings, "proportional_edit_falloff") + + # ********** View menus ********** @@ -2311,8 +2325,7 @@ class VIEW3D_MT_edit_mesh(Menu): layout.separator() layout.prop(toolsettings, "use_mesh_automerge") - layout.prop_menu_enum(toolsettings, "proportional_edit") - layout.prop_menu_enum(toolsettings, "proportional_edit_falloff") + layout.menu("VIEW3D_MT_edit_proportional") layout.separator() @@ -2427,6 +2440,8 @@ class VIEW3D_MT_edit_mesh_vertices(Menu): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' + with_bullet = bpy.app.build_options.bullet + layout.operator("mesh.merge") layout.operator("mesh.rip_move") layout.operator("mesh.rip_move_fill") @@ -2447,7 +2462,8 @@ class VIEW3D_MT_edit_mesh_vertices(Menu): layout.separator() layout.operator("mesh.bevel").vertex_only = True - layout.operator("mesh.convex_hull") + if with_bullet: + layout.operator("mesh.convex_hull") layout.operator("mesh.vertices_smooth") layout.operator("mesh.remove_doubles") @@ -2681,8 +2697,7 @@ def draw_curve(self, context): layout.separator() - layout.prop_menu_enum(toolsettings, "proportional_edit") - layout.prop_menu_enum(toolsettings, "proportional_edit_falloff") + layout.menu("VIEW3D_MT_edit_proportional") layout.separator() @@ -2841,8 +2856,7 @@ class VIEW3D_MT_edit_meta(Menu): layout.separator() - layout.prop_menu_enum(toolsettings, "proportional_edit") - layout.prop_menu_enum(toolsettings, "proportional_edit_falloff") + layout.menu("VIEW3D_MT_edit_proportional") layout.separator() @@ -2879,8 +2893,7 @@ class VIEW3D_MT_edit_lattice(Menu): layout.separator() - layout.prop_menu_enum(toolsettings, "proportional_edit") - layout.prop_menu_enum(toolsettings, "proportional_edit_falloff") + layout.menu("VIEW3D_MT_edit_proportional") class VIEW3D_MT_edit_armature(Menu): @@ -3040,8 +3053,7 @@ class VIEW3D_MT_edit_gpencil(Menu): layout.separator() - layout.prop_menu_enum(toolsettings, "proportional_edit") - layout.prop_menu_enum(toolsettings, "proportional_edit_falloff") + layout.menu("VIEW3D_MT_edit_proportional") layout.separator() diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc index 45bf9b7ab8a..14bcf6731ea 100644 --- a/source/blender/alembic/intern/abc_hair.cc +++ b/source/blender/alembic/intern/abc_hair.cc @@ -59,7 +59,7 @@ AbcHairWriter::AbcHairWriter(Scene *scene, { m_psys = psys; - OCurves curves(parent->alembicXform(), m_name, m_time_sampling); + OCurves curves(parent->alembicXform(), psys->name, m_time_sampling); m_schema = curves.getSchema(); } diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc index 322bb906bf5..03014547416 100644 --- a/source/blender/alembic/intern/abc_points.cc +++ b/source/blender/alembic/intern/abc_points.cc @@ -67,7 +67,7 @@ AbcPointsWriter::AbcPointsWriter(Scene *scene, { m_psys = psys; - OPoints points(parent->alembicXform(), m_name, m_time_sampling); + OPoints points(parent->alembicXform(), psys->name, m_time_sampling); m_schema = points.getSchema(); } diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index d057cc341f6..477448f1835 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -599,10 +599,6 @@ struct ImportJobData { ABC_INLINE bool is_mesh_and_strands(const IObject &object) { - if (object.getNumChildren() != 2) { - return false; - } - bool has_mesh = false; bool has_curve = false; @@ -624,6 +620,9 @@ ABC_INLINE bool is_mesh_and_strands(const IObject &object) else if (ICurves::matches(md)) { has_curve = true; } + else if (IPoints::matches(md)) { + has_curve = true; + } } return has_mesh && has_curve; diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 606488f85cc..789bc8df7e5 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -783,6 +783,7 @@ void DM_vertex_attributes_from_gpu( struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs); void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, int loop); +void DM_draw_attrib_vertex_uniforms(const DMVertexAttribs *attribs); void DM_calc_tangents_names_from_gpu( const struct GPUVertexAttribs *gattribs, diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 483fefbd89c..3ae01d8148a 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,8 +27,8 @@ /* these lines are grep'd, watch out for our not-so-awesome regex * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ -#define BLENDER_VERSION 277 -#define BLENDER_SUBVERSION 3 +#define BLENDER_VERSION 278 +#define BLENDER_SUBVERSION 0 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 6 diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 0d1ca1c33ad..5f759c61bcb 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -80,6 +80,7 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm); #include "GPU_shader.h" #ifdef WITH_OPENSUBDIV +# include "BKE_depsgraph.h" # include "DNA_userdef_types.h" #endif @@ -2282,7 +2283,7 @@ static void editbmesh_calc_modifiers( { ModifierData *md, *previewmd = NULL; float (*deformedVerts)[3] = NULL; - CustomDataMask mask, previewmask = 0, append_mask = 0; + CustomDataMask mask = 0, previewmask = 0, append_mask = 0; DerivedMesh *dm = NULL, *orcodm = NULL; int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); CDMaskLink *datamasks, *curr; @@ -2566,7 +2567,7 @@ static void editbmesh_calc_modifiers( * playback performance is kept as high as possible. */ static bool calc_modifiers_skip_orco(Scene *scene, - const Object *ob, + Object *ob, bool use_render_params) { ModifierData *last_md = ob->modifiers.last; @@ -2575,9 +2576,18 @@ static bool calc_modifiers_skip_orco(Scene *scene, last_md->type == eModifierType_Subsurf && modifier_isEnabled(scene, last_md, required_mode)) { + if (U.opensubdiv_compute_type == USER_OPENSUBDIV_COMPUTE_NONE) { + return false; + } + else if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) != 0) { + return false; + } + else if ((DAG_get_eval_flags_for_object(scene, ob) & DAG_EVAL_NEED_CPU) != 0) { + return false; + } SubsurfModifierData *smd = (SubsurfModifierData *)last_md; /* TODO(sergey): Deduplicate this with checks from subsurf_ccg.c. */ - return smd->use_opensubdiv && U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE; + return smd->use_opensubdiv != 0; } return false; } @@ -3797,7 +3807,6 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, glTexCoord3fv(orco); else glVertexAttrib3fv(attribs->orco.gl_index, orco); - glUniform1i(attribs->orco.gl_info_index, 0); } /* uv texture coordinates */ @@ -3816,7 +3825,6 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, glTexCoord2fv(uv); else glVertexAttrib2fv(attribs->tface[b].gl_index, uv); - glUniform1i(attribs->tface[b].gl_info_index, 0); } /* vertex colors */ @@ -3832,17 +3840,33 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, } glVertexAttrib4fv(attribs->mcol[b].gl_index, col); - glUniform1i(attribs->mcol[b].gl_info_index, GPU_ATTR_INFO_SRGB); } /* tangent for normal mapping */ for (b = 0; b < attribs->tottang; b++) { if (attribs->tang[b].array) { /*const*/ float (*array)[4] = attribs->tang[b].array; - const float *tang = (array) ? array[a * 4 + vert] : zero; + const float *tang = (array) ? array[loop] : zero; glVertexAttrib4fv(attribs->tang[b].gl_index, tang); } - glUniform1i(attribs->tang[b].gl_info_index, 0); + } +} + +void DM_draw_attrib_vertex_uniforms(const DMVertexAttribs *attribs) +{ + int i; + if (attribs->totorco) { + glUniform1i(attribs->orco.gl_info_index, 0); + } + for (i = 0; i < attribs->tottface; i++) { + glUniform1i(attribs->tface[i].gl_info_index, 0); + } + for (i = 0; i < attribs->totmcol; i++) { + glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB); + } + + for (i = 0; i < attribs->tottang; i++) { + glUniform1i(attribs->tang[i].gl_info_index, 0); } } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 2d06bc88aa7..f2dd2a3fcf6 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -941,8 +941,10 @@ static void cdDM_drawMappedFacesGLSL( matnr = new_matnr; do_draw = setMaterial(matnr + 1, &gattribs); - if (do_draw) + if (do_draw) { DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + DM_draw_attrib_vertex_uniforms(&attribs); + } glBegin(GL_TRIANGLES); } @@ -1210,6 +1212,7 @@ static void cdDM_drawMappedFacesMat( setMaterial(userData, matnr = new_matnr, &gattribs); DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + DM_draw_attrib_vertex_uniforms(&attribs); glBegin(GL_TRIANGLES); } diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 1aba76baa2c..e51a3c3c4b0 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -1410,24 +1410,6 @@ static void emDM_drawMappedFacesTex( emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); } -static void emdm_pass_attrib_update_uniforms(const DMVertexAttribs *attribs) -{ - int i; - if (attribs->totorco) { - glUniform1i(attribs->orco.gl_info_index, 0); - } - for (i = 0; i < attribs->tottface; i++) { - glUniform1i(attribs->tface[i].gl_info_index, 0); - } - for (i = 0; i < attribs->totmcol; i++) { - glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB); - } - - for (i = 0; i < attribs->tottang; i++) { - glUniform1i(attribs->tang[i].gl_info_index, 0); - } -} - /** * \note * @@ -1548,7 +1530,7 @@ static void emDM_drawMappedFacesGLSL( do_draw = setMaterial(matnr = new_matnr, &gattribs); if (do_draw) { DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - emdm_pass_attrib_update_uniforms(&attribs); + DM_draw_attrib_vertex_uniforms(&attribs); if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) { BM_mesh_elem_index_ensure(bm, BM_LOOP); } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d736a455163..cdd7560e3c4 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1138,7 +1138,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches) /* increase user numbers */ id_us_plus((ID *)obn->data); id_us_plus((ID *)obn->gpd); - id_lib_extern((ID *)obn->dup_group); + id_us_plus((ID *)obn->dup_group); for (a = 0; a < obn->totcol; a++) id_us_plus((ID *)obn->mat[a]); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 60f1eb6b98c..5eb60a9a4f7 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -2820,12 +2820,13 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int matnr = -1; int do_draw = 0; -#define PASSATTRIB(dx, dy, vert) { \ - if (attribs.totorco) \ - index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \ - else \ - index = 0; \ - DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \ +#define PASSATTRIB(dx, dy, vert) { \ + if (attribs.totorco) \ + index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \ + else \ + index = 0; \ + DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \ + DM_draw_attrib_vertex_uniforms(&attribs); \ } (void)0 totpoly = ccgSubSurf_getNumFaces(ss); @@ -3222,12 +3223,13 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, matnr = -1; -#define PASSATTRIB(dx, dy, vert) { \ - if (attribs.totorco) \ - index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \ - else \ - index = 0; \ - DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \ +#define PASSATTRIB(dx, dy, vert) { \ + if (attribs.totorco) \ + index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \ + else \ + index = 0; \ + DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \ + DM_draw_attrib_vertex_uniforms(&attribs); \ } (void)0 totface = ccgSubSurf_getNumFaces(ss); diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c index bd7b7f9cdbd..9d4d40e1eae 100644 --- a/source/blender/blenlib/intern/task.c +++ b/source/blender/blenlib/intern/task.c @@ -780,9 +780,10 @@ BLI_INLINE bool parallel_range_next_iter_get( ParallelRangeState * __restrict state, int * __restrict iter, int * __restrict count) { - uint32_t previter = atomic_fetch_and_add_uint32((uint32_t *)(&state->iter), state->chunk_size); + uint32_t uval = atomic_fetch_and_add_uint32((uint32_t *)(&state->iter), state->chunk_size); + int previter = *(int32_t*)&uval; - *iter = (int)previter; + *iter = previter; *count = max_ii(0, min_ii(state->chunk_size, state->stop - previter)); return (previter < state->stop); diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 0a36e7846fe..dfaa59c4e3f 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1348,7 +1348,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) /* ------- end of grease pencil initialization --------------- */ } - { + if (!MAIN_VERSION_ATLEAST(main, 278, 0)) { if (!DNA_struct_elem_find(fd->filesdna, "MovieTrackingTrack", "float", "weight_stab")) { MovieClip *clip; for (clip = main->movieclip.first; clip; clip = clip->id.next) { diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 49e5845e3ca..26a6fdd7d1f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1021,6 +1021,12 @@ void ED_keymap_ui(struct wmKeyConfig *keyconf); void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop); int UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event); +/* UI_OT_space_context_cycle direction */ +enum { + SPACE_CONTEXT_CYCLE_PREV, + SPACE_CONTEXT_CYCLE_NEXT, +}; + bool UI_context_copy_to_selected_list( struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, struct ListBase *r_lb, bool *r_use_path_from_id, char **r_path); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 1af6d902b18..cb539bb1c5d 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1082,6 +1082,78 @@ static void UI_OT_drop_color(wmOperatorType *ot) RNA_def_boolean(ot->srna, "gamma", 0, "Gamma Corrected", "The source color is gamma corrected "); } +/* ------------------------------------------------------------------------- */ + +static EnumPropertyItem space_context_cycle_direction[] = { + {SPACE_CONTEXT_CYCLE_PREV, "PREV", 0, "Previous", ""}, + {SPACE_CONTEXT_CYCLE_NEXT, "NEXT", 0, "Next", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static int space_context_cycle_poll(bContext *C) +{ + ScrArea *sa = CTX_wm_area(C); + return ELEM(sa->spacetype, SPACE_BUTS, SPACE_USERPREF); +} + +/** + * Helper to get the correct RNA pointer/property pair for changing + * the display context of active space type in \sa. + */ +static void context_cycle_prop_get( + bScreen *screen, const ScrArea *sa, + PointerRNA *r_ptr, PropertyRNA **r_prop) +{ + const char *propname; + + switch (sa->spacetype) { + case SPACE_BUTS: + RNA_pointer_create(&screen->id, &RNA_SpaceProperties, sa->spacedata.first, r_ptr); + propname = "context"; + break; + case SPACE_USERPREF: + RNA_pointer_create(NULL, &RNA_UserPreferences, &U, r_ptr); + propname = "active_section"; + break; + } + + *r_prop = RNA_struct_find_property(r_ptr, propname); +} + +static int space_context_cycle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + const int direction = RNA_enum_get(op->ptr, "direction"); + + PointerRNA ptr; + PropertyRNA *prop; + context_cycle_prop_get(CTX_wm_screen(C), CTX_wm_area(C), &ptr, &prop); + + const int old_context = RNA_property_enum_get(&ptr, prop); + const int new_context = RNA_property_enum_step( + C, &ptr, prop, old_context, + direction == SPACE_CONTEXT_CYCLE_PREV ? -1 : 1); + RNA_property_enum_set(&ptr, prop, new_context); + RNA_property_update(C, &ptr, prop); + + return OPERATOR_FINISHED; +} + +static void UI_OT_space_context_cycle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Cycle Space Context"; + ot->description = "Cycle through the editor context by activating the next/previous one"; + ot->idname = "UI_OT_space_context_cycle"; + + /* api callbacks */ + ot->invoke = space_context_cycle_invoke; + ot->poll = space_context_cycle_poll; + + ot->flag = 0; + + RNA_def_enum(ot->srna, "direction", space_context_cycle_direction, SPACE_CONTEXT_CYCLE_NEXT, "Direction", + "Direction to cycle through"); +} /* ********************************************************* */ @@ -1102,6 +1174,7 @@ void ED_operatortypes_ui(void) WM_operatortype_append(UI_OT_edittranslation_init); #endif WM_operatortype_append(UI_OT_reloadtranslation); + WM_operatortype_append(UI_OT_space_context_cycle); /* external */ WM_operatortype_append(UI_OT_eyedropper_color); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 79961eae79d..c131bcb8e14 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -1841,6 +1841,52 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) #undef USE_FLAT_INACTIVE } +static int ui_handle_panel_category_cycling(const wmEvent *event, ARegion *ar, const uiBut *active_but) +{ + const bool is_mousewheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE); + const bool inside_tabregion = (event->mval[0] < ((PanelCategoryDyn *)ar->panels_category.first)->rect.xmax); + + /* if mouse is inside non-tab region, ctrl key is required */ + if (is_mousewheel && !event->ctrl && !inside_tabregion) + return WM_UI_HANDLER_CONTINUE; + + + if (active_but && ui_but_supports_cycling(active_but)) { + /* skip - exception to make cycling buttons + * using ctrl+mousewheel work in tabbed regions */ + } + else { + const char *category = UI_panel_category_active_get(ar, false); + if (LIKELY(category)) { + PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category); + if (LIKELY(pc_dyn)) { + if (is_mousewheel) { + /* we can probably get rid of this and only allow ctrl+tabbing */ + pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev; + } + else { + const bool backwards = event->shift; + pc_dyn = backwards ? pc_dyn->prev : pc_dyn->next; + if (!pc_dyn) { + /* proper cyclic behavior, back to first/last category (only used for ctrl+tab) */ + pc_dyn = backwards ? ar->panels_category.last : ar->panels_category.first; + } + } + + if (pc_dyn) { + /* intentionally don't reset scroll in this case, + * this allows for quick browsing between tabs */ + UI_panel_category_active_set(ar, pc_dyn->idname); + ED_region_tag_redraw(ar); + } + } + } + return WM_UI_HANDLER_BREAK; + } + + return WM_UI_HANDLER_CONTINUE; +} + /* XXX should become modal keymap */ /* AKey is opening/closing panels, independent of button state now */ @@ -1853,6 +1899,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons retval = WM_UI_HANDLER_CONTINUE; + /* handle category tabs */ if (has_category_tabs) { if (event->val == KM_PRESS) { if (event->type == LEFTMOUSE) { @@ -1867,32 +1914,9 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons retval = WM_UI_HANDLER_BREAK; } } - else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) { - /* mouse wheel cycle tabs */ - - /* first check if the mouse is in the tab region */ - if (event->ctrl || (event->mval[0] < ((PanelCategoryDyn *)ar->panels_category.first)->rect.xmax)) { - if (active_but && ui_but_supports_cycling(active_but)) { - /* skip - exception to make cycling buttons - * using ctrl+mousewheel work in tabbed regions */ - } - else { - const char *category = UI_panel_category_active_get(ar, false); - if (LIKELY(category)) { - PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category); - if (LIKELY(pc_dyn)) { - pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev; - if (pc_dyn) { - /* intentionally don't reset scroll in this case, - * this allows for quick browsing between tabs */ - UI_panel_category_active_set(ar, pc_dyn->idname); - ED_region_tag_redraw(ar); - } - } - } - retval = WM_UI_HANDLER_BREAK; - } - } + else if ((event->type == TABKEY && event->ctrl) || ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) { + /* cycle tabs */ + retval = ui_handle_panel_category_cycling(event, ar, active_but); } } } diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index c507401b9a0..4ea5e2092b6 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -73,38 +73,6 @@ #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) -{ - EnumPropertyItem *item_array; - int totitem; - bool free; - int value; - int i, i_init; - int step = (direction < 0) ? -1 : 1; - int step_tot = 0; - - RNA_property_enum_items((bContext *)C, ptr, prop, &item_array, &totitem, &free); - value = RNA_property_enum_get(ptr, prop); - i = RNA_enum_from_value(item_array, value); - i_init = i; - - do { - i = mod_i(i + step, totitem); - if (item_array[i].identifier[0]) { - step_tot += step; - } - } while ((i != i_init) && (step_tot != direction)); - - if (i != i_init) { - value = item_array[i].value; - } - - if (free) { - MEM_freeN(item_array); - } - - return value; -} bool ui_but_menu_step_poll(const uiBut *but) { @@ -122,7 +90,8 @@ int ui_but_menu_step(uiBut *but, int direction) return but->menu_step_func(but->block->evil_C, direction, but->poin); } else { - return rna_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, direction); + const int curval = RNA_property_enum_get(&but->rnapoin, but->rnaprop); + return RNA_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, curval, direction); } } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 999d5b278ee..7e31deba2c7 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3121,8 +3121,10 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const BKE_material_resize_id(bmain, obdata, 1, true); ob->mat[0] = ma_ob; + id_us_plus((ID *)ma_ob); ob->matbits[0] = matbit; (*matarar)[0] = ma_obdata; + id_us_plus((ID *)ma_obdata); } else { BKE_material_clear_id(bmain, obdata, true); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index a8b0c28599d..9f91feee4c6 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -998,7 +998,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op) Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, loc, rot, false, layer); ob->dup_group = group; ob->transflag |= OB_DUPLIGROUP; - id_lib_extern(&group->id); + id_us_plus(&group->id); /* works without this except if you try render right after, see: 22027 */ DAG_relations_tag_update(bmain); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 3dc7d8ebd4b..111afcdc7a7 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -910,7 +910,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) base->object->dup_group = ob->dup_group; if (ob->dup_group) - id_lib_extern(&ob->dup_group->id); + id_us_plus(&ob->dup_group->id); } else if (event == 7) { /* mass */ base->object->mass = ob->mass; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 067a5ad2b49..82c6a14eb7f 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1609,7 +1609,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) case MAKE_LINKS_DUPLIGROUP: ob_dst->dup_group = ob_src->dup_group; if (ob_dst->dup_group) { - id_lib_extern(&ob_dst->dup_group->id); + id_us_plus(&ob_dst->dup_group->id); ob_dst->transflag |= OB_DUPLIGROUP; } break; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6dbb5db53d0..e446194a1da 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -4331,7 +4331,13 @@ void ED_keymap_screen(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0); - + + /* UI */ + kmi = WM_keymap_add_item(keymap, "UI_OT_space_context_cycle", TABKEY, KM_PRESS, KM_CTRL, 0); + RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_NEXT); + kmi = WM_keymap_add_item(keymap, "UI_OT_space_context_cycle", TABKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_PREV); + /* tests */ WM_keymap_add_item(keymap, "SCREEN_OT_region_quadview", QKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", F3KEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index ac3fc769ea1..52c39e5c7a1 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -217,32 +217,56 @@ static void SOUND_OT_open_mono(wmOperatorType *ot) /* ******************************************************* */ -static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op)) +static void sound_update_animation_flags(Scene *scene); + +static int sound_update_animation_flags_cb(Sequence *seq, void *user_data) { - Sequence *seq; - Scene *scene = CTX_data_scene(C); struct FCurve *fcu; + Scene *scene = (Scene *)user_data; bool driven; - SEQ_BEGIN(scene->ed, seq) - { - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, &driven); - if (fcu || driven) - seq->flag |= SEQ_AUDIO_VOLUME_ANIMATED; - else - seq->flag &= ~SEQ_AUDIO_VOLUME_ANIMATED; + fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, &driven); + if (fcu || driven) + seq->flag |= SEQ_AUDIO_VOLUME_ANIMATED; + else + seq->flag &= ~SEQ_AUDIO_VOLUME_ANIMATED; - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pitch", 0, &driven); - if (fcu || driven) - seq->flag |= SEQ_AUDIO_PITCH_ANIMATED; - else - seq->flag &= ~SEQ_AUDIO_PITCH_ANIMATED; + fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pitch", 0, &driven); + if (fcu || driven) + seq->flag |= SEQ_AUDIO_PITCH_ANIMATED; + else + seq->flag &= ~SEQ_AUDIO_PITCH_ANIMATED; - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pan", 0, &driven); - if (fcu || driven) - seq->flag |= SEQ_AUDIO_PAN_ANIMATED; - else - seq->flag &= ~SEQ_AUDIO_PAN_ANIMATED; + fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pan", 0, &driven); + if (fcu || driven) + seq->flag |= SEQ_AUDIO_PAN_ANIMATED; + else + seq->flag &= ~SEQ_AUDIO_PAN_ANIMATED; + + if (seq->type == SEQ_TYPE_SCENE) { + /* TODO(sergey): For now we do manual recursion into the scene strips, + * but perhaps it should be covered by recursive_apply? + */ + sound_update_animation_flags(seq->scene); + } + + return 0; +} + +static void sound_update_animation_flags(Scene *scene) +{ + struct FCurve *fcu; + bool driven; + Sequence *seq; + + if (scene->id.tag & LIB_TAG_DOIT) { + return; + } + scene->id.tag |= LIB_TAG_DOIT; + + SEQ_BEGIN(scene->ed, seq) + { + BKE_sequencer_recursive_apply(seq, sound_update_animation_flags_cb, scene); } SEQ_END @@ -251,7 +275,12 @@ static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op) scene->audio.flag |= AUDIO_VOLUME_ANIMATED; else scene->audio.flag &= ~AUDIO_VOLUME_ANIMATED; +} +static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op)) +{ + BKE_main_id_tag_idcode(CTX_data_main(C), ID_SCE, LIB_TAG_DOIT, false); + sound_update_animation_flags(CTX_data_scene(C)); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 1f591b5fb35..a89d3494af0 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1608,6 +1608,11 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, /* imtype */ simopts->im_format = scene->r.im_format; is_depth_set = true; + if (!BKE_image_is_multiview(ima)) { + /* In case multiview is disabled, render settings would be invalid for render result in this area. */ + simopts->im_format.stereo3d_format = *ima->stereo3d_format; + simopts->im_format.views_format = ima->views_format; + } } else { if (ima->source == IMA_SRC_GENERATED) { diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 47390578573..6ae2229af8e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -4227,7 +4227,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 /* If we are drawing shadows and any of the materials don't cast a shadow, * then don't draw the object */ if (v3d->flag2 & V3D_RENDER_SHADOW) { - for (int i = 0; i < ob->totcol; ++i) { + for (int i = 1; i <= ob->totcol; ++i) { Material *ma = give_current_material(ob, i); if (ma && !(ma->mode2 & MA_CASTSHADOW)) { return true; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 9cbe132282f..820465ee7d1 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -916,6 +916,7 @@ int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop); void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value); int RNA_property_enum_get_default(PointerRNA *ptr, PropertyRNA *prop); void *RNA_property_enum_py_data_get(PropertyRNA *prop); +int RNA_property_enum_step(const struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int direction); PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop); void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 047e5ea17ab..6879a0534e9 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -2873,6 +2873,45 @@ void *RNA_property_enum_py_data_get(PropertyRNA *prop) return eprop->py_data; } +/** + * Get the value of the item that is \a step items away from \a from_value. + * + * \param from_value: Item value to start stepping from. + * \param step: Absolute value defines step size, sign defines direction. + * E.g to get the next item, pass 1, for the previous -1. + */ +int RNA_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step) +{ + EnumPropertyItem *item_array; + int totitem; + bool free; + int result_value = from_value; + int i, i_init; + int single_step = (step < 0) ? -1 : 1; + int step_tot = 0; + + RNA_property_enum_items((bContext *)C, ptr, prop, &item_array, &totitem, &free); + i = RNA_enum_from_value(item_array, from_value); + i_init = i; + + do { + i = mod_i(i + single_step, totitem); + if (item_array[i].identifier[0]) { + step_tot += single_step; + } + } while ((i != i_init) && (step_tot != step)); + + if (i != i_init) { + result_value = item_array[i].value; + } + + if (free) { + MEM_freeN(item_array); + } + + return result_value; +} + PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index a751c414d83..9d55115a14c 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -618,7 +618,7 @@ void RNA_api_ui_layout(StructRNA *srna) #endif func = RNA_def_function(srna, "label", "rna_uiItemL"); - RNA_def_function_ui_description(func, "Item. Display text and/or icon in the layout"); + RNA_def_function_ui_description(func, "Item. Displays text and/or icon in the layout"); api_ui_item_common(func); parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED); RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item"); @@ -644,6 +644,7 @@ void RNA_api_ui_layout(StructRNA *srna) /* templates */ func = RNA_def_function(srna, "template_header", "uiTemplateHeader"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Inserts common Space header UI (editor type selector)"); func = RNA_def_function(srna, "template_ID", "uiTemplateID"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); @@ -853,9 +854,12 @@ void RNA_api_ui_layout(StructRNA *srna) func = RNA_def_function(srna, "template_header_3D", "uiTemplateHeader3D"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Inserts common 3DView header UI (selectors for context mode, shading, etc.)"); + func = RNA_def_function(srna, "template_edit_mode_selection", "uiTemplateEditModeSelection"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Inserts common 3DView Edit modes header UI (selector for selection mode)"); func = RNA_def_function(srna, "template_reports_banner", "uiTemplateReportsBanner"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index 7cf0cf67269..8d0b704a402 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -398,18 +398,21 @@ void RNA_api_wm(StructRNA *srna) rna_generic_op_invoke(func, 0); func = RNA_def_function(srna, "modal_handler_add", "rna_event_modal_handler_add"); + RNA_def_function_ui_description(func, "Add a modal handler to the window manager, for the given modal operator " + "(called by invoke() with self, just before returning {'RUNNING_MODAL'})"); RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT); parm = RNA_def_pointer(func, "operator", "Operator", "", "Operator to call"); RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_function_return(func, RNA_def_boolean(func, "handle", 1, "", "")); + RNA_def_function_return(func, RNA_def_boolean(func, "handle", 1, "", "Whether adding the handler was successful")); func = RNA_def_function(srna, "event_timer_add", "rna_event_timer_add"); + RNA_def_function_ui_description(func, "Add a timer to the given window, to generate periodic 'TIMER' events"); parm = RNA_def_property(func, "time_step", PROP_FLOAT, PROP_NONE); RNA_def_property_flag(parm, PROP_REQUIRED); RNA_def_property_range(parm, 0.0, FLT_MAX); RNA_def_property_ui_text(parm, "Time Step", "Interval in seconds between timer events"); - RNA_def_pointer(func, "window", "Window", "", "Window to attach the timer to or None"); + RNA_def_pointer(func, "window", "Window", "", "Window to attach the timer to, or None"); parm = RNA_def_pointer(func, "result", "Timer", "", ""); RNA_def_function_return(func, parm); @@ -421,44 +424,49 @@ void RNA_api_wm(StructRNA *srna) /* Progress bar interface */ func = RNA_def_function(srna, "progress_begin", "rna_progress_begin"); RNA_def_function_ui_description(func, "Start progress report"); - parm = RNA_def_property(func, "min", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_text(parm, "min", "any value in range [0,9999]"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_property(func, "max", PROP_FLOAT, PROP_NONE); RNA_def_property_flag(parm, PROP_REQUIRED); RNA_def_property_ui_text(parm, "max", "any value in range [min+1,9998]"); func = RNA_def_function(srna, "progress_update", "rna_progress_update"); + RNA_def_function_ui_description(func, "Update the progress feedback"); parm = RNA_def_property(func, "value", PROP_FLOAT, PROP_NONE); RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_property_ui_text(parm, "value", "any value between min and max as set in progress_begin()"); + RNA_def_property_ui_text(parm, "value", "Any value between min and max as set in progress_begin()"); func = RNA_def_function(srna, "progress_end", "rna_progress_end"); RNA_def_function_ui_description(func, "Terminate progress report"); /* invoke functions, for use with python */ func = RNA_def_function(srna, "invoke_props_popup", "rna_Operator_props_popup"); - RNA_def_function_ui_description(func, "Operator popup invoke"); + RNA_def_function_ui_description(func, "Operator popup invoke " + "(show operator properties and execute it automatically on changes)"); rna_generic_op_invoke(func, WM_GEN_INVOKE_EVENT | WM_GEN_INVOKE_RETURN); /* invoked dialog opens popup with OK button, does not auto-exec operator. */ func = RNA_def_function(srna, "invoke_props_dialog", "WM_operator_props_dialog_popup"); - RNA_def_function_ui_description(func, "Operator dialog (non-autoexec popup) invoke"); + RNA_def_function_ui_description(func, "Operator dialog (non-autoexec popup) invoke " + "(show operator properties and only execute it on click on OK button)"); rna_generic_op_invoke(func, WM_GEN_INVOKE_SIZE | WM_GEN_INVOKE_RETURN); /* invoke enum */ func = RNA_def_function(srna, "invoke_search_popup", "rna_Operator_enum_search_invoke"); + RNA_def_function_ui_description(func, "Operator search popup invoke (search in values of " + "operator's type 'prop' EnumProperty, and execute it on confirmation)"); rna_generic_op_invoke(func, 0); /* invoke functions, for use with python */ func = RNA_def_function(srna, "invoke_popup", "WM_operator_ui_popup"); - RNA_def_function_ui_description(func, "Operator popup invoke"); + RNA_def_function_ui_description(func, "Operator popup invoke " + "(only shows operator's properties, without executing it)"); rna_generic_op_invoke(func, WM_GEN_INVOKE_SIZE | WM_GEN_INVOKE_RETURN); func = RNA_def_function(srna, "invoke_confirm", "rna_Operator_confirm"); - RNA_def_function_ui_description(func, "Operator confirmation"); + RNA_def_function_ui_description(func, "Operator confirmation popup " + "(only to let user confirm the execution, no operator properties shown)"); rna_generic_op_invoke(func, WM_GEN_INVOKE_EVENT | WM_GEN_INVOKE_RETURN); diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 23ab61821f4..8711384e1ee 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -130,6 +130,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (U.opensubdiv_compute_type == USER_OPENSUBDIV_COMPUTE_NONE) { modifier_setError(md, "OpenSubdiv is disabled in User Preferences"); } + else if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) != 0) { + modifier_setError(md, "OpenSubdiv is not supported in paint modes"); + } else if ((DAG_get_eval_flags_for_object(md->scene, ob) & DAG_EVAL_NEED_CPU) == 0) { subsurf_flags |= SUBSURF_USE_GPU_BACKEND; do_cddm_convert = false; diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index fc02dfda9d1..f65688e1304 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -338,7 +338,8 @@ if(WITH_PYTHON) # install(CODE "message(\"copying blender scripts...\")") # exclude addons_contrib if release - if("${BLENDER_VERSION_CYCLE}" STREQUAL "release") + if("${BLENDER_VERSION_CYCLE}" STREQUAL "release" OR + "${BLENDER_VERSION_CYCLE}" STREQUAL "rc") set(ADDON_EXCLUDE_CONDITIONAL "addons_contrib/*") else() set(ADDON_EXCLUDE_CONDITIONAL "_addons_contrib/*") # dummy, wont do anything diff --git a/source/tools b/source/tools -Subproject 373945d0978b6601c55c9d5879e0f488b18515c +Subproject 896c5f78952adb2d091d28c65086d46992dabda |