diff --git a/CMakeLists.txt b/CMakeLists.txt index 86848d10422..39b75d9a32b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,9 +118,10 @@ mark_as_advanced(WITH_BLENDER) option(WITH_INTERNATIONAL "Enable I18N (International fonts and text)" ON) option(WITH_PYTHON "Enable Embedded Python API (only disable for development)" ON) -option(WITH_PYTHON_SECURITY "Disables execution of scripts within blend files by default (recommend to leave off)" OFF) +option(WITH_PYTHON_SECURITY "Disables execution of scripts within blend files by default" ON) mark_as_advanced(WITH_PYTHON) # dont want people disabling this unless they really know what they are doing. mark_as_advanced(WITH_PYTHON_SECURITY) # some distributions see this as a security issue, rather than have them patch it, make a build option. +set(WITH_PYTHON_SECURITY ON CACHE BOOL "ON" FORCE) # temp force on. option(WITH_PYTHON_SAFETY "Enable internal API error checking to track invalid data to prevent crash on access (at the expense of some effeciency, only enable for development)." OFF) option(WITH_PYTHON_MODULE "Enable building as a python module which runs without a user interface, like running regular blender in background mode (experimental, only enable for development)" OFF) diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index b8d036d9a84..d28521a8d07 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -96,7 +96,7 @@ def print_arguments(args, bc): def validate_arguments(args, bc): opts_list = [ - 'WITH_BF_FREESTYLE', 'WITH_BF_PYTHON', 'WITH_BF_PYTHON_SAFETY', 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LIBPATH_ARCH', 'WITH_BF_STATICPYTHON', 'WITH_OSX_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', 'BF_PYTHON_DLL', 'BF_PYTHON_ABI_FLAGS', + 'WITH_BF_FREESTYLE', 'WITH_BF_PYTHON', 'WITH_BF_PYTHON_SAFETY', 'WITH_BF_PYTHON_SECURITY', 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LIBPATH_ARCH', 'WITH_BF_STATICPYTHON', 'WITH_OSX_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', 'BF_PYTHON_DLL', 'BF_PYTHON_ABI_FLAGS', 'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_STATICOPENAL', 'BF_OPENAL_LIB_STATIC', 'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH', 'WITH_BF_JACK', 'BF_JACK', 'BF_JACK_INC', 'BF_JACK_LIB', 'BF_JACK_LIBPATH', 'WITH_BF_JACK_DYNLOAD', @@ -254,6 +254,7 @@ def read_opts(env, cfg, args): ('LIBDIR', 'Root dir of libs'), (BoolVariable('WITH_BF_PYTHON', 'Compile with python', True)), (BoolVariable('WITH_BF_PYTHON_SAFETY', 'Internal API error checking to track invalid data to prevent crash on access (at the expense of some effeciency)', False)), + (BoolVariable('WITH_BF_PYTHON_SECURITY', 'Disables execution of scripts within blend files by default', True)), ('BF_PYTHON', 'Base path for python', ''), ('BF_PYTHON_VERSION', 'Python version to use', ''), ('BF_PYTHON_INC', 'Include path for Python headers', ''), diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 526c5658b93..e1015fa3cee 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -40,6 +40,7 @@ class CyclesRender(bpy.types.RenderEngine): bl_label = "Cycles Render" bl_use_shading_nodes = True bl_use_preview = True + bl_use_exclude_layers = True def __init__(self): self.session = None diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 7ea84659764..0c6cf9f513a 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -589,6 +589,12 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup): type=cls, ) + bpy.types.World.cycles_visibility = PointerProperty( + name="Cycles Visibility Settings", + description="Cycles visibility settings", + type=cls, + ) + cls.camera = BoolProperty( name="Camera", description="Object visibility for camera rays", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 8950b4f83c4..a30622a36ac 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -542,7 +542,9 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel): flow.prop(visibility, "diffuse") flow.prop(visibility, "glossy") flow.prop(visibility, "transmission") - flow.prop(visibility, "shadow") + + if ob.type != 'LAMP': + flow.prop(visibility, "shadow") def find_node(material, nodetype): @@ -777,6 +779,29 @@ class CyclesWorld_PT_mist(CyclesButtonsPanel, Panel): layout.prop(world.mist_settings, "falloff") +class CyclesWorld_PT_ray_visibility(CyclesButtonsPanel, Panel): + bl_label = "Ray Visibility" + bl_context = "world" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + return CyclesButtonsPanel.poll(context) and context.world + + def draw(self, context): + layout = self.layout + + world = context.world + visibility = world.cycles_visibility + + flow = layout.column_flow() + + flow.prop(visibility, "camera") + flow.prop(visibility, "diffuse") + flow.prop(visibility, "glossy") + flow.prop(visibility, "transmission") + + class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel): bl_label = "Settings" bl_context = "world" diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 6c3b137fd52..9600340a1f3 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -317,11 +317,6 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) b_node.outputs.remove(b_sock); b_sock = BL::NodeSocket(PointerRNA_NULL); } - - if (!b_sock) { - /* create new socket */ - b_sock = b_node.outputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str()); - } } else { b_sock = b_node.inputs[param->name]; @@ -331,15 +326,16 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) b_node.inputs.remove(b_sock); b_sock = BL::NodeSocket(PointerRNA_NULL); } - - if (!b_sock) { - /* create new socket */ - b_sock = b_node.inputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str()); - } } - /* set default value */ - if(b_sock) { + if(!b_sock) { + /* create new socket */ + if(param->isoutput) + b_sock = b_node.outputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str()); + else + b_sock = b_node.inputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str()); + + /* set default value */ if(data_type == BL::NodeSocket::type_VALUE) { set_float(b_sock.ptr, "default_value", default_float); } diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index fc388f4bbef..a9db10b21d7 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -708,10 +708,13 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha graph->add(proxy); } } - else if (b_node->is_a(&RNA_ShaderNodeGroup)) { + else if (b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup)) { - BL::NodeGroup b_gnode(*b_node); - BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree()); + BL::ShaderNodeTree b_group_ntree(PointerRNA_NULL); + if (b_node->is_a(&RNA_ShaderNodeGroup)) + b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(*b_node)).node_tree()); + else + b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(*b_node)).node_tree()); ProxyMap group_proxy_input_map, group_proxy_output_map; /* Add a proxy node for each socket @@ -895,8 +898,8 @@ void BlenderSync::sync_world(bool update_all) graph->connect(closure->output("Background"), out->input("Surface")); } - /* AO */ if(b_world) { + /* AO */ BL::WorldLighting b_light = b_world.light_settings(); if(b_light.use_ambient_occlusion()) @@ -905,6 +908,17 @@ void BlenderSync::sync_world(bool update_all) background->ao_factor = 0.0f; background->ao_distance = b_light.distance(); + + /* visibility */ + PointerRNA cvisibility = RNA_pointer_get(&b_world.ptr, "cycles_visibility"); + uint visibility = 0; + + visibility |= get_boolean(cvisibility, "camera")? PATH_RAY_CAMERA: 0; + visibility |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0; + visibility |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0; + visibility |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0; + + background->visibility = visibility; } shader->set_graph(graph); diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 869c8539809..c430a40d814 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -199,11 +199,9 @@ __device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int p #ifdef __PASSES__ /* use visibility flag to skip lights */ if(ls.shader & SHADER_EXCLUDE_ANY) { - if((ls.shader & SHADER_EXCLUDE_DIFFUSE) && (path_flag & PATH_RAY_DIFFUSE)) - return false; - if((ls.shader & SHADER_EXCLUDE_GLOSSY) && (path_flag & PATH_RAY_GLOSSY)) - return false; - if((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (path_flag & PATH_RAY_TRANSMIT)) + if(((ls.shader & SHADER_EXCLUDE_DIFFUSE) && (path_flag & PATH_RAY_DIFFUSE)) || + ((ls.shader & SHADER_EXCLUDE_GLOSSY) && (path_flag & PATH_RAY_GLOSSY)) || + ((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (path_flag & PATH_RAY_TRANSMIT))) return false; } #endif @@ -229,9 +227,21 @@ __device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int p __device_noinline float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf) { #ifdef __BACKGROUND__ + int shader = kernel_data.background.shader; + + /* use visibility flag to skip lights */ + if(shader & SHADER_EXCLUDE_ANY) { + if(((shader & SHADER_EXCLUDE_DIFFUSE) && (path_flag & PATH_RAY_DIFFUSE)) || + ((shader & SHADER_EXCLUDE_GLOSSY) && (path_flag & PATH_RAY_GLOSSY)) || + ((shader & SHADER_EXCLUDE_TRANSMIT) && (path_flag & PATH_RAY_TRANSMIT)) || + ((shader & SHADER_EXCLUDE_CAMERA) && (path_flag & PATH_RAY_CAMERA))) + return make_float3(0.0f, 0.0f, 0.0f); + } + /* evaluate background closure */ ShaderData sd; shader_setup_from_background(kg, &sd, ray); + float3 L = shader_eval_background(kg, &sd, path_flag, SHADER_CONTEXT_EMISSION); #ifdef __BACKGROUND_MIS__ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 771c79ba637..6ae3b10595c 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -55,6 +55,7 @@ CCL_NAMESPACE_BEGIN #define __OSL__ #endif #define __SUBSURFACE__ +#define __CMJ__ #endif #ifdef __KERNEL_CUDA__ @@ -117,7 +118,6 @@ CCL_NAMESPACE_BEGIN #define __CAMERA_CLIPPING__ #define __INTERSECTION_REFINE__ #define __CLAMP_SAMPLE__ -#define __CMJ__ #ifdef __KERNEL_SHADING__ #define __SVM__ @@ -329,7 +329,8 @@ typedef enum ShaderFlag { SHADER_EXCLUDE_DIFFUSE = (1 << 27), SHADER_EXCLUDE_GLOSSY = (1 << 26), SHADER_EXCLUDE_TRANSMIT = (1 << 25), - SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE|SHADER_EXCLUDE_GLOSSY|SHADER_EXCLUDE_TRANSMIT), + SHADER_EXCLUDE_CAMERA = (1 << 24), + SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE|SHADER_EXCLUDE_GLOSSY|SHADER_EXCLUDE_TRANSMIT|SHADER_EXCLUDE_CAMERA), SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS|SHADER_EXCLUDE_ANY) } ShaderFlag; diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 8473f800d39..b1549e95920 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -198,6 +198,8 @@ void OSLShader::register_closures(OSLShadingSystem *ss_) bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare); register_closure(ss, "glossy_toon", id++, bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare); + register_closure(ss, "specular_toon", id++, + bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare); register_closure(ss, "westin_backscatter", id++, bsdf_westin_backscatter_params(), bsdf_westin_backscatter_prepare); register_closure(ss, "westin_sheen", id++, diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index e98d0c9a9ad..24c3e187783 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -465,6 +465,10 @@ closure color holdout() BUILTIN; closure color ambient_occlusion() BUILTIN; closure color bssrdf_cubic(normal N, vector radius) BUILTIN; +// Backwards compatibility + +closure color specular_toon(normal N, float size, float smooth) BUILTIN; + // Renderer state int raytype (string typename) BUILTIN; // the individual 'isFOOray' functions are deprecated diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp index 76d26dd34b5..3513665f256 100644 --- a/intern/cycles/render/background.cpp +++ b/intern/cycles/render/background.cpp @@ -37,6 +37,8 @@ Background::Background() use = true; + visibility = ~0; + transparent = false; need_update = true; } @@ -64,6 +66,15 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene else kbackground->shader = scene->shader_manager->get_shader_id(scene->default_empty); + if(!(visibility & PATH_RAY_DIFFUSE)) + kbackground->shader |= SHADER_EXCLUDE_DIFFUSE; + if(!(visibility & PATH_RAY_GLOSSY)) + kbackground->shader |= SHADER_EXCLUDE_GLOSSY; + if(!(visibility & PATH_RAY_TRANSMIT)) + kbackground->shader |= SHADER_EXCLUDE_TRANSMIT; + if(!(visibility & PATH_RAY_CAMERA)) + kbackground->shader |= SHADER_EXCLUDE_CAMERA; + need_update = false; } @@ -76,7 +87,8 @@ bool Background::modified(const Background& background) return !(transparent == background.transparent && use == background.use && ao_factor == background.ao_factor && - ao_distance == background.ao_distance); + ao_distance == background.ao_distance && + visibility == background.visibility); } void Background::tag_update(Scene *scene) diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h index 3c1cd3915e5..e0c0c42de37 100644 --- a/intern/cycles/render/background.h +++ b/intern/cycles/render/background.h @@ -34,6 +34,8 @@ public: bool use; + uint visibility; + bool transparent; bool need_update; diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index cc369e7abc9..796746e828f 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -173,7 +173,8 @@ bool Integrator::modified(const Integrator& integrator) ao_samples == integrator.ao_samples && mesh_light_samples == integrator.mesh_light_samples && subsurface_samples == integrator.subsurface_samples && - motion_blur == integrator.motion_blur); + motion_blur == integrator.motion_blur && + sampling_pattern == integrator.sampling_pattern); } void Integrator::tag_update(Scene *scene) diff --git a/release/scripts/startup/bl_operators/view3d.py b/release/scripts/startup/bl_operators/view3d.py index 8c732432c2b..cfdb5dbe677 100644 --- a/release/scripts/startup/bl_operators/view3d.py +++ b/release/scripts/startup/bl_operators/view3d.py @@ -96,6 +96,7 @@ class VIEW3D_OT_select_or_deselect_all(Operator): "Select element under the mouse, deselect everything is there's nothing under the mouse" bl_label = "Select or Deselect All" bl_idname = "view3d.select_or_deselect_all" + bl_options = {'UNDO'} extend = BoolProperty( name="Extend", diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 8a4529863a9..2b3be00e3c6 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -67,6 +67,8 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False): row.prop(dopesheet, "show_meshes", text="") if bpy.data.shape_keys: row.prop(dopesheet, "show_shapekeys", text="") + if bpy.data.meshes: + row.prop(dopesheet, "show_modifiers", text="") if bpy.data.materials: row.prop(dopesheet, "show_materials", text="") if bpy.data.lamps: diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index 4ea366e3541..7487aaf420d 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -64,6 +64,19 @@ class INFO_HT_header(Header): layout.template_reports_banner() row = layout.row(align=True) + + if bpy.app.autoexec_fail is True and bpy.app.autoexec_fail_quiet is False: + layout.operator_context = 'EXEC_DEFAULT' + row.label("Script failed to auto-run", icon='ERROR') + if bpy.data.is_saved: + props = row.operator("wm.open_mainfile", icon='SCREEN_BACK', text="Reload Trusted") + props.filepath = bpy.data.filepath + props.use_scripts = True + + row.operator("script.autoexec_warn_clear", icon='CANCEL') + row.label("Skipping: (%s)" % bpy.app.autoexec_fail_message) + return + row.operator("wm.splash", text="", icon='BLENDER', emboss=False) row.label(text=scene.statistics(), translate=False) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index e8531db3e23..c61b07800ca 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -959,27 +959,51 @@ class VIEW3D_MT_object_specials(Menu): props.header_text = "Empty Draw Size: %.3f" if obj.type == 'LAMP': + lamp = obj.data + layout.operator_context = 'INVOKE_REGION_WIN' if scene.render.use_shading_nodes: - props = layout.operator("wm.context_modal_mouse", text="Size") - props.data_path_iter = "selected_editable_objects" - props.data_path_item = "data.shadow_soft_size" - props.header_text = "Lamp Size: %.3f" + try: + value = lamp.node_tree.nodes["Emission"].inputs["Strength"].default_value + + props = layout.operator("wm.context_modal_mouse", text="Strength") + props.data_path_iter = "selected_editable_objects" + props.data_path_item = "data.node_tree.nodes[\"Emission\"].inputs[\"Strength\"].default_value" + props.header_text = "Lamp Strength: %.3f" + props.input_scale = 0.1 + except AttributeError: + pass + + if lamp.type == 'AREA' and lamp.shape == 'RECTANGLE': + props = layout.operator("wm.context_modal_mouse", text="Size X") + props.data_path_iter = "selected_editable_objects" + props.data_path_item = "data.size" + props.header_text = "Lamp Size X: %.3f" + + props = layout.operator("wm.context_modal_mouse", text="Size Y") + props.data_path_iter = "selected_editable_objects" + props.data_path_item = "data.size" + props.header_text = "Lamp Size Y: %.3f" + elif lamp.type in {'SPOT', 'AREA', 'POINT', 'SUN'}: + props = layout.operator("wm.context_modal_mouse", text="Size") + props.data_path_iter = "selected_editable_objects" + props.data_path_item = "data.shadow_soft_size" + props.header_text = "Lamp Size: %.3f" else: props = layout.operator("wm.context_modal_mouse", text="Energy") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.energy" props.header_text = "Lamp Energy: %.3f" - if obj.data.type in {'SPOT', 'AREA', 'POINT'}: + if lamp.type in {'SPOT', 'AREA', 'POINT'}: props = layout.operator("wm.context_modal_mouse", text="Falloff Distance") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.distance" props.input_scale = 0.1 props.header_text = "Lamp Falloff Distance: %.1f" - if obj.data.type == 'SPOT': + if lamp.type == 'SPOT': layout.separator() props = layout.operator("wm.context_modal_mouse", text="Spot Size") props.data_path_iter = "selected_editable_objects" diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index a0c6bcd4a5b..8a55d3e8a17 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -93,6 +93,9 @@ typedef struct Global { /* save the allowed windowstate of blender when using -W or -w (GHOST_TWindowState) */ int windowstate; + + /* message to use when autoexec fails */ + char autoexec_fail[200]; } Global; /* **************** GLOBAL ********************* */ @@ -109,6 +112,8 @@ typedef struct Global { #define G_SCRIPT_AUTOEXEC (1 << 13) #define G_SCRIPT_OVERRIDE_PREF (1 << 14) /* when this flag is set ignore the userprefs */ +#define G_SCRIPT_AUTOEXEC_FAIL (1 << 15) +#define G_SCRIPT_AUTOEXEC_FAIL_QUIET (1 << 16) /* #define G_NOFROZEN (1 << 17) also removed */ /* #define G_GREASEPENCIL (1 << 17) also removed */ diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index b195af18a8e..b0bf9513814 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -75,6 +75,7 @@ void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3]); void BKE_lattice_modifiers_calc(struct Scene *scene, struct Object *ob); struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *lattice); +struct BPoint *BKE_lattice_active_point_get(struct Lattice *lt); void BKE_lattice_minmax(struct Lattice *lt, float min[3], float max[3]); void BKE_lattice_center_median(struct Lattice *lt, float cent[3]); diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index d5e5e36cd42..92332116ba6 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -120,7 +120,7 @@ void BKE_mask_update_display(struct Mask *mask, float ctime); void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const int do_newframe); void BKE_mask_evaluate(struct Mask *mask, const float ctime, const int do_newframe); void BKE_mask_layer_evaluate(struct MaskLayer *masklay, const float ctime, const int do_newframe); -void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene, const int do_newframe); +void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene); void BKE_mask_parent_init(struct MaskParent *parent); void BKE_mask_calc_handle_adjacent_interp(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u); void BKE_mask_calc_tangent_polyline(struct MaskSpline *spline, struct MaskSplinePoint *point, float t[2]); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index db93e4f419e..c9668295173 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -97,7 +97,7 @@ void BKE_object_to_mat3(struct Object *ob, float mat[3][3]); void BKE_object_to_mat4(struct Object *ob, float mat[4][4]); void BKE_object_apply_mat4(struct Object *ob, float mat[4][4], const bool use_compat, const bool use_parent); -int BKE_object_pose_context_check(struct Object *ob); +bool BKE_object_pose_context_check(struct Object *ob); struct Object *BKE_object_pose_armature_get(struct Object *ob); void BKE_object_where_is_calc(struct Scene *scene, struct Object *ob); @@ -110,15 +110,15 @@ void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float /* possibly belong in own moduke? */ struct BoundBox *BKE_boundbox_alloc_unit(void); -void BKE_boundbox_init_from_minmax(struct BoundBox *bb, float min[3], float max[3]); -int BKE_boundbox_ray_hit_check(struct BoundBox *bb, float ray_start[3], float ray_normal[3]); +void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3]); +bool BKE_boundbox_ray_hit_check(struct BoundBox *bb, const float ray_start[3], const float ray_normal[3]); struct BoundBox *BKE_object_boundbox_get(struct Object *ob); void BKE_object_dimensions_get(struct Object *ob, float vec[3]); void BKE_object_dimensions_set(struct Object *ob, const float *value); void BKE_object_boundbox_flag(struct Object *ob, int flag, int set); void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden); -int BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden); +bool BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden); /* sometimes min-max isn't enough, we need to loop over each point */ void BKE_object_foreach_display_point(struct Object *ob, float obmat[4][4], diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 5730fd26bcc..fc226288f04 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -484,6 +484,8 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask) Mesh tmp = *me; int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; int did_shapekeys = 0; + float *texloc, *texrot, *texsize; + short *texflag; CustomData_reset(&tmp.vdata); CustomData_reset(&tmp.edata); @@ -529,6 +531,14 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask) shapekey_layers_to_keyblocks(dm, me, uid); did_shapekeys = 1; } + + /* copy texture space */ + if (BKE_object_obdata_texspace_get(ob, &texflag, &texloc, &texsize, &texrot)) { + tmp.texflag = *texflag; + copy_v3_v3(tmp.loc, texloc); + copy_v3_v3(tmp.size, texsize); + copy_v3_v3(tmp.rot, texrot); + } /* not all DerivedMeshes store their verts/edges/faces in CustomData, so * we set them here in case they are missing */ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 3e85c5503f1..65e1f433c20 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1689,43 +1689,39 @@ static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, ListBase *channels, N } /* accumulate (i.e. blend) the given value on to the channel it affects */ -static void nlaevalchan_accumulate(NlaEvalChannel *nec, NlaEvalStrip *nes, short newChan, float value) +static void nlaevalchan_accumulate(NlaEvalChannel *nec, NlaEvalStrip *nes, short UNUSED(newChan), float value) { NlaStrip *strip = nes->strip; short blendmode = strip->blendmode; float inf = strip->influence; - /* if channel is new, just store value regardless of blending factors, etc. */ - if (newChan) { - nec->value = value; - return; - } - /* if this is being performed as part of transition evaluation, incorporate * an additional weighting factor for the influence */ if (nes->strip_mode == NES_TIME_TRANSITION_END) inf *= nes->strip_time; - /* premultiply the value by the weighting factor */ + /* optimisation: no need to try applying if there is no influence */ if (IS_EQ(inf, 0)) return; - value *= inf; /* perform blending */ switch (blendmode) { case NLASTRIP_MODE_ADD: /* simply add the scaled value on to the stack */ - nec->value += value; + nec->value += (value * inf); break; case NLASTRIP_MODE_SUBTRACT: /* simply subtract the scaled value from the stack */ - nec->value -= value; + nec->value -= (value * inf); break; case NLASTRIP_MODE_MULTIPLY: /* multiply the scaled value with the stack */ - nec->value *= value; + /* Formula Used: + * result = fac * (a * b) + (1 - fac) * a + */ + nec->value = inf * (nec->value * value) + (1 - inf) * nec->value; break; case NLASTRIP_MODE_REPLACE: @@ -1734,7 +1730,7 @@ static void nlaevalchan_accumulate(NlaEvalChannel *nec, NlaEvalStrip *nes, short * - the influence of the accumulated data (elsewhere, that is called dstweight) * is 1 - influence, since the strip's influence is srcweight */ - nec->value = nec->value * (1.0f - inf) + value; + nec->value = nec->value * (1.0f - inf) + (value * inf); break; } } diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 428e9d70b96..2a742509635 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -268,9 +268,9 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res memset(result, 0, sizeof(bContextDataResult)); #ifdef WITH_PYTHON if (CTX_py_dict_get(C)) { - return BPY_context_member_get(C, member, result); -// if (BPY_context_member_get(C, member, result)) -// return 1; + if (BPY_context_member_get(C, member, result)) { + return 1; + } } #endif diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index dac6ba4a0f3..feb82a34708 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -168,6 +168,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) lt->pntsv = vNew; lt->pntsw = wNew; + lt->actbp = LT_ACTBP_NONE; MEM_freeN(lt->def); lt->def = MEM_callocN(lt->pntsu * lt->pntsv * lt->pntsw * sizeof(BPoint), "lattice bp"); @@ -192,6 +193,7 @@ Lattice *BKE_lattice_add(Main *bmain, const char *name) lt->def = MEM_callocN(sizeof(BPoint), "lattvert"); /* temporary */ BKE_lattice_resize(lt, 2, 2, 2, NULL); /* creates a uniform lattice */ + lt->actbp = LT_ACTBP_NONE; return lt; } @@ -1012,6 +1014,24 @@ struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *oblatt) return lt->dvert; } +struct BPoint *BKE_lattice_active_point_get(Lattice *lt) +{ + BLI_assert(GS(lt->id.name) == ID_LT); + + if (lt->editlatt) { + lt = lt->editlatt->latt; + } + + BLI_assert(lt->actbp < lt->pntsu * lt->pntsv * lt->pntsw); + + if ((lt->actbp != LT_ACTBP_NONE) && (lt->actbp < lt->pntsu * lt->pntsv * lt->pntsw)) { + return <->def[lt->actbp]; + } + else { + return NULL; + } +} + void BKE_lattice_center_median(struct Lattice *lt, float cent[3]) { int i, numVerts; diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 68500549539..b3c5ceefb2d 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1525,13 +1525,14 @@ void BKE_mask_evaluate_all_masks(Main *bmain, float ctime, const int do_newframe } } -void BKE_mask_update_scene(Main *bmain, Scene *scene, const int do_newframe) +void BKE_mask_update_scene(Main *bmain, Scene *scene) { Mask *mask; for (mask = bmain->mask.first; mask; mask = mask->id.next) { - if (mask->id.flag & LIB_ID_RECALC) { - BKE_mask_evaluate_all_masks(bmain, CFRA, do_newframe); + if (mask->id.flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA)) { + bool do_new_frame = (mask->id.flag & LIB_ID_RECALC_DATA) != 0; + BKE_mask_evaluate_all_masks(bmain, CFRA, do_new_frame); } } } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 9a08254157e..e556e6f23c3 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1139,7 +1139,7 @@ static void copy_object_pose(Object *obn, Object *ob) } } -int BKE_object_pose_context_check(Object *ob) +bool BKE_object_pose_context_check(Object *ob) { if ((ob) && (ob->type == OB_ARMATURE) && @@ -2223,7 +2223,7 @@ void BKE_object_workob_calc_parent(Scene *scene, Object *ob, Object *workob) BoundBox *BKE_boundbox_alloc_unit(void) { BoundBox *bb; - float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {-1.0f, -1.0f, -1.0f}; + const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {-1.0f, -1.0f, -1.0f}; bb = MEM_callocN(sizeof(BoundBox), "OB-BoundBox"); BKE_boundbox_init_from_minmax(bb, min, max); @@ -2231,7 +2231,7 @@ BoundBox *BKE_boundbox_alloc_unit(void) return bb; } -void BKE_boundbox_init_from_minmax(BoundBox *bb, float min[3], float max[3]) +void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float max[3]) { bb->vec[0][0] = bb->vec[1][0] = bb->vec[2][0] = bb->vec[3][0] = min[0]; bb->vec[4][0] = bb->vec[5][0] = bb->vec[6][0] = bb->vec[7][0] = max[0]; @@ -2412,9 +2412,9 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us } } -int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_max[3], const bool use_hidden) +bool BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_max[3], const bool use_hidden) { - int ok = FALSE; + bool ok = false; if ((ob->transflag & OB_DUPLI) == 0) { return ok; } @@ -2874,15 +2874,17 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc, * Test a bounding box for ray intersection * assumes the ray is already local to the boundbox space */ -int BKE_boundbox_ray_hit_check(struct BoundBox *bb, float ray_start[3], float ray_normal[3]) +bool BKE_boundbox_ray_hit_check(struct BoundBox *bb, const float ray_start[3], const float ray_normal[3]) { - static int triangle_indexes[12][3] = {{0, 1, 2}, {0, 2, 3}, - {3, 2, 6}, {3, 6, 7}, - {1, 2, 6}, {1, 6, 5}, - {5, 6, 7}, {4, 5, 7}, - {0, 3, 7}, {0, 4, 7}, - {0, 1, 5}, {0, 4, 5}}; - int result = 0; + const int triangle_indexes[12][3] = { + {0, 1, 2}, {0, 2, 3}, + {3, 2, 6}, {3, 6, 7}, + {1, 2, 6}, {1, 6, 5}, + {5, 6, 7}, {4, 5, 7}, + {0, 3, 7}, {0, 4, 7}, + {0, 1, 5}, {0, 4, 5}}; + + bool result = false; int i; for (i = 0; i < 12 && result == 0; i++) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 76727987355..9c376f9ea04 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1181,7 +1181,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen sound_update_scene(scene); /* update masking curves */ - BKE_mask_update_scene(bmain, scene, FALSE); + BKE_mask_update_scene(bmain, scene); } diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 4ebb1a1a1d9..96652c0e78d 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -111,30 +111,30 @@ int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], co int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float i1[3], float i2[3]); -int isect_line_line_strict_v3(const float v1[3], const float v2[3], - const float v3[3], const float v4[3], - float vi[3], float *r_lambda); +bool isect_line_line_strict_v3(const float v1[3], const float v2[3], + const float v3[3], const float v4[3], + float vi[3], float *r_lambda); -int isect_ray_plane_v3(const float p1[3], const float d[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, const int clip); +bool isect_ray_plane_v3(const float p1[3], const float d[3], + const float v0[3], const float v1[3], const float v2[3], + float *r_lambda, const int clip); -int isect_line_plane_v3(float out[3], const float l1[3], const float l2[3], - const float plane_co[3], const float plane_no[3], const bool no_flip); +bool isect_line_plane_v3(float out[3], const float l1[3], const float l2[3], + const float plane_co[3], const float plane_no[3], const bool no_flip); void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], const float plane_a_co[3], const float plane_a_no[3], const float plane_b_co[3], const float plane_b_no[3]); /* line/ray triangle */ -int isect_line_tri_v3(const float p1[3], const float p2[3], +bool isect_line_tri_v3(const float p1[3], const float p2[3], + const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2]); +bool isect_ray_tri_v3(const float p1[3], const float d[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2]); -int isect_ray_tri_v3(const float p1[3], const float d[3], - const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2]); -int isect_ray_tri_threshold_v3(const float p1[3], const float d[3], - const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float threshold); -int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], - const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon); +bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3], + const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float threshold); +bool isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], + const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon); /* point in polygon */ bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr); @@ -145,14 +145,14 @@ int isect_point_quad_v2(const float p[2], const float a[2], const float b[2], co int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2]); int isect_point_tri_v2_cw(const float pt[2], const float v1[2], const float v2[2], const float v3[2]); int isect_point_tri_v2_int(const int x1, const int y1, const int x2, const int y2, const int a, const int b); -int isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]); +bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]); void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float pt[2], float r_uv[2]); void isect_point_face_uv_v2(const int isquad, const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float pt[2], float r_uv[2]); /* axis-aligned bounding box */ -int isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3]); +bool isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3]); typedef struct { float ray_start[3]; @@ -161,14 +161,14 @@ typedef struct { } IsectRayAABBData; void isect_ray_aabb_initialize(IsectRayAABBData *data, const float ray_start[3], const float ray_direction[3]); -int isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3], const float bb_max[3], float *tmin); +bool isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3], const float bb_max[3], float *tmin); /* other */ -int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius, - const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float ipoint[3]); +bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius, + const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float ipoint[3]); -int isect_axial_line_tri_v3(const int axis, const float co1[3], const float co2[3], - const float v0[3], const float v1[3], const float v2[3], float *r_lambda); +bool isect_axial_line_tri_v3(const int axis, const float co1[3], const float co2[3], + const float v0[3], const float v1[3], const float v2[3], float *r_lambda); bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4]); bool clip_segment_v3_plane_n(float p1[3], float p2[3], float plane_array[][4], const int plane_tot); diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 5811bb51012..fff5bc52003 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -888,9 +888,9 @@ int isect_point_quad_v2(const float pt[2], const float v1[2], const float v2[2], * test if the line starting at p1 ending at p2 intersects the triangle v0..v2 * return non zero if it does */ -int isect_line_tri_v3(const float p1[3], const float p2[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float r_uv[2]) +bool isect_line_tri_v3(const float p1[3], const float p2[3], + const float v0[3], const float v1[3], const float v2[3], + float *r_lambda, float r_uv[2]) { float p[3], s[3], d[3], e1[3], e2[3], q[3]; @@ -930,9 +930,9 @@ int isect_line_tri_v3(const float p1[3], const float p2[3], * test if the ray starting at p1 going in d direction intersects the triangle v0..v2 * return non zero if it does */ -int isect_ray_tri_v3(const float p1[3], const float d[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float r_uv[2]) +bool isect_ray_tri_v3(const float p1[3], const float d[3], + const float v0[3], const float v1[3], const float v2[3], + float *r_lambda, float r_uv[2]) { float p[3], s[3], e1[3], e2[3], q[3]; float a, f, u, v; @@ -972,9 +972,9 @@ int isect_ray_tri_v3(const float p1[3], const float d[3], * if clip is nonzero, will only return true if lambda is >= 0.0 * (i.e. intersection point is along positive d) */ -int isect_ray_plane_v3(const float p1[3], const float d[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, const int clip) +bool isect_ray_plane_v3(const float p1[3], const float d[3], + const float v0[3], const float v1[3], const float v2[3], + float *r_lambda, const int clip) { float p[3], s[3], e1[3], e2[3], q[3]; float a, f; @@ -1004,9 +1004,9 @@ int isect_ray_plane_v3(const float p1[3], const float d[3], return 1; } -int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float uv[2], const float epsilon) +bool isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], + const float v0[3], const float v1[3], const float v2[3], + float *r_lambda, float uv[2], const float epsilon) { float p[3], s[3], e1[3], e2[3], q[3]; float a, f, u, v; @@ -1040,9 +1040,9 @@ int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], return 1; } -int isect_ray_tri_threshold_v3(const float p1[3], const float d[3], - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float r_uv[2], const float threshold) +bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3], + const float v0[3], const float v1[3], const float v2[3], + float *r_lambda, float r_uv[2], const float threshold) { float p[3], s[3], e1[3], e2[3], q[3]; float a, f, u, v; @@ -1100,9 +1100,9 @@ int isect_ray_tri_threshold_v3(const float p1[3], const float d[3], * \param plane_no The direction of the plane (does not need to be normalized). * \param no_flip When true, the intersection point will always be from l1 to l2, even if this is not on the plane. */ -int isect_line_plane_v3(float out[3], - const float l1[3], const float l2[3], - const float plane_co[3], const float plane_no[3], const bool no_flip) +bool isect_line_plane_v3(float out[3], + const float l1[3], const float l2[3], + const float plane_co[3], const float plane_no[3], const bool no_flip) { float l_vec[3]; /* l1 -> l2 normalized vector */ float p_no[3]; /* 'plane_no' normalized */ @@ -1174,7 +1174,7 @@ void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], /* Adapted from the paper by Kasper Fauerby */ /* "Improved Collision detection and Response" */ -static int getLowestRoot(const float a, const float b, const float c, const float maxR, float *root) +static bool getLowestRoot(const float a, const float b, const float c, const float maxR, float *root) { /* Check if a solution exists */ float determinant = b * b - 4.0f * a * c; @@ -1208,15 +1208,15 @@ static int getLowestRoot(const float a, const float b, const float c, const floa return 0; } -int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius, - const float v0[3], const float v1[3], const float v2[3], - float *r_lambda, float ipoint[3]) +bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius, + const float v0[3], const float v1[3], const float v2[3], + float *r_lambda, float ipoint[3]) { float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3]; float a, b, c, d, e, x, y, z, radius2 = radius * radius; float elen2, edotv, edotbv, nordotv; float newLambda; - int found_by_sweep = 0; + bool found_by_sweep = false; sub_v3_v3v3(e1, v1, v0); sub_v3_v3v3(e2, v2, v0); @@ -1396,8 +1396,8 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo return found_by_sweep; } -int isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3], - const float v0[3], const float v1[3], const float v2[3], float *r_lambda) +bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3], + const float v0[3], const float v1[3], const float v2[3], float *r_lambda) { float p[3], e1[3], e2[3]; float u, v, f; @@ -1513,7 +1513,9 @@ int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], /* Intersection point strictly between the two lines * 0 when no intersection is found * */ -int isect_line_line_strict_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float vi[3], float *r_lambda) +bool isect_line_line_strict_v3(const float v1[3], const float v2[3], + const float v3[3], const float v4[3], + float vi[3], float *r_lambda) { float a[3], b[3], c[3], ab[3], cb[3], ca[3], dir1[3], dir2[3]; float d; @@ -1561,7 +1563,7 @@ int isect_line_line_strict_v3(const float v1[3], const float v2[3], const float } } -int isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3]) +bool isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3]) { return (min1[0] < max2[0] && min1[1] < max2[1] && min1[2] < max2[2] && min2[0] < max1[0] && min2[1] < max1[1] && min2[2] < max1[2]); @@ -1581,8 +1583,8 @@ void isect_ray_aabb_initialize(IsectRayAABBData *data, const float ray_start[3], } /* Adapted from http://www.gamedev.net/community/forums/topic.asp?topic_id=459973 */ -int isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3], - const float bb_max[3], float *tmin_out) +bool isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3], + const float bb_max[3], float *tmin_out) { float bbox[2][3]; float tmin, tmax, tymin, tymax, tzmin, tzmax; @@ -1913,7 +1915,7 @@ int isect_point_tri_v2_int(const int x1, const int y1, const int x2, const int y return isect_point_tri_v2(p, v1, v2, v3); } -static int point_in_slice(const float p[3], const float v1[3], const float l1[3], const float l2[3]) +static bool point_in_slice(const float p[3], const float v1[3], const float l1[3], const float l2[3]) { /* * what is a slice ? @@ -1962,7 +1964,7 @@ static int point_in_slice_m(float p[3], float origin[3], float normal[3], float } #endif -int isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]) +bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]) { if (!point_in_slice(p, v1, v2, v3)) return 0; if (!point_in_slice(p, v2, v3, v1)) return 0; diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 497c99f3f8a..012cbccacc7 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1010,6 +1010,7 @@ static BMOpDefine bmo_subdivide_edges_def = { {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */ {"use_only_quads", BMO_OP_SLOT_BOOL}, /* only subdivide quads (for loopcut) */ {"use_sphere", BMO_OP_SLOT_BOOL}, /* for making new primitives only */ + {"use_smooth_even", BMO_OP_SLOT_BOOL}, /* maintain even offset when smoothing */ {{'\0'}}, }, /* slots_out */ diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 7f62d4cd21a..4c6129cf43f 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -122,7 +122,7 @@ extern const int bmo_opdefines_total; /*------specific operator helper functions-------*/ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, - const float smooth, const short smooth_falloff, + const float smooth, const short smooth_falloff, const bool use_smooth_even, const float fractal, const float along_normal, const int numcuts, const int seltype, const int cornertype, diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 0fcf17cd718..96771e00291 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -40,7 +40,6 @@ #include "intern/bmesh_private.h" #include "intern/bmesh_operators_private.h" - typedef struct SubDParams { int numcuts; float smooth; @@ -49,16 +48,37 @@ typedef struct SubDParams { float along_normal; //int beauty; bool use_smooth; + bool use_smooth_even; bool use_sphere; bool use_fractal; int seed; - int origkey; /* shapekey holding displaced vertex coordinates for current geometry */ BMOperator *op; BMOpSlot *slot_edge_percents; /* BMO_slot_get(params->op->slots_in, "edge_percents"); */ BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */ float fractal_ofs[3]; + + /* rumtime storage for shape key */ + struct { + int cd_vert_shape_offset; + int cd_vert_shape_offset_tmp; + int totlayer; + + /* shapekey holding displaced vertex coordinates for current geometry */ + int tmpkey; + } shape_info; + } SubDParams; +static void bmo_subd_init_shape_info(BMesh *bm, SubDParams *params) +{ + const int skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1; + params->shape_info.tmpkey = skey; + params->shape_info.cd_vert_shape_offset = CustomData_get_offset(&bm->vdata, CD_SHAPEKEY); + params->shape_info.cd_vert_shape_offset_tmp = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, skey); + params->shape_info.totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY); + +} + typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts, const SubDParams *params); @@ -141,16 +161,15 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace * return NULL; } /* calculates offset for co, based on fractal, sphere or smooth settings */ -static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc, +static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc, BMVert *vsta, BMVert *vend) { float tvec[3], prev_co[3], fac; - float *co = NULL; - int i, totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY); + float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp); + int i; BM_vert_normal_update_all(v); - co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, params->origkey); copy_v3_v3(co, v->co); copy_v3_v3(prev_co, co); @@ -180,14 +199,18 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDPar val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc)); val = bmesh_subd_falloff_calc(params->smooth_falloff, val); + if (params->use_smooth_even) { + val *= BM_vert_calc_shell_factor(v); + } + mul_v3_fl(tvec, params->smooth * val * len); add_v3_v3(co, tvec); } if (params->use_fractal) { - float len = len_v3v3(vsta->co, vend->co); - float normal[3] = {0.0f, 0.0f, 0.0f}, co2[3], base1[3], base2[3]; + const float len = len_v3v3(vsta->co, vend->co); + float normal[3], co2[3], base1[3], base2[3]; fac = params->fractal * len; @@ -214,13 +237,15 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDPar * for now its ok to simply apply the difference IMHO - campbell */ sub_v3_v3v3(tvec, prev_co, co); - for (i = 0; i < totlayer; i++) { - if (params->origkey != i) { - co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i); - sub_v3_v3(co, tvec); + if (params->shape_info.totlayer > 1) { + /* skip the last layer since its the temp */ + i = params->shape_info.totlayer - 1; + co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset); + while (i--) { + BLI_assert(co != BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp)); + sub_v3_v3(co += 3, tvec); } } - } /* assumes in the edge is the correct interpolated vertices already */ @@ -238,7 +263,7 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge, BMO_elem_flag_enable(bm, ev, ELE_INNER); /* offset for smooth or sphere or fractal */ - alter_co(bm, ev, oedge, params, percent2, vsta, vend); + alter_co(ev, oedge, params, percent2, vsta, vend); #if 0 //BMESH_TODO /* clip if needed by mirror modifier */ @@ -308,8 +333,8 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *par if (v->e && v->e->l) BM_CHECK_ELEMENT(v->e->l->f); } - alter_co(bm, v1, &e_tmp, params, 0, &v1_tmp, &v2_tmp); - alter_co(bm, v2, &e_tmp, params, 1.0, &v1_tmp, &v2_tmp); + alter_co(v1, &e_tmp, params, 0, &v1_tmp, &v2_tmp); + alter_co(v2, &e_tmp, params, 1.0, &v1_tmp, &v2_tmp); } /* note: the patterns are rotated as necessary to @@ -759,7 +784,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_declare(verts); float smooth, fractal, along_normal; bool use_sphere, use_single_edge, use_grid_fill, use_only_quads; - int cornertype, skey, seed, i, j, matched, a, b, numcuts, totesel, smooth_falloff; + int cornertype, seed, i, j, matched, a, b, numcuts, totesel, smooth_falloff; BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT); @@ -810,10 +835,11 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) /* add a temporary shapekey layer to store displacements on current geometry */ BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY); - skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1; + + bmo_subd_init_shape_info(bm, ¶ms); BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, skey); + float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp); copy_v3_v3(co, v->co); } @@ -830,9 +856,9 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) params.fractal = fractal; params.along_normal = along_normal; params.use_smooth = (smooth != 0.0f); + params.use_smooth_even = BMO_slot_bool_get(op->slots_in, "use_smooth_even"); params.use_fractal = (fractal != 0.0f); params.use_sphere = use_sphere; - params.origkey = skey; if (params.use_fractal) { RNG *rng = BLI_rng_new_srandom(seed); @@ -981,7 +1007,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) /* copy original-geometry displacements to current coordinates */ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, skey); + float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp); copy_v3_v3(v->co, co); } @@ -1126,11 +1152,11 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) /* copy original-geometry displacements to current coordinates */ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, skey); + float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp); copy_v3_v3(v->co, co); } - BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, skey); + BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey); if (facedata) BLI_array_free(facedata); if (edges) BLI_array_free(edges); @@ -1146,7 +1172,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) /* editmesh-emulating function */ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, - const float smooth, const short smooth_falloff, + const float smooth, const short smooth_falloff, const bool use_smooth_even, const float fractal, const float along_normal, const int numcuts, const int seltype, const int cornertype, @@ -1159,7 +1185,7 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, /* use_sphere isnt exposed here since its only used for new primitives */ BMO_op_initf(bm, &op, BMO_FLAG_DEFAULTS, "subdivide_edges edges=%he " - "smooth=%f smooth_falloff=%i " + "smooth=%f smooth_falloff=%i use_smooth_even=%b " "fractal=%f along_normal=%f " "cuts=%i " "quad_corner_type=%i " @@ -1167,7 +1193,7 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, "use_only_quads=%b " "seed=%i", edge_hflag, - smooth, smooth_falloff, + smooth, smooth_falloff, use_smooth_even, fractal, along_normal, numcuts, cornertype, @@ -1205,16 +1231,14 @@ void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op) BMOIter siter; BMEdge *e; SubDParams params = {0}; - int skey; params.numcuts = BMO_slot_int_get(op->slots_in, "cuts"); params.op = op; params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents"); BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY); - skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1; - - params.origkey = skey; + + bmo_subd_init_shape_info(bm, ¶ms); /* go through and split edges */ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { @@ -1223,5 +1247,5 @@ void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op) BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT); - BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, skey); + BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey); } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 9e769b32136..41aeb92e182 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -87,6 +87,7 @@ #include "BKE_key.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_modifier.h" #include "BKE_node.h" #include "BKE_mask.h" #include "BKE_sequencer.h" @@ -1550,20 +1551,20 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data { SceneRenderLayer *srl; size_t items = 0; - + for (srl = sce->r.layers.first; srl; srl = srl->next) { FreestyleLineSet *lineset; - + /* skip render layers without Freestyle enabled */ if (!(srl->layflag & SCE_LAY_FRS)) continue; - + /* loop over linesets defined in the render layer */ for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { FreestyleLineStyle *linestyle = lineset->linestyle; ListBase tmp_data = {NULL, NULL}; size_t tmp_items = 0; - + /* add scene-level animation channels */ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_LS_SCED(linestyle)) { @@ -1571,7 +1572,7 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)linestyle, filter_mode); } END_ANIMFILTER_SUBCHANNELS; - + /* did we find anything? */ if (tmp_items) { /* include anim-expand widget first */ @@ -1594,6 +1595,49 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data return items; } +static size_t animdata_filter_ds_texture(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, + Tex *tex, ID *owner_id, int filter_mode) +{ + ListBase tmp_data = {NULL, NULL}; + size_t tmp_items = 0; + size_t items = 0; + + /* add texture's animation data to temp collection */ + BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_TEX_DATA(tex)) + { + /* texture animdata */ + tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)tex, filter_mode); + + /* nodes */ + if ((tex->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE)) { + /* owner_id as id instead of texture, since it'll otherwise be impossible to track the depth */ + // FIXME: perhaps as a result, textures should NOT be included under materials, but under their own section instead + // so that free-floating textures can also be animated + tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)tex, tex->nodetree, filter_mode); + } + } + END_ANIMFILTER_SUBCHANNELS; + + /* did we find anything? */ + if (tmp_items) { + /* include texture-expand widget? */ + if (filter_mode & ANIMFILTER_LIST_CHANNELS) { + /* check if filtering by active status */ + if (ANIMCHANNEL_ACTIVEOK(tex)) { + ANIMCHANNEL_NEW_CHANNEL(tex, ANIMTYPE_DSTEX, owner_id); + } + } + + /* now add the list of collected channels */ + BLI_movelisttolist(anim_data, &tmp_data); + BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL)); + items += tmp_items; + } + + /* return the number of items added to the list */ + return items; +} + /* NOTE: owner_id is either material, lamp, or world block, which is the direct owner of the texture stack in question */ static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode) { @@ -1636,44 +1680,13 @@ static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data, /* firstly check that we actuallly have some textures, by gathering all textures in a temp list */ for (a = 0; a < MAX_MTEX; a++) { Tex *tex = (mtex[a]) ? mtex[a]->tex : NULL; - ListBase tmp_data = {NULL, NULL}; - size_t tmp_items = 0; /* for now, if no texture returned, skip (this shouldn't confuse the user I hope) */ if (tex == NULL) continue; - /* add texture's animation data to temp collection */ - BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_TEX_DATA(tex)) - { - /* texture animdata */ - tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)tex, filter_mode); - - /* nodes */ - if ((tex->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE)) { - /* owner_id as id instead of texture, since it'll otherwise be impossible to track the depth */ - // FIXME: perhaps as a result, textures should NOT be included under materials, but under their own section instead - // so that free-floating textures can also be animated - tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)tex, tex->nodetree, filter_mode); - } - } - END_ANIMFILTER_SUBCHANNELS; - - /* did we find anything? */ - if (tmp_items) { - /* include texture-expand widget? */ - if (filter_mode & ANIMFILTER_LIST_CHANNELS) { - /* check if filtering by active status */ - if (ANIMCHANNEL_ACTIVEOK(tex)) { - ANIMCHANNEL_NEW_CHANNEL(tex, ANIMTYPE_DSTEX, owner_id); - } - } - - /* now add the list of collected channels */ - BLI_movelisttolist(anim_data, &tmp_data); - BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL)); - items += tmp_items; - } + /* add texture's anim channels */ + items += animdata_filter_ds_texture(ac, anim_data, ads, tex, owner_id, filter_mode); } /* return the number of items added to the list */ @@ -1763,6 +1776,87 @@ static size_t animdata_filter_ds_materials(bAnimContext *ac, ListBase *anim_data return items; } + +/* ............ */ + +/* Temporary context for modifier linked-data channel extraction */ +typedef struct tAnimFilterModifiersContext { + bAnimContext *ac; /* anim editor context */ + bDopeSheet *ads; /* dopesheet filtering settings */ + + ListBase tmp_data; /* list of channels created (but not yet added to the main list) */ + size_t items; /* number of channels created */ + + int filter_mode; /* flags for stuff we want to filter */ +} tAnimFilterModifiersContext; + + +/* dependency walker callback for modifier dependencies */ +static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin) +{ + tAnimFilterModifiersContext *afm = (tAnimFilterModifiersContext *)afm_ptr; + ID *owner_id = &ob->id; + ID *id = *idpoin; + + /* NOTE: the walker only guarantees to give us all the ID-ptr *slots*, + * not just the ones which are actually used, so be careful! + */ + if (id == NULL) + return; + + /* check if this is something we're interested in... */ + switch (GS(id->name)) { + case ID_TE: /* Textures */ + { + Tex *tex = (Tex *)id; + if (!(afm->ads->filterflag & ADS_FILTER_NOTEX)) { + afm->items += animdata_filter_ds_texture(afm->ac, &afm->tmp_data, afm->ads, tex, owner_id, afm->filter_mode); + } + } + break; + + /* TODO: images? */ + } +} + +/* animation linked to data used by modifiers + * NOTE: strictly speaking, modifier animation is already included under Object level + * but for some modifiers (e.g. Displace), there can be linked data that has settings + * which would be nice to animate (i.e. texture parameters) but which are not actually + * attached to any other objects/materials/etc. in the scene + */ +// TODO: do we want an expander for this? +static size_t animdata_filter_ds_modifiers(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode) +{ + tAnimFilterModifiersContext afm = {NULL}; + size_t items = 0; + + /* 1) create a temporary "context" containing all the info we have here to pass to the callback + * use to walk thorugh the dependencies of the modifiers + * + * ! Assumes that all other unspecified values (i.e. accumulation buffers) are zero'd out properly + */ + afm.ac = ac; + afm.ads = ads; + afm.filter_mode = filter_mode; + + /* 2) walk over dependencies */ + modifiers_foreachIDLink(ob, animfilter_modifier_idpoin_cb, &afm); + + /* 3) extract data from the context, merging it back into the standard list */ + if (afm.items) { + /* now add the list of collected channels */ + BLI_movelisttolist(anim_data, &afm.tmp_data); + BLI_assert((afm.tmp_data.first == afm.tmp_data.last) && (afm.tmp_data.first == NULL)); + items += afm.items; + } + + return items; +} + +/* ............ */ + + static size_t animdata_filter_ds_particles(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode) { ParticleSystem *psys; @@ -1805,6 +1899,7 @@ static size_t animdata_filter_ds_particles(bAnimContext *ac, ListBase *anim_data return items; } + static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode) { ListBase tmp_data = {NULL, NULL}; @@ -1985,6 +2080,7 @@ static size_t animdata_filter_ds_keyanim(bAnimContext *ac, ListBase *anim_data, return items; } + /* object-level animation */ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode) { @@ -2063,6 +2159,11 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data tmp_items += animdata_filter_ds_keyanim(ac, &tmp_data, ads, ob, key, filter_mode); } + /* modifiers */ + if ((ob->modifiers.first) && !(ads->filterflag & ADS_FILTER_NOMODIFIERS)) { + tmp_items += animdata_filter_ds_modifiers(ac, &tmp_data, ads, ob, filter_mode); + } + /* materials */ if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT)) { tmp_items += animdata_filter_ds_materials(ac, &tmp_data, ads, ob, filter_mode); diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 3cf8c44f9aa..568178802bd 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -267,7 +267,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "ARMATURE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_extrude_move", EKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_extrude_forked", EKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "ARMATURE_OT_click_extrude", LEFTMOUSE, KM_CLICK, KM_CTRL, 0); + WM_keymap_add_item(keymap, "ARMATURE_OT_click_extrude", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_fill", FKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_merge", MKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index 07dd2b82a06..03b7697ecfa 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -223,7 +223,7 @@ void ED_keymap_curve(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CURVE_OT_handle_type_set", VKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "CURVE_OT_vertex_add", LEFTMOUSE, KM_CLICK, KM_CTRL, 0); + WM_keymap_add_item(keymap, "CURVE_OT_vertex_add", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); kmi = WM_keymap_add_item(keymap, "CURVE_OT_select_all", AKEY, KM_PRESS, 0, 0); RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 0383c0d1d1a..ae65cc9dbbe 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -4624,19 +4624,20 @@ static int add_vertex_exec(bContext *C, wmOperator *op) static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); + ViewContext vc; - if (rv3d && !RNA_struct_property_is_set(op->ptr, "location")) { + view3d_set_viewcontext(C, &vc); + + if (vc.rv3d && !RNA_struct_property_is_set(op->ptr, "location")) { Curve *cu; - ViewContext vc; float location[3]; + const bool use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) && + (vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE)); Nurb *nu; BezTriple *bezt; BPoint *bp; - view3d_set_viewcontext(C, &vc); - cu = vc.obedit->data; findselectedNurbvert(&cu->editnurb->nurbs, &nu, &bezt, &bp); @@ -4652,6 +4653,14 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) } ED_view3d_win_to_3d_int(vc.ar, location, event->mval, location); + + if (use_proj) { + const float mval[2] = {UNPACK2(event->mval)}; + float no_dummy[3]; + float dist_px_dummy; + snapObjectsContext(C, mval, &dist_px_dummy, location, no_dummy, SNAP_NOT_OBEDIT); + } + RNA_float_set_array(op->ptr, "location", location); } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 9ee1f59fe21..2d24b34e60b 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1268,7 +1268,7 @@ static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2 int i; /* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero [#35686] */ - if (IS_EQ(delta, minmax_weights[1])) + if (IS_EQF(delta, minmax_weights[1])) fac = 1.0f; else fac = 1.0f / (minmax_weights[1] - delta); diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index c5b9fc33a9b..93bdca93096 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -124,7 +124,7 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) if (change) { WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); - DAG_id_tag_update(&mask->id, 0); + DAG_id_tag_update(&mask->id, OB_RECALC_DATA); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index a126546c81c..2829aed4999 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -295,7 +295,8 @@ static void ringsel_finish(bContext *C, wmOperator *op) * Note though that it will break edgeslide in this specific case. * See [#31939]. */ BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, - smoothness, smooth_falloff, 0.0f, 0.0f, + smoothness, smooth_falloff, true, + 0.0f, 0.0f, cuts, SUBDIV_SELECT_LOOPCUT, SUBD_PATH, 0, true, use_only_quads, 0); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index b3463915080..1f7690b9b42 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -92,7 +92,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) } BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, - smooth, SUBD_FALLOFF_ROOT, + smooth, SUBD_FALLOFF_ROOT, false, fractal, along_normal, cuts, SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"), diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c index 9d3b2b7272d..d3537051861 100644 --- a/source/blender/editors/object/object_lattice.c +++ b/source/blender/editors/object/object_lattice.c @@ -154,6 +154,7 @@ void load_editLatt(Object *obedit) lt->typeu = editlt->typeu; lt->typev = editlt->typev; lt->typew = editlt->typew; + lt->actbp = editlt->actbp; } if (lt->dvert) { @@ -180,7 +181,8 @@ void ED_setflagsLatt(Object *obedit, int flag) bp = lt->editlatt->latt->def; a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; - + lt->editlatt->latt->actbp = LT_ACTBP_NONE; + while (a--) { if (bp->hide == 0) { bp->f1 = flag; @@ -224,6 +226,7 @@ static int lattice_select_all_exec(bContext *C, wmOperator *op) case SEL_INVERT: bp = lt->editlatt->latt->def; a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; + lt->editlatt->latt->actbp = LT_ACTBP_NONE; while (a--) { if (bp->hide == 0) { @@ -642,8 +645,10 @@ bool mouse_lattice(bContext *C, const int mval[2], bool extend, bool deselect, b { ViewContext vc; BPoint *bp = NULL; + Lattice *lt; view3d_set_viewcontext(C, &vc); + lt = ((Lattice *)vc.obedit->data)->editlatt->latt; bp = findnearestLattvert(&vc, mval, TRUE); if (bp) { @@ -661,6 +666,13 @@ bool mouse_lattice(bContext *C, const int mval[2], bool extend, bool deselect, b bp->f1 |= SELECT; } + if (bp->f1 & SELECT) { + lt->actbp = bp - lt->def; + } + else { + lt->actbp = LT_ACTBP_NONE; + } + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); return true; @@ -673,7 +685,7 @@ bool mouse_lattice(bContext *C, const int mval[2], bool extend, bool deselect, b typedef struct UndoLattice { BPoint *def; - int pntsu, pntsv, pntsw; + int pntsu, pntsv, pntsw, actbp; } UndoLattice; static void undoLatt_to_editLatt(void *data, void *edata, void *UNUSED(obdata)) @@ -683,6 +695,7 @@ static void undoLatt_to_editLatt(void *data, void *edata, void *UNUSED(obdata)) int a = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw; memcpy(editlatt->latt->def, ult->def, a * sizeof(BPoint)); + editlatt->latt->actbp = ult->actbp; } static void *editLatt_to_undoLatt(void *edata, void *UNUSED(obdata)) @@ -694,6 +707,7 @@ static void *editLatt_to_undoLatt(void *edata, void *UNUSED(obdata)) ult->pntsu = editlatt->latt->pntsu; ult->pntsv = editlatt->latt->pntsv; ult->pntsw = editlatt->latt->pntsw; + ult->actbp = editlatt->latt->actbp; return ult; } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 437bea07069..1089df2e00d 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -65,6 +65,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_object_deform.h" #include "BKE_object.h" +#include "BKE_lattice.h" #include "RNA_access.h" #include "RNA_define.h" @@ -992,7 +993,7 @@ static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum) EDBM_index_arrays_ensure(em, BM_VERT); - if ((cd_dvert_offset != -1) || (eve = EDBM_vert_at_index(em, vertnum))) { + if ((cd_dvert_offset != -1) && (eve = EDBM_vert_at_index(em, vertnum))) { dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); } else { @@ -1108,7 +1109,7 @@ static void vgroup_select_verts(Object *ob, int select) if (lt->dvert) { MDeformVert *dv; - BPoint *bp; + BPoint *bp, *actbp = BKE_lattice_active_point_get(lt); int a, tot; dv = lt->dvert; @@ -1117,7 +1118,10 @@ static void vgroup_select_verts(Object *ob, int select) for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) { if (defvert_find_index(dv, def_nr)) { if (select) bp->f1 |= SELECT; - else bp->f1 &= ~SELECT; + else { + bp->f1 &= ~SELECT; + if (actbp && bp == actbp) lt->actbp = LT_ACTBP_NONE; + } } } } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 4b62eb7c645..da2f8bd2f9d 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -422,7 +422,7 @@ static void render_endjob(void *rjv) free_main(rj->main); /* else the frame will not update for the original value */ - if (!(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) { + if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) { /* possible this fails of loading new file while rendering */ if (G.main->wm.first) { ED_update_for_newframe(G.main, rj->scene, 1); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 8ee09101cdf..89fa58cd750 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -2315,9 +2315,6 @@ static int node_shader_script_update_poll(bContext *C) bNode *node; Text *text; - if (!ED_operator_node_editable(C)) - return 0; - /* test if we have a render engine that supports shaders scripts */ if (!(type && type->update_script_node)) return 0; @@ -2325,14 +2322,14 @@ static int node_shader_script_update_poll(bContext *C) /* see if we have a shader script node in context */ node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data; - if (!node) + if (!node && snode && snode->edittree) node = nodeGetActive(snode->edittree); if (node && node->type == SH_NODE_SCRIPT) { NodeShaderScript *nss = node->storage; if (node->id || nss->filepath[0]) { - return 1; + return ED_operator_node_editable(C); } } diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c index 96008004ee4..8074ec57474 100644 --- a/source/blender/editors/space_script/script_edit.c +++ b/source/blender/editors/space_script/script_edit.c @@ -36,6 +36,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_global.h" #include "WM_api.h" #include "WM_types.h" @@ -110,3 +111,23 @@ void SCRIPT_OT_reload(wmOperatorType *ot) /* api callbacks */ ot->exec = script_reload_exec; } + +static int script_autoexec_warn_clear_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) +{ + G.f |= G_SCRIPT_AUTOEXEC_FAIL_QUIET; + return OPERATOR_FINISHED; +} + +void SCRIPT_OT_autoexec_warn_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Continue Untrusted"; + ot->description = "Ignore autoexec warning"; + ot->idname = "SCRIPT_OT_autoexec_warn_clear"; + + /* flags */ + ot->flag = OPTYPE_INTERNAL; + + /* api callbacks */ + ot->exec = script_autoexec_warn_clear_exec; +} diff --git a/source/blender/editors/space_script/script_intern.h b/source/blender/editors/space_script/script_intern.h index 00863863994..cef6082aa1c 100644 --- a/source/blender/editors/space_script/script_intern.h +++ b/source/blender/editors/space_script/script_intern.h @@ -40,6 +40,7 @@ void script_keymap(struct wmKeyConfig *keyconf); /* script_edit.c */ void SCRIPT_OT_reload(struct wmOperatorType *ot); void SCRIPT_OT_python_file_run(struct wmOperatorType *ot); +void SCRIPT_OT_autoexec_warn_clear(struct wmOperatorType *ot); #endif /* __SCRIPT_INTERN_H__ */ diff --git a/source/blender/editors/space_script/script_ops.c b/source/blender/editors/space_script/script_ops.c index 57a1112a832..7398126a8e5 100644 --- a/source/blender/editors/space_script/script_ops.c +++ b/source/blender/editors/space_script/script_ops.c @@ -56,6 +56,7 @@ void script_operatortypes(void) { WM_operatortype_append(SCRIPT_OT_python_file_run); WM_operatortype_append(SCRIPT_OT_reload); + WM_operatortype_append(SCRIPT_OT_autoexec_warn_clear); } void script_keymap(wmKeyConfig *keyconf) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 662437b72b9..db10c1c5957 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -260,18 +260,6 @@ static const unsigned int colortab[] = { 0x0, 0x403000, 0xFFFF88 }; - -static float cube[8][3] = { - {-1.0, -1.0, -1.0}, - {-1.0, -1.0, 1.0}, - {-1.0, 1.0, 1.0}, - {-1.0, 1.0, -1.0}, - { 1.0, -1.0, -1.0}, - { 1.0, -1.0, 1.0}, - { 1.0, 1.0, 1.0}, - { 1.0, 1.0, -1.0}, -}; - /* ----------------- OpenGL Circle Drawing - Tables for Optimized Drawing Speed ------------------ */ /* 32 values of sin function (still same result!) */ #define CIRCLE_RESOL 32 @@ -864,28 +852,6 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo /* ******************** primitive drawing ******************* */ -static void drawcube(void) -{ - - glBegin(GL_LINE_STRIP); - glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]); - glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); - glVertex3fv(cube[7]); glVertex3fv(cube[4]); - glEnd(); - - glBegin(GL_LINE_STRIP); - glVertex3fv(cube[1]); glVertex3fv(cube[5]); - glEnd(); - - glBegin(GL_LINE_STRIP); - glVertex3fv(cube[2]); glVertex3fv(cube[6]); - glEnd(); - - glBegin(GL_LINE_STRIP); - glVertex3fv(cube[3]); glVertex3fv(cube[7]); - glEnd(); -} - /* draws a cube on given the scaling of the cube, assuming that * all required matrices have been set (used for drawing empties) */ @@ -1847,13 +1813,15 @@ static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D glDisable(GL_BLEND); } -static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel) +static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel) { BPoint *bp = lt->def; float *co = dl ? dl->verts : NULL; int u, v, w; - UI_ThemeColor(sel ? TH_VERTEX_SELECT : TH_VERTEX); + const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX; + UI_ThemeColor(color); + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); bglBegin(GL_POINTS); @@ -1865,7 +1833,13 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel) int uxt = (u == 0 || u == lt->pntsu - 1); if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) { if (bp->hide == 0) { - if ((bp->f1 & SELECT) == sel) { + /* check for active BPoint and ensure selected */ + if ((bp == actbp) && (bp->f1 & SELECT)) { + UI_ThemeColor(TH_LASTSEL_POINT); + bglVertex3fv(dl ? co : bp->vec); + UI_ThemeColor(color); + } + else if ((bp->f1 & SELECT) == sel) { bglVertex3fv(dl ? co : bp->vec); } } @@ -1954,10 +1928,12 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob) glShadeModel(GL_FLAT); if (is_edit) { + BPoint *actbp = BKE_lattice_active_point_get(lt); + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); - lattice_draw_verts(lt, dl, 0); - lattice_draw_verts(lt, dl, 1); + lattice_draw_verts(lt, dl, actbp, 0); + lattice_draw_verts(lt, dl, actbp, 1); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -6111,6 +6087,7 @@ static void draw_bb_quadric(BoundBox *bb, char type) static void draw_bounding_volume(Scene *scene, Object *ob, char type) { + BoundBox bb_local; BoundBox *bb = NULL; if (ob->type == OB_MESH) { @@ -6132,8 +6109,9 @@ static void draw_bounding_volume(Scene *scene, Object *ob, char type) bb = BKE_armature_boundbox_get(ob); } else { - drawcube(); - return; + const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f}; + bb = &bb_local; + BKE_boundbox_init_from_minmax(bb, min, max); } if (bb == NULL) return; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index c864a3a78b4..d243f355b5c 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -1015,6 +1015,14 @@ static int snap_curs_to_active(bContext *C, wmOperator *UNUSED(op)) mul_m4_v3(obedit->obmat, curs); } + else if (obedit->type == OB_LATTICE) { + BPoint *actbp = BKE_lattice_active_point_get(obedit->data); + + if (actbp) { + copy_v3_v3(curs, actbp->vec); + mul_m4_v3(obedit->obmat, curs); + } + } } else { if (obact) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f0abd0743ac..2b99405c749 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -91,6 +91,7 @@ #include "BKE_editmesh.h" #include "BKE_tracking.h" #include "BKE_mask.h" +#include "BKE_lattice.h" #include "BIK_api.h" @@ -1554,7 +1555,7 @@ static void createTransLatticeVerts(TransInfo *t) { Lattice *latt = ((Lattice *)t->obedit->data)->editlatt->latt; TransData *td = NULL; - BPoint *bp; + BPoint *bp, *actbp = BKE_lattice_active_point_get(latt); float mtx[3][3], smtx[3][3]; int a; int count = 0, countsel = 0; @@ -1589,7 +1590,10 @@ static void createTransLatticeVerts(TransInfo *t) copy_v3_v3(td->iloc, bp->vec); td->loc = bp->vec; copy_v3_v3(td->center, td->loc); - if (bp->f1 & SELECT) td->flag = TD_SELECTED; + if (bp->f1 & SELECT) { + td->flag = TD_SELECTED; + if (actbp && bp == actbp) td->flag |= TD_ACTIVE; + } else td->flag = 0; copy_m3_m3(td->smtx, smtx); copy_m3_m3(td->mtx, mtx); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index abd19bc3121..9e075c9e8e0 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -908,6 +908,9 @@ static void recalcData_view3d(TransInfo *t) * otherwise proxies don't function correctly */ DAG_id_tag_update(&ob->id, OB_RECALC_OB); + + if(t->flag & T_TEXTURE) + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } } } @@ -1641,6 +1644,15 @@ void calculateCenter(TransInfo *t) break; } } + else if (t->obedit && t->obedit->type == OB_LATTICE) { + BPoint *actbp = BKE_lattice_active_point_get(t->obedit->data); + + if (actbp) { + copy_v3_v3(t->center, actbp->vec); + calculateCenter2D(t); + break; + } + } } /* END EDIT MODE ACTIVE ELEMENT */ calculateCenterMedian(t); @@ -1702,7 +1714,19 @@ void calculateCenter(TransInfo *t) else { copy_v3_v3(vec, t->center); } - t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, vec, NULL); + + /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW + * and never used in other cases. + * + * We need special case here as well, since ED_view3d_calc_zfac will crahs when called + * for a region different from RGN_TYPE_WINDOW. + */ + if (t->ar->regiontype == RGN_TYPE_WINDOW) { + t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, vec, NULL); + } + else { + t->zfac = 0.0f; + } } } diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index f336fc4651b..d1d40689a4a 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -65,6 +65,7 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_editmesh.h" +#include "BKE_lattice.h" #include "BIF_gl.h" @@ -469,18 +470,23 @@ int calc_manipulator_stats(const bContext *C) } } else if (obedit->type == OB_LATTICE) { + Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt; BPoint *bp; - Lattice *lt = obedit->data; - bp = lt->editlatt->latt->def; - - a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; - while (a--) { - if (bp->f1 & SELECT) { - calc_tw_center(scene, bp->vec); - totsel++; + if ((v3d->around == V3D_ACTIVE) && (bp = BKE_lattice_active_point_get(lt))) { + calc_tw_center(scene, bp->vec); + totsel++; + } + else { + bp = lt->def; + a = lt->pntsu * lt->pntsv * lt->pntsw; + while (a--) { + if (bp->f1 & SELECT) { + calc_tw_center(scene, bp->vec); + totsel++; + } + bp++; } - bp++; } } diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 124905cbe8a..294da904497 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -69,7 +69,7 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str old_scene = re->scene; - char name[22]; + char name[MAX_ID_NAME - 2]; BLI_snprintf(name, sizeof(name), "FRS%d_%s", render_count, re->scene->id.name + 2); freestyle_scene = BKE_scene_add(freestyle_bmain, name); freestyle_scene->r.cfra = old_scene->r.cfra; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index b0932148076..8159520f693 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -899,12 +899,36 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa printf("multilayer read: bad channel name: %s\n", name); return 0; } - else if (len > 1) { - BLI_strncpy(tokenbuf, token, len); - printf("multilayer read: channel token too long: %s\n", tokenbuf); - return 0; + else if (len == 1) { + echan->chan_id = token[0]; + } + else if (len > 1) { + bool ok = false; + + if (len == 2) { + /* some multilayers are using two-letter channels name, + * like, MX or NZ, which is basically has structure of + * + * + * This is a bit silly, but see file from [#35658]. + * + * Here we do some magic to distinguish such cases. + */ + if (ELEM3(token[1], 'X', 'Y', 'Z') || + ELEM3(token[1], 'R', 'G', 'B') || + ELEM3(token[1], 'U', 'V', 'A')) + { + echan->chan_id = token[1]; + ok = true; + } + } + + if (ok == false) { + BLI_strncpy(tokenbuf, token, std::min(len + 1, EXR_TOT_MAXNAME)); + printf("multilayer read: channel token too long: %s\n", tokenbuf); + return 0; + } } - echan->chan_id = token[0]; end -= len + 1; /* +1 to skip '.' separator */ /* second token is pass name */ diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index eded0b4b76e..76aacb5bebc 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -159,7 +159,9 @@ typedef enum eMotionPaths_ViewFlag { /* show keyframe/frame numbers */ MOTIONPATH_VIEW_KFNOS = (1 << 2), /* find keyframes in whole action (instead of just in matching group name) */ - MOTIONPATH_VIEW_KFACT = (1 << 3) + MOTIONPATH_VIEW_KFACT = (1 << 3), + /* draw lines on path */ + MOTIONPATH_VIEW_LINES = (1 << 4) } eMotionPath_ViewFlag; /* bAnimVizSettings->path_bakeflag */ @@ -561,6 +563,7 @@ typedef enum eDopeSheet_FilterFlag { ADS_FILTER_NOTEX = (1 << 20), ADS_FILTER_NOSPK = (1 << 21), ADS_FILTER_NOLINESTYLE = (1 << 22), + ADS_FILTER_NOMODIFIERS = (1 << 23), /* NLA-specific filters */ ADS_FILTER_NLA_NOACT = (1 << 25), /* if the AnimData block has no NLA data, don't include to just show Action-line */ @@ -571,7 +574,7 @@ typedef enum eDopeSheet_FilterFlag { ADS_FILTER_ONLY_ERRORS = (1 << 28), /* show only F-Curves which are disabled/have errors - for debugging drivers */ /* combination filters (some only used at runtime) */ - ADS_FILTER_NOOBDATA = (ADS_FILTER_NOCAM | ADS_FILTER_NOMAT | ADS_FILTER_NOLAM | ADS_FILTER_NOCUR | ADS_FILTER_NOPART | ADS_FILTER_NOARM | ADS_FILTER_NOSPK) + ADS_FILTER_NOOBDATA = (ADS_FILTER_NOCAM | ADS_FILTER_NOMAT | ADS_FILTER_NOLAM | ADS_FILTER_NOCUR | ADS_FILTER_NOPART | ADS_FILTER_NOARM | ADS_FILTER_NOSPK | ADS_FILTER_NOMODIFIERS) } eDopeSheet_FilterFlag; /* DopeSheet general flags */ diff --git a/source/blender/makesdna/DNA_lattice_types.h b/source/blender/makesdna/DNA_lattice_types.h index 1b4bd53151b..500b4ab88c3 100644 --- a/source/blender/makesdna/DNA_lattice_types.h +++ b/source/blender/makesdna/DNA_lattice_types.h @@ -56,8 +56,8 @@ typedef struct Lattice { short pntsu, pntsv, pntsw, flag; short opntsu, opntsv, opntsw, pad2; char typeu, typev, typew, pad3; - int pad; - + int actbp; /* active element index, unset with LT_ACTBP_NONE */ + float fu, fv, fw, du, dv, dw; struct BPoint *def; @@ -85,5 +85,7 @@ typedef struct Lattice { #define LT_INDEX(lt, u, v, w) ((w) * ((lt)->pntsu * (lt)->pntsv) + ((v) * (lt)->pntsu) + (u)) +#define LT_ACTBP_NONE -1 + #endif diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index f915b7e1cc0..44ce081f68f 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -366,6 +366,12 @@ static void rna_def_dopesheet(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_SHAPEKEY_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + prop = RNA_def_property(srna, "show_modifiers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOMODIFIERS); + RNA_def_property_ui_text(prop, "Display Modifier Data", "Include visualization of animation data related to datablocks linked to modifiers"); + RNA_def_property_ui_icon(prop, ICON_MODIFIER, 0); + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + prop = RNA_def_property(srna, "show_meshes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOMESH); RNA_def_property_ui_text(prop, "Display Meshes", "Include visualization of mesh related animation data"); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 5d8cc915dda..4433dc45601 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -201,6 +201,7 @@ EnumPropertyItem prop_wave_items[] = { #include "ED_node.h" #include "ED_render.h" +#include "NOD_common.h" #include "NOD_socket.h" #include "RE_engine.h" @@ -2317,6 +2318,25 @@ static void rna_NodeInternal_draw_buttons_ext(ID *id, bNode *node, struct bConte } } +static StructRNA *rna_NodeCustomGroup_register(Main *bmain, ReportList *reports, + void *data, const char *identifier, + StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) +{ + bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_NodeCustomGroup, data, identifier, validate, call, free); + if (!nt) + return NULL; + + /* this updates the group node instance from the tree's interface */ + nt->verifyfunc = node_group_verify; + + nodeRegisterType(nt); + + /* update while blender is running */ + WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); + + return nt->ext.srna; +} + static void rna_CompositorNode_tag_need_exec(bNode *node) { node->need_exec = TRUE; @@ -2861,6 +2881,19 @@ static void def_group(StructRNA *srna) RNA_def_property_ui_text(prop, "Interface", "Interface socket data"); } +static void def_custom_group(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "NodeCustomGroup", "Node"); + RNA_def_struct_ui_text(srna, "Custom Group", "Base node type for custom registered node group types"); + RNA_def_struct_sdna(srna, "bNode"); + + RNA_def_struct_register_funcs(srna, "rna_NodeCustomGroup_register", "rna_Node_unregister", NULL); + + def_group(srna); +} + static void def_frame(StructRNA *srna) { PropertyRNA *prop; @@ -7306,6 +7339,7 @@ void RNA_def_nodetree(BlenderRNA *brna) define_specific_node(brna, "ShaderNodeGroup", "ShaderNode", "Group", "", def_group); define_specific_node(brna, "CompositorNodeGroup", "CompositorNode", "Group", "", def_group); define_specific_node(brna, "TextureNodeGroup", "TextureNode", "Group", "", def_group); + def_custom_group(brna); /* special socket types */ rna_def_cmp_output_file_slot_file(brna); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 8cf352311f7..90c0282545c 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -452,6 +452,10 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_SHADING_NODES); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + prop = RNA_def_property(srna, "bl_use_exclude_layers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_EXCLUDE_LAYERS); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_define_verify_sdna(1); } diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index 7db522d7f5e..f9171887bfb 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -105,6 +105,15 @@ static int rna_Screen_fullscreen_get(PointerRNA *ptr) return (sc->full != 0); } +/* UI compatible list: should not be needed, but for now we need to keep EMPTY + * at least in the static version of this enum for python scripts. */ +static EnumPropertyItem *rna_Area_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), int *free) +{ + /* +1 to skip SPACE_EMPTY */ + *free = 0; + return space_type_items + 1; +} static void rna_Area_type_set(PointerRNA *ptr, int value) { @@ -204,7 +213,7 @@ static void rna_def_area(BlenderRNA *brna) prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "spacetype"); RNA_def_property_enum_items(prop, space_type_items); - RNA_def_property_enum_funcs(prop, NULL, "rna_Area_type_set", NULL); + RNA_def_property_enum_funcs(prop, NULL, "rna_Area_type_set", "rna_Area_type_itemf"); RNA_def_property_ui_text(prop, "Editor Type", "Current editor type for this area"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 7bc42700d2b..93b2bce4860 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -60,6 +60,8 @@ EnumPropertyItem space_type_items[] = { + /* empty must be here for python, is skipped for UI */ + {SPACE_EMPTY, "EMPTY", ICON_NONE, "Empty", ""}, {SPACE_VIEW3D, "VIEW_3D", ICON_VIEW3D, "3D View", ""}, {0, "", ICON_NONE, NULL, NULL}, {SPACE_TIME, "TIMELINE", ICON_TIME, "Timeline", ""}, diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 14aa6631d1f..347c57f9044 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -152,6 +152,13 @@ static void rna_userdef_script_autoexec_update(Main *UNUSED(bmain), Scene *UNUSE else G.f |= G_SCRIPT_AUTOEXEC; } +static void rna_userdef_load_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + UserDef *userdef = (UserDef *)ptr->data; + if (userdef->flag & USER_FILENOUI) G.fileflags |= G_FILE_NO_UI; + else G.fileflags &= ~G_FILE_NO_UI; +} + static void rna_userdef_mipmap_update(Main *bmain, Scene *scene, PointerRNA *ptr) { GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); @@ -3907,6 +3914,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) prop = RNA_def_property(srna, "use_load_ui", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_FILENOUI); RNA_def_property_ui_text(prop, "Load UI", "Load user interface setup when loading .blend files"); + RNA_def_property_update(prop, 0, "rna_userdef_load_ui_update"); prop = RNA_def_property(srna, "font_directory", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "fontdir"); diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index d8e2647426c..ffd202736a9 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -42,6 +42,7 @@ #include "BKE_cdderivedmesh.h" +#include "BKE_library.h" #include "BKE_modifier.h" #include "BKE_texture.h" #include "BKE_deform.h" @@ -79,6 +80,18 @@ static void copyData(ModifierData *md, ModifierData *target) tdmd->texmapping = dmd->texmapping; tdmd->map_object = dmd->map_object; BLI_strncpy(tdmd->uvlayer_name, dmd->uvlayer_name, sizeof(tdmd->uvlayer_name)); + + if (tdmd->texture) { + id_us_plus(&tdmd->texture->id); + } +} + +static void freeData(ModifierData *md) +{ + DisplaceModifierData *dmd = (DisplaceModifierData *) md; + if (dmd->texture) { + id_us_min(&dmd->texture->id); + } } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) @@ -292,7 +305,7 @@ ModifierTypeInfo modifierType_Displace = { /* applyModifierEM */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, - /* freeData */ NULL, + /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, /* dependsOnTime */ dependsOnTime, diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index bf5f9fb6ae9..8c6c483472e 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -43,9 +43,10 @@ #include "BLI_string.h" -#include "BKE_DerivedMesh.h" -#include "BKE_object.h" #include "BKE_deform.h" +#include "BKE_DerivedMesh.h" +#include "BKE_library.h" +#include "BKE_object.h" #include "BKE_scene.h" #include "depsgraph_private.h" @@ -77,6 +78,14 @@ static void initData(ModifierData *md) wmd->defgrp_name[0] = 0; } +static void freeData(ModifierData *md) +{ + WaveModifierData *wmd = (WaveModifierData *) md; + if (wmd->texture) { + id_us_min(&wmd->texture->id); + } +} + static void copyData(ModifierData *md, ModifierData *target) { WaveModifierData *wmd = (WaveModifierData *) md; @@ -98,6 +107,10 @@ static void copyData(ModifierData *md, ModifierData *target) twmd->map_object = wmd->map_object; twmd->texmapping = wmd->texmapping; BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name)); + + if (twmd->texture) { + id_us_plus(&twmd->texture->id); + } } static bool dependsOnTime(ModifierData *UNUSED(md)) @@ -378,7 +391,7 @@ ModifierTypeInfo modifierType_Wave = { /* applyModifierEM */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, - /* freeData */ NULL, + /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, /* dependsOnTime */ dependsOnTime, diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index eee0856d69e..959e4d4f59d 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -43,6 +43,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_colortools.h" /* CurveMapping. */ #include "BKE_deform.h" +#include "BKE_library.h" #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_texture.h" /* Texture masking. */ @@ -77,6 +78,10 @@ static void freeData(ModifierData *md) { WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md; curvemapping_free(wmd->cmap_curve); + + if (wmd->mask_texture) { + id_us_min(&wmd->mask_texture->id); + } } static void copyData(ModifierData *md, ModifierData *target) @@ -102,6 +107,10 @@ static void copyData(ModifierData *md, ModifierData *target) twmd->mask_tex_mapping = wmd->mask_tex_mapping; twmd->mask_tex_map_obj = wmd->mask_tex_map_obj; BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name, sizeof(twmd->mask_tex_uvlayer_name)); + + if (twmd->mask_texture) { + id_us_plus(&twmd->mask_texture->id); + } } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index a5843d04c24..1ec287b3b3a 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -39,6 +39,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_deform.h" +#include "BKE_library.h" #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_texture.h" /* Texture masking. */ @@ -123,6 +124,14 @@ static void initData(ModifierData *md) wmd->mask_tex_mapping = MOD_DISP_MAP_LOCAL; } +static void freeData(ModifierData *md) +{ + WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md; + if (wmd->mask_texture) { + id_us_min(&wmd->mask_texture->id); + } +} + static void copyData(ModifierData *md, ModifierData *target) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md; @@ -142,6 +151,10 @@ static void copyData(ModifierData *md, ModifierData *target) twmd->mask_tex_mapping = wmd->mask_tex_mapping; twmd->mask_tex_map_obj = wmd->mask_tex_map_obj; BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name, sizeof(twmd->mask_tex_uvlayer_name)); + + if (twmd->mask_texture) { + id_us_plus(&twmd->mask_texture->id); + } } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) @@ -418,7 +431,7 @@ ModifierTypeInfo modifierType_WeightVGMix = { /* applyModifierEM */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, - /* freeData */ NULL, + /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, /* dependsOnTime */ dependsOnTime, diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 7a9bb6b34d1..f0e9a26f10a 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -47,6 +47,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_deform.h" +#include "BKE_library.h" #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_shrinkwrap.h" /* For SpaceTransform stuff. */ @@ -242,6 +243,14 @@ static void initData(ModifierData *md) wmd->max_dist = 1.0f; /* vert arbitrary distance, but don't use 0 */ } +static void freeData(ModifierData *md) +{ + WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md; + if (wmd->mask_texture) { + id_us_min(&wmd->mask_texture->id); + } +} + static void copyData(ModifierData *md, ModifierData *target) { WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md; @@ -263,6 +272,10 @@ static void copyData(ModifierData *md, ModifierData *target) BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name, sizeof(twmd->mask_tex_uvlayer_name)); twmd->min_dist = wmd->min_dist; twmd->max_dist = wmd->max_dist; + + if (twmd->mask_texture) { + id_us_plus(&twmd->mask_texture->id); + } } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) @@ -563,7 +576,7 @@ ModifierTypeInfo modifierType_WeightVGProximity = { /* applyModifierEM */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, - /* freeData */ NULL, + /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, /* dependsOnTime */ dependsOnTime, diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 94c91831169..36b27094cc4 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -105,6 +105,12 @@ int nodeGroupPoll(bNodeTree *nodetree, bNodeTree *grouptree) bNode *node; int valid = 1; + /* unspecified node group, generally allowed + * (if anything, should be avoided on operator level) + */ + if (grouptree == NULL) + return 1; + if (nodetree == grouptree) return 0; diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 0f5be095e0f..e61b4847e2c 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -63,6 +63,7 @@ int BPY_is_pyconstraint(struct Text *text); void BPY_python_start(int argc, const char **argv); void BPY_python_end(void); +void BPY_python_reset(struct bContext *C); /* 2.5 UI Scripts */ int BPY_filepath_exec(struct bContext *C, const char *filepath, struct ReportList *reports); diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 17dafc4ac52..2edb0aee783 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -219,6 +219,12 @@ static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void return 0; } +static PyObject *bpy_app_global_flag_get(PyObject *UNUSED(self), void *closure) +{ + const int flag = GET_INT_FROM_POINTER(closure); + return PyBool_FromLong(G.f & flag); +} + PyDoc_STRVAR(bpy_app_tempdir_doc, "String, the temp directory used by blender (read-only)" ); @@ -243,6 +249,11 @@ static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(cl return bpy_pydriver_Dict; } +static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure)) +{ + return PyC_UnicodeFromByte(G.autoexec_fail); +} + static PyGetSetDef bpy_app_getsets[] = { {(char *)"debug", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG}, @@ -256,6 +267,11 @@ static PyGetSetDef bpy_app_getsets[] = { {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL}, {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL}, {(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)bpy_app_driver_dict_doc, NULL}, + + /* security */ + {(char *)"autoexec_fail", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL}, + {(char *)"autoexec_fail_quiet", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL_QUIET}, + {(char *)"autoexec_fail_message", bpy_app_autoexec_fail_message_get, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL, NULL} }; diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 72bfda89b64..e7c0b7b8811 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -37,6 +37,7 @@ #include "BLI_listbase.h" #include "BLI_math_base.h" +#include "BLI_string.h" #include "BKE_fcurve.h" #include "BKE_global.h" @@ -189,7 +190,12 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime) return 0.0f; if (!(G.f & G_SCRIPT_AUTOEXEC)) { - printf("skipping driver '%s', automatic scripts are disabled\n", driver->expression); + if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) { + G.f |= G_SCRIPT_AUTOEXEC_FAIL; + BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", driver->expression); + + printf("skipping driver '%s', automatic scripts are disabled\n", driver->expression); + } return 0.0f; } diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index f71ea02a510..79f856344d3 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -396,6 +396,17 @@ void BPY_python_end(void) } +void BPY_python_reset(bContext *C) +{ + /* unrelated security stuff */ + G.f &= ~(G_SCRIPT_AUTOEXEC_FAIL | G_SCRIPT_AUTOEXEC_FAIL_QUIET); + G.autoexec_fail[0] = '\0'; + + BPY_driver_reset(); + BPY_app_handlers_reset(false); + BPY_modules_load_user(C); +} + static void python_script_error_jump_text(struct Text *text) { int lineno; @@ -718,7 +729,12 @@ void BPY_modules_load_user(bContext *C) for (text = bmain->text.first; text; text = text->id.next) { if (text->flags & TXT_ISSCRIPT && BLI_testextensie(text->id.name + 2, ".py")) { if (!(G.f & G_SCRIPT_AUTOEXEC)) { - printf("scripts disabled for \"%s\", skipping '%s'\n", bmain->name, text->id.name + 2); + if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) { + G.f |= G_SCRIPT_AUTOEXEC_FAIL; + BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Register Text '%s'", text->id.name + 2); + + printf("scripts disabled for \"%s\", skipping '%s'\n", bmain->name, text->id.name + 2); + } } else { PyObject *module = bpy_text_import(text); @@ -761,7 +777,7 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * /* pass */ } else if (item == Py_None) { - /* pass */ + done = true; } else if (BPy_StructRNA_Check(item)) { ptr = &(((BPy_StructRNA *)item)->ptr); diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 7c1bc4d12d6..b6c3668512b 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -56,6 +56,7 @@ struct Scene; #define RE_USE_PREVIEW 4 #define RE_USE_POSTPROCESS 8 #define RE_USE_SHADING_NODES 16 +#define RE_USE_EXCLUDE_LAYERS 32 /* RenderEngine.flag */ #define RE_ENGINE_ANIMATION 1 diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index b76e67dd634..551f3686370 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -410,8 +410,30 @@ int RE_engine_render(Render *re, int do_all) /* update animation here so any render layer animation is applied before * creating the render result */ - if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) - BKE_scene_update_for_newframe(re->main, re->scene, re->lay); + if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) { + unsigned int lay = re->lay; + + /* don't update layers excluded on all render layers */ + if (type->flag & RE_USE_EXCLUDE_LAYERS) { + SceneRenderLayer *srl; + unsigned int non_excluded_lay = 0; + + if (re->r.scemode & R_SINGLE_LAYER) { + srl = BLI_findlink(&re->r.layers, re->r.actlay); + if (srl) + non_excluded_lay |= ~srl->lay_exclude; + } + else { + for (srl = re->r.layers.first; srl; srl = srl->next) + if (!(srl->layflag & SCE_LAY_DISABLE)) + non_excluded_lay |= ~srl->lay_exclude; + } + + lay &= non_excluded_lay; + } + + BKE_scene_update_for_newframe(re->main, re->scene, lay); + } /* create render result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); diff --git a/source/blender/windowmanager/SConscript b/source/blender/windowmanager/SConscript index 3a813d7d598..0a2f48f0488 100644 --- a/source/blender/windowmanager/SConscript +++ b/source/blender/windowmanager/SConscript @@ -78,4 +78,7 @@ if env['WITH_BF_INTERNATIONAL']: if env['WITH_BF_COMPOSITOR']: defs.append("WITH_COMPOSITOR") +if env['WITH_BF_PYTHON_SECURITY']: + defs.append("WITH_PYTHON_SECURITY") + env.BlenderLib ( 'bf_windowmanager', sources, Split(incs), defines=defs, libtype=['core'], priority=[5] ) diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 7a528e41995..406dbd8ca96 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -327,7 +327,7 @@ static int wm_read_exotic(Scene *UNUSED(scene), const char *name) /* make sure we're not trying to read a directory.... */ len = strlen(name); - if (ELEM(name[len - 1], '/', '\\')) { + if (len > 0 && ELEM(name[len - 1], '/', '\\')) { retval = BKE_READ_EXOTIC_FAIL_PATH; } else { @@ -437,9 +437,7 @@ void WM_file_read(bContext *C, const char *filepath, ReportList *reports) #ifdef WITH_PYTHON /* run any texts that were loaded in and flagged as modules */ - BPY_driver_reset(); - BPY_app_handlers_reset(FALSE); - BPY_modules_load_user(C); + BPY_python_reset(C); #endif /* important to do before NULL'ing the context */ @@ -543,7 +541,7 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL); if (wmbase.first == NULL) wm_clear_default_size(C); -#ifdef WITH_PYTHON_SECURITY /* not default */ +#ifdef WITH_PYTHON_SECURITY /* use alternative setting for security nuts * otherwise we'd need to patch the binary blob - startup.blend.c */ U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; @@ -590,9 +588,7 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory /* sync addons, these may have changed from the defaults */ BPY_string_exec(C, "__import__('addon_utils').reset_all()"); - BPY_driver_reset(); - BPY_app_handlers_reset(FALSE); - BPY_modules_load_user(C); + BPY_python_reset(C); } #endif diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 31f2b412a7f..8115779a7c6 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -174,10 +174,7 @@ void WM_init(bContext *C, int argc, const char **argv) BPY_context_set(C); /* necessary evil */ BPY_python_start(argc, argv); - BPY_driver_reset(); - BPY_app_handlers_reset(FALSE); /* causes addon callbacks to be freed [#28068], - * but this is actually what we want. */ - BPY_modules_load_user(C); + BPY_python_reset(C); #else (void)argc; /* unused */ (void)argv; /* unused */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 423ddfcc568..3d4bd2a1bc6 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1916,19 +1916,26 @@ static void WM_OT_read_factory_settings(wmOperatorType *ot) /* *************** open file **************** */ -static void open_set_load_ui(wmOperator *op) +static void open_set_load_ui(wmOperator *op, bool use_prefs) { - if (!RNA_struct_property_is_set(op->ptr, "load_ui")) - RNA_boolean_set(op->ptr, "load_ui", !(U.flag & USER_FILENOUI)); + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "load_ui"); + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_boolean_set(op->ptr, prop, use_prefs ? + (U.flag & USER_FILENOUI) == 0 : + (G.fileflags & G_FILE_NO_UI) == 0); + } } -static void open_set_use_scripts(wmOperator *op) +static void open_set_use_scripts(wmOperator *op, bool use_prefs) { - if (!RNA_struct_property_is_set(op->ptr, "use_scripts")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_scripts"); + if (!RNA_property_is_set(op->ptr, prop)) { /* use G_SCRIPT_AUTOEXEC rather than the userpref because this means if * the flag has been disabled from the command line, then opening * from the menu wont enable this setting. */ - RNA_boolean_set(op->ptr, "use_scripts", (G.f & G_SCRIPT_AUTOEXEC)); + RNA_property_boolean_set(op->ptr, prop, use_prefs ? + (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0 : + (G.f & G_SCRIPT_AUTOEXEC) != 0); } } @@ -1951,8 +1958,8 @@ static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U } RNA_string_set(op->ptr, "filepath", openname); - open_set_load_ui(op); - open_set_use_scripts(op); + open_set_load_ui(op, true); + open_set_use_scripts(op, true); WM_event_add_fileselect(C, op); @@ -1964,8 +1971,10 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op) char path[FILE_MAX]; RNA_string_get(op->ptr, "filepath", path); - open_set_load_ui(op); - open_set_use_scripts(op); + + /* re-use last loaded setting so we can reload a file without changing */ + open_set_load_ui(op, false); + open_set_use_scripts(op, false); if (RNA_boolean_get(op->ptr, "load_ui")) G.fileflags &= ~G_FILE_NO_UI; diff --git a/source/creator/creator.c b/source/creator/creator.c index fdd01691232..302467c6b3d 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1250,9 +1250,7 @@ static int load_file(int UNUSED(argc), const char **argv, void *data) /* WM_file_read() runs normally but since we're in background mode do here */ #ifdef WITH_PYTHON /* run any texts that were loaded in and flagged as modules */ - BPY_driver_reset(); - BPY_app_handlers_reset(FALSE); - BPY_modules_load_user(C); + BPY_python_reset(C); #endif /* happens for the UI on file reading too (huh? (ton))*/ @@ -1641,11 +1639,21 @@ int main(int argc, const char **argv) WM_exit(C); } else { - if ((G.fileflags & G_FILE_AUTOPLAY) && (G.f & G_SCRIPT_AUTOEXEC)) { - if (WM_init_game(C)) - return 0; + if (G.fileflags & G_FILE_AUTOPLAY) { + if (G.f & G_SCRIPT_AUTOEXEC) { + if (WM_init_game(C)) { + return 0; + } + } + else { + if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) { + G.f |= G_SCRIPT_AUTOEXEC_FAIL; + BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Game AutoStart"); + } + } } - else if (!G.file_loaded) { + + if (!G.file_loaded) { WM_init_splash(C); } }