diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-03-13 20:05:40 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-03-13 20:05:40 +0300 |
commit | 5a0efc9c8b5ad991109c97d52d476d8c071a78ac (patch) | |
tree | e5c8290bc613ef8eea923d0983cb51512c4b1ce7 | |
parent | 1ca7821b15f3883121552495436142814c73fbb7 (diff) | |
parent | 91dbc28363e5450f241eb9696aaca29075c01d20 (diff) |
Merge branch 'master' into temp-abc-features
358 files changed, 4670 insertions, 2646 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f8800fe303..f7d85969ba2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -502,7 +502,7 @@ else() set(WITH_EXPERIMENTAL_FEATURES OFF) endif() -# Unit testsing +# Unit testing option(WITH_GTESTS "Enable GTest unit testing" OFF) option(WITH_OPENGL_RENDER_TESTS "Enable OpenGL render related unit testing (Experimental)" OFF) option(WITH_OPENGL_DRAW_TESTS "Enable OpenGL UI drawing related unit testing (Experimental)" OFF) diff --git a/GNUmakefile b/GNUmakefile index 575f3e904df..8dc2a2e2a9a 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -32,7 +32,7 @@ Other Convenience Targets * config: Run cmake configuration tool to set build options. * deps: Build library dependencies (intended only for platform maintainers). - The existance of locally build dependencies overrides the pre-built dependencies from subversion. + The existence of locally build dependencies overrides the pre-built dependencies from subversion. These must be manually removed from '../lib/' to go back to using the pre-compiled libraries. Project Files diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 77d1db97997..0a7119802c8 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -858,7 +858,7 @@ endif() # If atomic operations are possible without libatomic then linker flags are left as-is. function(CONFIGURE_ATOMIC_LIB_IF_NEEDED) # Source which is used to enforce situation when software emulation of atomics is required. - # Assume that using 64bit integer gives a definitive asnwer (as in, if 64bit atomic operations + # Assume that using 64bit integer gives a definitive answer (as in, if 64bit atomic operations # are possible using assembly/intrinsics 8, 16, and 32 bit operations will also be possible. set(_source "#include <atomic> diff --git a/build_files/windows/find_dependencies.cmd b/build_files/windows/find_dependencies.cmd index fec2bd2e752..fa893c949cf 100644 --- a/build_files/windows/find_dependencies.cmd +++ b/build_files/windows/find_dependencies.cmd @@ -5,7 +5,7 @@ for %%X in (ctest.exe) do (set CTEST=%%~$PATH:X) for %%X in (git.exe) do (set GIT=%%~$PATH:X) REM For python, default on 39 but if that does not exist also check REM the 310,311 and 312 folders to see if those are there, it checks -REM this far ahead to ensure good lib folder compatiblity in the future. +REM this far ahead to ensure good lib folder compatibility in the future. set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe if EXIST %PYTHON% ( goto detect_python_done diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 10a72c598e2..2b74a1b7ccf 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -11,6 +11,7 @@ from bl_ui.utils import PresetPanel from bpy.types import Panel from bl_ui.properties_grease_pencil_common import GreasePencilSimplifyPanel +from bl_ui.properties_render import draw_hair_settings from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel class CyclesPresetPanel(PresetPanel, Panel): @@ -355,6 +356,13 @@ class CYCLES_RENDER_PT_hair(CyclesButtonsPanel, Panel): if ccscene.shape == 'RIBBONS': col.prop(ccscene, "subdivisions", text="Curve Subdivisions") +class CYCLES_RENDER_PT_hair_viewport_display(CyclesButtonsPanel, Panel): + bl_label = "Viewport Display" + bl_parent_id = "CYCLES_RENDER_PT_hair" + bl_options = {'DEFAULT_CLOSED'} + + def draw(self, context): + draw_hair_settings(self, context) class CYCLES_RENDER_PT_volumes(CyclesButtonsPanel, Panel): bl_label = "Volumes" @@ -2153,6 +2161,7 @@ classes = ( CYCLES_RENDER_PT_volumes, CYCLES_RENDER_PT_subdivision, CYCLES_RENDER_PT_hair, + CYCLES_RENDER_PT_hair_viewport_display, CYCLES_RENDER_PT_simplify, CYCLES_RENDER_PT_simplify_viewport, CYCLES_RENDER_PT_simplify_render, diff --git a/intern/cycles/blender/object.cpp b/intern/cycles/blender/object.cpp index 559b0d42a29..054142a9ca4 100644 --- a/intern/cycles/blender/object.cpp +++ b/intern/cycles/blender/object.cpp @@ -319,7 +319,9 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, (object->get_geometry() && object->get_geometry()->is_modified())) { object->name = b_ob.name().c_str(); object->set_pass_id(b_ob.pass_index()); - object->set_color(get_float3(b_ob.color())); + const BL::Array<float, 4> object_color = b_ob.color(); + object->set_color(get_float3(object_color)); + object->set_alpha(object_color[3]); object->set_tfm(tfm); /* dupli texture coordinates and random_id */ diff --git a/intern/cycles/device/optix/device_impl.cpp b/intern/cycles/device/optix/device_impl.cpp index cbe823c26ad..8830d8c44ac 100644 --- a/intern/cycles/device/optix/device_impl.cpp +++ b/intern/cycles/device/optix/device_impl.cpp @@ -33,6 +33,191 @@ CCL_NAMESPACE_BEGIN +// A minimal copy of functionality `optix_denoiser_tiling.h` which allows to fix integer overflow +// issues without bumping SDK or driver requirement. +// +// The original code is Copyright NVIDIA Corporation, BSD-3-Clause. +namespace { + +static OptixResult optixUtilDenoiserSplitImage(const OptixImage2D &input, + const OptixImage2D &output, + unsigned int overlapWindowSizeInPixels, + unsigned int tileWidth, + unsigned int tileHeight, + std::vector<OptixUtilDenoiserImageTile> &tiles) +{ + if (tileWidth == 0 || tileHeight == 0) + return OPTIX_ERROR_INVALID_VALUE; + + unsigned int inPixelStride = optixUtilGetPixelStride(input); + unsigned int outPixelStride = optixUtilGetPixelStride(output); + + int inp_w = std::min(tileWidth + 2 * overlapWindowSizeInPixels, input.width); + int inp_h = std::min(tileHeight + 2 * overlapWindowSizeInPixels, input.height); + int inp_y = 0, copied_y = 0; + + do { + int inputOffsetY = inp_y == 0 ? 0 : + std::max((int)overlapWindowSizeInPixels, + inp_h - ((int)input.height - inp_y)); + int copy_y = inp_y == 0 ? std::min(input.height, tileHeight + overlapWindowSizeInPixels) : + std::min(tileHeight, input.height - copied_y); + + int inp_x = 0, copied_x = 0; + do { + int inputOffsetX = inp_x == 0 ? 0 : + std::max((int)overlapWindowSizeInPixels, + inp_w - ((int)input.width - inp_x)); + int copy_x = inp_x == 0 ? std::min(input.width, tileWidth + overlapWindowSizeInPixels) : + std::min(tileWidth, input.width - copied_x); + + OptixUtilDenoiserImageTile tile; + tile.input.data = input.data + (size_t)(inp_y - inputOffsetY) * input.rowStrideInBytes + + +(size_t)(inp_x - inputOffsetX) * inPixelStride; + tile.input.width = inp_w; + tile.input.height = inp_h; + tile.input.rowStrideInBytes = input.rowStrideInBytes; + tile.input.pixelStrideInBytes = input.pixelStrideInBytes; + tile.input.format = input.format; + + tile.output.data = output.data + (size_t)inp_y * output.rowStrideInBytes + + (size_t)inp_x * outPixelStride; + tile.output.width = copy_x; + tile.output.height = copy_y; + tile.output.rowStrideInBytes = output.rowStrideInBytes; + tile.output.pixelStrideInBytes = output.pixelStrideInBytes; + tile.output.format = output.format; + + tile.inputOffsetX = inputOffsetX; + tile.inputOffsetY = inputOffsetY; + tiles.push_back(tile); + + inp_x += inp_x == 0 ? tileWidth + overlapWindowSizeInPixels : tileWidth; + copied_x += copy_x; + } while (inp_x < static_cast<int>(input.width)); + + inp_y += inp_y == 0 ? tileHeight + overlapWindowSizeInPixels : tileHeight; + copied_y += copy_y; + } while (inp_y < static_cast<int>(input.height)); + + return OPTIX_SUCCESS; +} + +static OptixResult optixUtilDenoiserInvokeTiled(OptixDenoiser denoiser, + CUstream stream, + const OptixDenoiserParams *params, + CUdeviceptr denoiserState, + size_t denoiserStateSizeInBytes, + const OptixDenoiserGuideLayer *guideLayer, + const OptixDenoiserLayer *layers, + unsigned int numLayers, + CUdeviceptr scratch, + size_t scratchSizeInBytes, + unsigned int overlapWindowSizeInPixels, + unsigned int tileWidth, + unsigned int tileHeight) +{ + if (!guideLayer || !layers) + return OPTIX_ERROR_INVALID_VALUE; + + std::vector<std::vector<OptixUtilDenoiserImageTile>> tiles(numLayers); + std::vector<std::vector<OptixUtilDenoiserImageTile>> prevTiles(numLayers); + for (unsigned int l = 0; l < numLayers; l++) { + if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[l].input, + layers[l].output, + overlapWindowSizeInPixels, + tileWidth, + tileHeight, + tiles[l])) + return res; + + if (layers[l].previousOutput.data) { + OptixImage2D dummyOutput = layers[l].previousOutput; + if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[l].previousOutput, + dummyOutput, + overlapWindowSizeInPixels, + tileWidth, + tileHeight, + prevTiles[l])) + return res; + } + } + + std::vector<OptixUtilDenoiserImageTile> albedoTiles; + if (guideLayer->albedo.data) { + OptixImage2D dummyOutput = guideLayer->albedo; + if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->albedo, + dummyOutput, + overlapWindowSizeInPixels, + tileWidth, + tileHeight, + albedoTiles)) + return res; + } + + std::vector<OptixUtilDenoiserImageTile> normalTiles; + if (guideLayer->normal.data) { + OptixImage2D dummyOutput = guideLayer->normal; + if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->normal, + dummyOutput, + overlapWindowSizeInPixels, + tileWidth, + tileHeight, + normalTiles)) + return res; + } + std::vector<OptixUtilDenoiserImageTile> flowTiles; + if (guideLayer->flow.data) { + OptixImage2D dummyOutput = guideLayer->flow; + if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->flow, + dummyOutput, + overlapWindowSizeInPixels, + tileWidth, + tileHeight, + flowTiles)) + return res; + } + + for (size_t t = 0; t < tiles[0].size(); t++) { + std::vector<OptixDenoiserLayer> tlayers; + for (unsigned int l = 0; l < numLayers; l++) { + OptixDenoiserLayer layer = {}; + layer.input = (tiles[l])[t].input; + layer.output = (tiles[l])[t].output; + if (layers[l].previousOutput.data) + layer.previousOutput = (prevTiles[l])[t].input; + tlayers.push_back(layer); + } + + OptixDenoiserGuideLayer gl = {}; + if (guideLayer->albedo.data) + gl.albedo = albedoTiles[t].input; + + if (guideLayer->normal.data) + gl.normal = normalTiles[t].input; + + if (guideLayer->flow.data) + gl.flow = flowTiles[t].input; + + if (const OptixResult res = optixDenoiserInvoke(denoiser, + stream, + params, + denoiserState, + denoiserStateSizeInBytes, + &gl, + &tlayers[0], + numLayers, + (tiles[0])[t].inputOffsetX, + (tiles[0])[t].inputOffsetY, + scratch, + scratchSizeInBytes)) + return res; + } + return OPTIX_SUCCESS; +} + +} // namespace + OptiXDevice::Denoiser::Denoiser(OptiXDevice *device) : device(device), queue(device), state(device, "__denoiser_state", true) { @@ -1075,20 +1260,20 @@ bool OptiXDevice::denoise_run(DenoiseContext &context, const DenoisePass &pass) /* Finally run denoising. */ OptixDenoiserParams params = {}; /* All parameters are disabled/zero. */ - optix_assert(optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser, - denoiser_.queue.stream(), - ¶ms, - denoiser_.state.device_pointer, - denoiser_.sizes.stateSizeInBytes, - &guide_layers, - &image_layers, - 1, - denoiser_.state.device_pointer + - denoiser_.sizes.stateSizeInBytes, - denoiser_.sizes.withOverlapScratchSizeInBytes, - denoiser_.sizes.overlapWindowSizeInPixels, - denoiser_.configured_size.x, - denoiser_.configured_size.y)); + optix_assert(ccl::optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser, + denoiser_.queue.stream(), + ¶ms, + denoiser_.state.device_pointer, + denoiser_.sizes.stateSizeInBytes, + &guide_layers, + &image_layers, + 1, + denoiser_.state.device_pointer + + denoiser_.sizes.stateSizeInBytes, + denoiser_.sizes.withOverlapScratchSizeInBytes, + denoiser_.sizes.overlapWindowSizeInPixels, + denoiser_.configured_size.x, + denoiser_.configured_size.y)); return true; } diff --git a/intern/cycles/device/queue.h b/intern/cycles/device/queue.h index 183ac1728a4..2bd6e7ae460 100644 --- a/intern/cycles/device/queue.h +++ b/intern/cycles/device/queue.h @@ -100,7 +100,7 @@ class DeviceQueue { * based on number of cores and/or available memory. */ virtual int num_concurrent_states(const size_t state_size) const = 0; - /* Number of states which keeps the device occupied with work without loosing performance. + /* Number of states which keeps the device occupied with work without losing performance. * The renderer will add more work (when available) when number of active paths falls below this * value. */ virtual int num_concurrent_busy_states() const = 0; diff --git a/intern/cycles/integrator/denoiser.cpp b/intern/cycles/integrator/denoiser.cpp index 0d3e49b7f21..23ab825a4d2 100644 --- a/intern/cycles/integrator/denoiser.cpp +++ b/intern/cycles/integrator/denoiser.cpp @@ -80,7 +80,8 @@ static bool is_single_supported_device(Device *device, DenoiserType type) if (!device->info.multi_devices.empty()) { /* Some configurations will use multi_devices, but keep the type of an individual device. - * This does simplify checks for homogenous setups, but here we really need a single device. */ + * This does simplify checks for homogeneous setups, but here we really need a single device. + */ return false; } diff --git a/intern/cycles/kernel/bvh/shadow_all.h b/intern/cycles/kernel/bvh/shadow_all.h index a5769e91a28..2f58929c1e5 100644 --- a/intern/cycles/kernel/bvh/shadow_all.h +++ b/intern/cycles/kernel/bvh/shadow_all.h @@ -29,8 +29,8 @@ ccl_device_inline IntegratorShadowState state, const uint visibility, const uint max_hits, - ccl_private uint *num_recorded_hits, - ccl_private float *throughput) + ccl_private uint *r_num_recorded_hits, + ccl_private float *r_throughput) { /* todo: * - likely and unlikely for if() statements @@ -60,15 +60,18 @@ ccl_device_inline * recorded hits is exceeded and we no longer need to find hits beyond the max * distance found. */ float t_max_world = ray->t; - /* Equal to t_max_world when traversing top level BVH, transformed into local - * space when entering instances. */ - float t_max_current = t_max_world; + + /* Current maximum distance to the intersection. + * Is calculated as a ray length, transformed to an object space when entering + * instance node. */ + float t_max_current = ray->t; + /* Conversion from world to local space for the current instance if any, 1.0 * otherwise. */ float t_world_to_instance = 1.0f; - *num_recorded_hits = 0; - *throughput = 1.0f; + *r_num_recorded_hits = 0; + *r_throughput = 1.0f; /* traversal loop */ do { @@ -237,10 +240,10 @@ ccl_device_inline /* Always use baked shadow transparency for curves. */ if (isect.type & PRIMITIVE_CURVE) { - *throughput *= intersection_curve_shadow_transparency( + *r_throughput *= intersection_curve_shadow_transparency( kg, isect.object, isect.prim, isect.u); - if (*throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) { + if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) { return true; } else { @@ -249,37 +252,39 @@ ccl_device_inline } if (record_intersection) { - /* Increase the number of hits, possibly beyond max_hits, we will - * simply not record those and only keep the max_hits closest. */ - uint record_index = (*num_recorded_hits)++; - + /* Test if we need to record this transparent intersection. */ const uint max_record_hits = min(max_hits, INTEGRATOR_SHADOW_ISECT_SIZE); - if (record_index >= max_record_hits - 1) { - /* If maximum number of hits reached, find the intersection with - * the largest distance to potentially replace when another hit - * is found. */ - const int num_recorded_hits = min(max_record_hits, record_index); - float max_recorded_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t); - int max_recorded_hit = 0; - - for (int i = 1; i < num_recorded_hits; i++) { - const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t); - if (isect_t > max_recorded_t) { - max_recorded_t = isect_t; - max_recorded_hit = i; + if (*r_num_recorded_hits < max_record_hits || isect.t < t_max_world) { + /* If maximum number of hits was reached, replace the intersection with the + * highest distance. We want to find the N closest intersections. */ + const uint num_recorded_hits = min(*r_num_recorded_hits, max_record_hits); + uint isect_index = num_recorded_hits; + if (num_recorded_hits + 1 >= max_record_hits) { + float max_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t); + uint max_recorded_hit = 0; + + for (uint i = 1; i < num_recorded_hits; ++i) { + const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t); + if (isect_t > max_t) { + max_recorded_hit = i; + max_t = isect_t; + } + } + + if (num_recorded_hits >= max_record_hits) { + isect_index = max_recorded_hit; } - } - if (record_index >= max_record_hits) { - record_index = max_recorded_hit; + /* Limit the ray distance and stop counting hits beyond this. */ + t_max_world = max(isect.t, max_t); } - /* Limit the ray distance and stop counting hits beyond this. */ - t_max_world = max(max_recorded_t, isect.t); - t_max_current = t_max_world * t_world_to_instance; + integrator_state_write_shadow_isect(state, &isect, isect_index); } - integrator_state_write_shadow_isect(state, &isect, record_index); + /* Always increase the number of recorded hits, even beyond the maximum, + * so that we can detect this and trace another ray if needed. */ + ++(*r_num_recorded_hits); } } } @@ -318,7 +323,7 @@ ccl_device_inline #endif /* Restore world space ray length. */ - t_max_current = t_max_world; + t_max_current = ray->t; object = OBJECT_NONE; t_world_to_instance = 1.0f; diff --git a/intern/cycles/kernel/device/gpu/image.h b/intern/cycles/kernel/device/gpu/image.h index 9c92f6a693c..83e7aa869c1 100644 --- a/intern/cycles/kernel/device/gpu/image.h +++ b/intern/cycles/kernel/device/gpu/image.h @@ -186,7 +186,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo const int texture_type = info.data_type; if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 || texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) { - if (info.interpolation == INTERPOLATION_CUBIC) { + if (info.interpolation == INTERPOLATION_CUBIC || info.interpolation == INTERPOLATION_SMART) { return kernel_tex_image_interp_bicubic<float4>(info, x, y); } else { @@ -198,7 +198,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo else { float f; - if (info.interpolation == INTERPOLATION_CUBIC) { + if (info.interpolation == INTERPOLATION_CUBIC || info.interpolation == INTERPOLATION_SMART) { f = kernel_tex_image_interp_bicubic<float>(info, x, y); } else { @@ -241,7 +241,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg, #endif if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 || texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) { - if (interpolation == INTERPOLATION_CUBIC) { + if (interpolation == INTERPOLATION_CUBIC || interpolation == INTERPOLATION_SMART) { return kernel_tex_image_interp_tricubic<float4>(info, x, y, z); } else { @@ -252,7 +252,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg, else { float f; - if (interpolation == INTERPOLATION_CUBIC) { + if (interpolation == INTERPOLATION_CUBIC || interpolation == INTERPOLATION_SMART) { f = kernel_tex_image_interp_tricubic<float>(info, x, y, z); } else { diff --git a/intern/cycles/kernel/geom/object.h b/intern/cycles/kernel/geom/object.h index e8f5dfcc529..86c57c84b47 100644 --- a/intern/cycles/kernel/geom/object.h +++ b/intern/cycles/kernel/geom/object.h @@ -263,6 +263,16 @@ ccl_device_inline float3 object_color(KernelGlobals kg, int object) return make_float3(kobject->color[0], kobject->color[1], kobject->color[2]); } +/* Alpha of the object */ + +ccl_device_inline float object_alpha(KernelGlobals kg, int object) +{ + if (object == OBJECT_NONE) + return 0.0f; + + return kernel_tex_fetch(__objects, object).alpha; +} + /* Pass ID number of object */ ccl_device_inline float object_pass_id(KernelGlobals kg, int object) diff --git a/intern/cycles/kernel/osl/services.cpp b/intern/cycles/kernel/osl/services.cpp index 85bdb47600e..79547872c68 100644 --- a/intern/cycles/kernel/osl/services.cpp +++ b/intern/cycles/kernel/osl/services.cpp @@ -76,6 +76,7 @@ ustring OSLRenderServices::u_raster("raster"); ustring OSLRenderServices::u_ndc("NDC"); ustring OSLRenderServices::u_object_location("object:location"); ustring OSLRenderServices::u_object_color("object:color"); +ustring OSLRenderServices::u_object_alpha("object:alpha"); ustring OSLRenderServices::u_object_index("object:index"); ustring OSLRenderServices::u_geom_dupli_generated("geom:dupli_generated"); ustring OSLRenderServices::u_geom_dupli_uv("geom:dupli_uv"); @@ -873,6 +874,10 @@ bool OSLRenderServices::get_object_standard_attribute(const KernelGlobalsCPU *kg float3 f = object_color(kg, sd->object); return set_attribute_float3(f, type, derivatives, val); } + else if (name == u_object_alpha) { + float f = object_alpha(kg, sd->object); + return set_attribute_float(f, type, derivatives, val); + } else if (name == u_object_index) { float f = object_pass_id(kg, sd->object); return set_attribute_float(f, type, derivatives, val); diff --git a/intern/cycles/kernel/osl/services.h b/intern/cycles/kernel/osl/services.h index 0685003ca5c..653fa017140 100644 --- a/intern/cycles/kernel/osl/services.h +++ b/intern/cycles/kernel/osl/services.h @@ -259,6 +259,7 @@ class OSLRenderServices : public OSL::RendererServices { static ustring u_ndc; static ustring u_object_location; static ustring u_object_color; + static ustring u_object_alpha; static ustring u_object_index; static ustring u_geom_dupli_generated; static ustring u_geom_dupli_uv; diff --git a/intern/cycles/kernel/osl/shaders/node_object_info.osl b/intern/cycles/kernel/osl/shaders/node_object_info.osl index 37e545f9988..8ed73231213 100644 --- a/intern/cycles/kernel/osl/shaders/node_object_info.osl +++ b/intern/cycles/kernel/osl/shaders/node_object_info.osl @@ -5,12 +5,14 @@ shader node_object_info(output point Location = point(0.0, 0.0, 0.0), output color Color = color(1.0, 1.0, 1.0), + output float Alpha = 1.0, output float ObjectIndex = 0.0, output float MaterialIndex = 0.0, output float Random = 0.0) { getattribute("object:location", Location); getattribute("object:color", Color); + getattribute("object:alpha", Alpha); getattribute("object:index", ObjectIndex); getattribute("material:index", MaterialIndex); getattribute("object:random", Random); diff --git a/intern/cycles/kernel/svm/geometry.h b/intern/cycles/kernel/svm/geometry.h index c1a5fdb8ca4..4b5368dd765 100644 --- a/intern/cycles/kernel/svm/geometry.h +++ b/intern/cycles/kernel/svm/geometry.h @@ -116,6 +116,9 @@ ccl_device_noinline void svm_node_object_info(KernelGlobals kg, stack_store_float3(stack, out_offset, object_color(kg, sd->object)); return; } + case NODE_INFO_OB_ALPHA: + data = object_alpha(kg, sd->object); + break; case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break; diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h index 777a27b8716..bede58f7a54 100644 --- a/intern/cycles/kernel/svm/types.h +++ b/intern/cycles/kernel/svm/types.h @@ -142,6 +142,7 @@ typedef enum NodeGeometry { typedef enum NodeObjectInfo { NODE_INFO_OB_LOCATION, NODE_INFO_OB_COLOR, + NODE_INFO_OB_ALPHA, NODE_INFO_OB_INDEX, NODE_INFO_MAT_INDEX, NODE_INFO_OB_RANDOM diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h index 24eb783daf9..07d4a95780b 100644 --- a/intern/cycles/kernel/types.h +++ b/intern/cycles/kernel/types.h @@ -1307,6 +1307,7 @@ typedef struct KernelObject { float pass_id; float random_number; float color[3]; + float alpha; int particle_index; float dupli_generated[3]; @@ -1330,6 +1331,7 @@ typedef struct KernelObject { uint visibility; int primitive_type; + int pad[2]; } KernelObject; static_assert_align(KernelObject, 16); diff --git a/intern/cycles/scene/alembic_read.cpp b/intern/cycles/scene/alembic_read.cpp index 0ad3782360d..26a4153a825 100644 --- a/intern/cycles/scene/alembic_read.cpp +++ b/intern/cycles/scene/alembic_read.cpp @@ -469,7 +469,7 @@ static void add_subd_edge_creases(CachedData &cached_data, const SubDSchemaData &data, chrono_t time) { - if (!(data.crease_indices.valid() && data.crease_indices.valid() && + if (!(data.crease_indices.valid() && data.crease_lengths.valid() && data.crease_sharpnesses.valid())) { return; } @@ -543,7 +543,7 @@ static void read_subd_geometry(CachedData &cached_data, const SubDSchemaData &da add_positions(data.positions.getValue(iss), time, cached_data); - if (data.topology_variance != kHomogenousTopology || cached_data.shader.size() == 0) { + if (data.topology_variance != kHomogeneousTopology || cached_data.shader.size() == 0) { add_subd_polygons(cached_data, data, time); add_subd_edge_creases(cached_data, data, time); add_subd_vertex_creases(cached_data, data, time); @@ -582,7 +582,7 @@ static void read_curves_data(CachedData &cached_data, const CurvesSchemaData &da array<int> curve_first_key; array<int> curve_shader; - const bool is_homogenous = data.topology_variance == kHomogenousTopology; + const bool is_homogeneous = data.topology_variance == kHomogeneousTopology; curve_keys.reserve(position->size()); curve_radius.reserve(position->size()); @@ -605,7 +605,7 @@ static void read_curves_data(CachedData &cached_data, const CurvesSchemaData &da curve_radius.push_back_slow(radius * data.radius_scale); } - if (!is_homogenous || cached_data.curve_first_key.size() == 0) { + if (!is_homogeneous || cached_data.curve_first_key.size() == 0) { curve_first_key.push_back_reserved(offset); curve_shader.push_back_reserved(0); } @@ -616,7 +616,7 @@ static void read_curves_data(CachedData &cached_data, const CurvesSchemaData &da cached_data.curve_keys.add_data(curve_keys, time); cached_data.curve_radius.add_data(curve_radius, time); - if (!is_homogenous || cached_data.curve_first_key.size() == 0) { + if (!is_homogeneous || cached_data.curve_first_key.size() == 0) { cached_data.curve_first_key.add_data(curve_first_key, time); cached_data.curve_shader.add_data(curve_shader, time); } diff --git a/intern/cycles/scene/mesh.cpp b/intern/cycles/scene/mesh.cpp index ebf1c3999b6..a459195efee 100644 --- a/intern/cycles/scene/mesh.cpp +++ b/intern/cycles/scene/mesh.cpp @@ -68,7 +68,7 @@ void Mesh::Triangle::verts_for_step(const float3 *verts, r_verts[2] = verts[v[2]]; } else { - /* Center step not stored in the attribute array array. */ + /* Center step not stored in the attribute array. */ if (step > center_step) { step--; } diff --git a/intern/cycles/scene/object.cpp b/intern/cycles/scene/object.cpp index 97c86804507..fda9a211e60 100644 --- a/intern/cycles/scene/object.cpp +++ b/intern/cycles/scene/object.cpp @@ -76,6 +76,7 @@ NODE_DEFINE(Object) SOCKET_TRANSFORM(tfm, "Transform", transform_identity()); SOCKET_UINT(visibility, "Visibility", ~0); SOCKET_COLOR(color, "Color", zero_float3()); + SOCKET_FLOAT(alpha, "Alpha", 0.0f); SOCKET_UINT(random_id, "Random ID", 0); SOCKET_INT(pass_id, "Pass ID", 0); SOCKET_BOOLEAN(use_holdout, "Use Holdout", false); @@ -414,6 +415,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s kobject.color[0] = color.x; kobject.color[1] = color.y; kobject.color[2] = color.z; + kobject.alpha = ob->alpha; kobject.pass_id = pass_id; kobject.random_number = random_number; kobject.particle_index = particle_index; diff --git a/intern/cycles/scene/object.h b/intern/cycles/scene/object.h index e18968bc0ed..55689ccfa58 100644 --- a/intern/cycles/scene/object.h +++ b/intern/cycles/scene/object.h @@ -44,6 +44,7 @@ class Object : public Node { NODE_SOCKET_API(uint, random_id) NODE_SOCKET_API(int, pass_id) NODE_SOCKET_API(float3, color) + NODE_SOCKET_API(float, alpha) NODE_SOCKET_API(ustring, asset_name) vector<ParamValue> attributes; NODE_SOCKET_API(uint, visibility) diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index ba85cbde1d0..272a0dde7d8 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -4216,6 +4216,7 @@ NODE_DEFINE(ObjectInfoNode) SOCKET_OUT_VECTOR(location, "Location"); SOCKET_OUT_COLOR(color, "Color"); + SOCKET_OUT_FLOAT(alpha, "Alpha"); SOCKET_OUT_FLOAT(object_index, "Object Index"); SOCKET_OUT_FLOAT(material_index, "Material Index"); SOCKET_OUT_FLOAT(random, "Random"); @@ -4239,6 +4240,11 @@ void ObjectInfoNode::compile(SVMCompiler &compiler) compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_COLOR, compiler.stack_assign(out)); } + out = output("Alpha"); + if (!out->links.empty()) { + compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_ALPHA, compiler.stack_assign(out)); + } + out = output("Object Index"); if (!out->links.empty()) { compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_INDEX, compiler.stack_assign(out)); diff --git a/intern/ghost/intern/GHOST_Wintab.cpp b/intern/ghost/intern/GHOST_Wintab.cpp index aaf9503b294..2547a38c0d1 100644 --- a/intern/ghost/intern/GHOST_Wintab.cpp +++ b/intern/ghost/intern/GHOST_Wintab.cpp @@ -326,7 +326,7 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo) ORIENTATION ort = pkt.pkOrientation; /* Convert raw fixed point data to radians. */ - float altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI / 2.0); + float altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI_2); float azmRad = (float)(((float)ort.orAzimuth / (float)m_maxAzimuth) * M_PI * 2.0); /* Find length of the stylus' projected vector on the XY plane. */ @@ -334,7 +334,7 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo) /* From there calculate X and Y components based on azimuth. */ out.tabletData.Xtilt = sin(azmRad) * vecLen; - out.tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen); + out.tabletData.Ytilt = (float)(sin(M_PI_2 - azmRad) * vecLen); } out.time = pkt.pkTime; diff --git a/intern/iksolver/intern/IK_QJacobian.cpp b/intern/iksolver/intern/IK_QJacobian.cpp index 39c0e6eb348..ea659414b73 100644 --- a/intern/iksolver/intern/IK_QJacobian.cpp +++ b/intern/iksolver/intern/IK_QJacobian.cpp @@ -193,7 +193,7 @@ void IK_QJacobian::InvertSDLS() // DLS. The SDLS damps individual singular values, instead of using a single // damping term. - double max_angle_change = M_PI / 4.0; + double max_angle_change = M_PI_4; double epsilon = 1e-10; int i, j; diff --git a/intern/itasc/Cache.hpp b/intern/itasc/Cache.hpp index a533d75b53a..d461bb32fa8 100644 --- a/intern/itasc/Cache.hpp +++ b/intern/itasc/Cache.hpp @@ -17,7 +17,7 @@ namespace iTaSC { #define CACHE_CHANNEL_EXTEND_SIZE 10 #define CACHE_MAX_ITEM_SIZE 0x3FFF0 -/* macro to get the alignement gap after an item header */ +/* macro to get the alignment gap after an item header */ #define CACHE_ITEM_GAPB(item) (unsigned int)(((size_t)item+sizeof(CacheItem))&(sizeof(void*)-1)) /* macro to get item data position, item=CacheItem pointer */ #define CACHE_ITEM_DATA_POINTER(item) (void*)((unsigned char*)item+sizeof(CacheItem)+CACHE_ITEM_GAPB(item)) diff --git a/release/freedesktop/org.blender.Blender.appdata.xml b/release/freedesktop/org.blender.Blender.appdata.xml index 4b413f6b38d..12291860050 100644 --- a/release/freedesktop/org.blender.Blender.appdata.xml +++ b/release/freedesktop/org.blender.Blender.appdata.xml @@ -40,6 +40,27 @@ </screenshot> </screenshots> <releases> + <release version="3.1" date="2022-03-09"> + <description> + <p>New features:</p> + <ul> + <li>GPU acceleration for the Subdivision modifier</li> + <li>Cycles Metal GPU backend, contributed by Apple</li> + <li>Point Cloud rendering</li> + <li>More Geometry Nodes, including extrude mesh</li> + </ul> + <p>Enhancements:</p> + <ul> + <li>Faster and less memory usage in geometry nodes</li> + <li>Grease Pencil Dilate/Contract fill</li> + <li>Vertex Creasing support</li> + <li>Faster .obj and .fbx export</li> + <li>Image editor is able to handle large images</li> + <li>Python 3.10</li> + <li>User Interface updates</li> + </ul> + </description> + </release> <release version="3.0" date="2021-12-03"> <description> <p>New features:</p> diff --git a/release/license/THIRD-PARTY-LICENSES.txt b/release/license/THIRD-PARTY-LICENSES.txt index 2bd4ac23d6d..933f03b5564 100644 --- a/release/license/THIRD-PARTY-LICENSES.txt +++ b/release/license/THIRD-PARTY-LICENSES.txt @@ -318,7 +318,7 @@ Copyright (c) 2006, Google Inc. All rights reserved. ** ISPC; version 1.16.0 -- https://github.com/ispc/ispc Copyright Intel Corporation -** NumPy; version 1.21.2 -- https://numpy.org/ +** NumPy; version 1.22.0 -- https://numpy.org/ Copyright (c) 2005-2021, NumPy Developers. ** Open Shading Language; version 1.11.14.1 -- https://github.com/imageworks/OpenShadingLanguage @@ -822,7 +822,7 @@ Yoyodyne, Inc., hereby disclaims all copyright interest in the program ** FFTW; version 3.3.8 -- http://www.fftw.org/ Copyright (c) 2003, 2007-14 Matteo Frigo Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology -** GMP; version 6.2.0 -- https://gmplib.org/ +** GMP; version 6.2.1 -- https://gmplib.org/ Copyright 1996-2020 Free Software Foundation, Inc. ** OpenAL; version 1.20.1 -- http://openal-soft.org Copyright (c) 2015, Archontis Politis @@ -1162,7 +1162,7 @@ Copyright (C) 2003-2021 x264 project ** miniLZO; version 2.08 -- http://www.oberhumer.com/opensource/lzo/ LZO and miniLZO are Copyright (C) 1996-2014 Markus Franz Xaver Oberhumer All Rights Reserved. -** The FreeType Project; version 2.10.2 -- +** The FreeType Project; version 2.11.1 -- https://sourceforge.net/projects/freetype Copyright (C) 1996-2020 by David Turner, Robert Wilhelm, and Werner Lemberg. ** X Drag and Drop; version 2000-08-08 -- @@ -1174,7 +1174,7 @@ Project initiators: Christoph Lampert <gruel@web.de> Michael Militzer <isibaar@xvid.org> Peter Ross <pross@xvid.org> -** Zstandard; version 1.5.0 -- https://github.com/facebook/zstd +** Zstandard; version 1.6.0 -- https://github.com/facebook/zstd Copyright (c) 2016-present, Facebook, Inc. All rights reserved. GNU GENERAL PUBLIC LICENSE @@ -2956,6 +2956,8 @@ December 9, 2010 ------ +** Brotli; version 1.0.9 -- https://github.com/google/brotli +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. ** Expat; version 2.2.10 -- https://github.com/libexpat/libexpat/ Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper Copyright (c) 2001-2019 Expat maintainers @@ -3627,7 +3629,7 @@ disclaims all warranties with regard to this software. ------ -** Python; version 3.9.7 -- https://www.python.org +** Python; version 3.10.2 -- https://www.python.org Copyright (c) 2001-2021 Python Software Foundation. All rights reserved. A. HISTORY OF THE SOFTWARE diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 54fcc8faf46..e0e20d0f8c9 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -580,15 +580,6 @@ class MeshPolygon(StructRNA): class Text(bpy_types.ID): __slots__ = () - def as_string(self): - """Return the text as a string.""" - return "\n".join(line.body for line in self.lines) - - def from_string(self, string): - """Replace text with this string.""" - self.clear() - self.write(string) - def as_module(self): import bpy from os.path import splitext, join diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 83946fbf68f..5a12d5c79f9 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -1,5 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-or-later +__all__ = ( + "generate_keymaps", + "Params", +) + # ------------------------------------------------------------------------------ # Developer Notes # @@ -361,12 +366,12 @@ def _template_items_editmode_mesh_select_mode(params): return [ ( "mesh.select_mode", - {"type": k, "value": 'PRESS', **key_expand, **key_extend}, + {"type": NUMBERS_1[i], "value": 'PRESS', **key_expand, **key_extend}, {"properties": [*prop_extend, *prop_expand, ("type", e)]} ) for key_expand, prop_expand in (({}, ()), ({"ctrl": True}, (("use_expand", True),))) for key_extend, prop_extend in (({}, ()), ({"shift": True}, (("use_extend", True),))) - for k, e in (('ONE', 'VERT'), ('TWO', 'EDGE'), ('THREE', 'FACE')) + for i, e in enumerate(('VERT', 'EDGE', 'FACE')) ] @@ -385,9 +390,9 @@ def _template_items_uv_select_mode(params): *_template_items_editmode_mesh_select_mode(params), # Hack to prevent fall-through, when sync select isn't enabled (and the island button isn't visible). ("mesh.select_mode", {"type": 'FOUR', "value": 'PRESS'}, None), - *(("uv.select_mode", {"type": k, "value": 'PRESS'}, + *(("uv.select_mode", {"type": NUMBERS_1[i], "value": 'PRESS'}, {"properties": [("type", e)]}) - for k, e in (('ONE', 'VERTEX'), ('TWO', 'EDGE'), ('THREE', 'FACE'), ('FOUR', 'ISLAND'))) + for i, e in enumerate(('VERTEX', 'EDGE', 'FACE', 'ISLAND'))) ] @@ -421,13 +426,18 @@ def _template_items_change_frame(params): # Tool System Templates -def _template_items_tool_select(params, operator, cursor_operator, *, extend): +def _template_items_tool_select(params, operator, cursor_operator, fallback, *, extend): if params.select_mouse == 'LEFTMOUSE': - # Immediate select without quick delay. + # By default use 'PRESS' for immediate select without quick delay. + # Fallback key-maps 'CLICK' since 'PRESS' events passes through (allowing either click or drag). + # + # NOTE: When the active (non-fallback) tool uses a key-map that activates it's primary tool on drag, + # it's important that this key-map uses click and not press. Otherwise it becomes impossible to use + # the tool without selecting elements under the cursor. return [ - (operator, {"type": 'LEFTMOUSE', "value": 'PRESS'}, + (operator, {"type": 'LEFTMOUSE', "value": 'CLICK' if fallback else 'PRESS'}, {"properties": [("deselect_all", True)]}), - (operator, {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + (operator, {"type": 'LEFTMOUSE', "value": 'CLICK' if fallback else 'PRESS', "shift": True}, {"properties": [(extend, True)]}), ] else: @@ -1214,7 +1224,7 @@ def km_uv_editor(params): ("transform.shear", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None), ("transform.mirror", {"type": 'M', "value": 'PRESS', "ctrl": True}, None), ("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True}, - {"properties": [("data_path", 'tool_settings.use_snap')]}), + {"properties": [("data_path", 'tool_settings.use_snap_uv')]}), ("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True}, {"properties": [("data_path", 'tool_settings.snap_uv_element')]}), *_template_items_context_menu("IMAGE_MT_uvs_context_menu", params.context_menu_event), @@ -2079,7 +2089,7 @@ def km_node_editor(params): {"type": params.select_mouse, "value": 'CLICK_DRAG', "alt": True}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}), ("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True}, - {"properties": [("data_path", 'tool_settings.use_snap')]}), + {"properties": [("data_path", 'tool_settings.use_snap_node')]}), ("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True}, {"properties": [("data_path", 'tool_settings.snap_node_element')]}), ("wm.context_toggle", {"type": 'Z', "value": 'PRESS', "alt": True, "shift": True}, @@ -3627,12 +3637,9 @@ def km_grease_pencil_stroke_edit_mode(params): # Vertex group menu op_menu("GPENCIL_MT_gpencil_vertex_group", {"type": 'G', "value": 'PRESS', "ctrl": True}), # Select mode - ("gpencil.selectmode_toggle", {"type": 'ONE', "value": 'PRESS'}, - {"properties": [("mode", 0)]}), - ("gpencil.selectmode_toggle", {"type": 'TWO', "value": 'PRESS'}, - {"properties": [("mode", 1)]}), - ("gpencil.selectmode_toggle", {"type": 'THREE', "value": 'PRESS'}, - {"properties": [("mode", 2)]}), + *(("gpencil.selectmode_toggle", {"type": NUMBERS_1[i], "value": 'PRESS'}, + {"properties": [("mode", i)]}) + for i in range(3)), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), # Keyframe menu @@ -6082,10 +6089,8 @@ def km_sculpt_expand_modal(_params): ("RECURSION_STEP_GEODESIC", {"type": 'R', "value": 'PRESS'}, None), ("RECURSION_STEP_TOPOLOGY", {"type": 'R', "value": 'PRESS', "alt": True}, None), ("MOVE_TOGGLE", {"type": 'SPACE', "value": 'ANY', "any": True}, None), - ("FALLOFF_GEODESICS", {"type": 'ONE', "value": 'PRESS', "any": True}, None), - ("FALLOFF_TOPOLOGY", {"type": 'TWO', "value": 'PRESS', "any": True}, None), - ("FALLOFF_TOPOLOGY_DIAGONALS", {"type": 'THREE', "value": 'PRESS', "any": True}, None), - ("FALLOFF_SPHERICAL", {"type": 'FOUR', "value": 'PRESS', "any": True}, None), + *((e, {"type": NUMBERS_1[i], "value": 'PRESS', "any": True}, None) for i, e in enumerate( + ("FALLOFF_GEODESICS", "FALLOFF_TOPOLOGY", "FALLOFF_TOPOLOGY_DIAGONALS", "FALLOFF_SPHERICAL"))), ("SNAP_TOGGLE", {"type": 'LEFT_CTRL', "value": 'ANY'}, None), ("LOOP_COUNT_INCREASE", {"type": 'W', "value": 'PRESS', "any": True, "repeat": True}, None), ("LOOP_COUNT_DECREASE", {"type": 'Q', "value": 'PRESS', "any": True, "repeat": True}, None), @@ -6280,7 +6285,7 @@ def km_image_editor_tool_uv_select(params, *, fallback): {"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'}, {"items": [ *([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select( - params, "uv.select", "uv.cursor_set", extend="extend")), + params, "uv.select", "uv.cursor_set", fallback, extend="extend")), *([] if (not params.use_fallback_tool_rmb) else _template_uv_select( type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)), ]}, @@ -6487,7 +6492,7 @@ def km_3d_view_tool_select(params, *, fallback): {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, {"items": [ *([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select( - params, "view3d.select", "view3d.cursor3d", extend="toggle")), + params, "view3d.select", "view3d.cursor3d", fallback, extend="toggle")), *([] if (not params.use_fallback_tool_rmb) else _template_view3d_select( type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy, exclude_mod="ctrl")), ]}, @@ -7399,7 +7404,7 @@ def km_3d_view_tool_edit_gpencil_select(params, *, fallback): {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, {"items": [ *([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select( - params, "gpencil.select", "view3d.cursor3d", extend="toggle")), + params, "gpencil.select", "view3d.cursor3d", fallback, extend="toggle")), *([] if (not params.use_fallback_tool_rmb) else _template_view3d_gpencil_select( type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)), ]}, @@ -7537,7 +7542,7 @@ def km_3d_view_tool_sculpt_gpencil_select(params): return ( "3D View Tool: Sculpt Gpencil, Tweak", {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, - {"items": _template_items_tool_select(params, "gpencil.select", "view3d.cursor3d", extend="toggle")}, + {"items": _template_items_tool_select(params, "gpencil.select", "view3d.cursor3d", False, extend="toggle")}, ) @@ -7577,7 +7582,7 @@ def km_sequencer_editor_tool_generic_select(params, *, fallback): {"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'}, {"items": [ *([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select( - params, "sequencer.select", "sequencer.cursor_set", extend="toggle")), + params, "sequencer.select", "sequencer.cursor_set", fallback, extend="toggle")), *([] if (not params.use_fallback_tool_rmb) else _template_sequencer_preview_select( type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)), diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index 3469dbdc175..55ee91af7cd 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -1152,7 +1152,7 @@ def km_node_editor(params): ("node.move_detach_links_release", {"type": params.action_mouse, "value": 'CLICK_DRAG', "alt": True}, None), ("node.move_detach_links", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG', "alt": True}, None), ("wm.context_toggle", {"type": 'X', "value": 'PRESS'}, - {"properties": [("data_path", 'tool_settings.use_snap')]}), + {"properties": [("data_path", 'tool_settings.use_snap_node')]}), ]) return keymap diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py index d83781b2ed8..23bf8a5cb60 100644 --- a/release/scripts/startup/bl_operators/clip.py +++ b/release/scripts/startup/bl_operators/clip.py @@ -107,8 +107,8 @@ def CLIP_default_settings_from_track(clip, track, framenr): search[1] = search[1] * height settings.default_correlation_min = track.correlation_min - settings.default_pattern_size = max(pattern[0], pattern[1]) - settings.default_search_size = max(search[0], search[1]) + settings.default_pattern_size = int(max(pattern[0], pattern[1])) + settings.default_search_size = int(max(search[0], search[1])) settings.default_frames_limit = track.frames_limit settings.default_pattern_match = track.pattern_match settings.default_margin = track.margin diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index 26e5cfaae60..d6e21053e3b 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -289,7 +289,6 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel): if is_surf: subsub = sub.column() - subsub.active = (not act_spline.use_cyclic_v) subsub.prop(act_spline, "use_bezier_v", text="V") sub = col.column(heading="Endpoint", align=True) @@ -297,7 +296,6 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel): if is_surf: subsub = sub.column() - subsub.active = (not act_spline.use_cyclic_v) subsub.prop(act_spline, "use_endpoint_v", text="V") sub = col.column(align=True) @@ -322,6 +320,17 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel): col.prop(act_spline, "radius_interpolation", text="Radius") layout.prop(act_spline, "use_smooth") + if act_spline.type == 'NURBS': + col = None + for direction in range(2): + message = act_spline.valid_message(direction) + if not message: + continue + if col is None: + layout.separator() + col = layout.column(align=True) + col.label(text=message, icon='INFO') + del col class DATA_PT_font(CurveButtonsPanelText, Panel): diff --git a/release/scripts/startup/bl_ui/properties_data_curves.py b/release/scripts/startup/bl_ui/properties_data_curves.py index 1bb5fc9afbe..4eefd5a0e0c 100644 --- a/release/scripts/startup/bl_ui/properties_data_curves.py +++ b/release/scripts/startup/bl_ui/properties_data_curves.py @@ -43,6 +43,8 @@ class DATA_PT_curves_surface(DataButtonsPanel, Panel): layout = self.layout ob = context.object + layout.use_property_split = True + layout.prop(ob.data, "surface") diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index b7522cbb04e..2a7af8357e7 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -484,6 +484,18 @@ class RENDER_PT_eevee_film(RenderButtonsPanel, Panel): sub.prop(props, "overscan_size", text="") +def draw_hair_settings(self, context): + layout = self.layout + scene = context.scene + rd = scene.render + + layout.use_property_split = True + layout.use_property_decorate = False # No animation. + + layout.prop(rd, "hair_type", text="Shape", expand=True) + layout.prop(rd, "hair_subdiv") + + class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel): bl_label = "Hair" bl_options = {'DEFAULT_CLOSED'} @@ -494,14 +506,7 @@ class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel): return (context.engine in cls.COMPAT_ENGINES) def draw(self, context): - layout = self.layout - scene = context.scene - rd = scene.render - - layout.use_property_split = True - - layout.prop(rd, "hair_type", expand=True) - layout.prop(rd, "hair_subdiv") + draw_hair_settings(self, context) class RENDER_PT_eevee_performance(RenderButtonsPanel, Panel): @@ -519,6 +524,7 @@ class RENDER_PT_eevee_performance(RenderButtonsPanel, Panel): rd = scene.render layout.use_property_split = True + layout.use_property_decorate = False # No animation. layout.prop(rd, "use_high_quality_normals") diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 65d624a253d..785a841a0e6 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -724,7 +724,7 @@ class IMAGE_HT_header(Header): act_snap_uv_element = tool_settings.bl_rna.properties['snap_uv_element'].enum_items[snap_uv_element] row = layout.row(align=True) - row.prop(tool_settings, "use_snap", text="") + row.prop(tool_settings, "use_snap_uv", text="") sub = row.row(align=True) sub.popover( diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index a89b201d648..7c88006a4d6 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -185,7 +185,7 @@ class NODE_HT_header(Header): # Snap row = layout.row(align=True) - row.prop(tool_settings, "use_snap", text="") + row.prop(tool_settings, "use_snap_node", text="") row.prop(tool_settings, "snap_node_element", icon_only=True) if tool_settings.snap_node_element != 'GRID': row.prop(tool_settings, "snap_target", text="") diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index a8a851bb228..1639a564508 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -25,7 +25,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 5 +#define BLENDER_FILE_SUBVERSION 6 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_callbacks.h b/source/blender/blenkernel/BKE_callbacks.h index 66089d29c45..2cd28c4dfa5 100644 --- a/source/blender/blenkernel/BKE_callbacks.h +++ b/source/blender/blenkernel/BKE_callbacks.h @@ -95,6 +95,8 @@ typedef enum { BKE_CB_EVT_LOAD_FACTORY_USERDEF_POST, BKE_CB_EVT_LOAD_FACTORY_STARTUP_POST, BKE_CB_EVT_XR_SESSION_START_PRE, + BKE_CB_EVT_ANNOTATION_PRE, + BKE_CB_EVT_ANNOTATION_POST, BKE_CB_EVT_TOT, } eCbEvent; diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 3f65ce83b3f..394d97223e3 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -269,6 +269,14 @@ void BKE_nurb_knot_calc_v(struct Nurb *nu); bool BKE_nurb_check_valid_u(const struct Nurb *nu); bool BKE_nurb_check_valid_v(const struct Nurb *nu); bool BKE_nurb_check_valid_uv(const struct Nurb *nu); +bool BKE_nurb_valid_message(int pnts, + short order, + short flag, + short type, + bool is_surf, + const char *dir, + char *message_dst, + size_t maxncpy); bool BKE_nurb_order_clamp_u(struct Nurb *nu); bool BKE_nurb_order_clamp_v(struct Nurb *nu); diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh index f3d9090d16b..875cf48ed43 100644 --- a/source/blender/blenkernel/BKE_curves.hh +++ b/source/blender/blenkernel/BKE_curves.hh @@ -62,7 +62,9 @@ class CurvesGeometry : public ::CurvesGeometry { */ CurvesGeometry(int point_size, int curve_size); CurvesGeometry(const CurvesGeometry &other); + CurvesGeometry(CurvesGeometry &&other); CurvesGeometry &operator=(const CurvesGeometry &other); + CurvesGeometry &operator=(CurvesGeometry &&other); ~CurvesGeometry(); static CurvesGeometry &wrap(::CurvesGeometry &dna_struct) @@ -95,6 +97,7 @@ class CurvesGeometry : public ::CurvesGeometry { * Access a range of indices of point data for a specific curve. */ IndexRange range_for_curve(int index) const; + IndexRange range_for_curves(IndexRange curves) const; /** The type (#CurveType) of each curve, or potentially a single if all are the same type. */ VArray<int8_t> curve_types() const; @@ -147,6 +150,8 @@ class CurvesGeometry : public ::CurvesGeometry { void update_customdata_pointers(); + void remove_curves(IndexMask curves_to_delete); + /* -------------------------------------------------------------------- * Attributes. */ diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index ea21fa9b404..940dc3c4f6c 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -716,7 +716,7 @@ void CustomData_data_transfer(const struct MeshPairRemap *me_remap, * \param write_layers_buff: An optional buffer for r_write_layers (to avoid allocating it). * \param write_layers_size: The size of pre-allocated \a write_layer_buff. * - * \warning After this funcion has ran, given custom data is no more valid from Blender POV + * \warning After this function has ran, given custom data is no more valid from Blender POV * (its `totlayer` is invalid). This function shall always be called with localized data * (as it is in write_meshes()). * diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index f7767cc2a60..0e121068cbc 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -500,8 +500,8 @@ struct GeometrySet { /** * Clear the existing curves data-block and replace it with the given one. */ - void replace_curve(Curves *curves, - GeometryOwnershipType ownership = GeometryOwnershipType::Owned); + void replace_curves(Curves *curves, + GeometryOwnershipType ownership = GeometryOwnershipType::Owned); private: /** @@ -678,7 +678,7 @@ class CurveComponentLegacy : public GeometryComponent { }; /** - * A geometry component that stores a group of curves, corresponding the the #Curves and + * A geometry component that stores a group of curves, corresponding the #Curves and * #CurvesGeometry types. */ class CurveComponent : public GeometryComponent { diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index b3001ecc880..ea0202e3b5f 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -371,7 +371,7 @@ void BKE_image_merge(struct Main *bmain, struct Image *dest, struct Image *sourc bool BKE_image_scale(struct Image *image, int width, int height); /** - * Check if texture has alpha (depth=32). + * Check if texture has alpha (planes == 32 || planes == 16). */ bool BKE_image_has_alpha(struct Image *image); @@ -486,7 +486,7 @@ bool BKE_image_is_dirty(struct Image *image); void BKE_image_mark_dirty(struct Image *image, struct ImBuf *ibuf); bool BKE_image_buffer_format_writable(struct ImBuf *ibuf); -bool BKE_image_is_dirty_writable(struct Image *image, bool *is_format_writable); +bool BKE_image_is_dirty_writable(struct Image *image, bool *r_is_writable); /** * Guess offset for the first frame in the sequence. diff --git a/source/blender/blenkernel/BKE_image_partial_update.hh b/source/blender/blenkernel/BKE_image_partial_update.hh index 45b08e17920..8cbb8819551 100644 --- a/source/blender/blenkernel/BKE_image_partial_update.hh +++ b/source/blender/blenkernel/BKE_image_partial_update.hh @@ -212,7 +212,7 @@ template<typename TileData = NoTileData> struct PartialUpdateChecker { ePartialUpdateCollectResult result_code; private: - TileNumber last_tile_number; + TileNumber last_tile_number = 0; public: CollectResult(PartialUpdateChecker<TileData> *checker, ePartialUpdateCollectResult result_code) diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index c56cb616a9a..040be8d1280 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -150,11 +150,11 @@ enum { LIB_ID_COPY_NO_PREVIEW = 1 << 17, /** Copy runtime data caches. */ LIB_ID_COPY_CACHES = 1 << 18, - /** Don't copy id->adt, used by ID datablock localization routines. */ + /** Don't copy id->adt, used by ID data-block localization routines. */ LIB_ID_COPY_NO_ANIMDATA = 1 << 19, /** Mesh: Reference CD data layers instead of doing real copy - USE WITH CAUTION! */ LIB_ID_COPY_CD_REFERENCE = 1 << 20, - /** Do not copy id->override_library, used by ID datablock override routines. */ + /** Do not copy id->override_library, used by ID data-block override routines. */ LIB_ID_COPY_NO_LIB_OVERRIDE = 1 << 21, /** When copying local sub-data (like constraints or modifiers), do not set their "library * override local data" flag. */ @@ -162,11 +162,11 @@ enum { /* *** XXX Hackish/not-so-nice specific behaviors needed for some corner cases. *** */ /* *** Ideally we should not have those, but we need them for now... *** */ - /** EXCEPTION! Deep-copy actions used by animdata of copied ID. */ + /** EXCEPTION! Deep-copy actions used by animation-data of copied ID. */ LIB_ID_COPY_ACTIONS = 1 << 24, - /** Keep the library pointer when copying datablock outside of bmain. */ + /** Keep the library pointer when copying data-block outside of bmain. */ LIB_ID_COPY_KEEP_LIB = 1 << 25, - /** EXCEPTION! Deep-copy shapekeys used by copied obdata ID. */ + /** EXCEPTION! Deep-copy shape-keys used by copied obdata ID. */ LIB_ID_COPY_SHAPEKEY = 1 << 26, /** EXCEPTION! Specific deep-copy of node trees used e.g. for rendering purposes. */ LIB_ID_COPY_NODETREE_LOCALIZE = 1 << 27, @@ -177,7 +177,7 @@ enum { LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING = 1 << 28, /* *** Helper 'defines' gathering most common flag sets. *** */ - /** Shapekeys are not real ID's, more like local data to geometry IDs... */ + /** Shape-keys are not real ID's, more like local data to geometry IDs. */ LIB_ID_COPY_DEFAULT = LIB_ID_COPY_SHAPEKEY, /** Create a local, outside of bmain, data-block to work on. */ @@ -412,7 +412,7 @@ struct ID *BKE_id_copy(struct Main *bmain, const struct ID *id); * * There are exceptions though: * - Embedded IDs (root node trees and master collections) are always copied with their owner. - * - If #LIB_ID_COPY_ACTIONS is defined, actions used by animdata will be duplicated. + * - If #LIB_ID_COPY_ACTIONS is defined, actions used by anim-data will be duplicated. * - If #LIB_ID_COPY_SHAPEKEY is defined, shape-keys will be duplicated. * - If #LIB_ID_CREATE_LOCAL is defined, root node trees will be deep-duplicated recursively. * diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh index 42b4702ee44..1e3134020c6 100644 --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@ -449,12 +449,6 @@ class BezierSpline final : public Spline { */ class NURBSpline final : public Spline { public: - enum class KnotsMode { - Normal, - EndPoint, - Bezier, - }; - /** Method used to recalculate the knots vector when points are added or removed. */ KnotsMode knots_mode; diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index e833b4a14bb..bc6df18ce25 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -14,6 +14,8 @@ struct Main; struct Text; struct TextLine; +#include "BLI_compiler_attrs.h" + /** * \note caller must handle `compiled` member. */ @@ -55,7 +57,8 @@ void BKE_text_write(struct Text *text, const char *str); int BKE_text_file_modified_check(struct Text *text); void BKE_text_file_modified_ignore(struct Text *text); -char *txt_to_buf(struct Text *text, int *r_buf_strlen); +char *txt_to_buf(struct Text *text, int *r_buf_strlen) + ATTR_NONNULL(1, 2) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL; void txt_clean_text(struct Text *text); void txt_order_cursors(struct Text *text, bool reverse); int txt_find_string(struct Text *text, const char *findstr, int wrap, int match_case); @@ -135,11 +138,12 @@ enum { /** * Create a buffer, the only requirement is #txt_from_buf_for_undo can decode it. */ -char *txt_to_buf_for_undo(struct Text *text, int *r_buf_len); +char *txt_to_buf_for_undo(struct Text *text, int *r_buf_len) + ATTR_NONNULL(1, 2) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL; /** * Decode a buffer from #txt_to_buf_for_undo. */ -void txt_from_buf_for_undo(struct Text *text, const char *buf, int buf_len); +void txt_from_buf_for_undo(struct Text *text, const char *buf, int buf_len) ATTR_NONNULL(1, 2); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index a12a956cbf5..bd632380ada 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -150,7 +150,7 @@ set(SRC intern/idprop_serialize.cc intern/idprop_utils.c intern/idtype.c - intern/image.c + intern/image.cc intern/image_partial_update.cc intern/image_gen.c intern/image_gpu.cc @@ -807,6 +807,7 @@ if(WITH_GTESTS) intern/asset_test.cc intern/bpath_test.cc intern/cryptomatte_test.cc + intern/curves_geometry_test.cc intern/fcurve_test.cc intern/idprop_serialize_test.cc intern/image_partial_update_test.cc diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 39074a5c75f..904a43a7c28 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -1468,7 +1468,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, /* set the DerivedMesh to only copy needed data */ CustomData_MeshMasks_update(&mask, &append_mask); - /* XXX WHAT? ovewrites mask ??? */ + /* XXX WHAT? overwrites mask ??? */ /* CD_MASK_ORCO may have been cleared above */ mask = md_datamask->mask; mask.vmask |= CD_MASK_ORIGINDEX; diff --git a/source/blender/blenkernel/intern/armature_test.cc b/source/blender/blenkernel/intern/armature_test.cc index 7475e6f36d4..4d266c8493a 100644 --- a/source/blender/blenkernel/intern/armature_test.cc +++ b/source/blender/blenkernel/intern/armature_test.cc @@ -285,7 +285,7 @@ TEST(vec_roll_to_mat3_normalized, Roll1) const float expected_roll_mat[3][3] = {{0.211324856f, 0.577350259f, -0.788675129f}, {0.577350259f, 0.577350259f, 0.577350259f}, {0.788675129f, -0.577350259f, -0.211324856f}}; - test_vec_roll_to_mat3_normalized(input, float(M_PI * 0.5), expected_roll_mat); + test_vec_roll_to_mat3_normalized(input, float(M_PI_2), expected_roll_mat); } /** Test that the matrix is orthogonal for an input close to -Y. */ diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c index ce36bfe81be..294fe57c923 100644 --- a/source/blender/blenkernel/intern/blendfile_link_append.c +++ b/source/blender/blenkernel/intern/blendfile_link_append.c @@ -926,7 +926,7 @@ static int foreach_libblock_link_append_callback(LibraryIDLinkCallbackData *cb_d * unfortunately they can use fully linkable valid IDs too, like actions. Those need to be * processed, so we need to recursively deal with them here. */ /* NOTE: Since we are by-passing checks in `BKE_library_foreach_ID_link` by manually calling it - * recursively, we need to take care of potential recursion cases ourselves (e.g.animdata of + * recursively, we need to take care of potential recursion cases ourselves (e.g.anim-data of * shape-key referencing the shape-key itself). * NOTE: in case both IDs (owner and 'used' ones) are non-linkable, we can assume we can break * the dependency here. Indeed, either they are both linked in another way (through their own diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 2afe4dda35c..7a97139748f 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -5515,7 +5515,7 @@ static void constraints_init_typeinfo(void) constraintsTypeInfo[12] = &CTI_ACTION; /* Action Constraint */ constraintsTypeInfo[13] = &CTI_LOCKTRACK; /* Locked-Track Constraint */ constraintsTypeInfo[14] = &CTI_DISTLIMIT; /* Limit Distance Constraint */ - constraintsTypeInfo[15] = &CTI_STRETCHTO; /* StretchTo Constaint */ + constraintsTypeInfo[15] = &CTI_STRETCHTO; /* StretchTo Constraint */ constraintsTypeInfo[16] = &CTI_MINMAX; /* Floor Constraint */ /* constraintsTypeInfo[17] = &CTI_RIGIDBODYJOINT; */ /* RigidBody Constraint - Deprecated */ constraintsTypeInfo[18] = &CTI_CLAMPTO; /* ClampTo Constraint */ diff --git a/source/blender/blenkernel/intern/curve.cc b/source/blender/blenkernel/intern/curve.cc index 6b7f7af44e8..0b619c1a969 100644 --- a/source/blender/blenkernel/intern/curve.cc +++ b/source/blender/blenkernel/intern/curve.cc @@ -17,8 +17,8 @@ #include "BLI_index_range.hh" #include "BLI_math.h" #include "BLI_math_vec_types.hh" +#include "BLI_string.h" #include "BLI_utildefines.h" - #include "BLT_translation.h" /* Allow using deprecated functionality for .blend file I/O. */ @@ -1156,12 +1156,13 @@ void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, BPoint *bp, float r_plane[3]) static void calcknots(float *knots, const int pnts, const short order, const short flag) { const bool is_cyclic = flag & CU_NURB_CYCLIC; - const bool is_bezier = flag & CU_NURB_BEZIER && !(flag & CU_NURB_ENDPOINT); - const bool is_end_point = flag & CU_NURB_ENDPOINT && !(flag & CU_NURB_BEZIER); + const bool is_bezier = flag & CU_NURB_BEZIER; + const bool is_end_point = flag & CU_NURB_ENDPOINT; /* Inner knots are always repeated once except on Bezier case. */ const int repeat_inner = is_bezier ? order - 1 : 1; /* How many times to repeat 0.0 at the beginning of knot. */ - const int head = is_end_point && !is_cyclic ? order : (is_bezier ? order / 2 : 1); + const int head = is_end_point ? (order - (is_cyclic ? 1 : 0)) : + (is_bezier ? min_ii(2, repeat_inner) : 1); /* Number of knots replicating widths of the starting knots. * Covers both Cyclic and EndPoint cases. */ const int tail = is_cyclic ? 2 * order - 1 : (is_end_point ? order : 0); @@ -1171,11 +1172,17 @@ static void calcknots(float *knots, const int pnts, const short order, const sho int r = head; float current = 0.0f; - for (const int i : IndexRange(knot_count - tail)) { + const int offset = is_end_point && is_cyclic ? 1 : 0; + if (offset) { + knots[0] = current; + current += 1.0f; + } + + for (const int i : IndexRange(offset, knot_count - offset - tail)) { knots[i] = current; r--; if (r == 0) { - current += 1.0; + current += 1.0f; r = repeat_inner; } } @@ -4693,59 +4700,56 @@ void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, const float *key) } } -bool BKE_nurb_check_valid_u(const Nurb *nu) +bool BKE_nurb_valid_message(const int pnts, + const short order, + const short flag, + const short type, + const bool is_surf, + const char *dir, + char *message_dst, + const size_t maxncpy) { - if (nu->pntsu <= 1) { - return false; - } - if (nu->type != CU_NURBS) { - return true; /* not a nurb, lets assume its valid */ - } + const char *msg_template = ""; + uint16_t points_needed = 0; - if (nu->pntsu < nu->orderu) { - return false; + if (pnts <= 1) { + msg_template = TIP_("At least two points required."); } - if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) { - /* Bezier U Endpoints */ - if (nu->orderu == 4) { - if (nu->pntsu < 5) { - return false; /* bezier with 4 orderu needs 5 points */ - } + else if (type == CU_NURBS) { + if (pnts < order) { + msg_template = TIP_("Must have more control points than Order"); } - else { - if (nu->orderu != 3) { - return false; /* order must be 3 or 4 */ + else if (flag & CU_NURB_BEZIER) { + if (flag & CU_NURB_CYCLIC) { + const uint16_t remainder = pnts % (order - 1); + points_needed = remainder > 0 ? order - 1 - remainder : 0; + } + else if (((flag & CU_NURB_ENDPOINT) == 0) && pnts <= order) { + points_needed = order + 1 - pnts; + } + if (points_needed) { + msg_template = is_surf ? TIP_("%d more %s row(s) needed for Bezier") : + TIP_("%d more point(s) needed for Bezier"); } } } - return true; + + if (message_dst) { + BLI_snprintf(message_dst, maxncpy, msg_template, points_needed, dir); + } + return msg_template[0]; } -bool BKE_nurb_check_valid_v(const Nurb *nu) + +bool BKE_nurb_check_valid_u(const Nurb *nu) { - if (nu->pntsv <= 1) { - return false; - } - if (nu->type != CU_NURBS) { - return true; /* not a nurb, lets assume its valid */ - } + return !BKE_nurb_valid_message( + nu->pntsu, nu->orderu, nu->flagu, nu->type, nu->pntsv > 1, "U", nullptr, 0); +} - if (nu->pntsv < nu->orderv) { - return false; - } - if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) { - /* Bezier V Endpoints */ - if (nu->orderv == 4) { - if (nu->pntsv < 5) { - return false; /* bezier with 4 orderu needs 5 points */ - } - } - else { - if (nu->orderv != 3) { - return false; /* order must be 3 or 4 */ - } - } - } - return true; +bool BKE_nurb_check_valid_v(const Nurb *nu) +{ + return !BKE_nurb_valid_message( + nu->pntsv, nu->orderv, nu->flagv, nu->type, nu->pntsv > 1, "V", nullptr, 0); } bool BKE_nurb_check_valid_uv(const Nurb *nu) @@ -4767,10 +4771,6 @@ bool BKE_nurb_order_clamp_u(struct Nurb *nu) nu->orderu = max_ii(2, nu->pntsu); changed = true; } - if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) { - CLAMP(nu->orderu, 3, 4); - changed = true; - } return changed; } @@ -4781,10 +4781,6 @@ bool BKE_nurb_order_clamp_v(struct Nurb *nu) nu->orderv = max_ii(2, nu->pntsv); changed = true; } - if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) { - CLAMP(nu->orderv, 3, 4); - changed = true; - } return changed; } diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc index d6525a11cff..191a510947e 100644 --- a/source/blender/blenkernel/intern/curve_eval.cc +++ b/source/blender/blenkernel/intern/curve_eval.cc @@ -203,19 +203,21 @@ static Spline::NormalCalculationMode normal_mode_from_dna_curve(const int twist_ return Spline::NormalCalculationMode::Minimum; } -static NURBSpline::KnotsMode knots_mode_from_dna_nurb(const short flag) +static KnotsMode knots_mode_from_dna_nurb(const short flag) { switch (flag & (CU_NURB_ENDPOINT | CU_NURB_BEZIER)) { case CU_NURB_ENDPOINT: - return NURBSpline::KnotsMode::EndPoint; + return NURBS_KNOT_MODE_ENDPOINT; case CU_NURB_BEZIER: - return NURBSpline::KnotsMode::Bezier; + return NURBS_KNOT_MODE_BEZIER; + case CU_NURB_ENDPOINT | CU_NURB_BEZIER: + return NURBS_KNOT_MODE_ENDPOINT_BEZIER; default: - return NURBSpline::KnotsMode::Normal; + return NURBS_KNOT_MODE_NORMAL; } BLI_assert_unreachable(); - return NURBSpline::KnotsMode::Normal; + return NURBS_KNOT_MODE_NORMAL; } static SplinePtr spline_from_dna_bezier(const Nurb &nurb) @@ -419,8 +421,7 @@ std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves) nurb_spline->resize(point_range.size()); nurb_spline->weights().copy_from(nurbs_weights.slice(point_range)); nurb_spline->set_order(nurbs_orders[curve_index]); - nurb_spline->knots_mode = static_cast<NURBSpline::KnotsMode>( - nurbs_knots_modes[curve_index]); + nurb_spline->knots_mode = static_cast<KnotsMode>(nurbs_knots_modes[curve_index]); spline = std::move(nurb_spline); break; @@ -436,6 +437,8 @@ std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves) curve_eval->add_spline(std::move(spline)); } + curve_eval->attributes.reallocate(curve_eval->splines().size()); + CurveComponentLegacy dst_component; dst_component.replace(curve_eval.get(), GeometryOwnershipType::Editable); diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 3eea579230a..dd91e788e5a 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -84,6 +84,42 @@ CurvesGeometry &CurvesGeometry::operator=(const CurvesGeometry &other) return *this; } +/* The source should be empty, but in a valid state so that using it further will work. */ +static void move_curves_geometry(CurvesGeometry &dst, CurvesGeometry &src) +{ + dst.point_size = src.point_size; + std::swap(dst.point_data, src.point_data); + CustomData_free(&src.point_data, src.point_size); + src.point_size = 0; + + dst.curve_size = src.curve_size; + std::swap(dst.curve_data, dst.curve_data); + CustomData_free(&src.curve_data, src.curve_size); + src.curve_size = 0; + + std::swap(dst.curve_offsets, src.curve_offsets); + MEM_SAFE_FREE(src.curve_offsets); + + std::swap(dst.runtime, src.runtime); + + src.update_customdata_pointers(); + dst.update_customdata_pointers(); +} + +CurvesGeometry::CurvesGeometry(CurvesGeometry &&other) + : CurvesGeometry(other.point_size, other.curve_size) +{ + move_curves_geometry(*this, other); +} + +CurvesGeometry &CurvesGeometry::operator=(CurvesGeometry &&other) +{ + if (this != &other) { + move_curves_geometry(*this, other); + } + return *this; +} + CurvesGeometry::~CurvesGeometry() { CustomData_free(&this->point_data, this->point_size); @@ -124,29 +160,83 @@ int CurvesGeometry::evaluated_points_size() const IndexRange CurvesGeometry::range_for_curve(const int index) const { + BLI_assert(this->curve_size > 0); + BLI_assert(this->curve_offsets != nullptr); const int offset = this->curve_offsets[index]; const int offset_next = this->curve_offsets[index + 1]; return {offset, offset_next - offset}; } -VArray<int8_t> CurvesGeometry::curve_types() const +IndexRange CurvesGeometry::range_for_curves(const IndexRange curves) const +{ + BLI_assert(this->curve_size > 0); + BLI_assert(this->curve_offsets != nullptr); + const int offset = this->curve_offsets[curves.start()]; + const int offset_next = this->curve_offsets[curves.one_after_last()]; + return {offset, offset_next - offset}; +} + +static int domain_size(const CurvesGeometry &curves, const AttributeDomain domain) { - if (const int8_t *data = (const int8_t *)CustomData_get_layer_named( - &this->curve_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str())) { - return VArray<int8_t>::ForSpan({data, this->curve_size}); + return domain == ATTR_DOMAIN_POINT ? curves.points_size() : curves.curves_size(); +} + +static CustomData &domain_custom_data(CurvesGeometry &curves, const AttributeDomain domain) +{ + return domain == ATTR_DOMAIN_POINT ? curves.point_data : curves.curve_data; +} + +static const CustomData &domain_custom_data(const CurvesGeometry &curves, + const AttributeDomain domain) +{ + return domain == ATTR_DOMAIN_POINT ? curves.point_data : curves.curve_data; +} + +template<typename T> +static VArray<T> get_varray_attribute(const CurvesGeometry &curves, + const AttributeDomain domain, + const StringRefNull name, + const T default_value) +{ + const int size = domain_size(curves, domain); + const CustomDataType type = cpp_type_to_custom_data_type(CPPType::get<T>()); + const CustomData &custom_data = domain_custom_data(curves, domain); + + const T *data = (const T *)CustomData_get_layer_named(&custom_data, type, name.c_str()); + if (data != nullptr) { + return VArray<T>::ForSpan(Span<T>(data, size)); + } + return VArray<T>::ForSingle(default_value, size); +} + +template<typename T> +static MutableSpan<T> get_mutable_attribute(CurvesGeometry &curves, + const AttributeDomain domain, + const StringRefNull name) +{ + const int size = domain_size(curves, domain); + const CustomDataType type = cpp_type_to_custom_data_type(CPPType::get<T>()); + CustomData &custom_data = domain_custom_data(curves, domain); + + T *data = (T *)CustomData_duplicate_referenced_layer_named( + &custom_data, type, name.c_str(), size); + if (data != nullptr) { + return {data, size}; } - return VArray<int8_t>::ForSingle(CURVE_TYPE_CATMULL_ROM, this->curve_size); + data = (T *)CustomData_add_layer_named( + &custom_data, type, CD_CALLOC, nullptr, size, name.c_str()); + return {data, size}; +} + +VArray<int8_t> CurvesGeometry::curve_types() const +{ + return get_varray_attribute<int8_t>( + *this, ATTR_DOMAIN_CURVE, ATTR_CURVE_TYPE, CURVE_TYPE_CATMULL_ROM); } MutableSpan<int8_t> CurvesGeometry::curve_types() { - int8_t *data = (int8_t *)CustomData_add_layer_named(&this->curve_data, - CD_PROP_INT8, - CD_CALLOC, - nullptr, - this->curve_size, - ATTR_CURVE_TYPE.c_str()); - return {data, this->curve_size}; + return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_CURVE_TYPE); } MutableSpan<float3> CurvesGeometry::positions() @@ -171,19 +261,12 @@ Span<int> CurvesGeometry::offsets() const VArray<bool> CurvesGeometry::cyclic() const { - const bool *data = (const bool *)CustomData_get_layer_named( - &this->curve_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str()); - if (data != nullptr) { - return VArray<bool>::ForSpan(Span(data, this->curve_size)); - } - return VArray<bool>::ForSingle(false, this->curve_size); + return get_varray_attribute<bool>(*this, ATTR_DOMAIN_CURVE, ATTR_CYCLIC, false); } MutableSpan<bool> CurvesGeometry::cyclic() { - bool *data = (bool *)CustomData_add_layer_named( - &this->curve_data, CD_PROP_BOOL, CD_CALLOC, nullptr, this->curve_size, ATTR_CYCLIC.c_str()); - return {data, this->curve_size}; + return get_mutable_attribute<bool>(*this, ATTR_DOMAIN_CURVE, ATTR_CYCLIC); } void CurvesGeometry::resize(const int point_size, const int curve_size) @@ -269,6 +352,134 @@ void CurvesGeometry::update_customdata_pointers() &this->point_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str()); } +static void *ensure_customdata_layer(CustomData &custom_data, + const StringRefNull name, + const CustomDataType data_type, + const int tot_elements) +{ + for (const int other_layer_i : IndexRange(custom_data.totlayer)) { + CustomDataLayer &new_layer = custom_data.layers[other_layer_i]; + if (name == StringRef(new_layer.name)) { + return new_layer.data; + } + } + return CustomData_add_layer_named( + &custom_data, data_type, CD_DEFAULT, nullptr, tot_elements, name.c_str()); +} + +static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves, + const IndexMask curves_to_delete) +{ + const Span<int> old_offsets = curves.offsets(); + const Vector<IndexRange> old_curve_ranges = curves_to_delete.extract_ranges_invert( + curves.curves_range(), nullptr); + Vector<IndexRange> new_curve_ranges; + Vector<IndexRange> old_point_ranges; + Vector<IndexRange> new_point_ranges; + int new_tot_points = 0; + int new_tot_curves = 0; + for (const IndexRange &curve_range : old_curve_ranges) { + new_curve_ranges.append(IndexRange(new_tot_curves, curve_range.size())); + new_tot_curves += curve_range.size(); + + const IndexRange old_point_range = curves.range_for_curves(curve_range); + old_point_ranges.append(old_point_range); + new_point_ranges.append(IndexRange(new_tot_points, old_point_range.size())); + new_tot_points += old_point_range.size(); + } + + CurvesGeometry new_curves{new_tot_points, new_tot_curves}; + + threading::parallel_invoke( + /* Initialize curve offsets. */ + [&]() { + MutableSpan<int> new_offsets = new_curves.offsets(); + new_offsets.last() = new_tot_points; + threading::parallel_for( + old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) { + for (const int range_i : ranges_range) { + const IndexRange old_curve_range = old_curve_ranges[range_i]; + const IndexRange new_curve_range = new_curve_ranges[range_i]; + const IndexRange old_point_range = old_point_ranges[range_i]; + const IndexRange new_point_range = new_point_ranges[range_i]; + const int offset_shift = new_point_range.start() - old_point_range.start(); + const int curves_in_range = old_curve_range.size(); + threading::parallel_for( + IndexRange(curves_in_range), 512, [&](const IndexRange range) { + for (const int i : range) { + const int old_curve_i = old_curve_range[i]; + const int new_curve_i = new_curve_range[i]; + const int old_offset = old_offsets[old_curve_i]; + const int new_offset = old_offset + offset_shift; + new_offsets[new_curve_i] = new_offset; + } + }); + } + }); + }, + /* Copy over point attributes. */ + [&]() { + const CustomData &old_point_data = curves.point_data; + CustomData &new_point_data = new_curves.point_data; + for (const int layer_i : IndexRange(old_point_data.totlayer)) { + const CustomDataLayer &old_layer = old_point_data.layers[layer_i]; + const CustomDataType data_type = static_cast<CustomDataType>(old_layer.type); + const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type); + + const void *src_buffer = old_layer.data; + void *dst_buffer = ensure_customdata_layer( + new_point_data, old_layer.name, data_type, new_tot_points); + + threading::parallel_for( + old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) { + for (const int range_i : ranges_range) { + const IndexRange old_point_range = old_point_ranges[range_i]; + const IndexRange new_point_range = new_point_ranges[range_i]; + + type.copy_construct_n( + POINTER_OFFSET(src_buffer, type.size() * old_point_range.start()), + POINTER_OFFSET(dst_buffer, type.size() * new_point_range.start()), + old_point_range.size()); + } + }); + } + }, + /* Copy over curve attributes. */ + [&]() { + const CustomData &old_curve_data = curves.curve_data; + CustomData &new_curve_data = new_curves.curve_data; + for (const int layer_i : IndexRange(old_curve_data.totlayer)) { + const CustomDataLayer &old_layer = old_curve_data.layers[layer_i]; + const CustomDataType data_type = static_cast<CustomDataType>(old_layer.type); + const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type); + + const void *src_buffer = old_layer.data; + void *dst_buffer = ensure_customdata_layer( + new_curve_data, old_layer.name, data_type, new_tot_points); + + threading::parallel_for( + old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) { + for (const int range_i : ranges_range) { + const IndexRange old_curve_range = old_curve_ranges[range_i]; + const IndexRange new_curve_range = new_curve_ranges[range_i]; + + type.copy_construct_n( + POINTER_OFFSET(src_buffer, type.size() * old_curve_range.start()), + POINTER_OFFSET(dst_buffer, type.size() * new_curve_range.start()), + old_curve_range.size()); + } + }); + } + }); + + return new_curves; +} + +void CurvesGeometry::remove_curves(const IndexMask curves_to_delete) +{ + *this = copy_with_removed_curves(*this, curves_to_delete); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/curves_geometry_test.cc b/source/blender/blenkernel/intern/curves_geometry_test.cc new file mode 100644 index 00000000000..3a43c0c8102 --- /dev/null +++ b/source/blender/blenkernel/intern/curves_geometry_test.cc @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup bke + */ + +#include "BKE_curves.hh" + +#include "testing/testing.h" + +namespace blender::bke::tests { + +static CurvesGeometry create_basic_curves(const int points_size, const int curves_size) +{ + CurvesGeometry curves(points_size, curves_size); + + const int curve_length = points_size / curves_size; + for (const int i : curves.curves_range()) { + curves.offsets()[i] = points_size * curve_length; + } + curves.offsets().last() = points_size; + + for (const int i : curves.points_range()) { + curves.positions()[i] = {float(i), float(i % curve_length), 0.0f}; + } + + return curves; +} + +TEST(curves_geometry, Empty) +{ + CurvesGeometry empty(0, 0); + empty.cyclic(); + float3 min; + float3 max; + EXPECT_FALSE(empty.bounds_min_max(min, max)); +} + +TEST(curves_geometry, Move) +{ + CurvesGeometry curves = create_basic_curves(100, 10); + + const int *offsets_data = curves.offsets().data(); + const float3 *positions_data = curves.positions().data(); + + CurvesGeometry other = std::move(curves); + + /* The old curves should be empty, and the offsets are expected to be null. */ + EXPECT_EQ(curves.points_size(), 0); /* NOLINT: bugprone-use-after-move */ + EXPECT_EQ(curves.curve_offsets, nullptr); /* NOLINT: bugprone-use-after-move */ + + /* Just a basic check that the new curves work okay. */ + float3 min; + float3 max; + EXPECT_TRUE(other.bounds_min_max(min, max)); + + curves = std::move(other); + + CurvesGeometry second_other(std::move(curves)); + + /* The data should not have been reallocated ever. */ + EXPECT_EQ(second_other.positions().data(), positions_data); + EXPECT_EQ(second_other.offsets().data(), offsets_data); +} + +} // namespace blender::bke::tests diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 4492f8bbc64..b348e18a6a8 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -1450,6 +1450,21 @@ static bool layerValidate_propfloat2(void *data, const uint totitems, const bool return has_errors; } +static void layerInterp_propbool(const void **sources, + const float *weights, + const float *UNUSED(sub_weights), + int count, + void *dest) +{ + bool result = false; + for (int i = 0; i < count; i++) { + const float interp_weight = weights[i]; + const bool src = *(const bool *)sources[i]; + result |= src && (interp_weight > 0.0f); + } + *(bool *)dest = result; +} + static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 0: CD_MVERT */ {sizeof(MVert), "MVert", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, @@ -1838,7 +1853,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { N_("Boolean"), nullptr, nullptr, - nullptr, + layerInterp_propbool, nullptr, nullptr, nullptr, diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 1818e5a9490..5be993ca1f7 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -973,8 +973,8 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map, return ret; } if (cddata_type == CD_FAKE_SHAPEKEY) { - /* TODO: leaving shapekeys aside for now, quite specific case, - * since we can't access them from MVert :/ */ + /* TODO: leaving shape-keys aside for now, quite specific case, + * since we can't access them from #MVert :/ */ return false; } } diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc index a33bca1db57..320124498d5 100644 --- a/source/blender/blenkernel/intern/displist.cc +++ b/source/blender/blenkernel/intern/displist.cc @@ -865,7 +865,7 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph, else { std::unique_ptr<CurveEval> curve_eval = curve_eval_from_dna_curve( *cu, ob->runtime.curve_cache->deformed_nurbs); - geometry_set.replace_curve(curve_eval_to_curves(*curve_eval)); + geometry_set.replace_curves(curve_eval_to_curves(*curve_eval)); } for (; md; md = md->next) { diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 1136ec45fd4..ce07e501897 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -6142,7 +6142,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface, /* generate surface space partitioning grid */ surfaceGenerateGrid(surface); - /* calculate current frame adjacency point distances and global dirs */ + /* Calculate current frame adjacency point distances and global directions. */ dynamicPaint_prepareAdjacencyData(surface, false); /* Copy current frame vertices to check against in next frame */ diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 6f2760e91a6..ca9d758c692 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -1845,8 +1845,8 @@ static void sample_mesh(FluidFlowSettings *ffs, const float surface_distance = 1.732; nearest.dist_sq = surface_distance * surface_distance; /* find_nearest uses squared distance. */ - bool is_gas_flow = (ffs->type == FLUID_FLOW_TYPE_SMOKE || ffs->type == FLUID_FLOW_TYPE_FIRE || - ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE); + bool is_gas_flow = ELEM( + ffs->type, FLUID_FLOW_TYPE_SMOKE, FLUID_FLOW_TYPE_FIRE, FLUID_FLOW_TYPE_SMOKEFIRE); /* Emission strength for gases will be computed below. * For liquids it's not needed. Just set to non zero value @@ -1937,7 +1937,7 @@ static void sample_mesh(FluidFlowSettings *ffs, interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights); - /* Map texure coord between -1.0f and 1.0f. */ + /* Map texture coord between -1.0f and 1.0f. */ tex_co[0] = tex_co[0] * 2.0f - 1.0f; tex_co[1] = tex_co[1] * 2.0f - 1.0f; tex_co[2] = ffs->texture_offset; @@ -2035,8 +2035,7 @@ static void emit_from_mesh_task_cb(void *__restrict userdata, /* Compute emission only for flow objects that produce fluid (i.e. skip outflow objects). * Result in bb->influence. Also computes initial velocities. Result in bb->velocity. */ - if ((data->ffs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY) || - (data->ffs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW)) { + if (ELEM(data->ffs->behavior, FLUID_FLOW_BEHAVIOR_GEOMETRY, FLUID_FLOW_BEHAVIOR_INFLOW)) { sample_mesh(data->ffs, data->mvert, data->vert_normals, @@ -2697,8 +2696,8 @@ static bool escape_flowsobject(Object *flowobj, bool is_static = is_static_object(flowobj); bool liquid_flow = ffs->type == FLUID_FLOW_TYPE_LIQUID; - bool gas_flow = (ffs->type == FLUID_FLOW_TYPE_SMOKE || ffs->type == FLUID_FLOW_TYPE_FIRE || - ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE); + bool gas_flow = ELEM( + ffs->type, FLUID_FLOW_TYPE_SMOKE, FLUID_FLOW_TYPE_FIRE, FLUID_FLOW_TYPE_SMOKEFIRE); bool is_geometry = (ffs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY); bool liquid_domain = fds->type == FLUID_DOMAIN_TYPE_LIQUID; diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc index 5723d110aa0..86cbea9a9bb 100644 --- a/source/blender/blenkernel/intern/geometry_component_curves.cc +++ b/source/blender/blenkernel/intern/geometry_component_curves.cc @@ -467,6 +467,18 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() make_array_write_attribute<int8_t>, tag_component_topology_changed); + static BuiltinCustomDataLayerProvider curve_type("curve_type", + ATTR_DOMAIN_CURVE, + CD_PROP_INT8, + CD_PROP_INT8, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + curve_access, + make_array_read_attribute<int8_t>, + make_array_write_attribute<int8_t>, + tag_component_topology_changed); + static BuiltinCustomDataLayerProvider resolution("resolution", ATTR_DOMAIN_CURVE, CD_PROP_INT32, @@ -504,6 +516,7 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() &handle_type_left, &nurbs_order, &nurbs_weight, + &curve_type, &resolution, &cyclic}, {&curve_custom_data, &point_custom_data}); diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 104166df913..cbd7ec9155a 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -1049,6 +1049,11 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { if (mesh->dvert == nullptr) { return true; } + + /* Copy the data layer if it is shared with some other mesh. */ + mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer( + &mesh->vdata, CD_MDEFORMVERT, mesh->totvert); + for (MDeformVert &dvert : MutableSpan(mesh->dvert, mesh->totvert)) { MDeformWeight *weight = BKE_defvert_find_index(&dvert, index); BKE_defvert_remove_group(&dvert, weight); diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index ca372ba8f38..0eece6e9ad0 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -353,7 +353,7 @@ void GeometrySet::replace_mesh(Mesh *mesh, GeometryOwnershipType ownership) component.replace(mesh, ownership); } -void GeometrySet::replace_curve(Curves *curves, GeometryOwnershipType ownership) +void GeometrySet::replace_curves(Curves *curves, GeometryOwnershipType ownership) { if (curves == nullptr) { this->remove<CurveComponent>(); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 16d43d40c50..92ed273cac8 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -2568,11 +2568,13 @@ void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer, layer_cb(gpl, gpf, NULL, thunk); } - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - if (gps->totpoints == 0) { - continue; + if (stroke_cb) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + if (gps->totpoints == 0) { + continue; + } + stroke_cb(gpl, gpf, gps, thunk); } - stroke_cb(gpl, gpf, gps, thunk); } } /* Draw Active frame on top. */ @@ -2590,12 +2592,13 @@ void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer, gpl->opacity = prev_opacity; continue; } - - LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) { - if (gps->totpoints == 0) { - continue; + if (stroke_cb) { + LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) { + if (gps->totpoints == 0) { + continue; + } + stroke_cb(gpl, act_gpf, gps, thunk); } - stroke_cb(gpl, act_gpf, gps, thunk); } } diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c index ee6b77e6463..20b8342f090 100644 --- a/source/blender/blenkernel/intern/gpencil_curve.c +++ b/source/blender/blenkernel/intern/gpencil_curve.c @@ -50,8 +50,8 @@ static int gpencil_check_same_material_color(Object *ob_gp, const float color_stroke[4], const float color_fill[4], - const bool do_fill, const bool do_stroke, + const bool do_fill, Material **r_mat) { int index = -1; diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index bc3aa88d096..33410b4521e 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -28,6 +28,7 @@ #include "DNA_screen_types.h" #include "BKE_colortools.h" +#include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" @@ -196,9 +197,11 @@ bool BKE_gpencil_has_transform_modifiers(Object *ob) LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) { /* Only if enabled in edit mode. */ if (!GPENCIL_MODIFIER_EDIT(md, true) && GPENCIL_MODIFIER_ACTIVE(md, false)) { - if ((md->type == eGpencilModifierType_Armature) || (md->type == eGpencilModifierType_Hook) || - (md->type == eGpencilModifierType_Lattice) || - (md->type == eGpencilModifierType_Offset)) { + if (ELEM(md->type, + eGpencilModifierType_Armature, + eGpencilModifierType_Hook, + eGpencilModifierType_Lattice, + eGpencilModifierType_Offset)) { return true; } } @@ -618,48 +621,70 @@ static void gpencil_assign_object_eval(Object *object) } } -/* Helper: Copy active frame from original datablock to evaluated datablock for modifiers. */ -static void gpencil_copy_activeframe_to_eval( - Depsgraph *depsgraph, Scene *scene, Object *ob, bGPdata *gpd_orig, bGPdata *gpd_eval) +static bGPdata *gpencil_copy_structure_for_eval(bGPdata *gpd) { + /* Create a temporary copy gpd. */ + ID *newid = NULL; + BKE_libblock_copy_ex(NULL, &gpd->id, &newid, LIB_ID_COPY_LOCALIZE); + bGPdata *gpd_eval = (bGPdata *)newid; + BLI_listbase_clear(&gpd_eval->layers); - bGPDlayer *gpl_eval = gpd_eval->layers.first; - LISTBASE_FOREACH (bGPDlayer *, gpl_orig, &gpd_orig->layers) { - - if (gpl_eval != NULL) { - bGPDframe *gpf_orig = gpl_orig->actframe; + if (gpd->mat != NULL) { + gpd_eval->mat = MEM_dupallocN(gpd->mat); + } - int remap_cfra = gpencil_remap_time_get(depsgraph, scene, ob, gpl_orig); - if ((gpf_orig == NULL) || (gpf_orig && gpf_orig->framenum != remap_cfra)) { - gpf_orig = BKE_gpencil_layer_frame_get(gpl_orig, remap_cfra, GP_GETFRAME_USE_PREV); - } + BKE_defgroup_copy_list(&gpd_eval->vertex_group_names, &gpd->vertex_group_names); - if (gpf_orig != NULL) { - int gpf_index = BLI_findindex(&gpl_orig->frames, gpf_orig); - bGPDframe *gpf_eval = BLI_findlink(&gpl_eval->frames, gpf_index); + /* Duplicate structure: layers and frames without strokes. */ + LISTBASE_FOREACH (bGPDlayer *, gpl_orig, &gpd->layers) { + bGPDlayer *gpl_eval = BKE_gpencil_layer_duplicate(gpl_orig, true, false); + BLI_addtail(&gpd_eval->layers, gpl_eval); + gpl_eval->runtime.gpl_orig = gpl_orig; + /* Update frames orig pointers (helps for faster lookup in copy_frame_to_eval_cb). */ + BKE_gpencil_layer_original_pointers_update(gpl_orig, gpl_eval); + } - if (gpf_eval != NULL) { - /* Delete old strokes. */ - BKE_gpencil_free_strokes(gpf_eval); - /* Copy again strokes. */ - BKE_gpencil_frame_copy_strokes(gpf_orig, gpf_eval); + return gpd_eval; +} - gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig; - BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval); - } - } +static void copy_frame_to_eval_cb(bGPDlayer *UNUSED(gpl), + bGPDframe *gpf, + bGPDstroke *UNUSED(gps), + void *UNUSED(thunk)) +{ + /* Early return when callback is not provided with a frame. */ + if (gpf == NULL) { + return; + } - gpl_eval = gpl_eval->next; - } + /* Free any existing eval stroke data. This happens in case we have a single user on the data + * block and the strokes have not been deleted. */ + if (!BLI_listbase_is_empty(&gpf->strokes)) { + BKE_gpencil_free_strokes(gpf); } + + /* Get original frame. */ + bGPDframe *gpf_orig = gpf->runtime.gpf_orig; + /* Copy strokes to eval frame and update internal orig pointers. */ + BKE_gpencil_frame_copy_strokes(gpf_orig, gpf); + BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf); } -static bGPdata *gpencil_copy_for_eval(bGPdata *gpd) +static void gpencil_copy_visible_frames_to_eval(Depsgraph *depsgraph, Scene *scene, Object *ob) { - const int flags = LIB_ID_COPY_LOCALIZE; + /* Remap layers' active frame with time modifiers applied. */ + bGPdata *gpd_eval = ob->data; + LISTBASE_FOREACH (bGPDlayer *, gpl_eval, &gpd_eval->layers) { + bGPDframe *gpf_eval = gpl_eval->actframe; + int remap_cfra = gpencil_remap_time_get(depsgraph, scene, ob, gpl_eval); + if (gpf_eval == NULL || gpf_eval->framenum != remap_cfra) { + gpl_eval->actframe = BKE_gpencil_layer_frame_get(gpl_eval, remap_cfra, GP_GETFRAME_USE_PREV); + } + } - bGPdata *result = (bGPdata *)BKE_id_copy_ex(NULL, &gpd->id, NULL, flags); - return result; + /* Copy only visible frames to evaluated version. */ + BKE_gpencil_visible_stroke_advanced_iter( + NULL, ob, copy_frame_to_eval_cb, NULL, NULL, true, scene->r.cfra); } void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *ob) @@ -688,7 +713,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o if (ob->runtime.gpd_eval != NULL) { /* Make sure to clear the pointer in case the runtime eval data points to the same data block. * This can happen when the gpencil data block was not tagged for a depsgraph update after last - * call to this function. */ + * call to this function (e.g. a frame change). */ if (gpd_eval == ob->runtime.gpd_eval) { gpd_eval = NULL; } @@ -707,18 +732,19 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o return; } - /* If only one user, don't need a new copy, just update data of the frame. */ - if (gpd_orig->id.us == 1) { - BLI_assert(ob->data != NULL); - gpencil_copy_activeframe_to_eval(depsgraph, scene, ob, ob_orig->data, gpd_eval); - return; + /* If datablock has only one user, we can update its eval data directly. + * Otherwise, we need to have distinct copies for each instance, since applied transformations + * may differ. */ + if (gpd_orig->id.us > 1) { + /* Copy of the original datablock's structure (layers and empty frames). */ + ob->runtime.gpd_eval = gpencil_copy_structure_for_eval(gpd_orig); + /* Overwrite ob->data with gpd_eval here. */ + gpencil_assign_object_eval(ob); } - /* Copy full datablock to evaluated version. */ - ob->runtime.gpd_eval = gpencil_copy_for_eval(gpd_orig); - /* Overwrite ob->data with gpd_eval here. */ - gpencil_assign_object_eval(ob); - BKE_gpencil_update_orig_pointers(ob_orig, ob); + BLI_assert(ob->data != NULL); + /* Only copy strokes from visible frames to evaluated data.*/ + gpencil_copy_visible_frames_to_eval(depsgraph, scene, ob); } void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index d00fc8814e0..7b8dfdc690c 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -903,8 +903,7 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char * break; case IDP_ARRAY: { /* for now, we only support float and int and double arrays */ - if ((val->array.type == IDP_FLOAT) || (val->array.type == IDP_INT) || - (val->array.type == IDP_DOUBLE) || (val->array.type == IDP_GROUP)) { + if (ELEM(val->array.type, IDP_FLOAT, IDP_INT, IDP_DOUBLE, IDP_GROUP)) { prop = MEM_callocN(sizeof(IDProperty), "IDProperty array"); prop->subtype = val->array.type; if (val->array.len) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.cc index 8a212ed0d7d..b4644b84f1e 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.cc @@ -5,18 +5,20 @@ * \ingroup bke */ -#include <ctype.h> +#include <cctype> +#include <cmath> +#include <cstdio> +#include <cstring> #include <fcntl.h> -#include <math.h> -#include <stdio.h> -#include <string.h> #ifndef WIN32 # include <unistd.h> #else # include <io.h> #endif -#include <time.h> +#include <ctime> + +#include "BLI_array.hh" #include "CLG_log.h" @@ -99,39 +101,45 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" +using blender::Array; + static CLG_LogRef LOG = {"bke.image"}; static void image_init(Image *ima, short source, short type); static void image_free_packedfiles(Image *ima); static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src); -/* Reset runtime image fields when data-block is being initialized. */ +/* -------------------------------------------------------------------- */ +/** \name Image #IDTypeInfo API + * \{ */ + +/** Reset runtime image fields when data-block is being initialized. */ static void image_runtime_reset(struct Image *image) { memset(&image->runtime, 0, sizeof(image->runtime)); image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex"); - BLI_mutex_init(image->runtime.cache_mutex); + BLI_mutex_init(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); } -/* Reset runtime image fields when data-block is being copied. */ +/** Reset runtime image fields when data-block is being copied. */ static void image_runtime_reset_on_copy(struct Image *image) { image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex"); - BLI_mutex_init(image->runtime.cache_mutex); + BLI_mutex_init(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); - image->runtime.partial_update_register = NULL; - image->runtime.partial_update_user = NULL; + image->runtime.partial_update_register = nullptr; + image->runtime.partial_update_user = nullptr; } static void image_runtime_free_data(struct Image *image) { - BLI_mutex_end(image->runtime.cache_mutex); + BLI_mutex_end(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); MEM_freeN(image->runtime.cache_mutex); - image->runtime.cache_mutex = NULL; + image->runtime.cache_mutex = nullptr; - if (image->runtime.partial_update_user != NULL) { + if (image->runtime.partial_update_user != nullptr) { BKE_image_partial_update_free(image->runtime.partial_update_user); - image->runtime.partial_update_user = NULL; + image->runtime.partial_update_user = nullptr; } BKE_image_partial_update_register_free(image); } @@ -140,7 +148,7 @@ static void image_init_data(ID *id) { Image *image = (Image *)id; - if (image != NULL) { + if (image != nullptr) { image_init(image, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST); } } @@ -155,16 +163,17 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c copy_image_packedfiles(&image_dst->packedfiles, &image_src->packedfiles); - image_dst->stereo3d_format = MEM_dupallocN(image_src->stereo3d_format); + image_dst->stereo3d_format = static_cast<Stereo3dFormat *>( + MEM_dupallocN(image_src->stereo3d_format)); BLI_duplicatelist(&image_dst->views, &image_src->views); /* Cleanup stuff that cannot be copied. */ - image_dst->cache = NULL; - image_dst->rr = NULL; + image_dst->cache = nullptr; + image_dst->rr = nullptr; BLI_duplicatelist(&image_dst->renderslots, &image_src->renderslots); LISTBASE_FOREACH (RenderSlot *, slot, &image_dst->renderslots) { - slot->render = NULL; + slot->render = nullptr; } BLI_listbase_clear(&image_dst->anims); @@ -174,7 +183,7 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c for (int eye = 0; eye < 2; eye++) { for (int i = 0; i < TEXTARGET_COUNT; i++) { for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) { - image_dst->gputexture[i][eye][resolution] = NULL; + image_dst->gputexture[i][eye][resolution] = nullptr; } } } @@ -183,7 +192,7 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c BKE_previewimg_id_copy(&image_dst->id, &image_src->id); } else { - image_dst->preview = NULL; + image_dst->preview = nullptr; } image_runtime_reset_on_copy(image_dst); @@ -193,7 +202,7 @@ static void image_free_data(ID *id) { Image *image = (Image *)id; - /* Also frees animdata. */ + /* Also frees animations (#Image.anims list). */ BKE_image_free_buffers(image); image_free_packedfiles(image); @@ -201,7 +210,7 @@ static void image_free_data(ID *id) LISTBASE_FOREACH (RenderSlot *, slot, &image->renderslots) { if (slot->render) { RE_FreeRenderResult(slot->render); - slot->render = NULL; + slot->render = nullptr; } } BLI_freelistN(&image->renderslots); @@ -222,21 +231,28 @@ static void image_foreach_cache(ID *id, void *user_data) { Image *image = (Image *)id; - IDCacheKey key = { - .id_session_uuid = id->session_uuid, - .offset_in_ID = offsetof(Image, cache), - .cache_v = image->cache, - }; + IDCacheKey key; + key.id_session_uuid = id->session_uuid; + key.offset_in_ID = offsetof(Image, cache); + key.cache_v = image->cache; function_callback(id, &key, (void **)&image->cache, 0, user_data); + auto gputexture_offset = [image](int target, int eye, int resolution) { + constexpr size_t base_offset = offsetof(Image, gputexture); + const auto first = &image->gputexture[0][0][0]; + const size_t array_offset = sizeof(*first) * + (&image->gputexture[target][eye][resolution] - first); + return base_offset + array_offset; + }; + for (int eye = 0; eye < 2; eye++) { for (int a = 0; a < TEXTARGET_COUNT; a++) { for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) { GPUTexture *texture = image->gputexture[a][eye][resolution]; - if (texture == NULL) { + if (texture == nullptr) { continue; } - key.offset_in_ID = offsetof(Image, gputexture[a][eye][resolution]); + key.offset_in_ID = gputexture_offset(a, eye, resolution); key.cache_v = texture; function_callback(id, &key, (void **)&image->gputexture[a][eye][resolution], 0, user_data); } @@ -302,7 +318,7 @@ static void image_foreach_path(ID *id, BPathForeachPathData *bpath_data) if (!BKE_image_has_packedfile(ima) && /* Image may have been painted onto (and not saved, T44543). */ !BKE_image_is_dirty(ima)) { - BKE_image_signal(bpath_data->bmain, ima, NULL, IMA_SIGNAL_RELOAD); + BKE_image_signal(bpath_data->bmain, ima, nullptr, IMA_SIGNAL_RELOAD); } } } @@ -316,22 +332,22 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres /* Clear all data that isn't read to reduce false detection of changed image during memfile undo. */ ima->lastused = 0; - ima->cache = NULL; + ima->cache = nullptr; ima->gpuflag = 0; BLI_listbase_clear(&ima->anims); - ima->runtime.partial_update_register = NULL; - ima->runtime.partial_update_user = NULL; + ima->runtime.partial_update_register = nullptr; + ima->runtime.partial_update_user = nullptr; for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) { - ima->gputexture[i][j][resolution] = NULL; + ima->gputexture[i][j][resolution] = nullptr; } } } ImagePackedFile *imapf; - BLI_assert(ima->packedfile == NULL); + BLI_assert(ima->packedfile == nullptr); if (!is_undo) { /* Do not store packed files in case this is a library override ID. */ if (ID_IS_OVERRIDE_LIBRARY(ima)) { @@ -339,8 +355,8 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres } else { /* Some trickery to keep forward compatibility of packed images. */ - if (ima->packedfiles.first != NULL) { - imapf = ima->packedfiles.first; + if (ima->packedfiles.first != nullptr) { + imapf = static_cast<ImagePackedFile *>(ima->packedfiles.first); ima->packedfile = imapf->packedfile; } } @@ -350,7 +366,8 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres BLO_write_id_struct(writer, Image, id_address, &ima->id); BKE_id_blend_write(writer, &ima->id); - for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { + for (imapf = static_cast<ImagePackedFile *>(ima->packedfiles.first); imapf; + imapf = imapf->next) { BLO_write_struct(writer, ImagePackedFile, imapf); BKE_packedfile_blend_write(writer, imapf->packedfile); } @@ -364,7 +381,7 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres BLO_write_struct_list(writer, ImageTile, &ima->tiles); - ima->packedfile = NULL; + ima->packedfile = nullptr; BLO_write_struct_list(writer, RenderSlot, &ima->renderslots); } @@ -387,7 +404,7 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id) LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) { BKE_packedfile_blend_read(reader, &imapf->packedfile); } - ima->packedfile = NULL; + ima->packedfile = nullptr; } else { BKE_packedfile_blend_read(reader, &ima->packedfile); @@ -407,44 +424,48 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id) static void image_blend_read_lib(BlendLibReader *UNUSED(reader), ID *id) { Image *ima = (Image *)id; - /* Images have some kind of 'main' cache, when NULL we should also clear all others. */ + /* Images have some kind of 'main' cache, when null we should also clear all others. */ /* Needs to be done *after* cache pointers are restored (call to * `foreach_cache`/`blo_cache_storage_entry_restore_in_new`), easier for now to do it in * lib_link... */ - if (ima->cache == NULL) { + if (ima->cache == nullptr) { BKE_image_free_buffers(ima); } } -IDTypeInfo IDType_ID_IM = { - .id_code = ID_IM, - .id_filter = FILTER_ID_IM, - .main_listbase_index = INDEX_ID_IM, - .struct_size = sizeof(Image), - .name = "Image", - .name_plural = "images", - .translation_context = BLT_I18NCONTEXT_ID_IMAGE, - .flags = IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE, - .asset_type_info = NULL, +constexpr IDTypeInfo get_type_info() +{ + IDTypeInfo info{}; + info.id_code = ID_IM; + info.id_filter = FILTER_ID_IM; + info.main_listbase_index = INDEX_ID_IM; + info.struct_size = sizeof(Image); + info.name = "Image"; + info.name_plural = "images"; + info.translation_context = BLT_I18NCONTEXT_ID_IMAGE; + info.flags = IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE; + info.asset_type_info = nullptr; - .init_data = image_init_data, - .copy_data = image_copy_data, - .free_data = image_free_data, - .make_local = NULL, - .foreach_id = NULL, - .foreach_cache = image_foreach_cache, - .foreach_path = image_foreach_path, - .owner_get = NULL, + info.init_data = image_init_data; + info.copy_data = image_copy_data; + info.free_data = image_free_data; + info.make_local = nullptr; + info.foreach_id = nullptr; + info.foreach_cache = image_foreach_cache; + info.foreach_path = image_foreach_path; + info.owner_get = nullptr; - .blend_write = image_blend_write, - .blend_read_data = image_blend_read_data, - .blend_read_lib = image_blend_read_lib, - .blend_read_expand = NULL, + info.blend_write = image_blend_write; + info.blend_read_data = image_blend_read_data; + info.blend_read_lib = image_blend_read_lib; + info.blend_read_expand = nullptr; - .blend_read_undo_preserve = NULL, + info.blend_read_undo_preserve = nullptr; - .lib_override_apply_post = NULL, -}; + info.lib_override_apply_post = nullptr; + return info; +} +IDTypeInfo IDType_ID_IM = get_type_info(); /* prototypes */ static int image_num_files(struct Image *ima); @@ -462,7 +483,11 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat # define IMA_INDEX_PASS(index) (index & ~1023) #endif -/* ******** IMAGE CACHE ************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Image Cache + * \{ */ typedef struct ImageCacheKey { int index; @@ -470,21 +495,21 @@ typedef struct ImageCacheKey { static unsigned int imagecache_hashhash(const void *key_v) { - const ImageCacheKey *key = key_v; + const ImageCacheKey *key = static_cast<const ImageCacheKey *>(key_v); return key->index; } static bool imagecache_hashcmp(const void *a_v, const void *b_v) { - const ImageCacheKey *a = a_v; - const ImageCacheKey *b = b_v; + const ImageCacheKey *a = static_cast<const ImageCacheKey *>(a_v); + const ImageCacheKey *b = static_cast<const ImageCacheKey *>(b_v); return (a->index != b->index); } static void imagecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags) { - ImageCacheKey *key = userkey; + ImageCacheKey *key = static_cast<ImageCacheKey *>(userkey); *framenr = IMA_INDEX_ENTRY(key->index); *proxy = IMB_PROXY_NONE; @@ -495,7 +520,7 @@ static void imagecache_put(Image *image, int index, ImBuf *ibuf) { ImageCacheKey key; - if (image->cache == NULL) { + if (image->cache == nullptr) { // char cache_name[64]; // SNPRINTF(cache_name, "Image Datablock %s", image->id.name); @@ -511,7 +536,7 @@ static void imagecache_put(Image *image, int index, ImBuf *ibuf) static void imagecache_remove(Image *image, int index) { - if (image->cache == NULL) { + if (image->cache == nullptr) { return; } @@ -528,23 +553,27 @@ static struct ImBuf *imagecache_get(Image *image, int index, bool *r_is_cached_e return IMB_moviecache_get(image->cache, &key, r_is_cached_empty); } - return NULL; + return nullptr; } -/* ***************** ALLOC & FREE, DATA MANAGING *************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Allocate & Free, Data Managing + * \{ */ static void image_free_cached_frames(Image *image) { if (image->cache) { IMB_moviecache_free(image->cache); - image->cache = NULL; + image->cache = nullptr; } } static void image_free_packedfiles(Image *ima) { while (ima->packedfiles.last) { - ImagePackedFile *imapf = ima->packedfiles.last; + ImagePackedFile *imapf = static_cast<ImagePackedFile *>(ima->packedfiles.last); if (imapf->packedfile) { BKE_packedfile_free(imapf->packedfile); } @@ -566,10 +595,10 @@ void BKE_image_free_views(Image *image) static void image_free_anims(Image *ima) { while (ima->anims.last) { - ImageAnim *ia = ima->anims.last; + ImageAnim *ia = static_cast<ImageAnim *>(ima->anims.last); if (ia->anim) { IMB_free_anim(ia->anim); - ia->anim = NULL; + ia->anim = nullptr; } BLI_remlink(&ima->anims, ia); MEM_freeN(ia); @@ -579,7 +608,7 @@ static void image_free_anims(Image *ima) void BKE_image_free_buffers_ex(Image *ima, bool do_lock) { if (do_lock) { - BLI_mutex_lock(ima->runtime.cache_mutex); + BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); } image_free_cached_frames(ima); @@ -587,13 +616,13 @@ void BKE_image_free_buffers_ex(Image *ima, bool do_lock) if (ima->rr) { RE_FreeRenderResult(ima->rr); - ima->rr = NULL; + ima->rr = nullptr; } BKE_image_free_gputextures(ima); if (do_lock) { - BLI_mutex_unlock(ima->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); } } @@ -621,27 +650,27 @@ static void image_init(Image *ima, short source, short type) ima->flag |= IMA_VIEW_AS_RENDER; } - ImageTile *tile = MEM_callocN(sizeof(ImageTile), "Image Tiles"); + ImageTile *tile = MEM_cnew<ImageTile>("Image Tiles"); tile->tile_number = 1001; BLI_addtail(&ima->tiles, tile); if (type == IMA_TYPE_R_RESULT) { for (int i = 0; i < 8; i++) { - BKE_image_add_renderslot(ima, NULL); + BKE_image_add_renderslot(ima, nullptr); } } image_runtime_reset(ima); BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings); - ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo Format"); + ima->stereo3d_format = MEM_cnew<Stereo3dFormat>("Image Stereo Format"); } static Image *image_alloc(Main *bmain, const char *name, short source, short type) { Image *ima; - ima = BKE_libblock_alloc(bmain, ID_IM, name, 0); + ima = static_cast<Image *>(BKE_libblock_alloc(bmain, ID_IM, name, 0)); if (ima) { image_init(ima, source, type); } @@ -649,12 +678,12 @@ static Image *image_alloc(Main *bmain, const char *name, short source, short typ return ima; } -/* Get the ibuf from an image cache by its index and entry. +/** + * Get the ibuf from an image cache by its index and entry. * Local use here only. * - * Returns referenced image buffer if it exists, callee is to - * call IMB_freeImBuf to de-reference the image buffer after - * it's done handling it. + * \returns referenced image buffer if it exists, callee is to call #IMB_freeImBuf + * to de-reference the image buffer after it's done handling it. */ static ImBuf *image_get_cached_ibuf_for_index_entry(Image *ima, int index, @@ -690,8 +719,10 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src) const ImagePackedFile *imapf_src; BLI_listbase_clear(lb_dst); - for (imapf_src = lb_src->first; imapf_src; imapf_src = imapf_src->next) { - ImagePackedFile *imapf_dst = MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)"); + for (imapf_src = static_cast<const ImagePackedFile *>(lb_src->first); imapf_src; + imapf_src = imapf_src->next) { + ImagePackedFile *imapf_dst = static_cast<ImagePackedFile *>( + MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)")); STRNCPY(imapf_dst->filepath, imapf_src->filepath); if (imapf_src->packedfile) { @@ -706,23 +737,23 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source) { /* sanity check */ if (dest && source && dest != source) { - BLI_mutex_lock(source->runtime.cache_mutex); - BLI_mutex_lock(dest->runtime.cache_mutex); + BLI_mutex_lock(static_cast<ThreadMutex *>(source->runtime.cache_mutex)); + BLI_mutex_lock(static_cast<ThreadMutex *>(dest->runtime.cache_mutex)); - if (source->cache != NULL) { + if (source->cache != nullptr) { struct MovieCacheIter *iter; iter = IMB_moviecacheIter_new(source->cache); while (!IMB_moviecacheIter_done(iter)) { ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter); - ImageCacheKey *key = IMB_moviecacheIter_getUserKey(iter); + ImageCacheKey *key = static_cast<ImageCacheKey *>(IMB_moviecacheIter_getUserKey(iter)); imagecache_put(dest, key->index, ibuf); IMB_moviecacheIter_step(iter); } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(dest->runtime.cache_mutex); - BLI_mutex_unlock(source->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(dest->runtime.cache_mutex)); + BLI_mutex_unlock(static_cast<ThreadMutex *>(source->runtime.cache_mutex)); BKE_id_free(bmain, source); } @@ -736,7 +767,7 @@ bool BKE_image_scale(Image *image, int width, int height) ImBuf *ibuf; void *lock; - ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); + ibuf = BKE_image_acquire_ibuf(image, nullptr, &lock); if (ibuf) { IMB_scaleImBuf(ibuf, width, height); @@ -745,7 +776,7 @@ bool BKE_image_scale(Image *image, int width, int height) BKE_image_release_ibuf(image, ibuf, lock); - return (ibuf != NULL); + return (ibuf != nullptr); } bool BKE_image_has_opengl_texture(Image *ima) @@ -753,7 +784,7 @@ bool BKE_image_has_opengl_texture(Image *ima) for (int eye = 0; eye < 2; eye++) { for (int i = 0; i < TEXTARGET_COUNT; i++) { for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) { - if (ima->gputexture[i][eye][resolution] != NULL) { + if (ima->gputexture[i][eye][resolution] != nullptr) { return true; } } @@ -764,26 +795,26 @@ bool BKE_image_has_opengl_texture(Image *ima) static int image_get_tile_number_from_iuser(Image *ima, const ImageUser *iuser) { - BLI_assert(ima != NULL && ima->tiles.first); - ImageTile *tile = ima->tiles.first; + BLI_assert(ima != nullptr && ima->tiles.first); + ImageTile *tile = static_cast<ImageTile *>(ima->tiles.first); return (iuser && iuser->tile) ? iuser->tile : tile->tile_number; } ImageTile *BKE_image_get_tile(Image *ima, int tile_number) { - if (ima == NULL) { - return NULL; + if (ima == nullptr) { + return nullptr; } /* Tiles 0 and 1001 are a special case and refer to the first tile, typically * coming from non-UDIM-aware code. */ if (ELEM(tile_number, 0, 1001)) { - return ima->tiles.first; + return static_cast<ImageTile *>(ima->tiles.first); } /* Must have a tiled image and a valid tile number at this point. */ if (ima->source != IMA_SRC_TILED || tile_number < 1001 || tile_number > IMA_UDIM_MAX) { - return NULL; + return nullptr; } LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { @@ -792,7 +823,7 @@ ImageTile *BKE_image_get_tile(Image *ima, int tile_number) } } - return NULL; + return nullptr; } ImageTile *BKE_image_get_tile_from_iuser(Image *ima, const ImageUser *iuser) @@ -806,7 +837,7 @@ int BKE_image_get_tile_from_pos(struct Image *ima, float r_ofs[2]) { float local_ofs[2]; - if (r_ofs == NULL) { + if (r_ofs == nullptr) { r_ofs = local_ofs; } @@ -821,7 +852,7 @@ int BKE_image_get_tile_from_pos(struct Image *ima, int iy = (int)uv[1]; int tile_number = 1001 + 10 * iy + ix; - if (BKE_image_get_tile(ima, tile_number) == NULL) { + if (BKE_image_get_tile(ima, tile_number) == nullptr) { return 0; } r_ofs[0] = ix; @@ -841,7 +872,8 @@ int BKE_image_find_nearest_tile(const Image *image, const float co[2]) LISTBASE_FOREACH (const ImageTile *, tile, &image->tiles) { const int tile_index = tile->tile_number - 1001; /* Coordinates of the current tile. */ - const float tile_index_co[2] = {tile_index % 10, tile_index / 10}; + const float tile_index_co[2] = {static_cast<float>(tile_index % 10), + static_cast<float>(tile_index / 10)}; if (equals_v2v2(co_floor, tile_index_co)) { return tile->tile_number; @@ -864,7 +896,7 @@ static void image_init_color_management(Image *ima) ImBuf *ibuf; char name[FILE_MAX]; - BKE_image_user_file_path(NULL, ima, name); + BKE_image_user_file_path(nullptr, ima, name); /* will set input color space to image format default's */ ibuf = IMB_loadiffname(name, IB_test | IB_alphamode_detect, ima->colorspace_settings.name); @@ -889,7 +921,7 @@ static void image_init_color_management(Image *ima) char BKE_image_alpha_mode_from_extension_ex(const char *filepath) { - if (BLI_path_extension_check_n(filepath, ".exr", ".cin", ".dpx", ".hdr", NULL)) { + if (BLI_path_extension_check_n(filepath, ".exr", ".cin", ".dpx", ".hdr", nullptr)) { return IMA_ALPHA_PREMUL; } @@ -914,7 +946,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath) file = BLI_open(str, O_BINARY | O_RDONLY, 0); if (file == -1) { if (!BKE_image_tile_filepath_exists(str)) { - return NULL; + return nullptr; } } else { @@ -942,7 +974,8 @@ Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exist BLI_path_abs(str, bmain->filepath); /* first search an identical filepath */ - for (ima = bmain->images.first; ima; ima = ima->id.next) { + for (ima = static_cast<Image *>(bmain->images.first); ima; + ima = static_cast<Image *>(ima->id.next)) { if (!ELEM(ima->source, IMA_SRC_VIEWER, IMA_SRC_GENERATED)) { STRNCPY(strtest, ima->filepath); BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &ima->id)); @@ -967,21 +1000,21 @@ Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exist Image *BKE_image_load_exists(Main *bmain, const char *filepath) { - return BKE_image_load_exists_ex(bmain, filepath, NULL); + return BKE_image_load_exists_ex(bmain, filepath, nullptr); } -typedef struct ImageFillData { +struct ImageFillData { short gen_type; uint width; uint height; unsigned char *rect; float *rect_float; float fill_color[4]; -} ImageFillData; +}; static void image_buf_fill_isolated(void *usersata_v) { - ImageFillData *usersata = usersata_v; + ImageFillData *usersata = static_cast<ImageFillData *>(usersata_v); const short gen_type = usersata->gen_type; const uint width = usersata->width; @@ -1013,8 +1046,8 @@ static ImBuf *add_ibuf_size(unsigned int width, ColorManagedColorspaceSettings *colorspace_settings) { ImBuf *ibuf; - unsigned char *rect = NULL; - float *rect_float = NULL; + unsigned char *rect = nullptr; + float *rect_float = nullptr; float fill_color[4]; if (floatbuf) { @@ -1027,7 +1060,7 @@ static ImBuf *add_ibuf_size(unsigned int width, STRNCPY(colorspace_settings->name, colorspace); } - if (ibuf != NULL) { + if (ibuf != nullptr) { rect_float = ibuf->rect_float; IMB_colormanagement_check_is_data(ibuf, colorspace_settings->name); } @@ -1051,7 +1084,7 @@ static ImBuf *add_ibuf_size(unsigned int width, STRNCPY(colorspace_settings->name, colorspace); } - if (ibuf != NULL) { + if (ibuf != nullptr) { rect = (unsigned char *)ibuf->rect; IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace_settings->name); } @@ -1060,7 +1093,7 @@ static ImBuf *add_ibuf_size(unsigned int width, } if (!ibuf) { - return NULL; + return nullptr; } STRNCPY(ibuf->name, name); @@ -1099,14 +1132,15 @@ Image *BKE_image_add_generated(Main *bmain, else { ima = image_alloc(bmain, name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST); } - if (ima == NULL) { - return NULL; + if (ima == nullptr) { + return nullptr; } int view_id; const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; - // STRNCPY(ima->filepath, name); /* don't do this, this writes in ain invalid filepath! */ + /* NOTE: leave `ima->filepath` unset, + * setting it to a dummy value may write to an invalid file-path. */ ima->gen_x = width; ima->gen_y = height; ima->gen_type = gen_type; @@ -1144,7 +1178,7 @@ Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name) /* on save, type is changed to FILE in editsima.c */ Image *ima; - if (name == NULL) { + if (name == nullptr) { name = BLI_path_basename(ibuf->name); } @@ -1158,14 +1192,14 @@ Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name) return ima; } -/* Pack image buffer to memory as PNG or EXR. */ +/** Pack image buffer to memory as PNG or EXR. */ static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath) { ibuf->ftype = (ibuf->rect_float) ? IMB_FTYPE_OPENEXR : IMB_FTYPE_PNG; IMB_saveiff(ibuf, filepath, IB_rect | IB_mem); - if (ibuf->encodedbuffer == NULL) { + if (ibuf->encodedbuffer == nullptr) { CLOG_STR_ERROR(&LOG, "memory save for pack error"); IMB_freeImBuf(ibuf); image_free_packedfiles(ima); @@ -1173,17 +1207,17 @@ static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath } ImagePackedFile *imapf; - PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile"); + PackedFile *pf = MEM_cnew<PackedFile>("PackedFile"); pf->data = ibuf->encodedbuffer; pf->size = ibuf->encodedsize; - imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile"); + imapf = static_cast<ImagePackedFile *>(MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile")); STRNCPY(imapf->filepath, filepath); imapf->packedfile = pf; BLI_addtail(&ima->packedfiles, imapf); - ibuf->encodedbuffer = NULL; + ibuf->encodedbuffer = nullptr; ibuf->encodedsize = 0; ibuf->userflags &= ~IB_BITMAPDIRTY; @@ -1201,8 +1235,9 @@ bool BKE_image_memorypack(Image *ima) ImageView *iv; int i; - for (i = 0, iv = ima->views.first; iv; iv = iv->next, i++) { - ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, 0, NULL); + for (i = 0, iv = static_cast<ImageView *>(ima->views.first); iv; + iv = static_cast<ImageView *>(iv->next), i++) { + ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, 0, nullptr); if (!ibuf) { ok = false; @@ -1222,7 +1257,7 @@ bool BKE_image_memorypack(Image *ima) ima->views_format = R_IMF_VIEWS_INDIVIDUAL; } else { - ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, NULL); + ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr); if (ibuf) { ok = ok && image_memorypack_imbuf(ima, ibuf, ibuf->name); @@ -1246,7 +1281,8 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath) const int totfiles = image_num_files(ima); if (totfiles == 1) { - ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"); + ImagePackedFile *imapf = static_cast<ImagePackedFile *>( + MEM_mallocN(sizeof(ImagePackedFile), "Image packed file")); BLI_addtail(&ima->packedfiles, imapf); imapf->packedfile = BKE_packedfile_new(reports, ima->filepath, basepath); if (imapf->packedfile) { @@ -1257,9 +1293,9 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath) } } else { - ImageView *iv; - for (iv = ima->views.first; iv; iv = iv->next) { - ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"); + for (ImageView *iv = static_cast<ImageView *>(ima->views.first); iv; iv = iv->next) { + ImagePackedFile *imapf = static_cast<ImagePackedFile *>( + MEM_mallocN(sizeof(ImagePackedFile), "Image packed file")); BLI_addtail(&ima->packedfiles, imapf); imapf->packedfile = BKE_packedfile_new(reports, iv->filepath, basepath); @@ -1284,7 +1320,8 @@ void BKE_image_packfiles_from_mem(ReportList *reports, BKE_report(reports, RPT_ERROR, "Cannot pack multiview images from raw data currently..."); } else { - ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), __func__); + ImagePackedFile *imapf = static_cast<ImagePackedFile *>( + MEM_mallocN(sizeof(ImagePackedFile), __func__)); BLI_addtail(&ima->packedfiles, imapf); imapf->packedfile = BKE_packedfile_new_from_memory(data, data_len); STRNCPY(imapf->filepath, ima->filepath); @@ -1305,15 +1342,15 @@ static uintptr_t image_mem_size(Image *image) return 0; } - BLI_mutex_lock(image->runtime.cache_mutex); + BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); - if (image->cache != NULL) { + if (image->cache != nullptr) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); while (!IMB_moviecacheIter_done(iter)) { ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter); IMB_moviecacheIter_step(iter); - if (ibuf == NULL) { + if (ibuf == nullptr) { continue; } ImBuf *ibufm; @@ -1341,7 +1378,7 @@ static uintptr_t image_mem_size(Image *image) IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); return size; } @@ -1351,13 +1388,15 @@ void BKE_image_print_memlist(Main *bmain) Image *ima; uintptr_t size, totsize = 0; - for (ima = bmain->images.first; ima; ima = ima->id.next) { + for (ima = static_cast<Image *>(bmain->images.first); ima; + ima = static_cast<Image *>(ima->id.next)) { totsize += image_mem_size(ima); } printf("\ntotal image memory len: %.3f MB\n", (double)totsize / (double)(1024 * 1024)); - for (ima = bmain->images.first; ima; ima = ima->id.next) { + for (ima = static_cast<Image *>(bmain->images.first); ima; + ima = static_cast<Image *>(ima->id.next)) { size = image_mem_size(ima); if (size) { @@ -1368,7 +1407,7 @@ void BKE_image_print_memlist(Main *bmain) static bool imagecache_check_dirty(ImBuf *ibuf, void *UNUSED(userkey), void *UNUSED(userdata)) { - if (ibuf == NULL) { + if (ibuf == nullptr) { return false; } return (ibuf->userflags & IB_BITMAPDIRTY) == 0; @@ -1384,23 +1423,26 @@ void BKE_image_free_all_textures(Main *bmain) uintptr_t tot_freed_size = 0; #endif - for (ima = bmain->images.first; ima; ima = ima->id.next) { + for (ima = static_cast<Image *>(bmain->images.first); ima; + ima = static_cast<Image *>(ima->id.next)) { ima->id.tag &= ~LIB_TAG_DOIT; } - for (tex = bmain->textures.first; tex; tex = tex->id.next) { + for (tex = static_cast<Tex *>(bmain->textures.first); tex; + tex = static_cast<Tex *>(tex->id.next)) { if (tex->ima) { tex->ima->id.tag |= LIB_TAG_DOIT; } } - for (ima = bmain->images.first; ima; ima = ima->id.next) { + for (ima = static_cast<Image *>(bmain->images.first); ima; + ima = static_cast<Image *>(ima->id.next)) { if (ima->cache && (ima->id.tag & LIB_TAG_DOIT)) { #ifdef CHECK_FREED_SIZE uintptr_t old_size = image_mem_size(ima); #endif - IMB_moviecache_cleanup(ima->cache, imagecache_check_dirty, NULL); + IMB_moviecache_cleanup(ima->cache, imagecache_check_dirty, nullptr); #ifdef CHECK_FREED_SIZE tot_freed_size += old_size - image_mem_size(ima); @@ -1414,7 +1456,7 @@ void BKE_image_free_all_textures(Main *bmain) static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void *userdata) { - if (ibuf == NULL) { + if (ibuf == nullptr) { return true; } int except_frame = *(int *)userdata; @@ -1424,25 +1466,30 @@ static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void void BKE_image_free_anim_ibufs(Image *ima, int except_frame) { - BLI_mutex_lock(ima->runtime.cache_mutex); - if (ima->cache != NULL) { + BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); + if (ima->cache != nullptr) { IMB_moviecache_cleanup(ima->cache, imagecache_check_free_anim, &except_frame); } - BLI_mutex_unlock(ima->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); } void BKE_image_all_free_anim_ibufs(Main *bmain, int cfra) { Image *ima; - for (ima = bmain->images.first; ima; ima = ima->id.next) { + for (ima = static_cast<Image *>(bmain->images.first); ima; + ima = static_cast<Image *>(ima->id.next)) { if (BKE_image_is_animated(ima)) { BKE_image_free_anim_ibufs(ima, cfra); } } } -/* *********** READ AND WRITE ************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Read and Write + * \{ */ int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options) { @@ -1577,7 +1624,7 @@ bool BKE_imtype_supports_zbuf(const char imtype) { switch (imtype) { case R_IMF_IMTYPE_IRIZ: - case R_IMF_IMTYPE_OPENEXR: /* but not R_IMF_IMTYPE_MULTILAYER */ + case R_IMF_IMTYPE_OPENEXR: /* But not #R_IMF_IMTYPE_MULTILAYER. */ return true; } return false; @@ -1765,7 +1812,7 @@ static bool do_add_image_extension(char *string, const char imtype, const ImageFormatData *im_format) { - const char *extension = NULL; + const char *extension = nullptr; const char *extension_test; (void)im_format; /* may be unused, depends on build options */ @@ -1815,7 +1862,7 @@ static bool do_add_image_extension(char *string, } #ifdef WITH_TIFF else if (imtype == R_IMF_IMTYPE_TIFF) { - if (!BLI_path_extension_check_n(string, extension_test = ".tif", ".tiff", NULL)) { + if (!BLI_path_extension_check_n(string, extension_test = ".tif", ".tiff", nullptr)) { extension = extension_test; } } @@ -1871,7 +1918,7 @@ static bool do_add_image_extension(char *string, } #endif else { // R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90 etc - if (!(BLI_path_extension_check_n(string, extension_test = ".jpg", ".jpeg", NULL))) { + if (!(BLI_path_extension_check_n(string, extension_test = ".jpg", ".jpeg", nullptr))) { extension = extension_test; } } @@ -1896,7 +1943,7 @@ int BKE_image_path_ensure_ext_from_imformat(char *string, const ImageFormatData int BKE_image_path_ensure_ext_from_imtype(char *string, const char imtype) { - return do_add_image_extension(string, imtype, NULL); + return do_add_image_extension(string, imtype, nullptr); } void BKE_imformat_defaults(ImageFormatData *im_format) @@ -2048,15 +2095,15 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i #define STAMP_NAME_SIZE ((MAX_ID_NAME - 2) + 16) /* could allow access externally - 512 is for long names, * STAMP_NAME_SIZE is for id names, allowing them some room for description */ -typedef struct StampDataCustomField { +struct StampDataCustomField { struct StampDataCustomField *next, *prev; /* TODO(sergey): Think of better size here, maybe dynamically allocated even. */ char key[512]; char *value; /* TODO(sergey): Support non-string values. */ -} StampDataCustomField; +}; -typedef struct StampData { +struct StampData { char file[512]; char note[512]; char date[512]; @@ -2078,7 +2125,7 @@ typedef struct StampData { * NOTE: This fields are not stamped onto the image. At least for now. */ ListBase custom_fields; -} StampData; +}; #undef STAMP_NAME_SIZE /** @@ -2111,7 +2158,7 @@ static void stampdata( } if (scene->r.stamp & R_STAMP_DATE) { - t = time(NULL); + t = time(nullptr); tl = localtime(&t); SNPRINTF(text, "%04d/%02d/%02d %02d:%02d:%02d", @@ -2226,7 +2273,7 @@ static void stampdata( { Render *re = RE_GetSceneRender(scene); - RenderStats *stats = re ? RE_GetStats(re) : NULL; + RenderStats *stats = re ? RE_GetStats(re) : nullptr; if (use_dynamic && stats && (scene->r.stamp & R_STAMP_RENDERTIME)) { BLI_timecode_string_from_time_simple(text, sizeof(text), stats->lastframetime); @@ -2399,7 +2446,7 @@ void BKE_image_stamp_buf(Scene *scene, display = IMB_colormanagement_display_get_named(display_device); bool do_prefix = (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0; - if (stamp_data_template == NULL) { + if (stamp_data_template == nullptr) { stampdata(scene, camera, &stamp_data, do_prefix, true); } else { @@ -2717,7 +2764,7 @@ void BKE_image_stamp_buf(Scene *scene, } /* cleanup the buffer. */ - BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL); + BLF_buffer(mono, nullptr, nullptr, 0, 0, 0, nullptr); BLF_wordwrap(mono, 0); #undef TEXT_SIZE_CHECK @@ -2738,7 +2785,7 @@ void BKE_render_result_stamp_info(Scene *scene, } if (!rr->stamp_data) { - stamp_data = MEM_callocN(sizeof(StampData), "RenderResult.stamp_data"); + stamp_data = MEM_cnew<StampData>("RenderResult.stamp_data"); } else { stamp_data = rr->stamp_data; @@ -2758,13 +2805,13 @@ struct StampData *BKE_stamp_info_from_scene_static(const Scene *scene) struct StampData *stamp_data; if (!(scene && (scene->r.stamp & R_STAMP_ALL))) { - return NULL; + return nullptr; } /* Memory is allocated here (instead of by the caller) so that the caller * doesn't have to know the size of the StampData struct. */ - stamp_data = MEM_callocN(sizeof(StampData), __func__); - stampdata(scene, NULL, stamp_data, 0, false); + stamp_data = MEM_cnew<StampData>(__func__); + stampdata(scene, nullptr, stamp_data, 0, false); return stamp_data; } @@ -2784,13 +2831,13 @@ static const char *stamp_metadata_fields[] = { "RenderTime", "Memory", "Hostname", - NULL, + nullptr, }; bool BKE_stamp_is_known_field(const char *field_name) { int i = 0; - while (stamp_metadata_fields[i] != NULL) { + while (stamp_metadata_fields[i] != nullptr) { if (STREQ(field_name, stamp_metadata_fields[i])) { return true; } @@ -2804,7 +2851,7 @@ void BKE_stamp_info_callback(void *data, StampCallback callback, bool noskip) { - if ((callback == NULL) || (stamp_data == NULL)) { + if ((callback == nullptr) || (stamp_data == nullptr)) { return; } @@ -2843,12 +2890,12 @@ void BKE_stamp_info_callback(void *data, void BKE_render_result_stamp_data(RenderResult *rr, const char *key, const char *value) { StampData *stamp_data; - if (rr->stamp_data == NULL) { - rr->stamp_data = MEM_callocN(sizeof(StampData), "RenderResult.stamp_data"); + if (rr->stamp_data == nullptr) { + rr->stamp_data = MEM_cnew<StampData>("RenderResult.stamp_data"); } stamp_data = rr->stamp_data; - StampDataCustomField *field = MEM_mallocN(sizeof(StampDataCustomField), - "StampData Custom Field"); + StampDataCustomField *field = static_cast<StampDataCustomField *>( + MEM_mallocN(sizeof(StampDataCustomField), "StampData Custom Field")); STRNCPY(field->key, key); field->value = BLI_strdup(value); BLI_addtail(&stamp_data->custom_fields, field); @@ -2856,15 +2903,15 @@ void BKE_render_result_stamp_data(RenderResult *rr, const char *key, const char StampData *BKE_stamp_data_copy(const StampData *stamp_data) { - if (stamp_data == NULL) { - return NULL; + if (stamp_data == nullptr) { + return nullptr; } - StampData *stamp_datan = MEM_dupallocN(stamp_data); + StampData *stamp_datan = static_cast<StampData *>(MEM_dupallocN(stamp_data)); BLI_duplicatelist(&stamp_datan->custom_fields, &stamp_data->custom_fields); LISTBASE_FOREACH (StampDataCustomField *, custom_fieldn, &stamp_datan->custom_fields) { - custom_fieldn->value = MEM_dupallocN(custom_fieldn->value); + custom_fieldn->value = static_cast<char *>(MEM_dupallocN(custom_fieldn->value)); } return stamp_datan; @@ -2872,7 +2919,7 @@ StampData *BKE_stamp_data_copy(const StampData *stamp_data) void BKE_stamp_data_free(StampData *stamp_data) { - if (stamp_data == NULL) { + if (stamp_data == nullptr) { return; } LISTBASE_FOREACH (StampDataCustomField *, custom_field, &stamp_data->custom_fields) { @@ -2886,14 +2933,14 @@ void BKE_stamp_data_free(StampData *stamp_data) static void metadata_set_field(void *data, const char *propname, char *propvalue, int UNUSED(len)) { /* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */ - struct ImBuf *imbuf = data; + ImBuf *imbuf = static_cast<ImBuf *>(data); IMB_metadata_set_field(imbuf->metadata, propname, propvalue); } static void metadata_get_field(void *data, const char *propname, char *propvalue, int len) { /* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */ - struct ImBuf *imbuf = data; + ImBuf *imbuf = static_cast<ImBuf *>(data); IMB_metadata_get_field(imbuf->metadata, propname, propvalue, len); } @@ -2915,8 +2962,8 @@ static void metadata_copy_custom_fields(const char *field, const char *value, vo void BKE_stamp_info_from_imbuf(RenderResult *rr, struct ImBuf *ibuf) { - if (rr->stamp_data == NULL) { - rr->stamp_data = MEM_callocN(sizeof(StampData), "RenderResult.stamp_data"); + if (rr->stamp_data == nullptr) { + rr->stamp_data = MEM_cnew<StampData>("RenderResult.stamp_data"); } struct StampData *stamp_data = rr->stamp_data; IMB_metadata_ensure(&ibuf->metadata); @@ -3101,7 +3148,7 @@ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf) } #endif else { - /* R_IMF_IMTYPE_JPEG90, etc. default we save jpegs */ + /* #R_IMF_IMTYPE_JPEG90, etc. fallback to JPEG image. */ if (quality < 10) { quality = 90; } @@ -3167,7 +3214,7 @@ static void do_makepicstring(char *string, const bool use_frames, const char *suffix) { - if (string == NULL) { + if (string == nullptr) { return; } BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */ @@ -3208,7 +3255,7 @@ void BKE_image_path_from_imtype(char *string, const bool use_frames, const char *suffix) { - do_makepicstring(string, base, relbase, frame, imtype, NULL, use_ext, use_frames, suffix); + do_makepicstring(string, base, relbase, frame, imtype, nullptr, use_ext, use_frames, suffix); } struct anim *openanim_noload(const char *name, @@ -3228,12 +3275,12 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp struct ImBuf *ibuf; anim = IMB_open_anim(name, flags, streamindex, colorspace); - if (anim == NULL) { - return NULL; + if (anim == nullptr) { + return nullptr; } ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); - if (ibuf == NULL) { + if (ibuf == nullptr) { if (BLI_exists(name)) { printf("not an anim: %s\n", name); } @@ -3241,14 +3288,18 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp printf("anim file doesn't exist: %s\n", name); } IMB_free_anim(anim); - return NULL; + return nullptr; } IMB_freeImBuf(ibuf); return anim; } -/* ************************* New Image API *************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name New Image API + * \{ */ /* Notes about Image storage * - packedfile @@ -3260,8 +3311,8 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp * - renderresult * -> comes from packedfile or filename * - listbase - * -> ibufs from exrhandle - * - flipbook array + * -> ibufs from EXR-handle. + * - flip-book array * -> ibufs come from movie, temporary renderresult or sequence * - ibuf * -> comes from packedfile or filename or generated @@ -3271,7 +3322,8 @@ Image *BKE_image_ensure_viewer(Main *bmain, int type, const char *name) { Image *ima; - for (ima = bmain->images.first; ima; ima = ima->id.next) { + for (ima = static_cast<Image *>(bmain->images.first); ima; + ima = static_cast<Image *>(ima->id.next)) { if (ima->source == IMA_SRC_VIEWER) { if (ima->type == type) { break; @@ -3279,7 +3331,7 @@ Image *BKE_image_ensure_viewer(Main *bmain, int type, const char *name) } } - if (ima == NULL) { + if (ima == nullptr) { ima = image_alloc(bmain, name, IMA_SRC_VIEWER, type); } @@ -3297,8 +3349,8 @@ static void image_viewer_create_views(const RenderData *rd, Image *ima) image_add_view(ima, "", ""); } else { - SceneRenderView *srv; - for (srv = rd->views.first; srv; srv = srv->next) { + for (SceneRenderView *srv = static_cast<SceneRenderView *>(rd->views.first); srv; + srv = srv->next) { if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) { continue; } @@ -3326,9 +3378,10 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser * SceneRenderView *srv; ImageView *iv; - for (iv = ima->views.first; iv; iv = iv->next) { - srv = BLI_findstring(&rd->views, iv->name, offsetof(SceneRenderView, name)); - if ((srv == NULL) || (BKE_scene_multiview_is_render_view_active(rd, srv) == false)) { + for (iv = static_cast<ImageView *>(ima->views.first); iv; iv = iv->next) { + srv = static_cast<SceneRenderView *>( + BLI_findstring(&rd->views, iv->name, offsetof(SceneRenderView, name))); + if ((srv == nullptr) || (BKE_scene_multiview_is_render_view_active(rd, srv) == false)) { do_reset = true; break; } @@ -3336,7 +3389,7 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser * } if (do_reset) { - BLI_mutex_lock(ima->runtime.cache_mutex); + BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); image_free_cached_frames(ima); BKE_image_free_views(ima); @@ -3344,7 +3397,7 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser * /* add new views */ image_viewer_create_views(rd, ima); - BLI_mutex_unlock(ima->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); } BLI_thread_unlock(LOCK_DRAW_IMAGE); @@ -3361,12 +3414,12 @@ static void image_walk_ntree_all_users( LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->id) { if (node->type == SH_NODE_TEX_IMAGE) { - NodeTexImage *tex = node->storage; + NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage); Image *ima = (Image *)node->id; callback(ima, id, &tex->iuser, customdata); } if (node->type == SH_NODE_TEX_ENVIRONMENT) { - NodeTexImage *tex = node->storage; + NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage); Image *ima = (Image *)node->id; callback(ima, id, &tex->iuser, customdata); } @@ -3377,7 +3430,7 @@ static void image_walk_ntree_all_users( LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->id && node->type == TEX_NODE_IMAGE) { Image *ima = (Image *)node->id; - ImageUser *iuser = node->storage; + ImageUser *iuser = static_cast<ImageUser *>(node->storage); callback(ima, id, iuser, customdata); } } @@ -3386,7 +3439,7 @@ static void image_walk_ntree_all_users( LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->id && node->type == CMP_NODE_IMAGE) { Image *ima = (Image *)node->id; - ImageUser *iuser = node->storage; + ImageUser *iuser = static_cast<ImageUser *>(node->storage); callback(ima, id, iuser, customdata); } } @@ -3421,7 +3474,7 @@ static void image_walk_id_all_users( case ID_OB: { Object *ob = (Object *)id; if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data) { - callback(ob->data, &ob->id, ob->iuser, customdata); + callback(static_cast<Image *>(ob->data), &ob->id, ob->iuser, customdata); } break; } @@ -3466,7 +3519,7 @@ static void image_walk_id_all_users( case ID_CA: { Camera *cam = (Camera *)id; LISTBASE_FOREACH (CameraBGImage *, bgpic, &cam->bg_images) { - callback(bgpic->ima, NULL, &bgpic->iuser, customdata); + callback(bgpic->ima, nullptr, &bgpic->iuser, customdata); } break; } @@ -3477,8 +3530,8 @@ static void image_walk_id_all_users( LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { if (area->spacetype == SPACE_IMAGE) { - SpaceImage *sima = area->spacedata.first; - callback(sima->image, NULL, &sima->iuser, customdata); + SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first); + callback(sima->image, nullptr, &sima->iuser, customdata); } } } @@ -3506,46 +3559,55 @@ void BKE_image_walk_all_users( void *customdata, void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata)) { - for (Scene *scene = mainp->scenes.first; scene; scene = scene->id.next) { + for (Scene *scene = static_cast<Scene *>(mainp->scenes.first); scene; + scene = static_cast<Scene *>(scene->id.next)) { image_walk_id_all_users(&scene->id, false, customdata, callback); } - for (Object *ob = mainp->objects.first; ob; ob = ob->id.next) { + for (Object *ob = static_cast<Object *>(mainp->objects.first); ob; + ob = static_cast<Object *>(ob->id.next)) { image_walk_id_all_users(&ob->id, false, customdata, callback); } - for (bNodeTree *ntree = mainp->nodetrees.first; ntree; ntree = ntree->id.next) { + for (bNodeTree *ntree = static_cast<bNodeTree *>(mainp->nodetrees.first); ntree; + ntree = static_cast<bNodeTree *>(ntree->id.next)) { image_walk_id_all_users(&ntree->id, false, customdata, callback); } - for (Material *ma = mainp->materials.first; ma; ma = ma->id.next) { + for (Material *ma = static_cast<Material *>(mainp->materials.first); ma; + ma = static_cast<Material *>(ma->id.next)) { image_walk_id_all_users(&ma->id, false, customdata, callback); } - for (Light *light = mainp->materials.first; light; light = light->id.next) { + for (Light *light = static_cast<Light *>(mainp->materials.first); light; + light = static_cast<Light *>(light->id.next)) { image_walk_id_all_users(&light->id, false, customdata, callback); } - for (World *world = mainp->materials.first; world; world = world->id.next) { + for (World *world = static_cast<World *>(mainp->materials.first); world; + world = static_cast<World *>(world->id.next)) { image_walk_id_all_users(&world->id, false, customdata, callback); } - for (Tex *tex = mainp->textures.first; tex; tex = tex->id.next) { + for (Tex *tex = static_cast<Tex *>(mainp->textures.first); tex; + tex = static_cast<Tex *>(tex->id.next)) { image_walk_id_all_users(&tex->id, false, customdata, callback); } - for (Camera *cam = mainp->cameras.first; cam; cam = cam->id.next) { + for (Camera *cam = static_cast<Camera *>(mainp->cameras.first); cam; + cam = static_cast<Camera *>(cam->id.next)) { image_walk_id_all_users(&cam->id, false, customdata, callback); } - for (wmWindowManager *wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */ + for (wmWindowManager *wm = static_cast<wmWindowManager *>(mainp->wm.first); wm; + wm = static_cast<wmWindowManager *>(wm->id.next)) { /* only 1 wm */ image_walk_id_all_users(&wm->id, false, customdata, callback); } } static void image_tag_frame_recalc(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata) { - Image *changed_image = customdata; + Image *changed_image = static_cast<Image *>(customdata); if (ima == changed_image && BKE_image_is_animated(ima)) { iuser->flag |= IMA_NEED_FRAME_RECALC; @@ -3559,7 +3621,7 @@ static void image_tag_frame_recalc(Image *ima, ID *iuser_id, ImageUser *iuser, v static void image_tag_reload(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata) { - Image *changed_image = customdata; + Image *changed_image = static_cast<Image *>(customdata); if (ima == changed_image) { if (iuser->scene) { @@ -3603,9 +3665,9 @@ static void image_free_tile(Image *ima, ImageTile *tile) for (int eye = 0; eye < 2; eye++) { for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) { - if (ima->gputexture[i][eye][resolution] != NULL) { + if (ima->gputexture[i][eye][resolution] != nullptr) { GPU_texture_free(ima->gputexture[i][eye][resolution]); - ima->gputexture[i][eye][resolution] = NULL; + ima->gputexture[i][eye][resolution] = nullptr; } } } @@ -3625,11 +3687,11 @@ static void image_free_tile(Image *ima, ImageTile *tile) void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) { - if (ima == NULL) { + if (ima == nullptr) { return; } - BLI_mutex_lock(ima->runtime.cache_mutex); + BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); switch (signal) { case IMA_SIGNAL_FREE: @@ -3650,7 +3712,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) if (ima->source == IMA_SRC_GENERATED) { if (ima->gen_x == 0 || ima->gen_y == 0) { - ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, NULL); + ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr); if (ibuf) { ima->gen_x = ibuf->x; ima->gen_y = ibuf->y; @@ -3677,7 +3739,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) image_free_tile(ima, tile); MEM_freeN(tile); } - base_tile->next = NULL; + base_tile->next = nullptr; ima->tiles.last = base_tile; } @@ -3691,7 +3753,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) BKE_image_free_buffers(ima); if (iuser) { - image_tag_frame_recalc(ima, NULL, iuser, ima); + image_tag_frame_recalc(ima, nullptr, iuser, ima); } BKE_image_walk_all_users(bmain, ima, image_tag_frame_recalc); @@ -3705,13 +3767,14 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) { /* in case there are new available files to be loaded */ image_free_packedfiles(ima); - BKE_image_packfiles(NULL, ima, ID_BLEND_PATH(bmain, &ima->id)); + BKE_image_packfiles(nullptr, ima, ID_BLEND_PATH(bmain, &ima->id)); } else { ImagePackedFile *imapf; - for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { + for (imapf = static_cast<ImagePackedFile *>(ima->packedfiles.first); imapf; + imapf = imapf->next) { PackedFile *pf; - pf = BKE_packedfile_new(NULL, imapf->filepath, ID_BLEND_PATH(bmain, &ima->id)); + pf = BKE_packedfile_new(nullptr, imapf->filepath, ID_BLEND_PATH(bmain, &ima->id)); if (pf) { BKE_packedfile_free(imapf->packedfile); imapf->packedfile = pf; @@ -3731,7 +3794,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) } if (ima->source == IMA_SRC_TILED) { - ListBase new_tiles = {NULL, NULL}; + ListBase new_tiles = {nullptr, nullptr}; int new_start, new_range; char filepath[FILE_MAX]; @@ -3743,7 +3806,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) * to account for how the two sets might or might not overlap. To be complete, we start * the refresh process by clearing all existing tiles, stopping when there's only 1 tile * left. */ - while (BKE_image_remove_tile(ima, ima->tiles.last)) { + while (BKE_image_remove_tile(ima, static_cast<ImageTile *>(ima->tiles.last))) { ; } @@ -3753,7 +3816,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) /* Add in all the new tiles. */ LISTBASE_FOREACH (LinkData *, new_tile, &new_tiles) { int new_tile_number = POINTER_AS_INT(new_tile->data); - BKE_image_add_tile(ima, new_tile_number, NULL); + BKE_image_add_tile(ima, new_tile_number, nullptr); if (new_tile_number == remaining_tile_number) { needs_final_cleanup = false; } @@ -3768,7 +3831,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) } if (iuser) { - image_tag_reload(ima, NULL, iuser, ima); + image_tag_reload(ima, nullptr, iuser, ima); } BKE_image_walk_all_users(bmain, ima, image_tag_reload); break; @@ -3786,26 +3849,29 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal) break; } - BLI_mutex_unlock(ima->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); BKE_ntree_update_tag_id_changed(bmain, &ima->id); - BKE_ntree_update_main(bmain, NULL); + BKE_ntree_update_main(bmain, nullptr); } -/* return renderpass for a given pass index and active view */ -/* fallback to available if there are missing passes for active view */ +/** + * \return render-pass for a given pass index and active view. + * fallback to available if there are missing passes for active view. + */ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const int view, int *r_passindex) { - RenderPass *rpass_ret = NULL; + RenderPass *rpass_ret = nullptr; RenderPass *rpass; int rp_index = 0; const char *rp_name = ""; - for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) { + for (rpass = static_cast<RenderPass *>(rl->passes.first); rpass; + rpass = rpass->next, rp_index++) { if (rp_index == pass) { rpass_ret = rpass; if (view == 0) { @@ -3823,9 +3889,9 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, } /* fallback to the first pass in the layer */ - if (rpass_ret == NULL) { + if (rpass_ret == nullptr) { rp_index = 0; - rpass_ret = rl->passes.first; + rpass_ret = static_cast<RenderPass *>(rl->passes.first); } if (r_passindex) { @@ -3838,7 +3904,7 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, void BKE_image_get_tile_label(Image *ima, ImageTile *tile, char *label, int len_label) { label[0] = '\0'; - if (ima == NULL || tile == NULL) { + if (ima == nullptr || tile == nullptr) { return; } @@ -3850,10 +3916,7 @@ void BKE_image_get_tile_label(Image *ima, ImageTile *tile, char *label, int len_ } } -bool BKE_image_get_tile_info(char *filepath, - ListBase *udim_tiles, - int *udim_start, - int *udim_range) +bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *tile_start, int *tile_range) { char filename[FILE_MAXFILE], dirname[FILE_MAXDIR]; BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename)); @@ -3884,7 +3947,7 @@ bool BKE_image_get_tile_info(char *filepath, break; } - BLI_addtail(udim_tiles, BLI_genericNodeN(POINTER_FROM_INT(id))); + BLI_addtail(tiles, BLI_genericNodeN(POINTER_FROM_INT(id))); min_udim = min_ii(min_udim, id); max_udim = max_ii(max_udim, id); } @@ -3894,8 +3957,8 @@ bool BKE_image_get_tile_info(char *filepath, if (is_udim && min_udim <= IMA_UDIM_MAX) { BLI_join_dirfile(filepath, FILE_MAX, dirname, filename); - *udim_start = min_udim; - *udim_range = max_udim - min_udim + 1; + *tile_start = min_udim; + *tile_range = max_udim - min_udim + 1; return true; } return false; @@ -3904,27 +3967,28 @@ bool BKE_image_get_tile_info(char *filepath, ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *label) { if (ima->source != IMA_SRC_TILED) { - return NULL; + return nullptr; } if (tile_number < 1001 || tile_number > IMA_UDIM_MAX) { - return NULL; + return nullptr; } /* Search the first tile that has a higher number. * We then insert before that to keep the list sorted. */ ImageTile *next_tile; - for (next_tile = ima->tiles.first; next_tile; next_tile = next_tile->next) { + for (next_tile = static_cast<ImageTile *>(ima->tiles.first); next_tile; + next_tile = next_tile->next) { if (next_tile->tile_number == tile_number) { /* Tile already exists. */ - return NULL; + return nullptr; } if (next_tile->tile_number > tile_number) { break; } } - ImageTile *tile = MEM_callocN(sizeof(ImageTile), "image new tile"); + ImageTile *tile = MEM_cnew<ImageTile>("image new tile"); tile->tile_number = tile_number; if (next_tile) { @@ -3941,13 +4005,13 @@ ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *la for (int eye = 0; eye < 2; eye++) { for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) { /* Reallocate GPU tile array. */ - if (ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] != NULL) { + if (ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] != nullptr) { GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution]); - ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] = NULL; + ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] = nullptr; } - if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] != NULL) { + if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] != nullptr) { GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution]); - ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] = NULL; + ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] = nullptr; } } } @@ -3958,7 +4022,7 @@ ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *la bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile) { - if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) { + if (ima == nullptr || tile == nullptr || ima->source != IMA_SRC_TILED) { return false; } @@ -3976,7 +4040,7 @@ bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile) void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_number) { - if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) { + if (ima == nullptr || tile == nullptr || ima->source != IMA_SRC_TILED) { return; } @@ -3990,14 +4054,14 @@ void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_nu if (BKE_image_is_multiview(ima)) { const int totviews = BLI_listbase_count(&ima->views); for (int i = 0; i < totviews; i++) { - ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, old_tile_number, NULL); + ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, old_tile_number, nullptr); image_remove_ibuf(ima, i, old_tile_number); image_assign_ibuf(ima, ibuf, i, new_tile_number); IMB_freeImBuf(ibuf); } } else { - ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, 0, old_tile_number, NULL); + ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, 0, old_tile_number, nullptr); image_remove_ibuf(ima, 0, old_tile_number); image_assign_ibuf(ima, ibuf, 0, new_tile_number); IMB_freeImBuf(ibuf); @@ -4007,13 +4071,13 @@ void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_nu for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) { /* Reallocate GPU tile array. */ - if (ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] != NULL) { + if (ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] != nullptr) { GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution]); - ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] = NULL; + ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] = nullptr; } - if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] != NULL) { + if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] != nullptr) { GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution]); - ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] = NULL; + ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] = nullptr; } } } @@ -4022,14 +4086,14 @@ void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_nu static int tile_sort_cb(const void *a, const void *b) { - const ImageTile *tile_a = a; - const ImageTile *tile_b = b; + const ImageTile *tile_a = static_cast<const ImageTile *>(a); + const ImageTile *tile_b = static_cast<const ImageTile *>(b); return (tile_a->tile_number > tile_b->tile_number) ? 1 : 0; } void BKE_image_sort_tiles(struct Image *ima) { - if (ima == NULL || ima->source != IMA_SRC_TILED) { + if (ima == nullptr || ima->source != IMA_SRC_TILED) { return; } @@ -4045,7 +4109,7 @@ bool BKE_image_fill_tile(struct Image *ima, int planes, bool is_float) { - if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) { + if (ima == nullptr || tile == nullptr || ima->source != IMA_SRC_TILED) { return false; } @@ -4054,9 +4118,9 @@ bool BKE_image_fill_tile(struct Image *ima, ImBuf *tile_ibuf = add_ibuf_size( width, height, ima->filepath, planes, is_float, gen_type, color, &ima->colorspace_settings); - if (tile_ibuf != NULL) { + if (tile_ibuf != nullptr) { image_assign_ibuf(ima, tile_ibuf, 0, tile->tile_number); - BKE_image_release_ibuf(ima, tile_ibuf, NULL); + BKE_image_release_ibuf(ima, tile_ibuf, nullptr); return true; } return false; @@ -4064,11 +4128,11 @@ bool BKE_image_fill_tile(struct Image *ima, void BKE_image_ensure_tile_token(char *filename) { - BLI_assert_msg(BLI_path_slash_find(filename) == NULL, + BLI_assert_msg(BLI_path_slash_find(filename) == nullptr, "Only the file-name component should be used!"); /* Is there a '<' character in the filename? Assume tokens already present. */ - if (strstr(filename, "<") != NULL) { + if (strstr(filename, "<") != nullptr) { return; } @@ -4176,21 +4240,21 @@ bool BKE_image_tile_filepath_exists(const char *filepath) char *BKE_image_get_tile_strformat(const char *filepath, eUDIM_TILE_FORMAT *r_tile_format) { - if (filepath == NULL || r_tile_format == NULL) { - return NULL; + if (filepath == nullptr || r_tile_format == nullptr) { + return nullptr; } - if (strstr(filepath, "<UDIM>") != NULL) { + if (strstr(filepath, "<UDIM>") != nullptr) { *r_tile_format = UDIM_TILE_FORMAT_UDIM; return BLI_str_replaceN(filepath, "<UDIM>", "%d"); } - if (strstr(filepath, "<UVTILE>") != NULL) { + if (strstr(filepath, "<UVTILE>") != nullptr) { *r_tile_format = UDIM_TILE_FORMAT_UVTILE; return BLI_str_replaceN(filepath, "<UVTILE>", "u%d_v%d"); } *r_tile_format = UDIM_TILE_FORMAT_NONE; - return NULL; + return nullptr; } bool BKE_image_get_tile_number_from_filepath(const char *filepath, @@ -4198,7 +4262,7 @@ bool BKE_image_get_tile_number_from_filepath(const char *filepath, eUDIM_TILE_FORMAT tile_format, int *r_tile_number) { - if (filepath == NULL || pattern == NULL || r_tile_number == NULL) { + if (filepath == nullptr || pattern == nullptr || r_tile_number == nullptr) { return false; } @@ -4226,7 +4290,7 @@ void BKE_image_set_filepath_from_tile_number(char *filepath, eUDIM_TILE_FORMAT tile_format, int tile_number) { - if (filepath == NULL || pattern == NULL) { + if (filepath == nullptr || pattern == nullptr) { return; } @@ -4245,10 +4309,10 @@ void BKE_image_set_filepath_from_tile_number(char *filepath, RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) { RenderLayer *rl; - RenderPass *rpass = NULL; + RenderPass *rpass = nullptr; - if (rr == NULL) { - return NULL; + if (rr == nullptr) { + return nullptr; } if (iuser) { @@ -4260,7 +4324,7 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) rl_index += 1; } - for (rl = rr->layers.first; rl; rl = rl->next, rl_index++) { + for (rl = static_cast<RenderLayer *>(rr->layers.first); rl; rl = rl->next, rl_index++) { if (iuser->layer == rl_index) { int rp_index; rpass = image_render_pass_get(rl, iuser->pass, rv_index, &rp_index); @@ -4313,7 +4377,7 @@ bool BKE_image_is_multilayer(Image *ima) bool BKE_image_is_multiview(Image *ima) { - ImageView *view = ima->views.first; + ImageView *view = static_cast<ImageView *>(ima->views.first); return (view && (view->next || view->name[0])); } @@ -4331,8 +4395,8 @@ static void image_init_multilayer_multiview(Image *ima, RenderResult *rr) * be acquired with a mutex along with the render result, but there are still * some places with just an image pointer that need to access views */ if (rr && BLI_listbase_count(&ima->views) == BLI_listbase_count(&rr->views)) { - ImageView *iv = ima->views.first; - RenderView *rv = rr->views.first; + ImageView *iv = static_cast<ImageView *>(ima->views.first); + RenderView *rv = static_cast<RenderView *>(rr->views.first); bool modified = false; for (; rv; rv = rv->next, iv = iv->next) { modified |= !STREQ(rv->name, iv->name); @@ -4346,7 +4410,7 @@ static void image_init_multilayer_multiview(Image *ima, RenderResult *rr) if (rr) { LISTBASE_FOREACH (RenderView *, rv, &rr->views) { - ImageView *iv = MEM_callocN(sizeof(ImageView), "Viewer Image View"); + ImageView *iv = MEM_cnew<ImageView>("Viewer Image View"); STRNCPY(iv->name, rv->name); BLI_addtail(&ima->views, iv); } @@ -4355,7 +4419,7 @@ static void image_init_multilayer_multiview(Image *ima, RenderResult *rr) RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima) { - RenderResult *rr = NULL; + RenderResult *rr = nullptr; if (ima->rr) { rr = ima->rr; } @@ -4407,7 +4471,7 @@ void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot) /* Ensure we always have a valid render slot. */ if (!ima->renderslots.first) { - BKE_image_add_renderslot(ima, NULL); + BKE_image_add_renderslot(ima, nullptr); ima->render_slot = 0; ima->last_render_slot = 0; } @@ -4420,12 +4484,12 @@ void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot) RenderSlot *cur_slot = BKE_image_get_renderslot(ima, ima->render_slot); if (last_slot && ima->render_slot != ima->last_render_slot) { - last_slot->render = NULL; + last_slot->render = nullptr; RE_SwapResult(re, &last_slot->render); if (cur_slot->render) { if (free_current_slot) { - BKE_image_clear_renderslot(ima, NULL, ima->render_slot); + BKE_image_clear_renderslot(ima, nullptr, ima->render_slot); } else { RE_SwapResult(re, &cur_slot->render); @@ -4436,13 +4500,17 @@ void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot) ima->last_render_slot = ima->render_slot; } -/**************************** multiview load openexr *********************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Multiview Load OpenEXR + * \{ */ static void image_add_view(Image *ima, const char *viewname, const char *filepath) { ImageView *iv; - iv = MEM_mallocN(sizeof(ImageView), "Viewer Image View"); + iv = static_cast<ImageView *>(MEM_mallocN(sizeof(ImageView), "Viewer Image View")); STRNCPY(iv->name, viewname); STRNCPY(iv->filepath, filepath); @@ -4454,9 +4522,10 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat BLI_addhead(&ima->views, iv); } else if (STREQ(viewname, STEREO_RIGHT_NAME)) { - ImageView *left_iv = BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)); + ImageView *left_iv = static_cast<ImageView *>( + BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name))); - if (left_iv == NULL) { + if (left_iv == nullptr) { BLI_addhead(&ima->views, iv); } else { @@ -4468,8 +4537,8 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat } } -/* after imbuf load, openexr type can return with a exrhandle open */ -/* in that case we have to build a render-result */ +/* After imbuf load, OpenEXR type can return with a EXR-handle open + * in that case we have to build a render-result. */ #ifdef WITH_OPENEXR static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) { @@ -4483,8 +4552,8 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) IMB_exr_close(ibuf->userdata); - ibuf->userdata = NULL; - if (ima->rr != NULL) { + ibuf->userdata = nullptr; + if (ima->rr != nullptr) { ima->rr->framenr = framenr; BKE_stamp_info_from_imbuf(ima->rr, ibuf); } @@ -4494,12 +4563,12 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) } #endif /* WITH_OPENEXR */ -/* common stuff to do with images after loading */ +/** Common stuff to do with images after loading. */ static void image_init_after_load(Image *ima, ImageUser *iuser, ImBuf *UNUSED(ibuf)) { - /* Preview is NULL when it has never been used as an icon before. + /* Preview is null when it has never been used as an icon before. * Never handle previews/icons outside of main thread. */ - if (G.background == 0 && ima->preview == NULL && BLI_thread_is_main()) { + if (G.background == 0 && ima->preview == nullptr && BLI_thread_is_main()) { BKE_icon_changed(BKE_icon_id_ensure(&ima->id)); } @@ -4509,7 +4578,7 @@ static void image_init_after_load(Image *ima, ImageUser *iuser, ImBuf *UNUSED(ib ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser); /* Images should never get loaded if the corresponding tile does not exist, * but we should at least not crash if it happens due to a bug elsewhere. */ - BLI_assert(tile != NULL); + BLI_assert(tile != nullptr); UNUSED_VARS_NDEBUG(tile); } @@ -4529,7 +4598,9 @@ static int imbuf_alpha_flags_for_image(Image *ima) return 0; } -/* the number of files will vary according to the stereo format */ +/** + * \return the number of files will vary according to the stereo format. + */ static int image_num_files(Image *ima) { const bool is_multiview = BKE_image_is_multiview(ima); @@ -4551,7 +4622,7 @@ static ImBuf *load_sequence_single( struct ImBuf *ibuf; char name[FILE_MAX]; int flag; - ImageUser iuser_t = {0}; + ImageUser iuser_t{}; *r_cache_ibuf = true; @@ -4593,9 +4664,9 @@ static ImBuf *load_sequence_single( image_create_multilayer(ima, ibuf, frame); ima->type = IMA_TYPE_MULTILAYER; IMB_freeImBuf(ibuf); - ibuf = NULL; - /* NULL ibuf in the cache means the image failed to load. However for multilayer we load - * pixels into RenderResult instead and intentionally leave ibuf NULL. */ + ibuf = nullptr; + /* Null ibuf in the cache means the image failed to load. However for multilayer we load + * pixels into RenderResult instead and intentionally leave ibuf null. */ *r_cache_ibuf = false; } } @@ -4612,7 +4683,7 @@ static ImBuf *load_sequence_single( static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, int frame) { - struct ImBuf *ibuf = NULL; + struct ImBuf *ibuf = nullptr; const bool is_multiview = BKE_image_is_multiview(ima); const int totfiles = image_num_files(ima); @@ -4625,13 +4696,11 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, } else { const int totviews = BLI_listbase_count(&ima->views); - struct ImBuf **ibuf_arr; - - ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs"); - bool *cache_ibuf_arr = MEM_mallocN(sizeof(bool) * totviews, "Image View Put In Cache"); + Array<ImBuf *> ibuf_arr(totviews); + Array<bool> cache_ibuf_arr(totviews); for (int i = 0; i < totfiles; i++) { - ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, cache_ibuf_arr + i); + ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, &cache_ibuf_arr[i]); } if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D) { @@ -4653,10 +4722,6 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, IMB_freeImBuf(ibuf_arr[i]); } } - - /* cleanup */ - MEM_freeN(ibuf_arr); - MEM_freeN(cache_ibuf_arr); } return ibuf; @@ -4664,12 +4729,12 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int entry, int frame) { - struct ImBuf *ibuf = NULL; + struct ImBuf *ibuf = nullptr; /* either we load from RenderResult, or we have to load a new one */ /* check for new RenderResult */ - if (ima->rr == NULL || frame != ima->rr->framenr) { + if (ima->rr == nullptr || frame != ima->rr->framenr) { if (ima->rr) { /* Cached image buffers shares pointers with render result, * need to ensure there's no image buffers are hanging around @@ -4677,7 +4742,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e */ image_free_cached_frames(ima); RE_FreeRenderResult(ima->rr); - ima->rr = NULL; + ima->rr = nullptr; } ibuf = image_load_sequence_file(ima, iuser, entry, frame); @@ -4694,7 +4759,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e // printf("load from pass %s\n", rpass->name); /* since we free render results, we copy the rect */ ibuf = IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0); - ibuf->rect_float = MEM_dupallocN(rpass->rect); + ibuf->rect_float = static_cast<float *>(MEM_dupallocN(rpass->rect)); ibuf->flags |= IB_rectfloat; ibuf->mall = IB_rectfloat; ibuf->channels = rpass->channels; @@ -4712,15 +4777,15 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const int view_id) { - struct ImBuf *ibuf = NULL; + struct ImBuf *ibuf = nullptr; ImageAnim *ia; - ia = BLI_findlink(&ima->anims, view_id); + ia = static_cast<ImageAnim *>(BLI_findlink(&ima->anims, view_id)); - if (ia->anim == NULL) { + if (ia->anim == nullptr) { char str[FILE_MAX]; int flags = IB_rect; - ImageUser iuser_t; + ImageUser iuser_t{}; if (ima->flag & IMA_DEINTERLACE) { flags |= IB_animdeinterlace; @@ -4765,7 +4830,7 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const i static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) { - struct ImBuf *ibuf = NULL; + struct ImBuf *ibuf = nullptr; const bool is_multiview = BKE_image_is_multiview(ima); const int totfiles = image_num_files(ima); @@ -4774,7 +4839,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) for (int i = 0; i < totfiles; i++) { /* allocate the ImageAnim */ - ImageAnim *ia = MEM_callocN(sizeof(ImageAnim), "Image Anim"); + ImageAnim *ia = MEM_cnew<ImageAnim>("Image Anim"); BLI_addtail(&ima->anims, ia); } } @@ -4784,10 +4849,8 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) image_assign_ibuf(ima, ibuf, 0, frame); } else { - struct ImBuf **ibuf_arr; const int totviews = BLI_listbase_count(&ima->views); - - ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views (movie) Imbufs"); + Array<ImBuf *> ibuf_arr(totviews); for (int i = 0; i < totfiles; i++) { ibuf_arr[i] = load_movie_single(ima, iuser, frame, i); @@ -4810,9 +4873,6 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) IMB_freeImBuf(ibuf_arr[i]); } } - - /* cleanup */ - MEM_freeN(ibuf_arr); } return ibuf; @@ -4826,7 +4886,7 @@ static ImBuf *load_image_single(Image *ima, bool *r_cache_ibuf) { char filepath[FILE_MAX]; - struct ImBuf *ibuf = NULL; + struct ImBuf *ibuf = nullptr; int flag; *r_cache_ibuf = true; @@ -4838,7 +4898,7 @@ static ImBuf *load_image_single(Image *ima, flag = IB_rect | IB_multilayer; flag |= imbuf_alpha_flags_for_image(ima); - imapf = BLI_findlink(&ima->packedfiles, view_id); + imapf = static_cast<ImagePackedFile *>(BLI_findlink(&ima->packedfiles, view_id)); if (imapf->packedfile) { ibuf = IMB_ibImageFromMemory((unsigned char *)imapf->packedfile->data, imapf->packedfile->size, @@ -4848,7 +4908,7 @@ static ImBuf *load_image_single(Image *ima, } } else { - ImageUser iuser_t; + ImageUser iuser_t{}; flag = IB_rect | IB_multilayer | IB_metadata; flag |= imbuf_alpha_flags_for_image(ima); @@ -4880,9 +4940,9 @@ static ImBuf *load_image_single(Image *ima, image_create_multilayer(ima, ibuf, cfra); ima->type = IMA_TYPE_MULTILAYER; IMB_freeImBuf(ibuf); - ibuf = NULL; - /* NULL ibuf in the cache means the image failed to load. However for multilayer we load - * pixels into RenderResult instead and intentionally leave ibuf NULL. */ + ibuf = nullptr; + /* Null ibuf in the cache means the image failed to load. However for multilayer we load + * pixels into RenderResult instead and intentionally leave ibuf null. */ *r_cache_ibuf = false; } } @@ -4893,12 +4953,13 @@ static ImBuf *load_image_single(Image *ima, /* Make packed file for auto-pack. */ if ((has_packed == false) && (G.fileflags & G_FILE_AUTOPACK)) { - ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Pack-file"); + ImagePackedFile *imapf = static_cast<ImagePackedFile *>( + MEM_mallocN(sizeof(ImagePackedFile), "Image Pack-file")); BLI_addtail(&ima->packedfiles, imapf); STRNCPY(imapf->filepath, filepath); imapf->packedfile = BKE_packedfile_new( - NULL, filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id)); + nullptr, filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id)); } } } @@ -4906,12 +4967,12 @@ static ImBuf *load_image_single(Image *ima, return ibuf; } -/* warning, 'iuser' can be NULL +/* warning, 'iuser' can be null * NOTE: Image->views was already populated (in image_update_views_format) */ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) { - struct ImBuf *ibuf = NULL; + struct ImBuf *ibuf = nullptr; const bool is_multiview = BKE_image_is_multiview(ima); const int totfiles = image_num_files(ima); bool has_packed = BKE_image_has_packedfile(ima); @@ -4935,18 +4996,17 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) } } else { - struct ImBuf **ibuf_arr; const int totviews = BLI_listbase_count(&ima->views); BLI_assert(totviews > 0); - ibuf_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs"); - bool *cache_ibuf_arr = MEM_mallocN(sizeof(bool) * totviews, "Image Views Put In Cache"); + Array<ImBuf *> ibuf_arr(totviews); + Array<bool> cache_ibuf_arr(totviews); for (int i = 0; i < totfiles; i++) { - ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, cache_ibuf_arr + i); + ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, &cache_ibuf_arr[i]); } - /* multi-views/multi-layers OpenEXR files directly populate ima, and return NULL ibuf... */ + /* multi-views/multi-layers OpenEXR files directly populate ima, and return null ibuf... */ if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D && ibuf_arr[0] && totfiles == 1 && totviews >= 2) { IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]); @@ -4968,10 +5028,6 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) IMB_freeImBuf(ibuf_arr[i]); } } - - /* cleanup */ - MEM_freeN(ibuf_arr); - MEM_freeN(cache_ibuf_arr); } return ibuf; @@ -4979,9 +5035,9 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) { - ImBuf *ibuf = NULL; + ImBuf *ibuf = nullptr; - if (ima->rr == NULL) { + if (ima->rr == nullptr) { ibuf = image_load_image_file(ima, iuser, 0); if (ibuf) { /* actually an error */ ima->type = IMA_TYPE_IMAGE; @@ -5015,7 +5071,6 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_lock) { Render *re; - RenderResult rres; RenderView *rv; float *rectf, *rectz; unsigned int *rect; @@ -5026,12 +5081,12 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc int actview; if (!(iuser && iuser->scene)) { - return NULL; + return nullptr; } /* if we the caller is not going to release the lock, don't give the image */ if (!r_lock) { - return NULL; + return nullptr; } re = RE_GetSceneRender(iuser->scene); @@ -5045,40 +5100,62 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc actview = iuser->multiview_eye; } + RenderResult rres{}; RenderSlot *slot; if (from_render) { RE_AcquireResultImage(re, &rres, actview); } else if ((slot = BKE_image_get_renderslot(ima, ima->render_slot))->render) { - rres = *(slot->render); - rres.have_combined = ((RenderView *)rres.views.first)->rectf != NULL; - } - else { - memset(&rres, 0, sizeof(RenderResult)); + /* Unfortunately each field needs to be set individually because RenderResult + * contains volatile fields and using memcpy would invoke undefined behavior with c++. */ + rres.next = slot->render->next; + rres.prev = slot->render->prev; + rres.rectx = slot->render->rectx; + rres.recty = slot->render->recty; + rres.sample_nr = slot->render->sample_nr; + rres.rect32 = slot->render->rect32; + rres.rectf = slot->render->rectf; + rres.rectz = slot->render->rectz; + rres.tilerect = slot->render->tilerect; + rres.xof = slot->render->xof; + rres.yof = slot->render->yof; + rres.layers = slot->render->layers; + rres.views = slot->render->views; + rres.renrect.xmin = slot->render->renrect.xmin; + rres.renrect.xmax = slot->render->renrect.xmax; + rres.renrect.ymin = slot->render->renrect.ymin; + rres.renrect.ymax = slot->render->renrect.ymax; + rres.renlay = slot->render->renlay; + rres.framenr = slot->render->framenr; + rres.text = slot->render->text; + rres.error = slot->render->error; + rres.stamp_data = slot->render->stamp_data; + rres.passes_allocated = slot->render->passes_allocated; + rres.have_combined = ((RenderView *)rres.views.first)->rectf != nullptr; } if (!(rres.rectx > 0 && rres.recty > 0)) { if (from_render) { RE_ReleaseResultImage(re); } - return NULL; + return nullptr; } /* release is done in BKE_image_release_ibuf using r_lock */ if (from_render) { BLI_thread_lock(LOCK_VIEWER); *r_lock = re; - rv = NULL; + rv = nullptr; } else { - rv = BLI_findlink(&rres.views, actview); - if (rv == NULL) { - rv = rres.views.first; + rv = static_cast<RenderView *>(BLI_findlink(&rres.views, actview)); + if (rv == nullptr) { + rv = static_cast<RenderView *>(rres.views.first); } } /* this gives active layer, composite or sequence result */ - if (rv == NULL) { + if (rv == nullptr) { rect = (unsigned int *)rres.rect32; rectf = rres.rectf; rectz = rres.rectz; @@ -5101,12 +5178,13 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc * in this case we ignore float buffer, because it could have * hung from previous pass which was float */ - rectf = NULL; + rectf = nullptr; } else if (rres.layers.first) { - RenderLayer *rl = BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0)); + RenderLayer *rl = static_cast<RenderLayer *>( + BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0))); if (rl) { - RenderPass *rpass = image_render_pass_get(rl, pass, actview, NULL); + RenderPass *rpass = image_render_pass_get(rl, pass, actview, nullptr); if (rpass) { rectf = rpass->rect; if (pass != 0) { @@ -5115,7 +5193,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc } } - for (rpass = rl->passes.first; rpass; rpass = rpass->next) { + for (rpass = static_cast<RenderPass *>(rl->passes.first); rpass; rpass = rpass->next) { if (STREQ(rpass->name, RE_PASSNAME_Z) && rpass->view_id == actview) { rectz = rpass->rect; } @@ -5123,10 +5201,10 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc } } - ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, NULL); + ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr); /* make ibuf if needed, and initialize it */ - if (ibuf == NULL) { + if (ibuf == nullptr) { ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, 0); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); } @@ -5164,7 +5242,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc * or if it's reusing buffer from render result */ if ((ibuf->mall & IB_rect) == 0) { - ibuf->rect = NULL; + ibuf->rect = nullptr; } } @@ -5174,7 +5252,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc ibuf->channels = channels; } else { - ibuf->rect_float = NULL; + ibuf->rect_float = nullptr; ibuf->flags &= ~IB_rectfloat; } @@ -5183,16 +5261,16 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc ibuf->flags |= IB_zbuffloat; } else { - ibuf->zbuf_float = NULL; + ibuf->zbuf_float = nullptr; ibuf->flags &= ~IB_zbuffloat; } /* TODO(sergey): Make this faster by either simply referencing the stamp * or by changing both ImBug and RenderResult to use same data type to * store metadata. */ - if (ibuf->metadata != NULL) { + if (ibuf->metadata != nullptr) { IMB_metadata_free(ibuf->metadata); - ibuf->metadata = NULL; + ibuf->metadata = nullptr; } BKE_imbuf_stamp_info(&rres, ibuf); @@ -5207,7 +5285,7 @@ static int image_get_multiview_index(Image *ima, ImageUser *iuser) { const bool is_multilayer = BKE_image_is_multilayer(ima); const bool is_backdrop = (ima->source == IMA_SRC_VIEWER) && (ima->type == IMA_TYPE_COMPOSITE) && - (iuser == NULL); + (iuser == nullptr); int index = BKE_image_has_multiple_ibufs(ima) ? 0 : IMA_NO_INDEX; if (is_multilayer) { @@ -5259,7 +5337,7 @@ static void image_get_entry_and_index(Image *ima, ImageUser *iuser, int *r_entry static ImBuf *image_get_cached_ibuf( Image *ima, ImageUser *iuser, int *r_entry, int *r_index, bool *r_is_cached_empty) { - ImBuf *ibuf = NULL; + ImBuf *ibuf = nullptr; int entry = 0, index = image_get_multiview_index(ima, iuser); /* see if we already have an appropriate ibuf, with image source and type */ @@ -5315,12 +5393,12 @@ static ImBuf *image_get_cached_ibuf( BLI_INLINE bool image_quick_test(Image *ima, const ImageUser *iuser) { - if (ima == NULL) { + if (ima == nullptr) { return false; } ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser); - if (tile == NULL) { + if (tile == nullptr) { return false; } @@ -5334,49 +5412,49 @@ BLI_INLINE bool image_quick_test(Image *ima, const ImageUser *iuser) */ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) { - ImBuf *ibuf = NULL; + ImBuf *ibuf = nullptr; int entry = 0, index = 0; if (r_lock) { - *r_lock = NULL; + *r_lock = nullptr; } /* quick reject tests */ if (!image_quick_test(ima, iuser)) { - return NULL; + return nullptr; } bool is_cached_empty = false; ibuf = image_get_cached_ibuf(ima, iuser, &entry, &index, &is_cached_empty); if (is_cached_empty) { - return NULL; + return nullptr; } - if (ibuf == NULL) { - /* we are sure we have to load the ibuf, using source and type */ + if (ibuf == nullptr) { + /* We are sure we have to load the ibuf, using source and type. */ if (ima->source == IMA_SRC_MOVIE) { - /* source is from single file, use flipbook to store ibuf */ + /* Source is from single file, use flip-book to store ibuf. */ ibuf = image_load_movie_file(ima, iuser, entry); } else if (ima->source == IMA_SRC_SEQUENCE) { if (ima->type == IMA_TYPE_IMAGE) { - /* regular files, ibufs in flipbook, allows saving */ + /* Regular files, ibufs in flip-book, allows saving. */ ibuf = image_load_sequence_file(ima, iuser, entry, entry); } /* no else; on load the ima type can change */ if (ima->type == IMA_TYPE_MULTILAYER) { - /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ + /* Only 1 layer/pass stored in imbufs, no EXR-handle anim storage, no saving. */ ibuf = image_load_sequence_multilayer(ima, iuser, entry, entry); } } else if (ima->source == IMA_SRC_TILED) { if (ima->type == IMA_TYPE_IMAGE) { - /* regular files, ibufs in flipbook, allows saving */ + /* Regular files, ibufs in flip-book, allows saving */ ibuf = image_load_sequence_file(ima, iuser, entry, 0); } /* no else; on load the ima type can change */ if (ima->type == IMA_TYPE_MULTILAYER) { - /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ + /* Only 1 layer/pass stored in imbufs, no EXR-handle anim storage, no saving. */ ibuf = image_load_sequence_multilayer(ima, iuser, entry, 0); } } @@ -5392,8 +5470,8 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) } } else if (ima->source == IMA_SRC_GENERATED) { - /* generated is: ibuf is allocated dynamically */ - /* UV testgrid or black or solid etc */ + /* Generated is: `ibuf` is allocated dynamically. */ + /* UV test-grid or black or solid etc. */ if (ima->gen_x == 0) { ima->gen_x = 1024; } @@ -5428,7 +5506,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) /* XXX anim play for viewer nodes not yet supported */ entry = 0; // XXX iuser ? iuser->framenr : 0; - ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, NULL); + ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, nullptr); if (!ibuf) { /* Composite Viewer, all handled in compositor */ @@ -5441,7 +5519,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) } /* We only want movies and sequences to be memory limited. */ - if (ibuf != NULL && !ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { + if (ibuf != nullptr && !ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { ibuf->userflags |= IB_PERSISTENT; } } @@ -5456,38 +5534,38 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) /* NOTE: same as #image_acquire_ibuf, but can be used to retrieve images being rendered in * a thread safe way, always call both acquire and release. */ - if (ima == NULL) { - return NULL; + if (ima == nullptr) { + return nullptr; } ImBuf *ibuf; - BLI_mutex_lock(ima->runtime.cache_mutex); + BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); ibuf = image_acquire_ibuf(ima, iuser, r_lock); - BLI_mutex_unlock(ima->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); return ibuf; } void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock) { - if (lock != NULL) { + if (lock != nullptr) { /* for getting image during threaded render / compositing, need to release */ if (lock == ima) { BLI_thread_unlock(LOCK_VIEWER); /* viewer image */ } else { - RE_ReleaseResultImage(lock); /* render result */ - BLI_thread_unlock(LOCK_VIEWER); /* view image imbuf */ + RE_ReleaseResultImage(static_cast<Render *>(lock)); /* render result */ + BLI_thread_unlock(LOCK_VIEWER); /* view image imbuf */ } } if (ibuf) { - BLI_mutex_lock(ima->runtime.cache_mutex); + BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); IMB_freeImBuf(ibuf); - BLI_mutex_unlock(ima->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); } } @@ -5500,40 +5578,44 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser) return false; } - BLI_mutex_lock(ima->runtime.cache_mutex); + BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); - ibuf = image_get_cached_ibuf(ima, iuser, NULL, NULL, NULL); + ibuf = image_get_cached_ibuf(ima, iuser, nullptr, nullptr, nullptr); if (!ibuf) { - ibuf = image_acquire_ibuf(ima, iuser, NULL); + ibuf = image_acquire_ibuf(ima, iuser, nullptr); } - BLI_mutex_unlock(ima->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex)); IMB_freeImBuf(ibuf); - return ibuf != NULL; + return ibuf != nullptr; } -/* ******** Pool for image buffers ******** */ +/** \} */ -typedef struct ImagePoolItem { +/* -------------------------------------------------------------------- */ +/** \name Pool for Image Buffers + * \{ */ + +struct ImagePoolItem { struct ImagePoolItem *next, *prev; Image *image; ImBuf *ibuf; int index; int entry; -} ImagePoolItem; +}; -typedef struct ImagePool { +struct ImagePool { ListBase image_buffers; BLI_mempool *memory_pool; ThreadMutex mutex; -} ImagePool; +}; ImagePool *BKE_image_pool_new(void) { - ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool"); + ImagePool *pool = MEM_cnew<ImagePool>("Image Pool"); pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolItem), 0, 128, BLI_MEMPOOL_NOP); BLI_mutex_init(&pool->mutex); @@ -5545,11 +5627,13 @@ void BKE_image_pool_free(ImagePool *pool) { /* Use single lock to dereference all the image buffers. */ BLI_mutex_lock(&pool->mutex); - for (ImagePoolItem *item = pool->image_buffers.first; item != NULL; item = item->next) { - if (item->ibuf != NULL) { - BLI_mutex_lock(item->image->runtime.cache_mutex); + for (ImagePoolItem *item = static_cast<ImagePoolItem *>(pool->image_buffers.first); + item != nullptr; + item = item->next) { + if (item->ibuf != nullptr) { + BLI_mutex_lock(static_cast<ThreadMutex *>(item->image->runtime.cache_mutex)); IMB_freeImBuf(item->ibuf); - BLI_mutex_unlock(item->image->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(item->image->runtime.cache_mutex)); } } BLI_mutex_unlock(&pool->mutex); @@ -5568,14 +5652,14 @@ BLI_INLINE ImBuf *image_pool_find_item( *found = false; - for (item = pool->image_buffers.first; item; item = item->next) { + for (item = static_cast<ImagePoolItem *>(pool->image_buffers.first); item; item = item->next) { if (item->image == image && item->entry == entry && item->index == index) { *found = true; return item->ibuf; } } - return NULL; + return nullptr; } ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool) @@ -5585,12 +5669,12 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool bool found; if (!image_quick_test(ima, iuser)) { - return NULL; + return nullptr; } - if (pool == NULL) { - /* Pool could be NULL, in this case use general acquire function. */ - return BKE_image_acquire_ibuf(ima, iuser, NULL); + if (pool == nullptr) { + /* Pool could be null, in this case use general acquire function. */ + return BKE_image_acquire_ibuf(ima, iuser, nullptr); } image_get_entry_and_index(ima, iuser, &entry, &index); @@ -5616,9 +5700,9 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool /* Thread-safe acquisition of an image buffer from the image. * The acquisition does not use image pools, so there is no risk of recursive or out-of-order * mutex locking. */ - ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); + ibuf = BKE_image_acquire_ibuf(ima, iuser, nullptr); - item = BLI_mempool_alloc(pool->memory_pool); + item = static_cast<ImagePoolItem *>(BLI_mempool_alloc(pool->memory_pool)); item->image = ima; item->entry = entry; item->index = index; @@ -5637,8 +5721,8 @@ void BKE_image_pool_release_ibuf(Image *ima, ImBuf *ibuf, ImagePool *pool) /* if pool wasn't actually used, use general release stuff, * for pools image buffers will be dereferenced on pool free */ - if (pool == NULL) { - BKE_image_release_ibuf(ima, ibuf, NULL); + if (pool == nullptr) { + BKE_image_release_ibuf(ima, ibuf, nullptr); } } @@ -5758,7 +5842,7 @@ void BKE_image_editors_update_frame(const Main *bmain, int cfra) { /* This only updates images used by the user interface. For others the * dependency graph will call BKE_image_user_id_eval_animation. */ - wmWindowManager *wm = bmain->wm.first; + wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); image_walk_id_all_users(&wm->id, false, &cfra, image_editors_update_frame); } @@ -5818,7 +5902,7 @@ void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath) void BKE_image_user_file_path_ex(ImageUser *iuser, Image *ima, char *filepath, bool resolve_udim) { if (BKE_image_is_multiview(ima)) { - ImageView *iv = BLI_findlink(&ima->views, iuser->view); + ImageView *iv = static_cast<ImageView *>(BLI_findlink(&ima->views, iuser->view)); if (iv->filepath[0]) { BLI_strncpy(filepath, iv->filepath, FILE_MAX); } @@ -5853,17 +5937,14 @@ void BKE_image_user_file_path_ex(ImageUser *iuser, Image *ima, char *filepath, b BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id)); } -bool BKE_image_has_alpha(struct Image *image) +bool BKE_image_has_alpha(Image *image) { - ImBuf *ibuf; void *lock; - int planes; - - ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); - planes = (ibuf ? ibuf->planes : 0); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); + const int planes = (ibuf ? ibuf->planes : 0); BKE_image_release_ibuf(image, ibuf, lock); - if (planes == 32) { + if (planes == 32 || planes == 16) { return true; } @@ -5872,10 +5953,10 @@ bool BKE_image_has_alpha(struct Image *image) void BKE_image_get_size(Image *image, ImageUser *iuser, int *r_width, int *r_height) { - ImBuf *ibuf = NULL; + ImBuf *ibuf = nullptr; void *lock; - if (image != NULL) { + if (image != nullptr) { ibuf = BKE_image_acquire_ibuf(image, iuser, &lock); } @@ -5883,8 +5964,8 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *r_width, int *r_hei *r_width = ibuf->x; *r_height = ibuf->y; } - else if (image != NULL && image->type == IMA_TYPE_R_RESULT && iuser != NULL && - iuser->scene != NULL) { + else if (image != nullptr && image->type == IMA_TYPE_R_RESULT && iuser != nullptr && + iuser->scene != nullptr) { Scene *scene = iuser->scene; *r_width = (scene->r.xsch * scene->r.size) / 100; *r_height = (scene->r.ysch * scene->r.size) / 100; @@ -5898,7 +5979,7 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *r_width, int *r_hei *r_height = IMG_SIZE_FALLBACK; } - if (image != NULL) { + if (image != nullptr) { BKE_image_release_ibuf(image, ibuf, lock); } } @@ -5931,7 +6012,7 @@ unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame, in BKE_imageuser_default(&iuser); void *lock; ImBuf *ibuf; - unsigned char *pixels = NULL; + unsigned char *pixels = nullptr; iuser.framenr = frame; iuser.tile = tile; @@ -5942,14 +6023,14 @@ unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame, in pixels = (unsigned char *)ibuf->rect; if (pixels) { - pixels = MEM_dupallocN(pixels); + pixels = static_cast<unsigned char *>(MEM_dupallocN(pixels)); } BKE_image_release_ibuf(image, ibuf, lock); } if (!pixels) { - return NULL; + return nullptr; } return pixels; @@ -5961,7 +6042,7 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int BKE_imageuser_default(&iuser); void *lock; ImBuf *ibuf; - float *pixels = NULL; + float *pixels = nullptr; iuser.framenr = frame; iuser.tile = tile; @@ -5972,14 +6053,14 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int pixels = ibuf->rect_float; if (pixels) { - pixels = MEM_dupallocN(pixels); + pixels = static_cast<float *>(MEM_dupallocN(pixels)); } BKE_image_release_ibuf(image, ibuf, lock); } if (!pixels) { - return NULL; + return nullptr; } return pixels; @@ -5987,7 +6068,7 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int int BKE_image_sequence_guess_offset(Image *image) { - return BLI_path_sequence_decode(image->filepath, NULL, NULL, NULL); + return BLI_path_sequence_decode(image->filepath, nullptr, nullptr, nullptr); } bool BKE_image_has_anim(Image *ima) @@ -6022,13 +6103,13 @@ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable) bool is_dirty = false; bool is_writable = false; - BLI_mutex_lock(image->runtime.cache_mutex); - if (image->cache != NULL) { + BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); + if (image->cache != nullptr) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); while (!IMB_moviecacheIter_done(iter)) { ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter); - if (ibuf != NULL && ibuf->userflags & IB_BITMAPDIRTY) { + if (ibuf != nullptr && ibuf->userflags & IB_BITMAPDIRTY) { is_writable = BKE_image_buffer_format_writable(ibuf); is_dirty = true; break; @@ -6037,7 +6118,7 @@ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable) } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); if (r_is_writable) { *r_is_writable = is_writable; @@ -6048,7 +6129,7 @@ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable) bool BKE_image_is_dirty(Image *image) { - return BKE_image_is_dirty_writable(image, NULL); + return BKE_image_is_dirty_writable(image, nullptr); } void BKE_image_mark_dirty(Image *UNUSED(image), ImBuf *ibuf) @@ -6066,34 +6147,34 @@ bool BKE_image_buffer_format_writable(ImBuf *ibuf) void BKE_image_file_format_set(Image *image, int ftype, const ImbFormatOptions *options) { - BLI_mutex_lock(image->runtime.cache_mutex); - if (image->cache != NULL) { + BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); + if (image->cache != nullptr) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); while (!IMB_moviecacheIter_done(iter)) { ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter); - if (ibuf != NULL) { - ibuf->ftype = ftype; + if (ibuf != nullptr) { + ibuf->ftype = static_cast<eImbFileType>(ftype); ibuf->foptions = *options; } IMB_moviecacheIter_step(iter); } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); } bool BKE_image_has_loaded_ibuf(Image *image) { bool has_loaded_ibuf = false; - BLI_mutex_lock(image->runtime.cache_mutex); - if (image->cache != NULL) { + BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); + if (image->cache != nullptr) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); while (!IMB_moviecacheIter_done(iter)) { ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter); - if (ibuf != NULL) { + if (ibuf != nullptr) { has_loaded_ibuf = true; break; } @@ -6101,22 +6182,22 @@ bool BKE_image_has_loaded_ibuf(Image *image) } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); return has_loaded_ibuf; } ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name) { - ImBuf *ibuf = NULL; + ImBuf *ibuf = nullptr; - BLI_mutex_lock(image->runtime.cache_mutex); - if (image->cache != NULL) { + BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); + if (image->cache != nullptr) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); while (!IMB_moviecacheIter_done(iter)) { ImBuf *current_ibuf = IMB_moviecacheIter_getImBuf(iter); - if (current_ibuf != NULL && STREQ(current_ibuf->name, name)) { + if (current_ibuf != nullptr && STREQ(current_ibuf->name, name)) { ibuf = current_ibuf; IMB_refImBuf(ibuf); break; @@ -6125,29 +6206,29 @@ ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name) } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); return ibuf; } ImBuf *BKE_image_get_first_ibuf(Image *image) { - ImBuf *ibuf = NULL; + ImBuf *ibuf = nullptr; - BLI_mutex_lock(image->runtime.cache_mutex); - if (image->cache != NULL) { + BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); + if (image->cache != nullptr) { struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); while (!IMB_moviecacheIter_done(iter)) { ibuf = IMB_moviecacheIter_getImBuf(iter); - if (ibuf != NULL) { + if (ibuf != nullptr) { IMB_refImBuf(ibuf); } break; } IMB_moviecacheIter_free(iter); } - BLI_mutex_unlock(image->runtime.cache_mutex); + BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex)); return ibuf; } @@ -6178,7 +6259,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser) /* R_IMF_VIEWS_INDIVIDUAL */ char prefix[FILE_MAX] = {'\0'}; char *name = ima->filepath; - const char *ext = NULL; + const char *ext = nullptr; BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext); @@ -6188,7 +6269,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser) } /* create all the image views */ - for (srv = scene->r.views.first; srv; srv = srv->next) { + for (srv = static_cast<SceneRenderView *>(scene->r.views.first); srv; srv = srv->next) { if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) { char filepath[FILE_MAX]; SNPRINTF(filepath, "%s%s%s", prefix, srv->suffix, ext); @@ -6197,7 +6278,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser) } /* check if the files are all available */ - iv = ima->views.last; + iv = static_cast<ImageView *>(ima->views.last); while (iv) { int file; char str[FILE_MAX]; @@ -6226,11 +6307,15 @@ static void image_update_views_format(Image *ima, ImageUser *iuser) } } -/**************************** Render Slots ***************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Render Slots + * \{ */ RenderSlot *BKE_image_add_renderslot(Image *ima, const char *name) { - RenderSlot *slot = MEM_callocN(sizeof(RenderSlot), "Image new Render Slot"); + RenderSlot *slot = MEM_cnew<RenderSlot>("Image new Render Slot"); if (name && name[0]) { BLI_strncpy(slot->name, name, sizeof(slot->name)); } @@ -6242,9 +6327,9 @@ RenderSlot *BKE_image_add_renderslot(Image *ima, const char *name) return slot; } -bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int index) +bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int slot) { - if (index == ima->last_render_slot) { + if (slot == ima->last_render_slot) { /* Don't remove render slot while rendering to it. */ if (G.is_rendering) { return false; @@ -6252,17 +6337,20 @@ bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int index) } int num_slots = BLI_listbase_count(&ima->renderslots); - if (index >= num_slots || num_slots == 1) { + if (slot >= num_slots || num_slots == 1) { return false; } - RenderSlot *remove_slot = BLI_findlink(&ima->renderslots, index); - RenderSlot *current_slot = BLI_findlink(&ima->renderslots, ima->render_slot); - RenderSlot *current_last_slot = BLI_findlink(&ima->renderslots, ima->last_render_slot); + RenderSlot *remove_slot = static_cast<RenderSlot *>(BLI_findlink(&ima->renderslots, slot)); + RenderSlot *current_slot = static_cast<RenderSlot *>( + BLI_findlink(&ima->renderslots, ima->render_slot)); + RenderSlot *current_last_slot = static_cast<RenderSlot *>( + BLI_findlink(&ima->renderslots, ima->last_render_slot)); RenderSlot *next_slot; if (current_slot == remove_slot) { - next_slot = BLI_findlink(&ima->renderslots, (index == num_slots - 1) ? index - 1 : index + 1); + next_slot = static_cast<RenderSlot *>( + BLI_findlink(&ima->renderslots, (slot == num_slots - 1) ? slot - 1 : slot + 1)); } else { next_slot = current_slot; @@ -6308,9 +6396,9 @@ bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int index) return true; } -bool BKE_image_clear_renderslot(Image *ima, ImageUser *iuser, int index) +bool BKE_image_clear_renderslot(Image *ima, ImageUser *iuser, int slot) { - if (index == ima->last_render_slot) { + if (slot == ima->last_render_slot) { if (!iuser) { return false; } @@ -6325,19 +6413,21 @@ bool BKE_image_clear_renderslot(Image *ima, ImageUser *iuser, int index) return true; } - RenderSlot *slot = BLI_findlink(&ima->renderslots, index); + RenderSlot *render_slot = static_cast<RenderSlot *>(BLI_findlink(&ima->renderslots, slot)); if (!slot) { return false; } - if (slot->render) { - RE_FreeRenderResult(slot->render); - slot->render = NULL; + if (render_slot->render) { + RE_FreeRenderResult(render_slot->render); + render_slot->render = nullptr; } return true; } RenderSlot *BKE_image_get_renderslot(Image *ima, int index) { - /* Can be NULL for images without render slots. */ - return BLI_findlink(&ima->renderslots, index); + /* Can be null for images without render slots. */ + return static_cast<RenderSlot *>(BLI_findlink(&ima->renderslots, index)); } + +/** \} */ diff --git a/source/blender/blenkernel/intern/image_gpu.cc b/source/blender/blenkernel/intern/image_gpu.cc index c4a43d8b023..0d470c5b663 100644 --- a/source/blender/blenkernel/intern/image_gpu.cc +++ b/source/blender/blenkernel/intern/image_gpu.cc @@ -280,7 +280,7 @@ static GPUTexture **get_image_gpu_texture_ptr(Image *ima, { const bool in_range = (textarget >= 0) && (textarget < TEXTARGET_COUNT); BLI_assert(in_range); - BLI_assert(multiview_eye == 0 || multiview_eye == 1); + BLI_assert(ELEM(multiview_eye, 0, 1)); const int resolution = (texture_resolution == IMA_TEXTURE_RESOLUTION_LIMITED) ? 1 : 0; if (in_range) { diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index e28094c0abc..bd6ffa2bc55 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -206,7 +206,7 @@ IDTypeInfo IDType_ID_KE = { .foreach_id = shapekey_foreach_id, .foreach_cache = NULL, .foreach_path = NULL, - /* A bit weird, due to shapekeys not being strictly speaking embedded data... But they also + /* A bit weird, due to shape-keys not being strictly speaking embedded data... But they also * share a lot with those (non linkable, only ever used by one owner ID, etc.). */ .owner_get = shapekey_owner_get, diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 7cd3204f3f1..28745f1d2c7 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -1875,7 +1875,7 @@ void BKE_library_make_local(Main *bmain, for (int a = set_listbasepointers(bmain, lbarray); a--;) { ID *id = lbarray[a]->first; - /* Do not explicitly make local non-linkable IDs (shapekeys, in fact), + /* Do not explicitly make local non-linkable IDs (shape-keys, in fact), * they are assumed to be handled by real data-blocks responsible of them. */ const bool do_skip = (id && !BKE_idtype_idcode_is_linkable(GS(id->name))); @@ -1902,8 +1902,8 @@ void BKE_library_make_local(Main *bmain, * to discover all your links are lost after appending). * Also, never ever make proxified objects local, would not make any sense. */ /* Some more notes: - * - Shapekeys are never tagged here (since they are not linkable). - * - Nodetrees used in materials etc. have to be tagged manually, + * - Shape-keys are never tagged here (since they are not linkable). + * - Node-trees used in materials etc. have to be tagged manually, * since they do not exist in Main (!). * This is ok-ish on 'make local' side of things * (since those are handled by their 'owner' IDs), diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 922c1beda38..7f34ccfc36f 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1063,7 +1063,7 @@ static void lib_override_library_create_post_process(Main *bmain, break; } default: - BLI_assert(0); + break; } } if (default_instantiating_collection == NULL) { @@ -2854,6 +2854,7 @@ bool BKE_lib_override_library_status_check_reference(Main *bmain, ID *local) bool BKE_lib_override_library_operations_create(Main *bmain, ID *local) { + BLI_assert(!ID_IS_LINKED(local)); BLI_assert(local->override_library != NULL); const bool is_template = (local->override_library->reference == NULL); bool created = false; @@ -2978,6 +2979,12 @@ bool BKE_lib_override_library_main_operations_create(Main *bmain, const bool for id->override_library, IDOVERRIDE_LIBRARY_TAG_UNUSED, false); } } + else { + /* Clear 'unused' tag for un-processed IDs, otherwise e.g. linked overrides will loose their + * list of overridden properties. */ + BKE_lib_override_library_properties_tag( + id->override_library, IDOVERRIDE_LIBRARY_TAG_UNUSED, false); + } id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH; } FOREACH_MAIN_ID_END; @@ -3413,7 +3420,7 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain, { if (ID_IS_OVERRIDE_LIBRARY_TEMPLATE(local) || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(local)) { /* This is actually purely local data with an override template, or one of those embedded IDs - * (root node trees, master collections or shapekeys) that cannot have their own override. + * (root node trees, master collections or shape-keys) that cannot have their own override. * Nothing to do here! */ return NULL; } diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index e50d6263423..bbcc886f3ff 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -2035,7 +2035,7 @@ bool BKE_linestyle_use_textures(FreestyleLineStyle *linestyle, const bool use_sh void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linestyle) { - bNode *uv_along_stroke, *input_texure, *output_linestyle; + bNode *uv_along_stroke, *input_texture, *output_linestyle; bNodeSocket *fromsock, *tosock; bNodeTree *ntree; @@ -2050,9 +2050,9 @@ void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linesty uv_along_stroke->locy = 300.0f; uv_along_stroke->custom1 = 0; /* use_tips */ - input_texure = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE); - input_texure->locx = 200.0f; - input_texure->locy = 300.0f; + input_texture = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE); + input_texture->locx = 200.0f; + input_texture->locy = 300.0f; output_linestyle = nodeAddStaticNode(C, ntree, SH_NODE_OUTPUT_LINESTYLE); output_linestyle->locx = 400.0f; @@ -2060,15 +2060,15 @@ void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linesty output_linestyle->custom1 = MA_RAMP_BLEND; output_linestyle->custom2 = 0; /* use_clamp */ - nodeSetActive(ntree, input_texure); + nodeSetActive(ntree, input_texture); fromsock = BLI_findlink(&uv_along_stroke->outputs, 0); /* UV */ - tosock = BLI_findlink(&input_texure->inputs, 0); /* UV */ - nodeAddLink(ntree, uv_along_stroke, fromsock, input_texure, tosock); + tosock = BLI_findlink(&input_texture->inputs, 0); /* UV */ + nodeAddLink(ntree, uv_along_stroke, fromsock, input_texture, tosock); - fromsock = BLI_findlink(&input_texure->outputs, 0); /* Color */ + fromsock = BLI_findlink(&input_texture->outputs, 0); /* Color */ tosock = BLI_findlink(&output_linestyle->inputs, 0); /* Color */ - nodeAddLink(ntree, input_texure, fromsock, output_linestyle, tosock); + nodeAddLink(ntree, input_texture, fromsock, output_linestyle, tosock); BKE_ntree_update_main_tree(CTX_data_main(C), ntree, NULL); } diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index fca7c10ca77..42e65a95404 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -609,7 +609,7 @@ float BKE_mask_spline_project_co(MaskSpline *spline, if (len_squared_v2(v1) > proj_eps_sq) { ang1 = angle_v2v2(v1, n1); - if (ang1 > (float)M_PI / 2.0f) { + if (ang1 > (float)M_PI_2) { ang1 = (float)M_PI - ang1; } @@ -635,7 +635,7 @@ float BKE_mask_spline_project_co(MaskSpline *spline, if (len_squared_v2(v2) > proj_eps_sq) { ang2 = angle_v2v2(v2, n2); - if (ang2 > (float)M_PI / 2.0f) { + if (ang2 > (float)M_PI_2) { ang2 = (float)M_PI - ang2; } @@ -1374,7 +1374,7 @@ static void mask_calc_point_handle(MaskSplinePoint *point, else if (handle_type == HD_AUTO) { BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0, 0); } - else if (handle_type == HD_ALIGN || handle_type == HD_ALIGN_DOUBLESIDE) { + else if (ELEM(handle_type, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) { float v1[3], v2[3]; float vec[3], h[3]; diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 37564f9334f..824c1ab1b90 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -142,11 +142,11 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int mesh_dst->mselect = (MSelect *)MEM_dupallocN(mesh_dst->mselect); - /* Set normal layers dirty, since they aren't included in CD_MASK_MESH and are therefore not - * copied to the destination mesh. Alternatively normal layers could be copied if they aren't - * dirty, avoiding recomputation in some cases. However, a copied mesh is often changed anyway, - * so that idea is not clearly better. With proper reference counting, all custom data layers - * could be copied as the cost would be much lower. */ + /* Set normal layers dirty. They should be dirty by default on new meshes anyway, but being + * explicit about it is safer. Alternatively normal layers could be copied if they aren't dirty, + * avoiding recomputation in some cases. However, a copied mesh is often changed anyway, so that + * idea is not clearly better. With proper reference counting, all custom data layers could be + * copied as the cost would be much lower. */ BKE_mesh_normals_tag_dirty(mesh_dst); /* TODO: Do we want to add flag to prevent this? */ @@ -510,7 +510,6 @@ static int customdata_compare( return MESHCMP_VERTCOMISMATCH; } } - /* I don't care about normals, let's just do coordinates. */ } break; } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index a53714c8a98..c23110b4703 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1609,8 +1609,10 @@ void BKE_movieclip_get_cache_segments(MovieClip *clip, if (clip->cache) { int proxy = rendersize_to_proxy(user, clip->flag); + BLI_thread_lock(LOCK_MOVIECLIP); IMB_moviecache_get_cache_segments( clip->cache->moviecache, proxy, user->render_flag, r_totseg, r_points); + BLI_thread_unlock(LOCK_MOVIECLIP); } } diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 1c0eb0ecd44..29770ea5475 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -553,7 +553,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage); } else if ((ntree->type == NTREE_TEXTURE) && - (node->type == TEX_NODE_CURVE_RGB || node->type == TEX_NODE_CURVE_TIME)) { + ELEM(node->type, TEX_NODE_CURVE_RGB, TEX_NODE_CURVE_TIME)) { BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage); } else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_MOVIEDISTORTION)) { @@ -579,7 +579,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage); } else if ((ntree->type == NTREE_COMPOSIT) && - (ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY))) { + ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY)) { NodeCryptomatte *nc = (NodeCryptomatte *)node->storage; BLO_write_string(writer, nc->matte_id); LISTBASE_FOREACH (CryptomatteEntry *, entry, &nc->entries) { diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index d42c8ea37d5..238cf1ad74e 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -551,6 +551,8 @@ ePaintMode BKE_paintmode_get_active_from_context(const bContext *C) return PAINT_MODE_TEXTURE_3D; case OB_MODE_EDIT: return PAINT_MODE_SCULPT_UV; + case OB_MODE_SCULPT_CURVES: + return PAINT_MODE_SCULPT_CURVES; default: return PAINT_MODE_TEXTURE_2D; } diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index 7a2e4eb4ac9..8106ae8b302 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -85,7 +85,7 @@ static void do_kink_spiral_deform(ParticleKey *state, * and goes up to the Golden Spiral for 1.0 * https://en.wikipedia.org/wiki/Golden_spiral */ - const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI * 0.25f; + const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI_4; /* angle of the spiral against the curve (rotated opposite to make a smooth transition) */ const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) : (float)-M_PI_2) + (b > 0.0f ? -(float)M_PI_2 : (float)M_PI_2); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 859e3499cc4..19abff19b77 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -683,8 +683,7 @@ static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v) if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { in_len = sizeof(PaintPoint) * total_points; } - else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || - surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) { + else if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WEIGHT)) { in_len = sizeof(float) * total_points; } else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) { diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index b1b9a24ebaa..ebc87c6ccc0 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -58,7 +58,7 @@ static void screen_free_data(ID *id) { bScreen *screen = (bScreen *)id; - /* No animdata here. */ + /* No animation-data here. */ LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) { BKE_area_region_free(NULL, region); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index fd9735ff07f..b991805fae8 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -87,7 +87,7 @@ static void sound_free_data(ID *id) { bSound *sound = (bSound *)id; - /* No animdata here. */ + /* No animation-data here. */ if (sound->packedfile) { BKE_packedfile_free(sound->packedfile); @@ -727,16 +727,11 @@ void *BKE_sound_add_scene_sound( } sound_verify_evaluated_id(&sequence->sound->id); const double fps = FPS; - void *handle = AUD_Sequence_add(scene->sound_scene, - sequence->sound->playback_handle, - startframe / fps, - endframe / fps, - frameskip / fps + sequence->sound->offset_time); - AUD_SequenceEntry_setMuted(handle, (sequence->flag & SEQ_MUTE) != 0); - AUD_SequenceEntry_setAnimationData(handle, AUD_AP_VOLUME, CFRA, &sequence->volume, 0); - AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, CFRA, &sequence->pitch, 0); - AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PANNING, CFRA, &sequence->pan, 0); - return handle; + return AUD_Sequence_add(scene->sound_scene, + sequence->sound->playback_handle, + startframe / fps, + endframe / fps, + frameskip / fps + sequence->sound->offset_time); } void *BKE_sound_add_scene_sound_defaults(Scene *scene, Sequence *sequence) diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc index 3c2ac1dae9c..e9ae51b16f8 100644 --- a/source/blender/blenkernel/intern/spline_bezier.cc +++ b/source/blender/blenkernel/intern/spline_bezier.cc @@ -365,7 +365,7 @@ BezierSpline::InsertResult BezierSpline::calculate_segment_insertion(const int i using namespace blender::math; BLI_assert(parameter <= 1.0f && parameter >= 0.0f); - BLI_assert(next_index == 0 || next_index == index + 1); + BLI_assert(ELEM(next_index, 0, index + 1)); const float3 &point_prev = positions_[index]; const float3 &handle_prev = handle_positions_right_[index]; const float3 &handle_next = handle_positions_left_[next_index]; diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc index c2479e9e595..7dc5ac3ea12 100644 --- a/source/blender/blenkernel/intern/spline_nurbs.cc +++ b/source/blender/blenkernel/intern/spline_nurbs.cc @@ -142,15 +142,11 @@ bool NURBSpline::check_valid_size_and_order() const return false; } - if (!is_cyclic_ && this->knots_mode == KnotsMode::Bezier) { - if (order_ == 4) { - if (this->size() < 5) { - return false; - } - } - else if (order_ != 3) { + if (ELEM(this->knots_mode, NURBS_KNOT_MODE_BEZIER, NURBS_KNOT_MODE_ENDPOINT_BEZIER)) { + if (this->knots_mode == NURBS_KNOT_MODE_BEZIER && this->size() <= order_) { return false; } + return (!is_cyclic_ || this->size() % (order_ - 1) == 0); } return true; @@ -166,12 +162,13 @@ void NURBSpline::calculate_knots() const { const KnotsMode mode = this->knots_mode; const int order = order_; - const bool is_bezier = mode == NURBSpline::KnotsMode::Bezier; - const bool is_end_point = mode == NURBSpline::KnotsMode::EndPoint; + const bool is_bezier = ELEM(mode, NURBS_KNOT_MODE_BEZIER, NURBS_KNOT_MODE_ENDPOINT_BEZIER); + const bool is_end_point = ELEM(mode, NURBS_KNOT_MODE_ENDPOINT, NURBS_KNOT_MODE_ENDPOINT_BEZIER); /* Inner knots are always repeated once except on Bezier case. */ const int repeat_inner = is_bezier ? order - 1 : 1; /* How many times to repeat 0.0 at the beginning of knot. */ - const int head = is_end_point && !is_cyclic_ ? order : (is_bezier ? order / 2 : 1); + const int head = is_end_point ? (order - (is_cyclic_ ? 1 : 0)) : + (is_bezier ? min_ii(2, repeat_inner) : 1); /* Number of knots replicating widths of the starting knots. * Covers both Cyclic and EndPoint cases. */ const int tail = is_cyclic_ ? 2 * order - 1 : (is_end_point ? order : 0); @@ -182,7 +179,13 @@ void NURBSpline::calculate_knots() const int r = head; float current = 0.0f; - for (const int i : IndexRange(knots.size() - tail)) { + const int offset = is_end_point && is_cyclic_ ? 1 : 0; + if (offset) { + knots[0] = current; + current += 1.0f; + } + + for (const int i : IndexRange(offset, knots.size() - offset - tail)) { knots[i] = current; r--; if (r == 0) { @@ -219,17 +222,17 @@ Span<float> NURBSpline::knots() const static void calculate_basis_for_point(const float parameter, const int size, - const int order, + const int degree, Span<float> knots, MutableSpan<float> basis_buffer, NURBSpline::BasisCache &basis_cache) { /* Clamp parameter due to floating point inaccuracy. */ - const float t = std::clamp(parameter, knots[0], knots[size + order - 1]); + const float t = std::clamp(parameter, knots[0], knots[size + degree]); int start = 0; int end = 0; - for (const int i : IndexRange(size + order - 1)) { + for (const int i : IndexRange(size + degree)) { const bool knots_equal = knots[i] == knots[i + 1]; if (knots_equal || t < knots[i] || t > knots[i + 1]) { basis_buffer[i] = 0.0f; @@ -237,16 +240,16 @@ static void calculate_basis_for_point(const float parameter, } basis_buffer[i] = 1.0f; - start = std::max(i - order - 1, 0); + start = std::max(i - degree, 0); end = i; - basis_buffer.slice(i + 1, size + order - 1 - i).fill(0.0f); + basis_buffer.slice(i + 1, size + degree - i).fill(0.0f); break; } - basis_buffer[size + order - 1] = 0.0f; + basis_buffer[size + degree] = 0.0f; - for (const int i_order : IndexRange(2, order - 1)) { - if (end + i_order >= size + order) { - end = size + order - 1 - i_order; + for (const int i_order : IndexRange(2, degree)) { + if (end + i_order >= size + degree + 1) { + end = size + degree - i_order; } for (const int i : IndexRange(start, end - start + 1)) { float new_basis = 0.0f; @@ -296,6 +299,7 @@ Span<NURBSpline::BasisCache> NURBSpline::calculate_basis_cache() const basis_cache_.resize(eval_size); const int order = this->order(); + const int degree = order - 1; Span<float> control_weights = this->weights(); Span<float> knots = this->knots(); @@ -305,14 +309,14 @@ Span<NURBSpline::BasisCache> NURBSpline::calculate_basis_cache() const * Theoretically it could be optimized away in the future. */ Array<float> basis_buffer(this->knots_size()); - const float start = knots[order - 1]; - const float end = is_cyclic_ ? knots[size + order - 1] : knots[size]; + const float start = knots[degree]; + const float end = is_cyclic_ ? knots[size + degree] : knots[size]; const float step = (end - start) / this->evaluated_edges_size(); float parameter = start; for (const int i : IndexRange(eval_size)) { BasisCache &basis = basis_cache[i]; calculate_basis_for_point( - parameter, size + (is_cyclic_ ? order - 1 : 0), order, knots, basis_buffer, basis); + parameter, size + (is_cyclic_ ? degree : 0), degree, knots, basis_buffer, basis); BLI_assert(basis.weights.size() <= order); for (const int j : basis.weights.index_range()) { diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 5d0e515040d..486449c3f86 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -1436,78 +1436,20 @@ void txt_from_buf_for_undo(Text *text, const char *buf, int buf_len) char *txt_to_buf(Text *text, int *r_buf_strlen) { - int length; - TextLine *tmp, *linef, *linel; - int charf, charl; - char *buf; - - if (r_buf_strlen) { - *r_buf_strlen = 0; - } - - if (!text->curl) { - return NULL; - } - if (!text->sell) { - return NULL; - } - if (!text->lines.first) { - return NULL; - } - - linef = text->lines.first; - charf = 0; - - linel = text->lines.last; - charl = linel->len; - - if (linef == text->lines.last) { - length = charl - charf; - - buf = MEM_mallocN(length + 2, "text buffer"); - - BLI_strncpy(buf, linef->line + charf, length + 1); - buf[length] = 0; - } - else { - length = linef->len - charf; - length += charl; - length += 2; /* For the 2 '\n' */ - - tmp = linef->next; - while (tmp && tmp != linel) { - length += tmp->len + 1; - tmp = tmp->next; - } - - buf = MEM_mallocN(length + 1, "cut buffer"); - - strncpy(buf, linef->line + charf, linef->len - charf); - length = linef->len - charf; - - buf[length++] = '\n'; - - tmp = linef->next; - while (tmp && tmp != linel) { - strncpy(buf + length, tmp->line, tmp->len); - length += tmp->len; - - buf[length++] = '\n'; - - tmp = tmp->next; - } - strncpy(buf + length, linel->line, charl); - length += charl; - - /* python compiler wants an empty end line */ - buf[length++] = '\n'; - buf[length] = 0; + /* Identical to #txt_to_buf_for_undo except that the string is nil terminated. */ + int buf_len = 0; + LISTBASE_FOREACH (const TextLine *, l, &text->lines) { + buf_len += l->len + 1; } - - if (r_buf_strlen) { - *r_buf_strlen = length; + char *buf = MEM_mallocN(buf_len + 1, __func__); + char *buf_step = buf; + LISTBASE_FOREACH (const TextLine *, l, &text->lines) { + memcpy(buf_step, l->line, l->len); + buf_step += l->len; + *buf_step++ = '\n'; } - + *buf_step = '\0'; + *r_buf_strlen = buf_len; return buf; } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 5708d3eeaec..2a415b8f6fb 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1473,7 +1473,7 @@ static const MovieTrackingMarker *get_usable_marker_for_interpolation( const MovieTrackingMarker *anchor_marker, const int direction) { - BLI_assert(direction == -1 || direction == 1); + BLI_assert(ELEM(direction, -1, 1)); const MovieTrackingMarker *last_marker = track->markers + track->markersnr - 1; const MovieTrackingMarker *current_marker = anchor_marker; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index b9d013d4756..5e11cd0703a 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -622,8 +622,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context, if (codec_id == AV_CODEC_ID_VP9 && rd->im_format.planes == R_IMF_PLANES_RGBA) { c->pix_fmt = AV_PIX_FMT_YUVA420P; } - else if ((codec_id == AV_CODEC_ID_H264 || codec_id == AV_CODEC_ID_VP9) && - context->ffmpeg_crf == 0) { + else if (ELEM(codec_id, AV_CODEC_ID_H264, AV_CODEC_ID_VP9) && (context->ffmpeg_crf == 0)) { /* Use 4:4:4 instead of 4:2:0 pixel format for lossless rendering. */ c->pix_fmt = AV_PIX_FMT_YUV444P; } diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 6f8b479dddd..04b40904187 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -149,10 +149,10 @@ eFileAttributes BLI_file_attributes(const char *path); * \{ */ /** - * Scans the contents of the directory named *dirname, and allocates and fills in an - * array of entries describing them in *filelist. + * Scans the contents of the directory named `dir`, and allocates and fills in an + * array of entries describing them in `r_filelist`. * - * \return The length of filelist array. + * \return The length of `r_filelist` array. */ unsigned int BLI_filelist_dir_contents(const char *dir, struct direntry **r_filelist); /** diff --git a/source/blender/blenlib/BLI_memiter.h b/source/blender/blenlib/BLI_memiter.h index 727092706c4..bf54b0ea14d 100644 --- a/source/blender/blenlib/BLI_memiter.h +++ b/source/blender/blenlib/BLI_memiter.h @@ -34,11 +34,12 @@ BLI_memiter *BLI_memiter_create(unsigned int chunk_size_min) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL; void *BLI_memiter_alloc(BLI_memiter *mi, unsigned int size) /* WARNING: `ATTR_MALLOC` attribute on #BLI_memiter_alloc causes crash, see: D2756. */ - ATTR_RETURNS_NONNULL ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1); + ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1); void BLI_memiter_alloc_from(BLI_memiter *mi, uint elem_size, const void *data_from) ATTR_NONNULL(1, 3); -void *BLI_memiter_calloc(BLI_memiter *mi, unsigned int size) - ATTR_RETURNS_NONNULL ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1); +void *BLI_memiter_calloc(BLI_memiter *mi, + unsigned int size) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL + ATTR_NONNULL(1); void BLI_memiter_destroy(BLI_memiter *mi) ATTR_NONNULL(1); void BLI_memiter_clear(BLI_memiter *mi) ATTR_NONNULL(1); unsigned int BLI_memiter_count(const BLI_memiter *mi) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 90a91cbe26f..bb6bc0db00d 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -95,10 +95,10 @@ MINLINE float saacos(float fac) MINLINE float saasin(float fac) { if (UNLIKELY(fac <= -1.0f)) { - return (float)-M_PI / 2.0f; + return (float)-M_PI_2; } else if (UNLIKELY(fac >= 1.0f)) { - return (float)M_PI / 2.0f; + return (float)M_PI_2; } else { return asinf(fac); @@ -131,10 +131,10 @@ MINLINE float saacosf(float fac) MINLINE float saasinf(float fac) { if (UNLIKELY(fac <= -1.0f)) { - return (float)-M_PI / 2.0f; + return (float)-M_PI_2; } else if (UNLIKELY(fac >= 1.0f)) { - return (float)M_PI / 2.0f; + return (float)M_PI_2; } else { return asinf(fac); diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index e71b1150d8f..da6a6dff16f 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -289,7 +289,7 @@ void mid_v3_v3v3_angle_weighted(float r[3], const float a[3], const float b[3]) BLI_ASSERT_UNIT_V3(b); add_v3_v3v3(r, a, b); - angle = ((float)(1.0 / (M_PI / 2.0)) * + angle = ((float)M_2_PI * /* normally we would only multiply by 2, * but instead of an angle make this 0-1 factor */ 2.0f) * @@ -305,7 +305,7 @@ void mid_v3_angle_weighted(float r[3]) /* double check they are normalized */ BLI_assert(len_squared_v3(r) <= 1.0f + FLT_EPSILON); - angle = ((float)(1.0 / (M_PI / 2.0)) * + angle = ((float)M_2_PI * /* normally we would only multiply by 2, * but instead of an angle make this 0-1 factor */ 2.0f) * diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 69ba9f7fb7b..f94d49cf1dd 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -470,7 +470,7 @@ void BLI_path_rel(char *file, const char *relfile) * can happen with old recent-files.txt files */ BLI_windows_get_default_root_dir(temp); ptemp = &temp[2]; - if (relfile[0] != '\\' && relfile[0] != '/') { + if (!ELEM(relfile[0], '\\', '/')) { ptemp++; } BLI_strncpy(ptemp, relfile, FILE_MAX - 3); @@ -629,7 +629,7 @@ bool BLI_path_parent_dir(char *path) BLI_path_normalize(NULL, tmp); /* does all the work of normalizing the path for us */ if (!BLI_path_extension_check(tmp, parent_dir)) { - strcpy(path, tmp); /* We assume pardir is always shorter... */ + strcpy(path, tmp); /* We assume the parent directory is always shorter. */ return true; } diff --git a/source/blender/blenlib/tests/BLI_task_test.cc b/source/blender/blenlib/tests/BLI_task_test.cc index 6a12ff10415..52852873a06 100644 --- a/source/blender/blenlib/tests/BLI_task_test.cc +++ b/source/blender/blenlib/tests/BLI_task_test.cc @@ -91,7 +91,7 @@ TEST(task, MempoolIter) int i; - /* 'Randomly' add and remove some items from mempool, to create a non-homogenous one. */ + /* 'Randomly' add and remove some items from mempool, to create a non-homogeneous one. */ int num_items = 0; for (i = 0; i < NUM_ITEMS; i++) { data[i] = (int *)BLI_mempool_alloc(mempool); diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h index 8f0f9fae97f..536c3989aff 100644 --- a/source/blender/blenloader/BLO_read_write.h +++ b/source/blender/blenloader/BLO_read_write.h @@ -286,8 +286,8 @@ void BLO_expand_id(BlendExpander *expander, struct ID *id); * This function ensures that reports are printed, * in the case of library linking errors this is important! * - * bit kludge but better than doubling up on prints, - * we could alternatively have a versions of a report function which forces printing - campbell + * NOTE(@campbellbarton) a kludge but better than doubling up on prints, + * we could alternatively have a versions of a report function which forces printing. */ void BLO_reportf_wrap(struct BlendFileReadReport *reports, eReportType type, diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9539436cf69..4ea6287399c 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -161,14 +161,14 @@ * which keeps large arrays in memory from data-blocks we may not even use. * * \note This is disabled when using compression, - * while zlib supports seek it's unusably slow, see: T61880. + * while ZLIB supports seek it's unusably slow, see: T61880. */ #define USE_BHEAD_READ_ON_DEMAND -/* use GHash for BHead name-based lookups (speeds up linking) */ +/** Use #GHash for #BHead name-based lookups (speeds up linking). */ #define USE_GHASH_BHEAD -/* Use GHash for restoring pointers by name */ +/** Use #GHash for restoring pointers by name. */ #define USE_GHASH_RESTORE_POINTER static CLG_LogRef LOG = {"blo.readfile"}; @@ -194,8 +194,10 @@ typedef struct BHeadN { #define BHEADN_FROM_BHEAD(bh) ((BHeadN *)POINTER_OFFSET(bh, -(int)offsetof(BHeadN, bhead))) -/* We could change this in the future, for now it's simplest if only data is delayed - * because ID names are used in lookup tables. */ +/** + * We could change this in the future, for now it's simplest if only data is delayed + * because ID names are used in lookup tables. + */ #define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == DATA) void BLO_reportf_wrap(BlendFileReadReport *reports, eReportType type, const char *format, ...) @@ -4711,9 +4713,9 @@ static void read_library_linked_ids(FileData *basefd, read_library_linked_id(basefd, fd, mainvar, id, realid); } - /* realid shall never be NULL - unless some source file/lib is broken + /* `realid` shall never be NULL - unless some source file/lib is broken * (known case: some directly linked shapekey from a missing lib...). */ - /* BLI_assert(*realid != NULL); */ + // BLI_assert(*realid != NULL); /* Now that we have a real ID, replace all pointers to placeholders in * fd->libmap with pointers to the real data-blocks. We do this for all diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 28b934843af..655dc297c35 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -1838,7 +1838,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain) Image *image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima); if (image && (image->flag & IMA_DO_PREMUL) == 0) { - const int IMA_IGNORE_ALPHA = (1 << 12); + enum { IMA_IGNORE_ALPHA = (1 << 12) }; image->flag |= IMA_IGNORE_ALPHA; } } diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 32dbabf2643..b1c982649d2 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -1550,7 +1550,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) { /* Unify DOF settings (EEVEE part only) */ - const int SCE_EEVEE_DOF_ENABLED = (1 << 7); + enum { SCE_EEVEE_DOF_ENABLED = (1 << 7) }; LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) { if (scene->eevee.flag & SCE_EEVEE_DOF_ENABLED) { @@ -2312,7 +2312,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } \ } \ ((void)0) - const int SCE_EEVEE_DOF_ENABLED = (1 << 7); + enum { SCE_EEVEE_DOF_ENABLED = (1 << 7) }; IDProperty *props = IDP_GetPropertyFromGroup(scene->layer_properties, RE_engine_id_BLENDER_EEVEE); // EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED); @@ -4032,7 +4032,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) if (!MAIN_VERSION_ATLEAST(bmain, 280, 70)) { /* New image alpha modes. */ LISTBASE_FOREACH (Image *, image, &bmain->images) { - const int IMA_IGNORE_ALPHA = (1 << 12); + enum { IMA_IGNORE_ALPHA = (1 << 12) }; if (image->flag & IMA_IGNORE_ALPHA) { image->alpha_mode = IMA_ALPHA_IGNORE; image->flag &= ~IMA_IGNORE_ALPHA; @@ -4497,7 +4497,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) clmd->sim_parms->max_internal_tension = 15.0f; clmd->sim_parms->internal_compression = 15.0f; clmd->sim_parms->max_internal_compression = 15.0f; - clmd->sim_parms->internal_spring_max_diversion = M_PI / 4.0f; + clmd->sim_parms->internal_spring_max_diversion = M_PI_4; } } } diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index ada011f191d..3ae26dea767 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -701,8 +701,10 @@ static void panels_remove_x_closed_flag_recursive(Panel *panel) static void do_versions_point_attributes(CustomData *pdata) { /* Change to generic named float/float3 attributes. */ - const int CD_LOCATION = 43; - const int CD_RADIUS = 44; + enum { + CD_LOCATION = 43, + CD_RADIUS = 44, + }; for (int i = 0; i < pdata->totlayer; i++) { CustomDataLayer *layer = &pdata->layers[i]; diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 2a840ea585a..accb3e521e1 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -42,6 +42,7 @@ #include "BKE_armature.h" #include "BKE_asset.h" #include "BKE_collection.h" +#include "BKE_curve.h" #include "BKE_deform.h" #include "BKE_fcurve.h" #include "BKE_fcurve_driver.h" @@ -1481,6 +1482,10 @@ static void version_liboverride_rnacollections_insertion_animdata(ID *id) /* NOLINTNEXTLINE: readability-function-size */ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) { + /* The #SCE_SNAP_SEQ flag has been removed in favor of the #SCE_SNAP which can be used for each + * snap_flag member individually. */ + enum { SCE_SNAP_SEQ = (1 << 7) }; + if (!MAIN_VERSION_ATLEAST(bmain, 300, 1)) { /* Set default value for the new bisect_threshold parameter in the mirror modifier. */ if (!DNA_struct_elem_find(fd->filesdna, "MirrorModifierData", "float", "bisect_threshold")) { @@ -2567,6 +2572,59 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 302, 6)) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + ToolSettings *ts = scene->toolsettings; + if (ts->uv_relax_method == 0) { + ts->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN; + } + } + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + ToolSettings *tool_settings = scene->toolsettings; + tool_settings->snap_flag_seq = tool_settings->snap_flag & ~(SCE_SNAP | SCE_SNAP_SEQ); + if (tool_settings->snap_flag & SCE_SNAP_SEQ) { + tool_settings->snap_flag_seq |= SCE_SNAP; + tool_settings->snap_flag &= ~SCE_SNAP_SEQ; + } + + tool_settings->snap_flag_node = tool_settings->snap_flag; + tool_settings->snap_uv_flag |= tool_settings->snap_flag & SCE_SNAP; + } + + /* Alter NURBS knot mode flags to fit new modes. */ + LISTBASE_FOREACH (Curve *, curve, &bmain->curves) { + LISTBASE_FOREACH (Nurb *, nurb, &curve->nurb) { + /* Previously other flags were ignored if CU_NURB_CYCLIC is set. */ + if (nurb->flagu & CU_NURB_CYCLIC) { + nurb->flagu = CU_NURB_CYCLIC; + } + /* CU_NURB_BEZIER and CU_NURB_ENDPOINT were ignored if combined. */ + else if (nurb->flagu & CU_NURB_BEZIER && nurb->flagu & CU_NURB_ENDPOINT) { + nurb->flagu &= ~(CU_NURB_BEZIER | CU_NURB_ENDPOINT); + BKE_nurb_knot_calc_u(nurb); + } + /* Bezier NURBS of order 3 were clamped to first control point. */ + else if (nurb->orderu == 3 && (nurb->flagu & CU_NURB_BEZIER)) { + nurb->flagu |= CU_NURB_ENDPOINT; + } + + /* Previously other flags were ignored if CU_NURB_CYCLIC is set. */ + if (nurb->flagv & CU_NURB_CYCLIC) { + nurb->flagv = CU_NURB_CYCLIC; + } + /* CU_NURB_BEZIER and CU_NURB_ENDPOINT were ignored if used together. */ + else if (nurb->flagv & CU_NURB_BEZIER && nurb->flagv & CU_NURB_ENDPOINT) { + nurb->flagv &= ~(CU_NURB_BEZIER | CU_NURB_ENDPOINT); + BKE_nurb_knot_calc_v(nurb); + } + /* Bezier NURBS of order 3 were clamped to first control point. */ + else if (nurb->orderv == 3 && (nurb->flagv & CU_NURB_BEZIER)) { + nurb->flagv |= CU_NURB_ENDPOINT; + } + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c index c654972730f..e1ceed82ba7 100644 --- a/source/blender/blenloader/intern/versioning_cycles.c +++ b/source/blender/blenloader/intern/versioning_cycles.c @@ -330,7 +330,7 @@ static void image_node_colorspace(bNode *node) return; } - const int SHD_COLORSPACE_NONE = 0; + enum { SHD_COLORSPACE_NONE = 0 }; Image *image = (Image *)node->id; if (color_space == SHD_COLORSPACE_NONE) { STRNCPY(image->colorspace_settings.name, @@ -1362,10 +1362,12 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm void do_versions_after_linking_cycles(Main *bmain) { - const int DENOISER_AUTO = 0; - const int DENOISER_NLM = 1; - const int DENOISER_OPTIX = 2; - const int DENOISER_OPENIMAGEDENOISE = 4; + enum { + DENOISER_AUTO = 0, + DENOISER_NLM = 1, + DENOISER_OPTIX = 2, + DENOISER_OPENIMAGEDENOISE = 4, + }; if (!MAIN_VERSION_ATLEAST(bmain, 280, 66)) { /* Shader node tree changes. After lib linking so we have all the typeinfo diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 2908b2b151b..5b026c1cca0 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1075,11 +1075,10 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) } } - /* ton: made this 230 instead of 229, - * to be sure (tuho files) and this is a reliable check anyway + /* NOTE(@ton): made this 230 instead of 229, + * to be sure (files from the `tuhopuu` branch) and this is a reliable check anyway * nevertheless, we might need to think over a fitness (initialize) - * check apart from the do_versions() - */ + * check apart from the do_versions(). */ if (bmain->versionfile <= 230) { bScreen *screen; diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc index f581e2967c0..fd14a3416e2 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc @@ -607,7 +607,7 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert) * * WARNING: There is an exception to the rule of ignoring coordinates in the destination: * that is when shape-key data in `bm` can't be found (which is itself an error/exception). - * In this case our own rule is violated as the alternative is loosing the shape-data entirely. + * In this case our own rule is violated as the alternative is losing the shape-data entirely. * * Flushing Coordinates Back to the #BMesh * --------------------------------------- @@ -677,8 +677,16 @@ static int bm_to_mesh_shape_layer_index_from_kb(BMesh *bm, KeyBlock *currkey) * \param bm: The source BMesh. * \param key: The destination key. * \param mvert: The destination vertex array (in some situations it's coordinates are updated). + * \param active_shapekey_to_mvert: When editing a non-basis shape key, the coordinates for the + * basis are typically copied into the `mvert` array since it makes sense for the meshes + * vertex coordinates to match the "Basis" key. + * When enabled, skip this step and copy #BMVert.co directly to #MVert.co, + * See #BMeshToMeshParams.active_shapekey_to_mvert doc-string. */ -static void bm_to_mesh_shape(BMesh *bm, Key *key, MVert *mvert) +static void bm_to_mesh_shape(BMesh *bm, + Key *key, + MVert *mvert, + const bool active_shapekey_to_mvert) { KeyBlock *actkey = static_cast<KeyBlock *>(BLI_findlink(&key->block, bm->shapenr - 1)); @@ -762,12 +770,14 @@ static void bm_to_mesh_shape(BMesh *bm, Key *key, MVert *mvert) * In this case it's important to overwrite these coordinates with the basis-keys coordinates. */ bool update_vertex_coords_from_refkey = false; int cd_shape_offset_refkey = -1; - if ((actkey != key->refkey) && (cd_shape_keyindex_offset != -1)) { - const int refkey_uuid = bm_to_mesh_shape_layer_index_from_kb(bm, key->refkey); - if (refkey_uuid != -1) { - cd_shape_offset_refkey = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, refkey_uuid); - if (cd_shape_offset_refkey != -1) { - update_vertex_coords_from_refkey = true; + if (active_shapekey_to_mvert == false) { + if ((actkey != key->refkey) && (cd_shape_keyindex_offset != -1)) { + const int refkey_uuid = bm_to_mesh_shape_layer_index_from_kb(bm, key->refkey); + if (refkey_uuid != -1) { + cd_shape_offset_refkey = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, refkey_uuid); + if (cd_shape_offset_refkey != -1) { + update_vertex_coords_from_refkey = true; + } } } } @@ -1137,7 +1147,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh } if (me->key) { - bm_to_mesh_shape(bm, me->key, me->mvert); + bm_to_mesh_shape(bm, me->key, me->mvert, params->active_shapekey_to_mvert); } /* Run this even when shape keys aren't used since it may be used for hooks or vertex parents. */ diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.h b/source/blender/bmesh/intern/bmesh_mesh_convert.h index 8e87fc86b6d..0bd70749cb1 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.h +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.h @@ -53,6 +53,11 @@ struct BMeshToMeshParams { * that have become invalid from updating the shape-key, see T71865. */ uint update_shapekey_indices : 1; + /** + * Instead of copying the basis shape-key into the #MVert array, + * copy the #BMVert.co directly to #MVert.co (used for reading undo data). + */ + uint active_shapekey_to_mvert : 1; struct CustomData_MeshMasks cd_mask_extra; }; /** diff --git a/source/blender/bmesh/operators/bmo_fill_edgeloop.c b/source/blender/bmesh/operators/bmo_fill_edgeloop.c index 352b9336a20..86d204ea6a7 100644 --- a/source/blender/bmesh/operators/bmo_fill_edgeloop.c +++ b/source/blender/bmesh/operators/bmo_fill_edgeloop.c @@ -3,7 +3,7 @@ /** \file * \ingroup bmesh * - * Fill discreet edge loop(s) with faces. + * Fill discrete edge loop(s) with faces. */ #include "MEM_guardedalloc.h" diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 10bdc2c7294..5790d76936f 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1859,7 +1859,7 @@ static void move_weld_profile_planes(BevVert *bv, BoundVert *bndv1, BoundVert *b float l1 = normalize_v3(no); /* "no" is new normal projection plane, but don't move if it is coplanar with both of the - * projection dirs. */ + * projection directions. */ float no2[3], no3[3]; cross_v3_v3v3(no2, d1, bndv1->profile.proj_dir); float l2 = normalize_v3(no2); @@ -5571,7 +5571,7 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv) /* Add verts from each cutoff face. */ face_bmverts[i] = mesh_vert(bv->vmesh, i, 1, 0)->v; } - /* BLI_array_append(bmfaces, repface); */ + // BLI_array_append(bmfaces, repface); bev_create_ngon(bm, face_bmverts, n_bndv, bmfaces, NULL, bmedges, bp->mat_nr, true); BLI_array_free(bmedges); @@ -7106,7 +7106,7 @@ static void find_even_superellipse_chords(int n, float r, double *xvals, double return; } if (r == PRO_CIRCLE_R) { - double temp = (M_PI / 2) / n; + double temp = M_PI_2 / n; /* Angle spacing. */ for (int i = 0; i <= n; i++) { xvals[i] = sin(i * temp); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 77597e0db06..49e850b1979 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -1408,7 +1408,7 @@ void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *particle_se } } -/* Shapekeys */ +/* Shape-keys. */ void DepsgraphNodeBuilder::build_shapekeys(Key *key) { if (built_map_.checkIsBuiltAndTag(key)) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index faad053e30c..68c644cc422 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1598,6 +1598,14 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu) add_relation(property_exit_key, parameters_key, "Driven Property -> Properties"); } } + + /* Assume drivers on a node tree affect the evaluated output of the node tree. In theory we could + * check if the driven value actually affects the output, i.e. if it drives a node that is linked + * to the output. */ + if (GS(id_ptr->name) == ID_NT) { + ComponentKey ntree_output_key(id_ptr, NodeType::NTREE_OUTPUT); + add_relation(driver_key, ntree_output_key, "Drivers -> NTree Output"); + } } void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu) diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index b8c85430f06..f945e9b6fbc 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -483,7 +483,7 @@ void deg_graph_node_tag_zero(Main *bmain, if (comp_node->type == NodeType::ANIMATION) { continue; } - else if (comp_node->type == NodeType::COPY_ON_WRITE) { + if (comp_node->type == NodeType::COPY_ON_WRITE) { id_node->is_cow_explicitly_tagged = true; } @@ -865,7 +865,7 @@ void DEG_ids_clear_recalc(Depsgraph *depsgraph, const bool backup) if (!DEG_id_type_any_updated(depsgraph)) { return; } - /* Go over all ID nodes nodes, clearing tags. */ + /* Go over all ID nodes, clearing tags. */ for (deg::IDNode *id_node : deg_graph->id_nodes) { if (backup) { id_node->id_cow_recalc_backup |= id_node->id_cow->recalc; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 6346bab1fe8..19022d534b2 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -41,6 +41,7 @@ #include "DNA_ID.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" +#include "DNA_gpencil_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" @@ -733,6 +734,16 @@ void update_id_after_copy(const Depsgraph *depsgraph, scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast<Scene *>(id_cow)); break; } + /* FIXME: This is a temporary fix to update the runtime pointers properly, see T96216. Should + * be removed at some point. */ + case ID_GD: { + bGPdata *gpd_cow = (bGPdata *)id_cow; + bGPDlayer *gpl = (bGPDlayer *)(gpd_cow->layers.first); + if (gpl != nullptr && gpl->runtime.gpl_orig == nullptr) { + BKE_gpencil_data_update_orig_pointers((bGPdata *)id_orig, gpd_cow); + } + break; + } default: break; } diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c index ef4d88bd521..0d14a0c5f61 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -62,7 +62,7 @@ static float circle_to_polygon_radius(float sides_count, float theta) cosf(theta - side_angle * floorf((sides_count * theta + M_PI) / (2.0f * M_PI))); } -/* Remap input angle to have homogenous spacing of points along a polygon edge. +/* Remap input angle to have homogeneous spacing of points along a polygon edge. * Expect theta to be in [0..2pi] range. */ static float circle_to_polygon_angle(float sides_count, float theta) { diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index a20fe156eda..7029d015b22 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -613,7 +613,7 @@ void EEVEE_lightprobes_planar_data_from_object(Object *ob, eplanar->clip_edge_y_neg = dot_v3v3(eplanar->clip_vec_y, vec); /* Facing factors */ - float max_angle = max_ff(1e-2f, 1.0f - probe->falloff) * M_PI * 0.5f; + float max_angle = max_ff(1e-2f, 1.0f - probe->falloff) * M_PI_2; float min_angle = 0.0f; eplanar->facing_scale = 1.0f / max_ff(1e-8f, cosf(min_angle) - cosf(max_angle)); eplanar->facing_bias = -min_ff(1.0f - 1e-8f, cosf(max_angle)) * eplanar->facing_scale; diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index 0ef78d97a79..874c2815b8b 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -217,7 +217,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, float x_rot_matrix[3][3]; DRW_view_viewmat_get(NULL, view_matrix, false); copy_m3_m4(view_rot_matrix, view_matrix); - axis_angle_to_mat3_single(x_rot_matrix, 'X', M_PI / 2.0f); + axis_angle_to_mat3_single(x_rot_matrix, 'X', M_PI_2); mul_m3_m3m3(view_rot_matrix, x_rot_matrix, view_rot_matrix); mul_m3_m3m3(view_rot_matrix, g_data->studiolight_matrix, view_rot_matrix); copy_m3_m3(studiolight_matrix, view_rot_matrix); diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_bokeh_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_bokeh_frag.glsl index 051a08d25e6..d724b4d4609 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_bokeh_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_bokeh_frag.glsl @@ -35,7 +35,7 @@ float circle_to_polygon_radius(float sides_count, float theta) cos(theta - side_angle * floor((sides_count * theta + M_PI) / M_2PI)); } -/* Remap input angle to have homogenous spacing of points along a polygon edge. +/* Remap input angle to have homogeneous spacing of points along a polygon edge. * Expect theta to be in [0..2pi] range. */ float circle_to_polygon_angle(float sides_count, float theta) { diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl index f5c45d147e6..fe1ab395a54 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl @@ -12,7 +12,7 @@ #pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) #pragma BLENDER_REQUIRE(effect_dof_lib.glsl) -/* Mipmapped input buffers, halfres but with padding to ensure mipmap alignement. */ +/* Mipmapped input buffers, halfres but with padding to ensure mipmap alignment. */ uniform sampler2D colorBuffer; uniform sampler2D cocBuffer; diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl index 59564890d7e..b05223e755d 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl @@ -103,7 +103,7 @@ void main() color4 = colors[3] * weights[3]; /* Extend to cover at least the unit circle */ - const float extend = (cos(M_PI / 4.0) + 1.0) * 2.0; + const float extend = (cos(M_PI_4) + 1.0) * 2.0; /* Crappy diagram * ex 1 * | \ diff --git a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl index 8ef39a55921..ce455123987 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl @@ -4,7 +4,7 @@ * Adapted from http://rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/ * * Major simplification has been made since we pad the buffer to always be bigger than input to - * avoid mipmapping misalignement. + * avoid mipmapping misalignment. */ #ifdef LAYERED diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl index ba90f5ae531..831ed0a119a 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl @@ -40,7 +40,7 @@ float light_translucent_power_with_falloff(LightData ld, vec3 N, vec4 l_vector) if (ld.l_type >= AREA_RECT) { power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); if (ld.l_type == AREA_ELLIPSE) { - power *= M_PI * 0.25; + power *= M_PI_4; } power *= 0.3 * 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ diff --git a/source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl index 9077b414026..7ab532ea0fb 100644 --- a/source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl @@ -16,9 +16,9 @@ out vec4 FragColor; vec3 background_transform_to_world(vec3 viewvec) { vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); + vec4 co_homogeneous = (ProjectionMatrixInverse * v); - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + vec4 co = vec4(co_homogeneous.xyz / co_homogeneous.w, 0.0); return (ViewMatrixInverse * co).xyz; } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c index 6c904745709..c3f96ecd0a2 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c @@ -387,7 +387,7 @@ void gpencil_light_pool_populate(GPENCIL_LightPool *lightpool, Object *ob) normalize_m4_m4(mat, ob->obmat); invert_m4(mat); gp_light->type = GP_LIGHT_TYPE_SPOT; - gp_light->spotsize = cosf(M_PI * 0.5f); + gp_light->spotsize = cosf(M_PI_2); gp_light->spotblend = (1.0f - gp_light->spotsize) * 1.0f; } else if (la->type == LA_SUN) { diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl index 36a52e05a4a..b4a26ec8103 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl @@ -442,7 +442,7 @@ void stroke_vertex() if (is_dot) { # ifdef GP_MATERIAL_BUFFER_LEN int alignement = GP_FLAG(m) & GP_STROKE_ALIGNMENT; - /* For one point strokes use object aligment. */ + /* For one point strokes use object alignment. */ if (ma.x == -1 && ma2.x == -1 && alignement == GP_STROKE_ALIGNMENT_STROKE) { alignement = GP_STROKE_ALIGNMENT_OBJECT; } diff --git a/source/blender/draw/engines/image/image_buffer_cache.hh b/source/blender/draw/engines/image/image_buffer_cache.hh index ef11551c879..470e9f225b4 100644 --- a/source/blender/draw/engines/image/image_buffer_cache.hh +++ b/source/blender/draw/engines/image/image_buffer_cache.hh @@ -1,20 +1,5 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Copyright 2022, Blender Foundation. - */ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. */ /** \file * \ingroup draw_engine diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c index 2636d7876d5..b3c0c5da9b5 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.c +++ b/source/blender/draw/engines/overlay/overlay_wireframe.c @@ -276,8 +276,12 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, const bool is_sculpt_mode = ((ob->mode & OB_MODE_SCULPT) != 0) && (ob->sculpt != NULL); const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && !DRW_state_is_image_render(); + const bool is_instance = (ob->base_flag & BASE_FROM_DUPLI); + const bool instance_parent_in_edit_mode = is_instance ? DRW_object_is_in_edit_mode( + DRW_object_get_dupli_parent(ob)) : + false; const bool use_coloring = (use_wire && !is_edit_mode && !is_sculpt_mode && - !has_edit_mesh_cage); + !has_edit_mesh_cage && !instance_parent_in_edit_mode); geom = DRW_cache_object_face_wireframe_get(ob); if (geom || use_sculpt_pbvh) { diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index bf197986687..010f424b9da 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -275,7 +275,7 @@ void workbench_update_world_ubo(WORKBENCH_PrivateData *wpd) copy_v2_v2(wd.viewport_size_inv, DRW_viewport_invert_size_get()); copy_v3_v3(wd.object_outline_color, wpd->shading.object_outline_color); wd.object_outline_color[3] = 1.0f; - wd.ui_scale = G_draw.block.sizePixel; + wd.ui_scale = DRW_state_is_image_render() ? 1.0f : G_draw.block.sizePixel; wd.matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0; workbench_studiolight_data_update(wpd, &wd); diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c index 6b64a9d7f09..58d49cf226e 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_dof.c +++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c @@ -31,22 +31,22 @@ static void square_to_circle(float x, float y, float *r, float *T) if (x > -y) { if (x > y) { *r = x; - *T = (M_PI / 4.0f) * (y / x); + *T = M_PI_4 * (y / x); } else { *r = y; - *T = (M_PI / 4.0f) * (2 - (x / y)); + *T = M_PI_4 * (2 - (x / y)); } } else { if (x < y) { *r = -x; - *T = (M_PI / 4.0f) * (4 + (y / x)); + *T = M_PI_4 * (4 + (y / x)); } else { *r = -y; if (y != 0) { - *T = (M_PI / 4.0f) * (6 - (x / y)); + *T = M_PI_4 * (6 - (x / y)); } else { *T = 0.0f; diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index dea3fa9b75a..e84f2c7a327 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -854,6 +854,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache, } mesh_render_data_update_looptris(mr, MR_ITER_LOOPTRI, MR_DATA_LOOPTRI); + mesh_render_data_update_normals(mr, MR_DATA_TAN_LOOP_NOR); mesh_render_data_update_loose_geom(mr, mbc, MR_ITER_LEDGE | MR_ITER_LVERT, MR_DATA_LOOSE_GEOM); DRW_subdivide_loose_geom(subdiv_cache, mbc); diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc index df1ac12605a..aea71d965d1 100644 --- a/source/blender/draw/intern/draw_cache_impl_curves.cc +++ b/source/blender/draw/intern/draw_cache_impl_curves.cc @@ -340,7 +340,7 @@ bool hair_ensure_procedural_data(Object *object, HairBatchCache *cache = curves_batch_cache_get(curves); *r_hair_cache = &cache->hair; - const int steps = 2; /* TODO: don't hard-code? */ + const int steps = 3; /* TODO: don't hard-code? */ (*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv); /* Refreshed on combing and simulation. */ diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index 2897234f4dc..c7edf003346 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -135,7 +135,7 @@ void DRW_globals_update(void) UI_GetThemeColor4fv(TH_CFRAME, gb->colorCurrentFrame); - /* Metaball */ + /* Meta-ball. */ UI_COLOR_RGBA_FROM_U8(0xA0, 0x30, 0x30, 0xFF, gb->colorMballRadius); UI_COLOR_RGBA_FROM_U8(0xF0, 0xA0, 0xA0, 0xFF, gb->colorMballRadiusSelect); UI_COLOR_RGBA_FROM_U8(0x30, 0xA0, 0x30, 0xFF, gb->colorMballStiffness); diff --git a/source/blender/draw/intern/shaders/common_math_lib.glsl b/source/blender/draw/intern/shaders/common_math_lib.glsl index 479f9cd1827..bc31649fd0f 100644 --- a/source/blender/draw/intern/shaders/common_math_lib.glsl +++ b/source/blender/draw/intern/shaders/common_math_lib.glsl @@ -6,6 +6,7 @@ #define M_PI 3.14159265358979323846 /* pi */ #define M_2PI 6.28318530717958647692 /* 2*pi */ #define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_PI_4 0.78539816339744830962 /* pi/4 */ #define M_1_PI 0.318309886183790671538 /* 1/pi */ #define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */ #define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */ @@ -93,7 +94,7 @@ vec2 sqr(vec2 a) { return a * a; } vec3 sqr(vec3 a) { return a * a; } vec4 sqr(vec4 a) { return a * a; } -/* Use manual powers for fixed powers. pow() can have unpredicatble results on some implementations. +/* Use manual powers for fixed powers. pow() can have unpredictable results on some implementations. * (see T87369, T87541) */ float pow6(float x) { return sqr(sqr(x) * x); } float pow8(float x) { return sqr(sqr(sqr(x))); } diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index edb6d188ab8..445d3715658 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -203,7 +203,7 @@ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, floa rgb_uchar_to_float(r_color, cp); } else { - /* FIXME: what happens when the indention is 1 greater than what it should be + /* FIXME: what happens when the indentation is 1 greater than what it should be * (due to grouping)? */ int colOfs = 10 - 10 * indent; UI_GetThemeColorShade3fv(TH_SHADE2, colOfs, r_color); @@ -252,44 +252,44 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, immUnbindProgram(); } -/* Indention + Offset ------------------------------------------- */ +/* Indentation + Offset ------------------------------------------- */ -/* indention level is always the value in the name */ -static short acf_generic_indention_0(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) +/* indentation level is always the value in the name */ +static short acf_generic_indentation_0(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) { return 0; } -static short acf_generic_indention_1(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) +static short acf_generic_indentation_1(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) { return 1; } #if 0 /* XXX not used */ -static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale) +static short acf_generic_indentation_2(bAnimContext *ac, bAnimListElem *ale) { return 2; } #endif -/* indention which varies with the grouping status */ -static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale) +/* indentation which varies with the grouping status */ +static short acf_generic_indentation_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale) { short indent = 0; - /* grouped F-Curves need extra level of indention */ + /* grouped F-Curves need extra level of indentation */ if (ale->type == ANIMTYPE_FCURVE) { FCurve *fcu = (FCurve *)ale->data; - /* TODO: we need some way of specifying that the indention color should be one less. */ + /* TODO: we need some way of specifying that the indentation color should be one less. */ if (fcu->grp) { indent++; } } - /* no indention */ + /* no indentation */ return indent; } -/* basic offset for channels derived from indention */ +/* basic offset for channels derived from indentation */ static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale) { const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); @@ -352,7 +352,7 @@ static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale) } } - /* offset is just the normal type - i.e. based on indention */ + /* offset is just the normal type - i.e. based on indentation */ return offset; } @@ -525,15 +525,15 @@ static void *acf_summary_setting_ptr(bAnimListElem *ale, return NULL; } -/* all animation summary (DopeSheet only) type define */ +/** All animation summary (dope-sheet only) type define. */ static bAnimChannelType ACF_SUMMARY = { "Summary", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ - acf_summary_color, /* backdrop color */ - acf_summary_backdrop, /* backdrop */ - acf_generic_indention_0, /* indent level */ - NULL, /* offset */ + acf_summary_color, /* backdrop color */ + acf_summary_backdrop, /* backdrop */ + acf_generic_indentation_0, /* indent level */ + NULL, /* offset */ acf_summary_name, /* name */ NULL, /* name prop */ @@ -634,14 +634,14 @@ static void *acf_scene_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set } } -/* scene type define */ +/** Scene type define. */ static bAnimChannelType ACF_SCENE = { "Scene", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_root_color, /* backdrop color */ acf_generic_root_backdrop, /* backdrop */ - acf_generic_indention_0, /* indent level */ + acf_generic_indentation_0, /* indent level */ NULL, /* offset */ acf_generic_idblock_name, /* name */ @@ -810,14 +810,14 @@ static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se } } -/* object type define */ +/** Object type define. */ static bAnimChannelType ACF_OBJECT = { "Object", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_root_color, /* backdrop color */ acf_generic_root_backdrop, /* backdrop */ - acf_generic_indention_0, /* indent level */ + acf_generic_indentation_0, /* indent level */ NULL, /* offset */ acf_object_name, /* name */ @@ -987,15 +987,15 @@ static void *acf_group_setting_ptr(bAnimListElem *ale, return GET_ACF_FLAG_PTR(agrp->flag, type); } -/* group type define */ +/** Group type define. */ static bAnimChannelType ACF_GROUP = { "Group", /* type name */ ACHANNEL_ROLE_CHANNEL, /* role */ - acf_group_color, /* backdrop color */ - acf_group_backdrop, /* backdrop */ - acf_generic_indention_0, /* indent level */ - acf_generic_group_offset, /* offset */ + acf_group_color, /* backdrop color */ + acf_group_backdrop, /* backdrop */ + acf_generic_indentation_0, /* indent level */ + acf_generic_group_offset, /* offset */ acf_group_name, /* name */ acf_group_name_prop, /* name prop */ @@ -1111,14 +1111,14 @@ static void *acf_fcurve_setting_ptr(bAnimListElem *ale, return GET_ACF_FLAG_PTR(fcu->flag, type); } -/* fcurve type define */ +/** F-Curve type define. */ static bAnimChannelType ACF_FCURVE = { "F-Curve", /* type name */ ACHANNEL_ROLE_CHANNEL, /* role */ acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ - acf_generic_indention_flexible, + acf_generic_indentation_flexible, /* indent level */ /* XXX rename this to f-curves only? */ acf_generic_group_offset, /* offset */ @@ -1231,14 +1231,14 @@ static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale)) return ICON_NLA; } -/* NLA Control FCurves Expander type define */ +/** NLA Control F-Curves expander type define. */ static bAnimChannelType ACF_NLACONTROLS = { "NLA Controls Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_nla_controls_color, /* backdrop color */ acf_nla_controls_backdrop, /* backdrop */ - acf_generic_indention_0, /* indent level */ + acf_generic_indentation_0, /* indent level */ acf_generic_group_offset, /* offset */ acf_nla_controls_name, /* name */ @@ -1271,14 +1271,14 @@ static void acf_nla_curve_name(bAnimListElem *ale, char *name) } } -/* NLA Control F-Curve type define */ +/** NLA Control F-Curve type define. */ static bAnimChannelType ACF_NLACURVE = { "NLA Control F-Curve", /* type name */ ACHANNEL_ROLE_CHANNEL, /* role */ acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_group_offset, /* offset */ acf_nla_curve_name, /* name */ @@ -1361,14 +1361,14 @@ static void *acf_fillactd_setting_ptr(bAnimListElem *ale, } } -/* object action expander type define */ +/** Object action expander type define. */ static bAnimChannelType ACF_FILLACTD = { "Ob-Action Filler", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -1446,14 +1446,14 @@ static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, } } -/* drivers expander type define */ +/** Drivers expander type define. */ static bAnimChannelType ACF_FILLDRIVERS = { "Drivers Filler", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_filldrivers_name, /* name */ @@ -1525,14 +1525,14 @@ static void *acf_dsmat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set } } -/* material expander type define */ +/** Material expander type define. */ static bAnimChannelType ACF_DSMAT = { "Material Data Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -1606,14 +1606,14 @@ static void *acf_dslight_setting_ptr(bAnimListElem *ale, } } -/* light expander type define */ +/** Light expander type define. */ static bAnimChannelType ACF_DSLIGHT = { "Light Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -1637,7 +1637,7 @@ static int acf_dstex_icon(bAnimListElem *UNUSED(ale)) /* FIXME: soon to be obsolete? */ static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) { - return 14; /* XXX: simply include this in indention instead? */ + return 14; /* XXX: simply include this in indentation instead? */ } /* Get the appropriate flag(s) for the setting when it is valid. */ @@ -1692,14 +1692,14 @@ static void *acf_dstex_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set } } -/* texture expander type define */ +/** Texture expander type define. */ static bAnimChannelType ACF_DSTEX = { "Texture Data Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_dstex_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -1775,14 +1775,14 @@ static void *acf_dscachefile_setting_ptr(bAnimListElem *ale, } } -/* CacheFile expander type define. */ +/** CacheFile expander type define.. */ static bAnimChannelType ACF_DSCACHEFILE = { "Cache File Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -1858,14 +1858,14 @@ static void *acf_dscam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set } } -/* camera expander type define */ +/** Camera expander type define. */ static bAnimChannelType ACF_DSCAM = { "Camera Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -1947,14 +1947,14 @@ static void *acf_dscur_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set } } -/* curve expander type define */ +/** Curve expander type define. */ static bAnimChannelType ACF_DSCUR = { "Curve Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -2045,14 +2045,14 @@ static void *acf_dsskey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se } } -/* shapekey expander type define */ +/** Shape-key expander type define. */ static bAnimChannelType ACF_DSSKEY = { "Shape Key Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -2124,14 +2124,14 @@ static void *acf_dswor_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set } } -/* world expander type define */ +/** World expander type define. */ static bAnimChannelType ACF_DSWOR = { "World Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -2203,14 +2203,14 @@ static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se } } -/* particle expander type define */ +/** Particle expander type define. */ static bAnimChannelType ACF_DSPART = { "Particle Data Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -2284,14 +2284,14 @@ static void *acf_dsmball_setting_ptr(bAnimListElem *ale, } } -/* metaball expander type define */ +/** Meta-ball expander type define. */ static bAnimChannelType ACF_DSMBALL = { "Metaball Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -2363,14 +2363,14 @@ static void *acf_dsarm_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set } } -/* metaball expander type define */ +/** Armature expander type define. */ static bAnimChannelType ACF_DSARM = { "Armature Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -2455,14 +2455,14 @@ static void *acf_dsntree_setting_ptr(bAnimListElem *ale, } } -/* node tree expander type define */ +/** Node tree expander type define. */ static bAnimChannelType ACF_DSNTREE = { "Node Tree Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_dsntree_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -2536,14 +2536,14 @@ static void *acf_dslinestyle_setting_ptr(bAnimListElem *ale, } } -/* node tree expander type define */ +/** Line Style expander type define. */ static bAnimChannelType ACF_DSLINESTYLE = { "Line Style Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -2615,14 +2615,14 @@ static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se } } -/* node tree expander type define */ +/** Mesh expander type define. */ static bAnimChannelType ACF_DSMESH = { "Mesh Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, + acf_generic_indentation_1, /* indent level */ /* XXX this only works for compositing */ acf_generic_basic_offset, /* offset */ @@ -2695,14 +2695,14 @@ static void *acf_dslat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set } } -/* node tree expander type define */ +/** Lattice expander type define. */ static bAnimChannelType ACF_DSLAT = { "Lattice Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, + acf_generic_indentation_1, /* indent level */ /* XXX this only works for compositing */ acf_generic_basic_offset, /* offset */ @@ -2775,14 +2775,14 @@ static void *acf_dsspk_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set } } -/* speaker expander type define */ +/** Speaker expander type define. */ static bAnimChannelType ACF_DSSPK = { "Speaker Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -2856,14 +2856,14 @@ static void *acf_dscurves_setting_ptr(bAnimListElem *ale, } } -/* Curves expander type define */ +/** Curves expander type define. */ static bAnimChannelType ACF_DSHAIR = { "Curves Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -2937,14 +2937,14 @@ static void *acf_dspointcloud_setting_ptr(bAnimListElem *ale, } } -/* pointcloud expander type define */ +/** Point-cloud expander type define. */ static bAnimChannelType ACF_DSPOINTCLOUD = { "PointCloud Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -3018,14 +3018,14 @@ static void *acf_dsvolume_setting_ptr(bAnimListElem *ale, } } -/* volume expander type define */ +/** Volume expander type define. */ static bAnimChannelType ACF_DSVOLUME = { "Volume Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -3097,13 +3097,14 @@ static void *acf_dssimulation_setting_ptr(bAnimListElem *ale, } } +/** Simulation expander type define. */ static bAnimChannelType ACF_DSSIMULATION = { "Simulation Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -3177,14 +3178,14 @@ static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale, } } -/* grease pencil expander type define */ +/** Grease-pencil expander type define. */ static bAnimChannelType ACF_DSGPENCIL = { "GPencil DS Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -3258,14 +3259,14 @@ static void *acf_dsmclip_setting_ptr(bAnimListElem *ale, } } -/* world expander type define */ +/** Movie-clip expander type define. */ static bAnimChannelType ACF_DSMCLIP = { "Movieclip Expander", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop, /* backdrop */ - acf_generic_indention_1, /* indent level */ + acf_generic_indentation_1, /* indent level */ acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ @@ -3373,14 +3374,14 @@ static void *acf_shapekey_setting_ptr(bAnimListElem *ale, } } -/* shapekey expander type define */ +/** Shape-key expander type define. */ static bAnimChannelType ACF_SHAPEKEY = { "Shape Key", /* type name */ ACHANNEL_ROLE_CHANNEL, /* role */ acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ - acf_generic_indention_0, /* indent level */ + acf_generic_indentation_0, /* indent level */ acf_generic_basic_offset, /* offset */ acf_shapekey_name, /* name */ @@ -3453,15 +3454,15 @@ static void *acf_gpd_setting_ptr(bAnimListElem *ale, return GET_ACF_FLAG_PTR(gpd->flag, type); } -/* gpencil datablock type define */ +/** Grease-pencil data-block type define. */ static bAnimChannelType ACF_GPD = { "GPencil Datablock", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ - acf_gpd_color, /* backdrop color */ - acf_group_backdrop, /* backdrop */ - acf_generic_indention_0, /* indent level */ - acf_generic_group_offset, /* offset */ + acf_gpd_color, /* backdrop color */ + acf_group_backdrop, /* backdrop */ + acf_generic_indentation_0, /* indent level */ + acf_generic_group_offset, /* offset */ acf_generic_idblock_name, /* name */ acf_generic_idfill_name_prop, /* name prop */ @@ -3552,15 +3553,15 @@ static void *acf_gpl_setting_ptr(bAnimListElem *ale, return GET_ACF_FLAG_PTR(gpl->flag, type); } -/* grease pencil layer type define */ +/** Grease-pencil layer type define. */ static bAnimChannelType ACF_GPL = { "GPencil Layer", /* type name */ ACHANNEL_ROLE_CHANNEL, /* role */ - acf_gpencil_channel_color, /* backdrop color */ - acf_generic_channel_backdrop, /* backdrop */ - acf_generic_indention_flexible, /* indent level */ - acf_generic_group_offset, /* offset */ + acf_gpencil_channel_color, /* backdrop color */ + acf_generic_channel_backdrop, /* backdrop */ + acf_generic_indentation_flexible, /* indent level */ + acf_generic_group_offset, /* offset */ acf_gpl_name, /* name */ acf_gpl_name_prop, /* name prop */ @@ -3634,15 +3635,15 @@ static void *acf_mask_setting_ptr(bAnimListElem *ale, return GET_ACF_FLAG_PTR(mask->flag, type); } -/* mask datablock type define */ +/** Mask data-block type define. */ static bAnimChannelType ACF_MASKDATA = { "Mask Datablock", /* type name */ ACHANNEL_ROLE_EXPANDER, /* role */ - acf_mask_color, /* backdrop color */ - acf_group_backdrop, /* backdrop */ - acf_generic_indention_0, /* indent level */ - acf_generic_group_offset, /* offset */ + acf_mask_color, /* backdrop color */ + acf_group_backdrop, /* backdrop */ + acf_generic_indentation_0, /* indent level */ + acf_generic_group_offset, /* offset */ acf_generic_idblock_name, /* name */ acf_generic_idfill_name_prop, /* name prop */ @@ -3730,15 +3731,15 @@ static void *acf_masklay_setting_ptr(bAnimListElem *ale, return GET_ACF_FLAG_PTR(masklay->flag, type); } -/* grease pencil layer type define */ +/** Mask layer type define. */ static bAnimChannelType ACF_MASKLAYER = { "Mask Layer", /* type name */ ACHANNEL_ROLE_CHANNEL, /* role */ - acf_generic_channel_color, /* backdrop color */ - acf_generic_channel_backdrop, /* backdrop */ - acf_generic_indention_flexible, /* indent level */ - acf_generic_group_offset, /* offset */ + acf_generic_channel_color, /* backdrop color */ + acf_generic_channel_backdrop, /* backdrop */ + acf_generic_indentation_flexible, /* indent level */ + acf_generic_group_offset, /* offset */ acf_masklay_name, /* name */ acf_masklay_name_prop, /* name prop */ @@ -3870,14 +3871,14 @@ static void *acf_nlatrack_setting_ptr(bAnimListElem *ale, return GET_ACF_FLAG_PTR(nlt->flag, type); } -/* nla track type define */ +/** NLA track type define. */ static bAnimChannelType ACF_NLATRACK = { "NLA Track", /* type name */ ACHANNEL_ROLE_CHANNEL, /* role */ - acf_nlatrack_color, /* backdrop color */ - acf_generic_channel_backdrop, /* backdrop */ - acf_generic_indention_flexible, /* indent level */ + acf_nlatrack_color, /* backdrop color */ + acf_generic_channel_backdrop, /* backdrop */ + acf_generic_indentation_flexible, /* indent level */ acf_generic_group_offset, /* offset */ /* XXX? */ @@ -4056,10 +4057,10 @@ static bAnimChannelType ACF_NLAACTION = { "NLA Active Action", /* type name */ ACHANNEL_ROLE_CHANNEL, /* role */ - acf_nlaaction_color, /* backdrop color (NOTE: the backdrop handles this too, - * since it needs special hacks). */ - acf_nlaaction_backdrop, /* backdrop */ - acf_generic_indention_flexible, /* indent level */ + acf_nlaaction_color, /* backdrop color (NOTE: the backdrop handles this too, + * since it needs special hacks). */ + acf_nlaaction_backdrop, /* backdrop */ + acf_generic_indentation_flexible, /* indent level */ acf_generic_group_offset, /* offset */ /* XXX? */ diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 3a57287cd60..df418b204f9 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -490,7 +490,7 @@ static void anim_flush_channel_setting_up(bAnimContext *ac, } /* Go backwards in the list, until the highest-ranking element - * (by indention has been covered). */ + * (by indentation has been covered). */ int prevLevel = matchLevel; for (bAnimListElem *ale = match->prev; ale; ale = ale->prev) { const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); @@ -539,7 +539,7 @@ static void anim_flush_channel_setting_down(bAnimContext *ac, bAnimListElem *const match, const int matchLevel) { - /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */ + /* go forwards in the list, until the lowest-ranking element (by indentation has been covered) */ for (bAnimListElem *ale = match->next; ale; ale = ale->next) { const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h index e7277c51cd3..8d8d624c69b 100644 --- a/source/blender/editors/animation/anim_intern.h +++ b/source/blender/editors/animation/anim_intern.h @@ -14,49 +14,80 @@ extern ListBase builtin_keyingsets; /* Operator Define Prototypes ------------------- */ -/* Main Keyframe Management operators: - * These handle keyframes management from various spaces. They only make use of - * Keying Sets. - */ +/* -------------------------------------------------------------------- */ +/** \name Main Keyframe Management operators + * + * These handle keyframes management from various spaces. + * They only make use of Keying Sets. + * \{ */ + void ANIM_OT_keyframe_insert(struct wmOperatorType *ot); void ANIM_OT_keyframe_delete(struct wmOperatorType *ot); void ANIM_OT_keyframe_insert_by_name(struct wmOperatorType *ot); void ANIM_OT_keyframe_delete_by_name(struct wmOperatorType *ot); -/* Main Keyframe Management operators: - * These handle keyframes management from various spaces. They will handle the menus - * required for each space. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Main Keyframe Management operators + * + * These handle keyframes management from various spaces. + * They will handle the menus required for each space. + * \{ */ + void ANIM_OT_keyframe_insert_menu(struct wmOperatorType *ot); void ANIM_OT_keyframe_delete_v3d(struct wmOperatorType *ot); void ANIM_OT_keyframe_clear_v3d(struct wmOperatorType *ot); -/* Keyframe management operators for UI buttons (RMB menu). */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Keyframe management operators for UI buttons (RMB menu) + * \{ */ + void ANIM_OT_keyframe_insert_button(struct wmOperatorType *ot); void ANIM_OT_keyframe_delete_button(struct wmOperatorType *ot); void ANIM_OT_keyframe_clear_button(struct wmOperatorType *ot); -/* .......... */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name KeyingSet management operators for UI buttons (RMB menu) + * \{ */ -/* KeyingSet management operators for UI buttons (RMB menu) */ void ANIM_OT_keyingset_button_add(struct wmOperatorType *ot); void ANIM_OT_keyingset_button_remove(struct wmOperatorType *ot); -/* KeyingSet management operators for RNA collections/UI buttons */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name KeyingSet management operators for RNA collections/UI buttons + * \{ */ + void ANIM_OT_keying_set_add(struct wmOperatorType *ot); void ANIM_OT_keying_set_remove(struct wmOperatorType *ot); void ANIM_OT_keying_set_path_add(struct wmOperatorType *ot); void ANIM_OT_keying_set_path_remove(struct wmOperatorType *ot); -/* KeyingSet general operators */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name KeyingSet general operators + * \{ */ + void ANIM_OT_keying_set_active_set(struct wmOperatorType *ot); -/* .......... */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver management operators for UI buttons (RMB menu) + * \{ */ -/* Driver management operators for UI buttons (RMB menu) */ void ANIM_OT_driver_button_add(struct wmOperatorType *ot); void ANIM_OT_driver_button_remove(struct wmOperatorType *ot); void ANIM_OT_driver_button_edit(struct wmOperatorType *ot); void ANIM_OT_copy_driver_button(struct wmOperatorType *ot); void ANIM_OT_paste_driver_button(struct wmOperatorType *ot); + +/** \} */ diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 1e8f46fd490..5b0c5eac11b 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -233,7 +233,7 @@ static bool use_sequencer_snapping(bContext *C) Scene *scene = CTX_data_scene(C); short snap_flag = SEQ_tool_settings_snap_flag_get(scene); - return (scene->toolsettings->snap_flag & SCE_SNAP_SEQ) && + return (scene->toolsettings->snap_flag_seq & SCE_SNAP) && (snap_flag & SEQ_SNAP_CURRENT_FRAME_TO_STRIPS); } diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 6ae82a754aa..e1e974ff119 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -979,7 +979,7 @@ static int add_driver_button_menu_exec(bContext *C, wmOperator *op) /* XXX: We assume that it's fine to use the same set of properties, * since they're actually the same. */ - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, op->ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, op->ptr, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index 8da96e4f42b..bdfec49fe42 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -411,7 +411,7 @@ static void generator_panel_draw(const bContext *C, Panel *panel) uiLayout *first_row = uiLayoutRow(col, true); uiItemFullR(first_row, ptr, prop, 0, 0, 0, IFACE_("y = (Ax + B)"), ICON_NONE); uiItemFullR(first_row, ptr, prop, 1, 0, 0, "", ICON_NONE); - for (int i = 2; i < data->arraysize - 1; i++) { + for (int i = 2; i < data->arraysize - 1; i += 2) { /* \u2715 is the multiplication symbol. */ uiLayout *row = uiLayoutRow(col, true); uiItemFullR(row, ptr, prop, i, 0, 0, IFACE_("\u2715 (Ax + B)"), ICON_NONE); diff --git a/source/blender/editors/animation/keyframes_keylist.cc b/source/blender/editors/animation/keyframes_keylist.cc index 0b795fea278..3356ef4d47d 100644 --- a/source/blender/editors/animation/keyframes_keylist.cc +++ b/source/blender/editors/animation/keyframes_keylist.cc @@ -807,8 +807,11 @@ static void add_bezt_to_keyblocks_list(AnimKeylist *keylist, BezTriple *bezt, co continue; } - /* Normal sequence */ - BLI_assert(is_cfra_eq(col->cfra, bezt[0].vec[1][0])); + /* In normal situations all keyframes are sorted. However, while keys are transformed, they + * may change order and then this assertion no longer holds. The effect is that the drawing + * isn't perfect during the transform; the "constant value" bars aren't updated until the + * transformation is confirmed. */ + // BLI_assert(is_cfra_eq(col->cfra, bezt[0].vec[1][0])); compute_keyblock_data(&block, bezt, bezt + 1); diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index a4845de7d7d..0f93d728c8c 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -244,7 +244,7 @@ FCurve *ED_action_fcurve_ensure(struct Main *bmain, return fcu; } -/* Helper for update_autoflags_fcurve() */ +/** Helper for #update_autoflags_fcurve(). */ static void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop) { /* set additional flags for the F-Curve (i.e. only integer values) */ @@ -304,7 +304,8 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin /* ************************************************** */ /* KEYFRAME INSERTION */ -/* Move the point where a key is about to be inserted to be inside the main cycle range. +/** + * Move the point where a key is about to be inserted to be inside the main cycle range. * Returns the type of the cycle if it is enabled and valid. */ static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, float *py) @@ -345,7 +346,7 @@ static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, fl return type; } -/* Used to make curves newly added to a cyclic Action cycle with the correct period. */ +/** Used to make curves newly added to a cyclic Action cycle with the correct period. */ static void make_new_fcurve_cyclic(const bAction *act, FCurve *fcu) { /* The curve must contain one (newly-added) keyframe. */ @@ -652,11 +653,13 @@ enum { KEYNEEDED_DELNEXT, } /*eKeyNeededStatus*/; -/* This helper function determines whether a new keyframe is needed */ -/* Cases where keyframes should not be added: - * 1. Keyframe to be added between two keyframes with similar values - * 2. Keyframe to be added on frame where two keyframes are already situated - * 3. Keyframe lies at point that intersects the linear line between two keyframes +/** + * This helper function determines whether a new keyframe is needed. + * + * Cases where keyframes should not be added: + * 1. Keyframe to be added between two keyframes with similar values. + * 2. Keyframe to be added on frame where two keyframes are already situated. + * 3. Keyframe lies at point that intersects the linear line between two keyframes. */ static short new_key_needed(FCurve *fcu, float cFrame, float nValue) { @@ -769,7 +772,7 @@ static short new_key_needed(FCurve *fcu, float cFrame, float nValue) /* ------------------ RNA Data-Access Functions ------------------ */ -/* Try to read value using RNA-properties obtained already */ +/** Try to read value using RNA-properties obtained already. */ static float *setting_get_rna_values( PointerRNA *ptr, PropertyRNA *prop, float *buffer, int buffer_size, int *r_count) { @@ -844,7 +847,8 @@ enum { VISUALKEY_SCA, }; -/* This helper function determines if visual-keyframing should be used when +/** + * This helper function determines if visual-keyframing should be used when * inserting keyframes for the given channel. As visual-keyframing only works * on Object and Pose-Channel blocks, this should only get called for those * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying @@ -1012,7 +1016,8 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop) return false; } -/* This helper function extracts the value to use for visual-keyframing +/** + * This helper function extracts the value to use for visual-keyframing * In the event that it is not possible to perform visual keying, try to fall-back * to using the default method. Assumes that all data it has been passed is valid. */ @@ -1305,7 +1310,7 @@ bool insert_keyframe_direct(ReportList *reports, return insert_keyframe_value(reports, &ptr, prop, fcu, anim_eval_context, curval, keytype, flag); } -/* Find or create the FCurve based on the given path, and insert the specified value into it. */ +/** Find or create the #FCurve based on the given path, and insert the specified value into it. */ static bool insert_keyframe_fcurve_value(Main *bmain, ReportList *reports, PointerRNA *ptr, @@ -1829,9 +1834,10 @@ enum { COMMONKEY_MODE_DELETE, } /*eCommonModifyKey_Modes*/; -/* Polling callback for use with ANIM_*_keyframe() operators +/** + * Polling callback for use with `ANIM_*_keyframe()` operators * This is based on the standard ED_operator_areaactive callback, - * except that it does special checks for a few spacetypes too... + * except that it does special checks for a few space-types too. */ static bool modify_key_op_poll(bContext *C) { @@ -1957,7 +1963,8 @@ void ANIM_OT_keyframe_insert_by_name(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* keyingset to use (idname) */ - prop = RNA_def_string_file_path(ot->srna, "type", "Type", MAX_ID_NAME - 2, "", ""); + prop = RNA_def_string( + ot->srna, "type", NULL, MAX_ID_NAME - 2, "Keying Set", "The Keying Set to use"); RNA_def_property_flag(prop, PROP_HIDDEN); ot->prop = prop; } @@ -2117,7 +2124,8 @@ void ANIM_OT_keyframe_delete_by_name(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* keyingset to use (idname) */ - prop = RNA_def_string_file_path(ot->srna, "type", "Type", MAX_ID_NAME - 2, "", ""); + prop = RNA_def_string( + ot->srna, "type", NULL, MAX_ID_NAME - 2, "Keying Set", "The Keying Set to use"); RNA_def_property_flag(prop, PROP_HIDDEN); ot->prop = prop; } @@ -2840,13 +2848,12 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter) } } - /* try shapekey keyframes (if available, and allowed by filter) */ + /* Try shape-key keyframes (if available, and allowed by filter). */ if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY)) { Key *key = BKE_key_from_object(ob); - /* shapekeys can have keyframes ('Relative Shape Keys') - * or depend on time (old 'Absolute Shape Keys') - */ + /* Shape-keys can have keyframes ('Relative Shape Keys') + * or depend on time (old 'Absolute Shape Keys'). */ /* 1. test for relative (with keyframes) */ if (id_frame_has_keyframe((ID *)key, frame, filter)) { diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 6fcdd21bad8..dcf8835c911 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -715,55 +715,54 @@ const EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C, PropertyRNA *UNUSED(prop), bool *r_free) { - Scene *scene = CTX_data_scene(C); KeyingSet *ks; EnumPropertyItem *item = NULL, item_tmp = {0}; int totitem = 0; int i = 0; - if (C == NULL) { - return DummyRNA_DEFAULT_items; - } + if (C != NULL) { + Scene *scene = CTX_data_scene(C); + /* active Keying Set + * - only include entry if it exists + */ + if (scene->active_keyingset) { + /* active Keying Set */ + item_tmp.identifier = "__ACTIVE__"; + item_tmp.name = "Active Keying Set"; + item_tmp.value = i; + RNA_enum_item_add(&item, &totitem, &item_tmp); - /* active Keying Set - * - only include entry if it exists - */ - if (scene->active_keyingset) { - /* active Keying Set */ - item_tmp.identifier = "__ACTIVE__"; - item_tmp.name = "Active Keying Set"; - item_tmp.value = i; - RNA_enum_item_add(&item, &totitem, &item_tmp); - - /* separator */ - RNA_enum_item_add_separator(&item, &totitem); - } + /* separator */ + RNA_enum_item_add_separator(&item, &totitem); + } - i++; + i++; - /* user-defined Keying Sets - * - these are listed in the order in which they were defined for the active scene - */ - if (scene->keyingsets.first) { - for (ks = scene->keyingsets.first; ks; ks = ks->next, i++) { - if (ANIM_keyingset_context_ok_poll(C, ks)) { - item_tmp.identifier = ks->idname; - item_tmp.name = ks->name; - item_tmp.description = ks->description; - item_tmp.value = i; - RNA_enum_item_add(&item, &totitem, &item_tmp); + /* user-defined Keying Sets + * - these are listed in the order in which they were defined for the active scene + */ + if (scene->keyingsets.first) { + for (ks = scene->keyingsets.first; ks; ks = ks->next, i++) { + if (ANIM_keyingset_context_ok_poll(C, ks)) { + item_tmp.identifier = ks->idname; + item_tmp.name = ks->name; + item_tmp.description = ks->description; + item_tmp.value = i; + RNA_enum_item_add(&item, &totitem, &item_tmp); + } } - } - /* separator */ - RNA_enum_item_add_separator(&item, &totitem); + /* separator */ + RNA_enum_item_add_separator(&item, &totitem); + } } /* builtin Keying Sets */ i = -1; for (ks = builtin_keyingsets.first; ks; ks = ks->next, i--) { - /* only show KeyingSet if context is suitable */ - if (ANIM_keyingset_context_ok_poll(C, ks)) { + /* Only show #KeyingSet if context is suitable or if there is no context which is needed + * to support key-bindings to be assigned since key bindings are not context aware. */ + if ((C == NULL) || ANIM_keyingset_context_ok_poll(C, ks)) { item_tmp.identifier = ks->idname; item_tmp.name = ks->name; item_tmp.description = ks->description; diff --git a/source/blender/editors/asset/intern/asset_ops.cc b/source/blender/editors/asset/intern/asset_ops.cc index 1d484f9ce85..f0768ebc907 100644 --- a/source/blender/editors/asset/intern/asset_ops.cc +++ b/source/blender/editors/asset/intern/asset_ops.cc @@ -754,7 +754,7 @@ static int asset_bundle_install_exec(bContext *C, wmOperator *op) cat_service->prepare_to_merge_on_write(); const int operator_result = WM_operator_name_call( - C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, op->ptr); + C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, op->ptr, nullptr); WM_cursor_wait(false); if (operator_result != OPERATOR_FINISHED) { diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index a33fbb29f85..2dcddd01670 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -4863,6 +4863,12 @@ bool ED_curve_editnurb_select_pick( BKE_curve_nurb_active_set(cu, nu); } + /* Change active material on object. */ + if (nu->mat_nr != obedit->actcol - 1) { + obedit->actcol = nu->mat_nr + 1; + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); + } + if (vc.view_layer->basact != basact) { ED_object_base_activate(C, basact); } @@ -4900,7 +4906,7 @@ bool ed_editnurb_spin( copy_m3_m4(bmat, obedit->obmat); invert_m3_m3(imat, bmat); - axis_angle_to_mat3(cmat, axis, M_PI / 4.0); + axis_angle_to_mat3(cmat, axis, M_PI_4); mul_m3_m3m3(tmat, cmat, bmat); mul_m3_m3m3(rotmat, imat, tmat); @@ -4952,7 +4958,7 @@ bool ed_editnurb_spin( /* It is challenging to create a good approximation of a circle with uniform knots vector * (which is forced in Blender for cyclic NURBS curves). Here a NURBS circle is constructed * by connecting four Bezier arcs. */ - nu->flagv |= CU_NURB_CYCLIC | CU_NURB_BEZIER; + nu->flagv |= CU_NURB_CYCLIC | CU_NURB_BEZIER | CU_NURB_ENDPOINT; BKE_nurb_knot_calc_v(nu); } } diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index d7201495f75..ba5a7409ba7 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -292,7 +292,7 @@ Nurb *ED_curve_add_nurbs_primitive( nu->pntsv = 1; nu->orderu = 3; nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "addNurbprim6"); - nu->flagu = CU_NURB_CYCLIC | CU_NURB_BEZIER; + nu->flagu = CU_NURB_CYCLIC | CU_NURB_BEZIER | CU_NURB_ENDPOINT; bp = nu->bp; for (a = 0; a < 8; a++) { @@ -407,7 +407,7 @@ Nurb *ED_curve_add_nurbs_primitive( mul_m4_v3(mat, bp->vec); bp++; } - nu->flagu = CU_NURB_BEZIER; + nu->flagu = CU_NURB_BEZIER | CU_NURB_ENDPOINT; BKE_nurb_knot_calc_u(nu); BLI_addtail(editnurb, nu); /* temporal for spin */ diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 1a7b034f2f8..338f6be4c89 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -22,6 +22,7 @@ #include "PIL_time.h" +#include "BKE_callbacks.h" #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_global.h" @@ -1509,6 +1510,9 @@ static void annotation_paint_initstroke(tGPsdata *p, Scene *scene = p->scene; ToolSettings *ts = scene->toolsettings; + /* Call to the annotation pre handler to notify python the annotation starts. */ + BKE_callback_exec_id_depsgraph(p->bmain, &p->gpd->id, p->depsgraph, BKE_CB_EVT_ANNOTATION_PRE); + /* get active layer (or add a new one if non-existent) */ p->gpl = BKE_gpencil_layer_active_get(p->gpd); if (p->gpl == NULL) { @@ -1675,6 +1679,9 @@ static void annotation_paint_strokeend(tGPsdata *p) annotation_stroke_newfrombuffer(p); } + /* Call to the annotation post handler to notify python the annotation is done. */ + BKE_callback_exec_id_depsgraph(p->bmain, &p->gpd->id, p->depsgraph, BKE_CB_EVT_ANNOTATION_POST); + /* clean up buffer now */ annotation_session_validatebuffer(p); } @@ -2477,7 +2484,7 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve * - Since this operator is non-modal, we can just call it here, and keep going... * - This operator is especially useful when animating */ - WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL, event); estate = OPERATOR_RUNNING_MODAL; } else { diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index d734fb2678e..8506e90191f 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1928,7 +1928,7 @@ static int gpencil_blank_frame_add_exec(bContext *C, wmOperator *op) if (ELEM(NULL, gpd, active_gpl)) { /* Let's just be lazy, and call the "Add New Layer" operator, * which sets everything up as required. */ - WM_operator_name_call(C, "GPENCIL_OT_layer_add", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "GPENCIL_OT_layer_add", WM_OP_EXEC_DEFAULT, NULL, NULL); } /* Go through each layer, adding a frame after the active one @@ -5430,9 +5430,10 @@ static int gpencil_stroke_normalize_exec(bContext *C, wmOperator *op) if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - - bool selected = (is_curve_edit) ? gps->editcurve->flag |= GP_CURVE_SELECT : - (gps->flag & GP_STROKE_SELECT); + bool is_curve_ready = (gps->editcurve != NULL); + bool selected = (is_curve_edit && is_curve_ready) ? + (gps->editcurve->flag & GP_CURVE_SELECT) : + (gps->flag & GP_STROKE_SELECT); if (!selected) { continue; } @@ -5445,7 +5446,7 @@ static int gpencil_stroke_normalize_exec(bContext *C, wmOperator *op) } /* Loop all Polyline points. */ - if (!is_curve_edit) { + if (!is_curve_edit || !is_curve_ready) { for (int i = 0; i < gps->totpoints; i++) { bGPDspoint *pt = &gps->points[i]; if (mode == GP_NORMALIZE_THICKNESS) { diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c index f49523925bc..c0888968a2d 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_ops.c +++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c @@ -959,7 +959,7 @@ static int gpencil_material_to_vertex_exec(bContext *C, wmOperator *op) /* Clean unused materials. */ if (remove) { WM_operator_name_call( - C, "OBJECT_OT_material_slot_remove_unused", WM_OP_INVOKE_REGION_WIN, NULL); + C, "OBJECT_OT_material_slot_remove_unused", WM_OP_INVOKE_REGION_WIN, NULL, NULL); } return OPERATOR_FINISHED; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 4b6f5e4cac6..4cae8bdab18 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -51,8 +51,9 @@ struct PropertyRNA; /** \name Context * \{ */ -/* This struct defines a structure used for animation-specific - * 'context' information +/** + * This struct defines a structure used for animation-specific + * 'context' information. */ typedef struct bAnimContext { /** data to be filtered for use in animation editor */ @@ -118,8 +119,9 @@ typedef enum eAnimCont_Types { /** \name Channels * \{ */ -/* This struct defines a structure used for quick and uniform access for - * channels of animation data +/** + * This struct defines a structure used for quick and uniform access for + * channels of animation data. */ typedef struct bAnimListElem { struct bAnimListElem *next, *prev; @@ -257,7 +259,8 @@ typedef enum eAnim_KeyType { ALE_GROUP, /* Action Group summary */ } eAnim_KeyType; -/* Flags for specifying the types of updates (i.e. recalculation/refreshing) that +/** + * Flags for specifying the types of updates (i.e. recalculation/refreshing) that * needs to be performed to the data contained in a channel following editing. * For use with ANIM_animdata_update() */ @@ -379,13 +382,13 @@ typedef enum eAnimFilter_Flags { #define EXPANDED_DRVD(adt) ((adt->flag & ADT_DRIVERS_COLLAPSED) == 0) /* Actions (also used for Dopesheet) */ -/* Action Channel Group */ +/** Action Channel Group. */ #define EDITABLE_AGRP(agrp) (((agrp)->flag & AGRP_PROTECTED) == 0) #define EXPANDED_AGRP(ac, agrp) \ (((!(ac) || ((ac)->spacetype != SPACE_GRAPH)) && ((agrp)->flag & AGRP_EXPANDED)) || \ (((ac) && ((ac)->spacetype == SPACE_GRAPH)) && ((agrp)->flag & AGRP_EXPANDED_G))) #define SEL_AGRP(agrp) (((agrp)->flag & AGRP_SELECTED) || ((agrp)->flag & AGRP_ACTIVE)) -/* F-Curve Channels */ +/** F-Curve Channels. */ #define EDITABLE_FCU(fcu) ((fcu->flag & FCURVE_PROTECTED) == 0) #define SEL_FCU(fcu) (fcu->flag & FCURVE_SELECTED) @@ -394,16 +397,16 @@ typedef enum eAnimFilter_Flags { #define SEL_SHAPEKEY(kb) (kb->flag & KEYBLOCK_SEL) /* Grease Pencil only */ -/* Grease Pencil datablock settings */ +/** Grease Pencil data-block settings. */ #define EXPANDED_GPD(gpd) (gpd->flag & GP_DATA_EXPAND) -/* Grease Pencil Layer settings */ +/** Grease Pencil Layer settings. */ #define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED) == 0) #define SEL_GPL(gpl) (gpl->flag & GP_LAYER_SELECT) /* Mask Only */ -/* Grease Pencil datablock settings */ +/** Grease Pencil data-block settings. */ #define EXPANDED_MASK(mask) (mask->flag & MASK_ANIMF_EXPAND) -/* Grease Pencil Layer settings */ +/** Grease Pencil Layer settings. */ #define EDITABLE_MASK(masklay) ((masklay->flag & MASK_LAYERFLAG_LOCKED) == 0) #define SEL_MASKLAY(masklay) (masklay->flag & SELECT) @@ -426,20 +429,20 @@ typedef enum eAnimFilter_Flags { /** \name Channel Defines * \{ */ -/* channel heights */ +/** Channel heights. */ #define ACHANNEL_FIRST_TOP(ac) \ (UI_view2d_scale_get_y(&(ac)->region->v2d) * -UI_TIME_SCRUB_MARGIN_Y - ACHANNEL_SKIP) #define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit) #define ACHANNEL_SKIP (0.1f * U.widget_unit) #define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP) -/* Additional offset to give some room at the end. */ +/** Additional offset to give some room at the end. */ #define ACHANNEL_TOT_HEIGHT(ac, item_amount) \ (-ACHANNEL_FIRST_TOP(ac) + ACHANNEL_STEP(ac) * (item_amount + 1)) -/* channel widths */ +/** Channel widths. */ #define ACHANNEL_NAMEWIDTH (10 * U.widget_unit) -/* channel toggle-buttons */ +/** Channel toggle-buttons. */ #define ACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit) /** \} */ @@ -448,7 +451,7 @@ typedef enum eAnimFilter_Flags { /** \name NLA Channel Defines * \{ */ -/* NLA channel heights */ +/** NLA channel heights */ #define NLACHANNEL_FIRST_TOP(ac) \ (UI_view2d_scale_get_y(&(ac)->region->v2d) * -UI_TIME_SCRUB_MARGIN_Y - NLACHANNEL_SKIP) #define NLACHANNEL_HEIGHT(snla) \ @@ -456,14 +459,14 @@ typedef enum eAnimFilter_Flags { (1.2f * U.widget_unit)) #define NLACHANNEL_SKIP (0.1f * U.widget_unit) #define NLACHANNEL_STEP(snla) (NLACHANNEL_HEIGHT(snla) + NLACHANNEL_SKIP) -/* Additional offset to give some room at the end. */ +/** Additional offset to give some room at the end. */ #define NLACHANNEL_TOT_HEIGHT(ac, item_amount) \ (-NLACHANNEL_FIRST_TOP(ac) + NLACHANNEL_STEP(((SpaceNla *)(ac)->sl)) * (item_amount + 1)) -/* channel widths */ +/** Channel widths */ #define NLACHANNEL_NAMEWIDTH (10 * U.widget_unit) -/* channel toggle-buttons */ +/** Channel toggle-buttons */ #define NLACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit) /** \} */ @@ -521,7 +524,7 @@ void ANIM_animdata_freelist(ListBase *anim_data); /** \name Drawing TypeInfo * \{ */ -/* role or level of animchannel in the hierarchy */ +/** Role or level of anim-channel in the hierarchy. */ typedef enum eAnimChannel_Role { /** datablock expander - a "composite" channel type */ ACHANNEL_ROLE_EXPANDER = -1, @@ -561,7 +564,7 @@ typedef enum eAnimChannel_Settings { ACHANNEL_SETTING_ALWAYS_VISIBLE = 8, } eAnimChannel_Settings; -/* Drawing, mouse handling, and flag setting behavior... */ +/** Drawing, mouse handling, and flag setting behavior. */ typedef struct bAnimChannelType { /* -- Type data -- */ /* name of the channel type, for debugging */ @@ -570,30 +573,31 @@ typedef struct bAnimChannelType { eAnimChannel_Role channel_role; /* -- Drawing -- */ - /* get RGB color that is used to draw the majority of the backdrop */ + /** Get RGB color that is used to draw the majority of the backdrop. */ void (*get_backdrop_color)(bAnimContext *ac, bAnimListElem *ale, float r_color[3]); - /* draw backdrop strip for channel */ + /** Draw backdrop strip for channel. */ void (*draw_backdrop)(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc); - /* get depth of indention (relative to the depth channel is nested at) */ + /** Get depth of indentation (relative to the depth channel is nested at). */ short (*get_indent_level)(bAnimContext *ac, bAnimListElem *ale); - /* get offset in pixels for the start of the channel (in addition to the indent depth) */ + /** Get offset in pixels for the start of the channel (in addition to the indent depth). */ short (*get_offset)(bAnimContext *ac, bAnimListElem *ale); - /* get name (for channel lists) */ + /** Get name (for channel lists). */ void (*name)(bAnimListElem *ale, char *name); - /* get RNA property+pointer for editing the name */ + /** Get RNA property+pointer for editing the name. */ bool (*name_prop)(bAnimListElem *ale, struct PointerRNA *ptr, struct PropertyRNA **prop); - /* get icon (for channel lists) */ + /** Get icon (for channel lists). */ int (*icon)(bAnimListElem *ale); /* -- Settings -- */ - /* check if the given setting is valid in the current context */ + /** Check if the given setting is valid in the current context. */ bool (*has_setting)(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting); - /* get the flag used for this setting */ + /** Get the flag used for this setting. */ int (*setting_flag)(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg); - /* get the pointer to int/short where data is stored, - * with type being sizeof(ptr_data) which should be fine for runtime use... - * - assume that setting has been checked to be valid for current context + /** + * Get the pointer to int/short where data is stored, + * with type being `sizeof(ptr_data)` which should be fine for runtime use. + * - assume that setting has been checked to be valid for current context. */ void *(*setting_ptr)(bAnimListElem *ale, eAnimChannel_Settings setting, short *type); } bAnimChannelType; @@ -720,11 +724,11 @@ bool ANIM_remove_empty_action_from_animdata(struct AnimData *adt); /* flags for Current Frame Drawing */ typedef enum eAnimEditDraw_CurrentFrame { - /* plain time indicator with no special indicators */ + /** Plain time indicator with no special indicators. */ /* DRAWCFRA_PLAIN = 0, */ /* UNUSED */ - /* time indication in seconds or frames */ + /** Time indication in seconds or frames. */ DRAWCFRA_UNIT_SECONDS = (1 << 0), - /* draw indicator extra wide (for timeline) */ + /** Draw indicator extra wide (for timeline). */ DRAWCFRA_WIDE = (1 << 1), } eAnimEditDraw_CurrentFrame; @@ -784,9 +788,9 @@ struct NlaTrack *ANIM_nla_context_track(const struct bContext *C); struct NlaStrip *ANIM_nla_context_strip(const struct bContext *C); struct FCurve *ANIM_graph_context_fcurve(const struct bContext *C); -/* Needed for abstraction between the graph editor and the NLA editor. */ +/** Needed for abstraction between the graph editor and the NLA editor. */ typedef bool (*PanelTypePollFn)(const struct bContext *C, struct PanelType *pt); -/* Avoid including "UI_interface.h" here. */ +/** Avoid including `UI_interface.h` here. */ typedef void (*uiListPanelIDFromDataFunc)(void *data_link, char *r_idname); /** @@ -912,20 +916,21 @@ void ED_nla_postop_refresh(bAnimContext *ac); /* anim_draw.c */ -/* flags for conversion mapping */ +/** Flags for conversion mapping. */ typedef enum eAnimUnitConv_Flags { - /* restore to original internal values */ + /** Restore to original internal values. */ ANIM_UNITCONV_RESTORE = (1 << 0), - /* ignore handles (i.e. only touch main keyframes) */ + /** Ignore handles (i.e. only touch main keyframes). */ ANIM_UNITCONV_ONLYKEYS = (1 << 1), - /* only touch selected BezTriples */ + /** Only touch selected BezTriples. */ ANIM_UNITCONV_ONLYSEL = (1 << 2), - /* only touch selected vertices */ + /** Only touch selected vertices. */ ANIM_UNITCONV_SELVERTS = (1 << 3), /* ANIM_UNITCONV_SKIPKNOTS = (1 << 4), */ /* UNUSED */ - /* Scale FCurve i a way it fits to -1..1 space */ + /** Scale FCurve i a way it fits to -1..1 space. */ ANIM_UNITCONV_NORMALIZE = (1 << 5), - /* Only when normalization is used: use scale factor from previous run, + /** + * Only when normalization is used: use scale factor from previous run, * prevents curves from jumping all over the place when tweaking them. */ ANIM_UNITCONV_NORMALIZE_FREEZE = (1 << 6), @@ -953,10 +958,11 @@ float ANIM_unit_mapping_get_factor( */ #define BEZKEYTYPE(bezt) ((bezt)->hide) -/* set/clear/toggle macro - * - channel - channel with a 'flag' member that we're setting - * - smode - 0=clear, 1=set, 2=invert - * - sflag - bitflag to set +/** + * Set/Clear/Toggle macro. + * \param channel: Channel with a 'flag' member that we're setting. + * \param smode: 0=clear, 1=set, 2=invert. + * \param sflag: bit-flag to set. */ #define ACHANNEL_SET_FLAG(channel, smode, sflag) \ { \ @@ -972,10 +978,11 @@ float ANIM_unit_mapping_get_factor( } \ ((void)0) -/* set/clear/toggle macro, where the flag is negative - * - channel - channel with a 'flag' member that we're setting - * - smode - 0=clear, 1=set, 2=invert - * - sflag - bitflag to set +/** + * Set/Clear/Toggle macro, where the flag is negative. + * \param channel: channel with a 'flag' member that we're setting. + * \param smode: 0=clear, 1=set, 2=invert. + * \param sflag: Bit-flag to set. */ #define ACHANNEL_SET_FLAG_NEG(channel, smode, sflag) \ { \ @@ -1067,13 +1074,13 @@ void ED_drivers_editor_init(struct bContext *C, struct ScrArea *area); /* ************************************************ */ typedef enum eAnimvizCalcRange { - /* Update motion paths at the current frame only. */ + /** Update motion paths at the current frame only. */ ANIMVIZ_CALC_RANGE_CURRENT_FRAME, - /* Try to limit updates to a close neighborhood of the current frame. */ + /** Try to limit updates to a close neighborhood of the current frame. */ ANIMVIZ_CALC_RANGE_CHANGED, - /* Update an entire range of the motion paths. */ + /** Update an entire range of the motion paths. */ ANIMVIZ_CALC_RANGE_FULL, } eAnimvizCalcRange; diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index 86fb5251ff3..21bb412d072 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -13,7 +13,9 @@ extern "C" { /* ----------------------------------------------------- */ -/* for animplayer */ +/** + * For animation playback operator, stored in #bScreen.animtimer.customdata. + */ typedef struct ScreenAnimData { ARegion *region; /* do not read from this, only for comparing if region exists */ short redraws; @@ -24,7 +26,7 @@ typedef struct ScreenAnimData { bool from_anim_edit; /* playback was invoked from animation editor */ } ScreenAnimData; -/* for animplayer */ +/** #ScreenAnimData.flag */ enum { /* user-setting - frame range is played backwards */ ANIMPLAY_FLAG_REVERSE = (1 << 0), diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index cf4d023ccdf..40a57a321d8 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -223,7 +223,7 @@ void uvedit_edge_select_set_noflush(const struct Scene *scene, * Updates selection state for UVs based on the select mode and sticky mode. Similar to * #EDBM_selectmode_set. */ -void ED_uvedit_selectmode_clean(struct Scene *scene, struct Object *obedit); +void ED_uvedit_selectmode_clean(const struct Scene *scene, struct Object *obedit); void ED_uvedit_selectmode_clean_multi(struct bContext *C); /** @@ -231,16 +231,16 @@ void ED_uvedit_selectmode_clean_multi(struct bContext *C); * * Flushes selections upwards as dictated by the UV select mode. */ -void ED_uvedit_selectmode_flush(struct Scene *scene, struct BMEditMesh *em); +void ED_uvedit_selectmode_flush(const struct Scene *scene, struct BMEditMesh *em); /** * Mode independent UV de-selection flush. */ -void uvedit_deselect_flush(struct Scene *scene, struct BMEditMesh *em); +void uvedit_deselect_flush(const struct Scene *scene, struct BMEditMesh *em); /** * Mode independent UV selection flush. */ -void uvedit_select_flush(struct Scene *scene, struct BMEditMesh *em); +void uvedit_select_flush(const struct Scene *scene, struct BMEditMesh *em); bool ED_uvedit_nearest_uv(const struct Scene *scene, struct Object *obedit, @@ -254,15 +254,15 @@ bool ED_uvedit_nearest_uv_multi(const struct Scene *scene, float *dist_sq, float r_uv[2]); -struct BMFace **ED_uvedit_selected_faces(struct Scene *scene, +struct BMFace **ED_uvedit_selected_faces(const struct Scene *scene, struct BMesh *bm, int len_max, int *r_faces_len); -struct BMLoop **ED_uvedit_selected_edges(struct Scene *scene, +struct BMLoop **ED_uvedit_selected_edges(const struct Scene *scene, struct BMesh *bm, int len_max, int *r_edges_len); -struct BMLoop **ED_uvedit_selected_verts(struct Scene *scene, +struct BMLoop **ED_uvedit_selected_verts(const struct Scene *scene, struct BMesh *bm, int len_max, int *r_verts_len); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index b1435e76eb2..d2ff5637a13 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -646,7 +646,7 @@ bool ED_view3d_win_to_3d_on_plane_int(const struct ARegion *region, * * \param region: The region (used for the window width and height). * \param xy_delta: 2D difference (in pixels) such as `event->mval[0] - other_x`. - * \param zfac: The depth result typically calculated by by #ED_view3d_calc_zfac + * \param zfac: The depth result typically calculated by #ED_view3d_calc_zfac * (see it's doc-string for details). * \param r_out: The resulting world-space delta. */ @@ -661,7 +661,7 @@ void ED_view3d_win_to_delta(const struct ARegion *region, * the origin in this case is close to zero coordinate. * * \param region: The region (used for the window width and height). - * \param mval: The area relative 2d location (such as event->mval converted to floats). + * \param mval: The area relative 2d location (such as `event->mval` converted to float). * \param r_out: The resulting normalized world-space direction vector. */ void ED_view3d_win_to_origin(const struct ARegion *region, const float mval[2], float r_out[3]); @@ -675,7 +675,7 @@ void ED_view3d_win_to_origin(const struct ARegion *region, const float mval[2], * the mouse cursor as a normalized vector. * * \param region: The region (used for the window width and height). - * \param mval: The area relative 2d location (such as event->mval converted to floats). + * \param mval: The area relative 2d location (such as `event->mval` converted to float). * \param r_out: The resulting normalized world-space direction vector. */ void ED_view3d_win_to_vector(const struct ARegion *region, const float mval[2], float r_out[3]); diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 46baf3033ff..e838ce37d8e 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -299,13 +299,13 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra) void ui_but_anim_copy_driver(bContext *C) { /* this operator calls UI_context_active_but_prop_get */ - WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL, NULL); } void ui_but_anim_paste_driver(bContext *C) { /* this operator calls UI_context_active_but_prop_get */ - WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL, NULL); } void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)) @@ -331,7 +331,7 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy) wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false); WM_operator_properties_create_ptr(&props_ptr, ot); RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL); WM_operator_properties_free(&props_ptr); } else { @@ -339,7 +339,7 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy) wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false); WM_operator_properties_create_ptr(&props_ptr, ot); RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL); WM_operator_properties_free(&props_ptr); } diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 07efcdcbe38..4d30d6731a2 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -1036,7 +1036,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev /* We do have a shortcut, but only keyboard ones are editable that way... */ if (kmi) { - if (ISKEYBOARD(kmi->type)) { + if (ISKEYBOARD(kmi->type) || ISNDOF_BUTTON(kmi->type)) { #if 0 /* would rather use a block but, but gets weirdly positioned... */ uiDefBlockBut(block, menu_change_shortcut, diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 9a51aa5cb9d..decd8c03d70 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -411,6 +411,8 @@ static void histogram_draw_one(float r, immVertex2f(pos_attr, x2, y + (data[i] * h)); } immEnd(); + + GPU_line_width(1.0f); } else { /* under the curve */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 8262be163b7..a8b21bebb2b 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1007,7 +1007,7 @@ static void ui_apply_but_funcs_after(bContext *C) if (after.optype) { WM_operator_name_call_ptr_with_depends_on_cursor( - C, after.optype, after.opcontext, (after.opptr) ? &opptr : NULL, after.drawstr); + C, after.optype, after.opcontext, (after.opptr) ? &opptr : NULL, NULL, after.drawstr); } if (after.opptr) { @@ -3930,7 +3930,7 @@ static void ui_do_but_textedit( } #ifdef WITH_INPUT_IME - if (event->type == WM_IME_COMPOSITE_START || event->type == WM_IME_COMPOSITE_EVENT) { + if (ELEM(event->type, WM_IME_COMPOSITE_START, WM_IME_COMPOSITE_EVENT)) { changed = true; if (event->type == WM_IME_COMPOSITE_START && but->selend > but->selsta) { @@ -4190,6 +4190,7 @@ static void ui_but_extra_operator_icon_apply(bContext *C, uiBut *but, uiButExtra op_icon->optype_params->optype, op_icon->optype_params->opcontext, op_icon->optype_params->opptr, + NULL, NULL); /* Force recreation of extra operator icons (pseudo update). */ @@ -9394,7 +9395,9 @@ static int ui_list_activate_hovered_row(bContext *C, } } - const int *mouse_xy = (event->val == KM_CLICK_DRAG) ? event->prev_click_xy : event->xy; + int mouse_xy[2]; + WM_event_drag_start_xy(event, mouse_xy); + uiBut *listrow = ui_list_row_find_mouse_over(region, mouse_xy); if (listrow) { wmOperatorType *custom_activate_optype = ui_list->dyn_data->custom_activate_optype; @@ -9421,7 +9424,9 @@ static bool ui_list_is_hovering_draggable_but(bContext *C, const wmEvent *event) { /* On a tweak event, uses the coordinates from where tweaking was started. */ - const int *mouse_xy = (event->val == KM_CLICK_DRAG) ? event->prev_click_xy : event->xy; + int mouse_xy[2]; + WM_event_drag_start_xy(event, mouse_xy); + const uiBut *hovered_but = ui_but_find_mouse_over_ex(region, mouse_xy, false, NULL, NULL); if (list->dyn_data->custom_drag_optype) { diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 0722584c7d8..1d1bb85bd36 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1673,7 +1673,7 @@ static int edittranslation_exec(bContext *C, wmOperator *op) RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo); RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo); RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo); - const int ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); + const int ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL); /* Clean up */ if (but_label.strinfo) { diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index c37d8ec7a2b..2f2556225b5 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -557,6 +557,7 @@ uiBlock *ui_popup_block_refresh(bContext *C, #ifdef DEBUG wmEvent *event_back = window->eventstate; + wmEvent *event_last_back = window->event_last_handled; #endif /* create ui block */ @@ -740,6 +741,7 @@ uiBlock *ui_popup_block_refresh(bContext *C, #ifdef DEBUG window->eventstate = event_back; + window->event_last_handled = event_last_back; #endif return block; diff --git a/source/blender/editors/interface/interface_template_search_menu.cc b/source/blender/editors/interface/interface_template_search_menu.cc index 160cc909036..8e4b2baed53 100644 --- a/source/blender/editors/interface/interface_template_search_menu.cc +++ b/source/blender/editors/interface/interface_template_search_menu.cc @@ -951,7 +951,7 @@ static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2) case MenuSearch_Item::Type::Operator: { CTX_store_set(C, item->op.context); WM_operator_name_call_ptr_with_depends_on_cursor( - C, item->op.type, item->op.opcontext, item->op.opptr, item->drawstr); + C, item->op.type, item->op.opcontext, item->op.opptr, nullptr, item->drawstr); CTX_store_set(C, nullptr); break; } diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c index 4783a3f2ac6..41de2ab197d 100644 --- a/source/blender/editors/interface/interface_template_search_operator.c +++ b/source/blender/editors/interface/interface_template_search_operator.c @@ -38,7 +38,7 @@ static void operator_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2) wmOperatorType *ot = arg2; if (ot) { - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL, NULL); } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 801477bb28a..9d19eb9ba9c 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -686,7 +686,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); - undo_push_label = "Override Data-Block"; + undo_push_label = "Make Local"; } break; case UI_ID_ALONE: @@ -1004,7 +1004,7 @@ static void template_ID(const bContext *C, UI_but_flag_enable(but, UI_BUT_REDALERT); } - if (id->lib) { + if (ID_IS_LINKED(id)) { if (id->tag & LIB_TAG_INDIRECT) { but = uiDefIconBut(block, UI_BTYPE_BUT, @@ -2013,7 +2013,7 @@ static void constraint_reorder(bContext *C, Panel *panel, int new_index) RNA_int_set(&props_ptr, "index", new_index); /* Set owner to #EDIT_CONSTRAINT_OWNER_OBJECT or #EDIT_CONSTRAINT_OWNER_BONE. */ RNA_enum_set(&props_ptr, "owner", constraint_from_bone ? 1 : 0); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL); WM_operator_properties_free(&props_ptr); } @@ -5653,7 +5653,7 @@ static void do_running_jobs(bContext *C, void *UNUSED(arg), int event) WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL); break; case B_STOPANIM: - WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL); + WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL, NULL); break; case B_STOPCOMPO: WM_jobs_stop(CTX_wm_manager(C), CTX_data_scene(C), NULL); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index d1f3843c643..35cf952b5ce 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -3319,6 +3319,8 @@ static void ui_draw_separator(const rcti *rect, const uiWidgetColors *wcol) /** \name Button Draw Callbacks * \{ */ +#define NUM_BUT_PADDING_FACTOR 0.425f + static void widget_numbut_draw( uiWidgetColors *wcol, rcti *rect, const float zoom, int state, int roundboxalign, bool emboss) { @@ -3413,11 +3415,10 @@ static void widget_numbut_draw( } if (!(state & UI_STATE_TEXT_INPUT)) { - const float textofs = 0.425f * BLI_rcti_size_y(rect); + const float text_padding = NUM_BUT_PADDING_FACTOR * BLI_rcti_size_y(rect); - /* text space */ - rect->xmin += textofs; - rect->xmax -= textofs; + rect->xmin += text_padding; + rect->xmax -= text_padding; } } @@ -3745,7 +3746,6 @@ static void widget_numslider( /* Backdrop first. */ const float ofs = widget_radius_from_zoom(zoom, wcol); - const float toffs = ofs * 0.75f; round_box_edges(&wtb, roundboxalign, rect, ofs); wtb.draw_outline = false; @@ -3838,8 +3838,9 @@ static void widget_numslider( /* Add space at either side of the button so text aligns with number-buttons * (which have arrow icons). */ if (!(state & UI_STATE_TEXT_INPUT)) { - rect->xmax -= toffs; - rect->xmin += toffs; + const float text_padding = NUM_BUT_PADDING_FACTOR * BLI_rcti_size_y(rect); + rect->xmax -= text_padding; + rect->xmin += text_padding; } } diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 28a025ee581..0b4d00a7def 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -270,7 +270,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event) view_pan_exit(op); WM_cursor_modal_restore(CTX_wm_window(C)); - WM_operator_name_call(C, "VIEW2D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW2D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL, event); return OPERATOR_FINISHED; } #endif diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 819ffd96b1c..b2d49bcc642 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -111,7 +111,7 @@ void ED_operatortypes_mask(void) WM_operatortype_append(MASK_OT_parent_set); WM_operatortype_append(MASK_OT_parent_clear); - /* shapekeys */ + /* Shape-keys. */ WM_operatortype_append(MASK_OT_shape_key_insert); WM_operatortype_append(MASK_OT_shape_key_clear); WM_operatortype_append(MASK_OT_shape_key_feather_reset); diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c index 8bb6e8a71db..8a23a53a5d2 100644 --- a/source/blender/editors/mask/mask_editaction.c +++ b/source/blender/editors/mask/mask_editaction.c @@ -30,8 +30,8 @@ /* ***************************************** */ /* NOTE ABOUT THIS FILE: * This file contains code for editing Mask data in the Action Editor - * as a 'keyframes', so that a user can adjust the timing of Mask shapekeys. - * Therefore, this file mostly contains functions for selecting Mask frames (shapekeys). + * as a 'keyframes', so that a user can adjust the timing of Mask shape-keys. + * Therefore, this file mostly contains functions for selecting Mask frames (shape-keys). */ /* ***************************************** */ /* Generics - Loopers */ diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c index 8d75e2aaf37..687f06c8dcf 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c @@ -44,7 +44,7 @@ # include "BKE_editmesh.h" #endif -static const float dial_angle_partial = M_PI / 2; +static const float dial_angle_partial = M_PI_2; static const float dial_angle_partial_margin = 0.92f; #define ORTHO_AXIS_OFFSET 2 diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index a8d62d90698..6b4edea498e 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -1017,7 +1017,7 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (bm->totfacesel) { /* highly nifty but hard to support since the operator can fail and we're left * with modified selection */ - // WM_operator_name_call(C, "MESH_OT_region_to_loop", WM_OP_INVOKE_DEFAULT, NULL); + // WM_operator_name_call(C, "MESH_OT_region_to_loop", WM_OP_INVOKE_DEFAULT, NULL, event); continue; } error_face_selected = false; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 2577218d6a9..6b3f50549ef 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4349,7 +4349,7 @@ static Base *mesh_separate_tagged( Base *base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, dupflag); /* normally would call directly after but in this case delay recalc */ - /* DAG_relations_tag_update(bmain); */ + // DAG_relations_tag_update(bmain); /* new in 2.5 */ BKE_object_material_array_assign(bmain, @@ -4423,7 +4423,7 @@ static Base *mesh_separate_arrays(Main *bmain, Base *base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, dupflag); /* normally would call directly after but in this case delay recalc */ - /* DAG_relations_tag_update(bmain); */ + // DAG_relations_tag_update(bmain); /* new in 2.5 */ BKE_object_material_array_assign(bmain, diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 97f67060c82..9c7d712a739 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -591,7 +591,8 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo um->me.key = NULL; } - /* BM_mesh_validate(em->bm); */ /* for troubleshooting */ + /* Uncomment for troubleshooting. */ + // BM_mesh_validate(em->bm); BM_mesh_bm_to_me( NULL, @@ -602,6 +603,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo .calc_object_remap = false, .update_shapekey_indices = false, .cd_mask_extra = {.vmask = CD_MASK_SHAPE_KEYINDEX}, + .active_shapekey_to_mvert = true, })); um->selectmode = em->selectmode; diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index f3782c17845..d57471b658c 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -137,22 +137,22 @@ static void join_mesh_single(Depsgraph *depsgraph, mul_m4_v3(cmat, mvert->co); } - /* For each shapekey in destination mesh: + /* For each shape-key in destination mesh: * - if there's a matching one, copy it across * (will need to transform vertices into new space...). * - otherwise, just copy own coordinates of mesh * (no need to transform vertex coordinates into new space). */ if (key) { - /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ + /* if this mesh has any shape-keys, check first, otherwise just copy coordinates */ LISTBASE_FOREACH (KeyBlock *, kb, &key->block) { - /* get pointer to where to write data for this mesh in shapekey's data array */ + /* get pointer to where to write data for this mesh in shape-key's data array */ float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs; - /* check if this mesh has such a shapekey */ + /* Check if this mesh has such a shape-key. */ KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL; if (okb) { - /* copy this mesh's shapekey to the destination shapekey + /* copy this mesh's shape-key to the destination shape-key * (need to transform first) */ float(*ocos)[3] = okb->data; for (a = 0; a < me->totvert; a++, cos++, ocos++) { @@ -161,7 +161,7 @@ static void join_mesh_single(Depsgraph *depsgraph, } } else { - /* copy this mesh's vertex coordinates to the destination shapekey */ + /* Copy this mesh's vertex coordinates to the destination shape-key. */ for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) { copy_v3_v3(*cos, mvert->co); } @@ -170,26 +170,26 @@ static void join_mesh_single(Depsgraph *depsgraph, } } else { - /* for each shapekey in destination mesh: + /* for each shape-key in destination mesh: * - if it was an 'original', copy the appropriate data from nkey * - otherwise, copy across plain coordinates (no need to transform coordinates) */ if (key) { LISTBASE_FOREACH (KeyBlock *, kb, &key->block) { - /* get pointer to where to write data for this mesh in shapekey's data array */ + /* get pointer to where to write data for this mesh in shape-key's data array */ float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs; - /* check if this was one of the original shapekeys */ + /* Check if this was one of the original shape-keys. */ KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; if (okb) { - /* copy this mesh's shapekey to the destination shapekey */ + /* copy this mesh's shape-key to the destination shape-key */ float(*ocos)[3] = okb->data; for (a = 0; a < me->totvert; a++, cos++, ocos++) { copy_v3_v3(*cos, *ocos); } } else { - /* copy base-coordinates to the destination shapekey */ + /* Copy base-coordinates to the destination shape-key. */ for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) { copy_v3_v3(*cos, mvert->co); } @@ -365,7 +365,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) join_parent = true; } - /* check for shapekeys */ + /* Check for shape-keys. */ if (me->key) { haskey++; } @@ -428,10 +428,10 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) /* increase id->us : will be lowered later */ } - /* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders - * with arrays that are large enough to hold shapekey data for all meshes - * - if destination mesh didn't have shapekeys, but we encountered some in the meshes we're - * joining, set up a new keyblock and assign to the mesh + /* - If destination mesh had shape-keys, move them somewhere safe, and set up placeholders + * with arrays that are large enough to hold shape-key data for all meshes. + * - If destination mesh didn't have shape-keys, but we encountered some in the meshes we're + * joining, set up a new key-block and assign to the mesh. */ if (key) { /* make a duplicate copy that will only be used here... (must remember to free it!) */ @@ -518,8 +518,8 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) } } - /* if this mesh has shapekeys, - * check if destination mesh already has matching entries too */ + /* If this mesh has shape-keys, + * check if destination mesh already has matching entries too. */ if (me->key && key) { /* for remapping KeyBlock.relative */ int *index_map = MEM_mallocN(sizeof(int) * me->key->totkey, __func__); @@ -713,7 +713,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) /* other mesh users */ BKE_objects_materials_test_all(bmain, (ID *)me); - /* free temp copy of destination shapekeys (if applicable) */ + /* Free temporary copy of destination shape-keys (if applicable). */ if (nkey) { /* We can assume nobody is using that ID currently. */ BKE_id_free_ex(bmain, nkey, LIB_ID_FREE_NO_UI_USER, false); diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index 7befad3b8d7..b8ffaf87118 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -3385,7 +3385,8 @@ Base *ED_object_add_duplicate( const int remap_flag = BKE_object_is_in_editmode(ob) ? ID_REMAP_FORCE_OBDATA_IN_EDITMODE : 0; BKE_libblock_relink_to_newid(bmain, &ob->id, remap_flag); - /* DAG_relations_tag_update(bmain); */ /* caller must do */ + /* Correct but the caller must do this. */ + // DAG_relations_tag_update(bmain); if (ob->data != nullptr) { DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS); diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index 8e9e8558016..cc6aa34d39d 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -158,7 +158,7 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, Report if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) { const char *opstring = object_mode_op_string(ob->mode); - WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL); + WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL, NULL); ok = ELEM(ob->mode, mode, OB_MODE_OBJECT); if (!ok) { wmOperatorType *ot = WM_operatortype_find(opstring, false); @@ -209,7 +209,7 @@ bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportL if (!use_undo) { wm->op_undo_depth++; } - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL); + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL, NULL); if (!use_undo) { wm->op_undo_depth--; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index ee3bc3cba76..9343f4a3b34 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1421,7 +1421,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) area->winy, SPACE_EMPTY, false, - true, + false, false, WIN_ALIGN_ABSOLUTE); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc index 12c03804981..47bf7a28352 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc @@ -7,10 +7,12 @@ #include "BKE_bvhutils.h" #include "BKE_context.h" #include "BKE_curves.hh" +#include "BKE_geometry_set.hh" #include "BKE_lib_id.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_paint.h" +#include "BKE_spline.hh" #include "WM_api.h" #include "WM_toolsystem.h" @@ -66,6 +68,7 @@ bool CURVES_SCULPT_mode_poll_view3d(bContext *C) namespace blender::ed::sculpt_paint { using blender::bke::CurvesGeometry; +using blender::fn::CPPType; /* -------------------------------------------------------------------- */ /** \name * SCULPT_CURVES_OT_brush_stroke @@ -133,14 +136,7 @@ class DeleteOperation : public CurvesSculptStrokeOperation { return false; }); - /* Just reset positions instead of actually removing the curves. This is just a prototype. */ - threading::parallel_for(curves_to_remove.index_range(), 512, [&](const IndexRange range) { - for (const int curve_i : curves_to_remove.slice(range)) { - for (const int point_i : curves.range_for_curve(curve_i)) { - positions[point_i] = {0.0f, 0.0f, 0.0f}; - } - } - }); + curves.remove_curves(curves_to_remove); curves.tag_positions_changed(); DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); @@ -150,15 +146,22 @@ class DeleteOperation : public CurvesSculptStrokeOperation { } }; -class MoveOperation : public CurvesSculptStrokeOperation { +/** + * Moves individual points under the brush and does a length preservation step afterwards. + */ +class CombOperation : public CurvesSculptStrokeOperation { private: - Vector<int64_t> points_to_move_indices_; - IndexMask points_to_move_; float2 last_mouse_position_; public: void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override { + BLI_SCOPED_DEFER([&]() { last_mouse_position_ = stroke_extension.mouse_position; }); + + if (stroke_extension.is_first) { + return; + } + Scene &scene = *CTX_data_scene(C); Object &object = *CTX_data_active_object(C); ARegion *region = CTX_wm_region(C); @@ -168,6 +171,10 @@ class MoveOperation : public CurvesSculptStrokeOperation { CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt; Brush &brush = *BKE_paint_brush(&curves_sculpt.paint); const float brush_radius = BKE_brush_size_get(&scene, &brush); + const float brush_strength = BKE_brush_alpha_get(&scene, &brush); + + const float4x4 ob_mat = object.obmat; + const float4x4 ob_imat = ob_mat.inverted(); float4x4 projection; ED_view3d_ob_project_mat_get(rv3d, &object, projection.values); @@ -176,39 +183,312 @@ class MoveOperation : public CurvesSculptStrokeOperation { CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry); MutableSpan<float3> positions = curves.positions(); - if (stroke_extension.is_first) { - /* Find point indices to move. */ - points_to_move_ = index_mask_ops::find_indices_based_on_predicate( - curves.points_range(), 512, points_to_move_indices_, [&](const int64_t point_i) { - const float3 position = positions[point_i]; - float2 screen_position; - ED_view3d_project_float_v2_m4(region, position, screen_position, projection.values); - const float distance = len_v2v2(screen_position, stroke_extension.mouse_position); - return distance <= brush_radius; - }); - } - else { - /* Move points based on mouse movement. */ - const float2 mouse_diff = stroke_extension.mouse_position - last_mouse_position_; - threading::parallel_for(points_to_move_.index_range(), 512, [&](const IndexRange range) { - for (const int point_i : points_to_move_.slice(range)) { + const float2 mouse_prev = last_mouse_position_; + const float2 mouse_cur = stroke_extension.mouse_position; + const float2 mouse_diff = mouse_cur - mouse_prev; + const float mouse_diff_len = math::length(mouse_diff); + + threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange curves_range) { + for (const int curve_i : curves_range) { + const IndexRange curve_points = curves.range_for_curve(curve_i); + /* Compute lengths of the segments. Those are used to make sure that the lengths don't + * change. */ + Vector<float, 16> segment_lengths(curve_points.size() - 1); + for (const int segment_i : IndexRange(curve_points.size() - 1)) { + const float3 &p1 = positions[curve_points[segment_i]]; + const float3 &p2 = positions[curve_points[segment_i] + 1]; + const float length = math::distance(p1, p2); + segment_lengths[segment_i] = length; + } + bool curve_changed = false; + for (const int point_i : curve_points.drop_front(1)) { const float3 old_position = positions[point_i]; + + /* Find the position of the point in screen space. */ float2 old_position_screen; ED_view3d_project_float_v2_m4( region, old_position, old_position_screen, projection.values); - const float2 new_position_screen = old_position_screen + mouse_diff; + + /* Project the point onto the line drawn by the mouse. Note, it's projected on the + * infinite line, not only on the line segment. */ + float2 old_position_screen_proj; + /* t is 0 when the point is closest to the previous mouse position and 1 when it's + * closest to the current mouse position. */ + const float t = closest_to_line_v2( + old_position_screen_proj, old_position_screen, mouse_prev, mouse_cur); + + /* Compute the distance to the mouse line segment. */ + const float2 old_position_screen_proj_segment = mouse_prev + + std::clamp(t, 0.0f, 1.0f) * mouse_diff; + const float distance_screen = math::distance(old_position_screen, + old_position_screen_proj_segment); + if (distance_screen > brush_radius) { + /* Ignore the point because it's too far away. */ + continue; + } + /* Compute a falloff that is based on how far along the point along the last stroke + * segment is. */ + const float t_overshoot = brush_radius / mouse_diff_len; + const float t_falloff = 1.0f - std::max(t, 0.0f) / (1.0f + t_overshoot); + /* A falloff that is based on how far away the point is from the stroke. */ + const float radius_falloff = pow2f(1.0f - distance_screen / brush_radius); + /* Combine the different falloffs and brush strength. */ + const float weight = brush_strength * t_falloff * radius_falloff; + + /* Offset the old point position in screen space and transform it back into 3D space. */ + const float2 new_position_screen = old_position_screen + mouse_diff * weight; float3 new_position; - ED_view3d_win_to_3d(v3d, region, old_position, new_position_screen, new_position); + ED_view3d_win_to_3d( + v3d, region, ob_mat * old_position, new_position_screen, new_position); + new_position = ob_imat * new_position; positions[point_i] = new_position; + + curve_changed = true; + } + if (!curve_changed) { + continue; } - }); + /* Ensure that the length of each segment stays the same. */ + for (const int segment_i : IndexRange(curve_points.size() - 1)) { + const float3 &p1 = positions[curve_points[segment_i]]; + float3 &p2 = positions[curve_points[segment_i] + 1]; + const float3 direction = math::normalize(p2 - p1); + const float desired_length = segment_lengths[segment_i]; + p2 = p1 + direction * desired_length; + } + } + }); + + curves.tag_positions_changed(); + DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); + ED_region_tag_redraw(region); + } +}; + +/** + * Drags the tip point of each curve and resamples the rest of the curve. + */ +class SnakeHookOperation : public CurvesSculptStrokeOperation { + private: + float2 last_mouse_position_; - curves.tag_positions_changed(); - DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); - ED_region_tag_redraw(region); + public: + void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override + { + BLI_SCOPED_DEFER([&]() { last_mouse_position_ = stroke_extension.mouse_position; }); + + if (stroke_extension.is_first) { + return; } - last_mouse_position_ = stroke_extension.mouse_position; + Scene &scene = *CTX_data_scene(C); + Object &object = *CTX_data_active_object(C); + ARegion *region = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + + CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt; + Brush &brush = *BKE_paint_brush(&curves_sculpt.paint); + const float brush_radius = BKE_brush_size_get(&scene, &brush); + const float brush_strength = BKE_brush_alpha_get(&scene, &brush); + + const float4x4 ob_mat = object.obmat; + const float4x4 ob_imat = ob_mat.inverted(); + + float4x4 projection; + ED_view3d_ob_project_mat_get(rv3d, &object, projection.values); + + Curves &curves_id = *static_cast<Curves *>(object.data); + CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry); + MutableSpan<float3> positions = curves.positions(); + + const float2 mouse_prev = last_mouse_position_; + const float2 mouse_cur = stroke_extension.mouse_position; + const float2 mouse_diff = mouse_cur - mouse_prev; + + threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange curves_range) { + for (const int curve_i : curves_range) { + const IndexRange curve_points = curves.range_for_curve(curve_i); + const int last_point_i = curve_points.last(); + + const float3 old_position = positions[last_point_i]; + + float2 old_position_screen; + ED_view3d_project_float_v2_m4( + region, old_position, old_position_screen, projection.values); + + const float distance_screen = math::distance(old_position_screen, mouse_prev); + if (distance_screen > brush_radius) { + continue; + } + + const float radius_falloff = pow2f(1.0f - distance_screen / brush_radius); + const float weight = brush_strength * radius_falloff; + + const float2 new_position_screen = old_position_screen + mouse_diff * weight; + float3 new_position; + ED_view3d_win_to_3d(v3d, region, ob_mat * old_position, new_position_screen, new_position); + new_position = ob_imat * new_position; + + this->move_last_point_and_resample(positions, curve_points, new_position); + } + }); + + curves.tag_positions_changed(); + DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); + ED_region_tag_redraw(region); + } + + void move_last_point_and_resample(MutableSpan<float3> positions, + const IndexRange curve_points, + const float3 &new_last_point_position) const + { + Vector<float> old_lengths; + old_lengths.append(0.0f); + /* Used to (1) normalize the segment sizes over time and (2) support making zero-length + * segments */ + const float extra_length = 0.001f; + for (const int segment_i : IndexRange(curve_points.size() - 1)) { + const float3 &p1 = positions[curve_points[segment_i]]; + const float3 &p2 = positions[curve_points[segment_i] + 1]; + const float length = math::distance(p1, p2); + old_lengths.append(old_lengths.last() + length + extra_length); + } + Vector<float> point_factors; + for (float &old_length : old_lengths) { + point_factors.append(old_length / old_lengths.last()); + } + + PolySpline new_spline; + new_spline.resize(curve_points.size()); + MutableSpan<float3> new_spline_positions = new_spline.positions(); + for (const int i : IndexRange(curve_points.size() - 1)) { + new_spline_positions[i] = positions[curve_points[i]]; + } + new_spline_positions.last() = new_last_point_position; + new_spline.mark_cache_invalid(); + + for (const int i : IndexRange(curve_points.size())) { + const float factor = point_factors[i]; + const Spline::LookupResult lookup = new_spline.lookup_evaluated_factor(factor); + const float index_factor = lookup.evaluated_index + lookup.factor; + float3 p; + new_spline.sample_with_index_factors<float3>( + new_spline_positions, {&index_factor, 1}, {&p, 1}); + positions[curve_points[i]] = p; + } + } +}; + +/** + * Resamples the curves to a shorter length. + */ +class ShrinkOperation : public CurvesSculptStrokeOperation { + private: + float2 last_mouse_position_; + + public: + void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override + { + BLI_SCOPED_DEFER([&]() { last_mouse_position_ = stroke_extension.mouse_position; }); + + if (stroke_extension.is_first) { + return; + } + + Scene &scene = *CTX_data_scene(C); + Object &object = *CTX_data_active_object(C); + ARegion *region = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + + CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt; + Brush &brush = *BKE_paint_brush(&curves_sculpt.paint); + const float brush_radius = BKE_brush_size_get(&scene, &brush); + const float brush_strength = BKE_brush_alpha_get(&scene, &brush); + + const float4x4 ob_mat = object.obmat; + const float4x4 ob_imat = ob_mat.inverted(); + + float4x4 projection; + ED_view3d_ob_project_mat_get(rv3d, &object, projection.values); + + Curves &curves_id = *static_cast<Curves *>(object.data); + CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry); + MutableSpan<float3> positions = curves.positions(); + + const float2 mouse_prev = last_mouse_position_; + const float2 mouse_cur = stroke_extension.mouse_position; + const float2 mouse_diff = mouse_cur - mouse_prev; + + threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange curves_range) { + for (const int curve_i : curves_range) { + const IndexRange curve_points = curves.range_for_curve(curve_i); + const int last_point_i = curve_points.last(); + + const float3 old_tip_position = positions[last_point_i]; + + float2 old_tip_position_screen; + ED_view3d_project_float_v2_m4( + region, old_tip_position, old_tip_position_screen, projection.values); + + const float distance_screen = math::distance(old_tip_position_screen, mouse_prev); + if (distance_screen > brush_radius) { + continue; + } + + const float radius_falloff = pow2f(1.0f - distance_screen / brush_radius); + const float weight = brush_strength * radius_falloff; + + const float2 offset_tip_position_screen = old_tip_position_screen + weight * mouse_diff; + float3 offset_tip_position; + ED_view3d_win_to_3d(v3d, + region, + ob_mat * old_tip_position, + offset_tip_position_screen, + offset_tip_position); + offset_tip_position = ob_imat * offset_tip_position; + const float shrink_length = math::distance(offset_tip_position, old_tip_position); + + this->shrink_curve(positions, curve_points, shrink_length); + } + }); + + curves.tag_positions_changed(); + DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); + ED_region_tag_redraw(region); + } + + void shrink_curve(MutableSpan<float3> positions, + const IndexRange curve_points, + const float shrink_length) const + { + PolySpline spline; + spline.resize(curve_points.size()); + MutableSpan<float3> spline_positions = spline.positions(); + spline_positions.copy_from(positions.slice(curve_points)); + spline.mark_cache_invalid(); + const float old_length = spline.length(); + const float new_length = std::max(0.0f, old_length - shrink_length); + const float length_factor = new_length / old_length; + + Vector<float> old_point_lengths; + old_point_lengths.append(0.0f); + for (const int i : spline_positions.index_range().drop_back(1)) { + const float3 &p1 = spline_positions[i]; + const float3 &p2 = spline_positions[i + 1]; + const float length = math::distance(p1, p2); + old_point_lengths.append(old_point_lengths.last() + length); + } + + for (const int i : spline_positions.index_range()) { + const float eval_length = old_point_lengths[i] * length_factor; + const Spline::LookupResult lookup = spline.lookup_evaluated_length(eval_length); + const float index_factor = lookup.evaluated_index + lookup.factor; + float3 p; + spline.sample_with_index_factors<float3>(spline_positions, {&index_factor, 1}, {&p, 1}); + positions[curve_points[i]] = p; + } } }; @@ -233,7 +513,7 @@ class AddOperation : public CurvesSculptStrokeOperation { }; public: - ~AddOperation() + ~AddOperation() override { if (old_kdtree_ != nullptr) { BLI_kdtree_3d_free(old_kdtree_); @@ -651,12 +931,16 @@ static std::unique_ptr<CurvesSculptStrokeOperation> start_brush_operation(bConte CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt; Brush &brush = *BKE_paint_brush(&curves_sculpt.paint); switch (brush.curves_sculpt_tool) { - case CURVES_SCULPT_TOOL_TEST1: - return std::make_unique<MoveOperation>(); - case CURVES_SCULPT_TOOL_TEST2: + case CURVES_SCULPT_TOOL_COMB: + return std::make_unique<CombOperation>(); + case CURVES_SCULPT_TOOL_DELETE: return std::make_unique<DeleteOperation>(); - case CURVES_SCULPT_TOOL_TEST3: + case CURVES_SCULPT_TOOL_SNAKE_HOOK: + return std::make_unique<SnakeHookOperation>(); + case CURVES_SCULPT_TOOL_TEST1: return std::make_unique<AddOperation>(); + case CURVES_SCULPT_TOOL_TEST2: + return std::make_unique<ShrinkOperation>(); } BLI_assert_unreachable(); return {}; diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c index 57c8bd58549..22d6626ab16 100644 --- a/source/blender/editors/sculpt_paint/paint_curve.c +++ b/source/blender/editors/sculpt_paint/paint_curve.c @@ -680,7 +680,7 @@ static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_PASS_THROUGH; } - return WM_operator_name_call(C, name, WM_OP_INVOKE_DEFAULT, NULL); + return WM_operator_name_call(C, name, WM_OP_INVOKE_DEFAULT, NULL, NULL); } void PAINTCURVE_OT_draw(wmOperatorType *ot) diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index ae7570d21a1..1705e36363e 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -1000,6 +1000,10 @@ bool paint_space_stroke_enabled(Brush *br, ePaintMode mode) return true; } + if (mode == PAINT_MODE_SCULPT_CURVES) { + return false; + } + return paint_supports_dynamic_size(br, mode); } diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 80ba7601cb1..a4cfb611138 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -1502,7 +1502,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent return OPERATOR_RUNNING_MODAL; } - const float len = event->prev_click_xy[0] - event->xy[0]; + const float len = event->prev_press_xy[0] - event->xy[0]; filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC; SCULPT_vertex_random_access_ensure(ss); diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c index 0f1f7c57287..dd8921d575f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.c +++ b/source/blender/editors/sculpt_paint/sculpt_detail.c @@ -408,7 +408,7 @@ static void sculpt_detail_size_set_radial_control(bContext *C) RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_size"); } - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL); WM_operator_properties_free(&props_ptr); } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c index 93e2d721962..377f1e0ed32 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -215,7 +215,7 @@ static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent return OPERATOR_RUNNING_MODAL; } - const float len = event->prev_click_xy[0] - event->xy[0]; + const float len = event->prev_press_xy[0] - event->xy[0]; filter_strength = filter_strength * -len * 0.001f; float fill_color[3]; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index ac2c83d3a9c..b73e182fcab 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -606,7 +606,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * return OPERATOR_RUNNING_MODAL; } - const float len = event->prev_click_xy[0] - event->xy[0]; + const float len = event->prev_press_xy[0] - event->xy[0]; filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC; SCULPT_vertex_random_access_ensure(ss); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index f3f47f71f60..2ec553c63c7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -31,6 +31,7 @@ #include "BKE_key.h" #include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" #include "BKE_multires.h" #include "BKE_object.h" #include "BKE_paint.h" @@ -528,6 +529,8 @@ static void sculpt_undo_geometry_restore_data(SculptUndoNodeGeometry *geometry, &geometry->pdata, &mesh->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly); BKE_mesh_update_customdata_pointers(mesh, false); + + BKE_mesh_runtime_clear_cache(mesh); } static void sculpt_undo_geometry_free_data(SculptUndoNodeGeometry *geometry) diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 65815983767..b972ccbaf89 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -511,8 +511,12 @@ static int actkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEvent } bool tweak = RNA_boolean_get(op->ptr, "tweak"); - if (tweak && actkeys_is_key_at_position(&ac, event->mval[0], event->mval[1])) { - return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; + if (tweak) { + int mval[2]; + WM_event_drag_start_mval(event, ac.region, mval); + if (actkeys_is_key_at_position(&ac, mval[0], mval[1])) { + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; + } } return WM_gesture_box_invoke(C, op, event); diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index e215b7c7992..3de181fa540 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -295,7 +295,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event) WM_operator_properties_create_ptr(&props_ptr, ot); RNA_string_set(&props_ptr, "filepath", str); - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr, NULL); WM_operator_properties_free(&props_ptr); MEM_freeN(str); diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index a24eae6a0ce..17fbef23eac 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -469,10 +469,10 @@ static int console_indent_or_autocomplete_exec(bContext *C, wmOperator *UNUSED(o } if (text_before_cursor) { - WM_operator_name_call(C, "CONSOLE_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "CONSOLE_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL, NULL); } else { - WM_operator_name_call(C, "CONSOLE_OT_indent", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "CONSOLE_OT_indent", WM_OP_EXEC_DEFAULT, NULL, NULL); } return OPERATOR_FINISHED; } @@ -1070,7 +1070,7 @@ static int console_paste_exec(bContext *C, wmOperator *UNUSED(op)) } if (buf_next != buf_str) { - WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL, NULL); ci = console_history_verify(C); } diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index d051f14d264..8e33f7fa97f 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -189,7 +189,7 @@ static void console_main_region_draw(const bContext *C, ARegion *region) View2D *v2d = ®ion->v2d; if (BLI_listbase_is_empty(&sc->scrollback)) { - WM_operator_name_call((bContext *)C, "CONSOLE_OT_banner", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call((bContext *)C, "CONSOLE_OT_banner", WM_OP_EXEC_DEFAULT, NULL, NULL); } /* clear and setup matrix */ diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index c859cad1c27..578288ca289 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -2221,7 +2221,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w RNA_int_set(&op_ptr, "deltax", deltax); RNA_int_set(&op_ptr, "deltay", deltay); - WM_operator_name_call(C, "VIEW2D_OT_pan", WM_OP_EXEC_DEFAULT, &op_ptr); + WM_operator_name_call(C, "VIEW2D_OT_pan", WM_OP_EXEC_DEFAULT, &op_ptr, event); WM_operator_properties_free(&op_ptr); ED_region_tag_redraw(region); @@ -2580,7 +2580,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN BLI_strncpy(params->dir, lastdir, sizeof(params->dir)); } - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL); WM_operator_properties_free(&ptr); } } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index daa4b53803f..363e19a8905 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -339,7 +339,7 @@ typedef struct FileListEntryPreview { char path[FILE_MAX]; uint flags; int index; - + int attributes; /* from FileDirEntry. */ int icon_id; } FileListEntryPreview; @@ -1623,8 +1623,10 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat IMB_thumb_path_lock(preview->path); /* Always generate biggest preview size for now, it's simpler and avoids having to re-generate - * in case user switch to a bigger preview size. */ - ImBuf *imbuf = IMB_thumb_manage(preview->path, THB_LARGE, source); + * in case user switch to a bigger preview size. Do not create preview when file is offline. */ + ImBuf *imbuf = (preview->attributes & FILE_ATTR_OFFLINE) ? + IMB_thumb_read(preview->path, THB_LARGE) : + IMB_thumb_manage(preview->path, THB_LARGE, source); IMB_thumb_path_unlock(preview->path); if (imbuf) { preview->icon_id = BKE_icon_imbuf_create(imbuf); @@ -1704,11 +1706,6 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE); - if (!entry->preview_icon_id && (entry->attributes & FILE_ATTR_OFFLINE)) { - entry->flags |= FILE_ENTRY_INVALID_PREVIEW; - return; - } - if (entry->preview_icon_id) { return; } @@ -1735,6 +1732,7 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__); preview->index = index; preview->flags = entry->typeflag; + preview->attributes = entry->attributes; preview->icon_id = 0; if (preview_in_memory) { @@ -3462,8 +3460,7 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist) // files->entry->nr = totbl + 1; files->entry->poin = id; fake = id->flag & LIB_FAKEUSER; - if (idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || - idcode == ID_IM) { + if (ELEM(idcode, ID_MA, ID_TE, ID_LA, ID_WO, ID_IM)) { files->typeflag |= FILE_TYPE_IMAGE; } # if 0 diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index f6629061878..011506368ee 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -515,19 +515,15 @@ void ED_fileselect_activate_by_id(SpaceFile *sfile, ID *asset_id, const bool def FileSelectParams *params = ED_fileselect_get_active_params(sfile); struct FileList *files = sfile->files; - const int num_files_filtered = filelist_files_ensure(files); - for (int file_index = 0; file_index < num_files_filtered; ++file_index) { - const FileDirEntry *file = filelist_file_ex(files, file_index, false); - - if (filelist_file_get_id(file) != asset_id) { - continue; - } - - params->active_file = file_index; - filelist_entry_select_set(files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); - break; + const int file_index = filelist_file_find_id(files, asset_id); + const FileDirEntry *file = filelist_file_ex(files, file_index, true); + if (file == NULL) { + return; } + params->active_file = file_index; + filelist_entry_select_set(files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); + WM_main_add_notifier(NC_ASSET | NA_ACTIVATED, NULL); WM_main_add_notifier(NC_ASSET | NA_SELECTED, NULL); } @@ -1129,8 +1125,8 @@ int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matche */ for (int i = 0; i < n; i++) { FileDirEntry *file = filelist_file(sfile->files, i); - /* Do not check whether file is a file or dir here! Causes T44243 - * (we do accept dirs at this stage). */ + /* Do not check whether file is a file or dir here! Causes: T44243 + * (we do accept directories at this stage). */ if (fnmatch(pattern, file->relpath, 0) == 0) { filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); if (!match) { diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 988ba7728f1..847bf89bba8 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -29,6 +29,7 @@ * because 'near' is disabled through BLI_windstuff. */ # include "BLI_winstuff.h" # include <shlobj.h> +# include <shlwapi.h> #endif #include "UI_interface_icons.h" @@ -642,14 +643,29 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) tmps[3] = '\0'; name = NULL; - /* Flee from horrible win querying hover floppy drives! */ + /* Skip over floppy disks A & B. */ if (i > 1) { - /* Try to get a friendly drive description. */ - SHFILEINFOW shFile = {0}; + /* Friendly volume descriptions without using SHGetFileInfoW (T85689). */ BLI_strncpy_wchar_from_utf8(wline, tmps, 4); - if (SHGetFileInfoW(wline, 0, &shFile, sizeof(SHFILEINFOW), SHGFI_DISPLAYNAME)) { - BLI_strncpy_wchar_as_utf8(line, shFile.szDisplayName, FILE_MAXDIR); - name = line; + IShellFolder *desktop; + if (SHGetDesktopFolder(&desktop) == S_OK) { + PIDLIST_RELATIVE volume; + if (desktop->lpVtbl->ParseDisplayName( + desktop, NULL, NULL, wline, NULL, &volume, NULL) == S_OK) { + STRRET volume_name; + volume_name.uType = STRRET_WSTR; + if (desktop->lpVtbl->GetDisplayNameOf( + desktop, volume, SHGDN_FORADDRESSBAR, &volume_name) == S_OK) { + wchar_t *volume_name_wchar; + if (StrRetToStrW(&volume_name, volume, &volume_name_wchar) == S_OK) { + BLI_strncpy_wchar_as_utf8(line, volume_name_wchar, FILE_MAXDIR); + name = line; + CoTaskMemFree(volume_name_wchar); + } + } + CoTaskMemFree(volume); + } + desktop->lpVtbl->Release(desktop); } } if (name == NULL) { diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 2ed684c6e97..39b980ac4c3 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -799,7 +799,9 @@ static int graphkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEven } if (RNA_boolean_get(op->ptr, "tweak")) { - tNearestVertInfo *under_mouse = find_nearest_fcurve_vert(&ac, event->mval); + int mval[2]; + WM_event_drag_start_mval(event, ac.region, mval); + tNearestVertInfo *under_mouse = find_nearest_fcurve_vert(&ac, mval); bool mouse_is_over_element = under_mouse != NULL; if (under_mouse) { MEM_freeN(under_mouse); diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 22427675ff3..f041f2d1d3b 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -295,16 +295,14 @@ static void graph_main_region_draw_overlay(const bContext *C, ARegion *region) /* draw entirely, view changes should be handled here */ const SpaceGraph *sipo = CTX_wm_space_graph(C); - /* Driver Editor's X axis is not time. */ - if (sipo->mode == SIPO_MODE_DRIVERS) { - return; - } - const Scene *scene = CTX_data_scene(C); View2D *v2d = ®ion->v2d; - /* scrubbing region */ - ED_time_scrub_draw_current_frame(region, scene, sipo->flag & SIPO_DRAWTIME); + /* Driver Editor's X axis is not time. */ + if (sipo->mode != SIPO_MODE_DRIVERS) { + /* scrubbing region */ + ED_time_scrub_draw_current_frame(region, scene, sipo->flag & SIPO_DRAWTIME); + } /* scrollers */ /* FIXME: args for scrollers depend on the type of data being shown. */ diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 6f3d40abce1..0af32a717a4 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -718,22 +718,6 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg)) RNA_property_update(C, &cb->ptr, cb->prop); } -static bool image_has_alpha(Image *ima, ImageUser *iuser) -{ - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - if (ibuf == NULL) { - return false; - } - - int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions); - char valid_channels = BKE_imtype_valid_channels(imtype, false); - bool has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0; - - BKE_image_release_ibuf(ima, ibuf, NULL); - - return has_alpha; -} - void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, @@ -943,7 +927,7 @@ void uiTemplateImage(uiLayout *layout, if (compact == 0) { if (ima->source != IMA_SRC_GENERATED) { - if (image_has_alpha(ima, iuser)) { + if (BKE_image_has_alpha(ima)) { uiLayout *sub = uiLayoutColumn(col, false); uiItemR(sub, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index cc86852e0d1..342f2df0020 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -541,7 +541,10 @@ void draw_image_cache(const bContext *C, ARegion *region) int num_segments = 0; int *points = NULL; + BLI_mutex_lock(image->runtime.cache_mutex); IMB_moviecache_get_cache_segments(image->cache, IMB_PROXY_NONE, 0, &num_segments, &points); + BLI_mutex_unlock(image->runtime.cache_mutex); + ED_region_cache_draw_cached_segments( region, num_segments, points, sfra + sima->iuser.offset, efra + sima->iuser.offset); } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index aed4a2ccabd..6a16efdb413 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2155,7 +2155,7 @@ static int image_save_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Image *ima = image_from_context(C); ImageUser *iuser = image_user_from_context(C); @@ -2163,7 +2163,7 @@ static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( /* Not writable formats or images without a file-path will go to "Save As". */ if (!BKE_image_has_packedfile(ima) && (!BKE_image_has_filepath(ima) || !image_file_format_writable(ima, iuser))) { - WM_operator_name_call(C, "IMAGE_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "IMAGE_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL, event); return OPERATOR_CANCELLED; } return image_save_exec(C, op); diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index e9997fe8d42..c3a48abcae1 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -557,7 +557,8 @@ static void uhandle_restore_list(ListBase *undo_handles, bool use_init) if (changed) { BKE_image_mark_dirty(image, ibuf); - BKE_image_free_gputextures(image); /* force OpenGL reload */ + /* TODO(jbakker): only mark areas that are actually updated to improve performance. */ + BKE_image_partial_update_mark_full_update(image); if (ibuf->rect_float) { ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */ diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c index 603c7c9ad37..ba11c5b2958 100644 --- a/source/blender/editors/space_info/info_report.c +++ b/source/blender/editors/space_info/info_report.c @@ -101,7 +101,7 @@ static int report_replay_exec(bContext *C, wmOperator *UNUSED(op)) if ((report->type & report_mask) && (report->type & RPT_OPERATOR_ALL | RPT_PROPERTY_ALL) && (report->flag & SELECT)) { console_history_add_str(sc, report->message, 0); - WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL, NULL); ED_area_tag_redraw(CTX_wm_area(C)); } diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index e94221fab04..eeeadb6e60a 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -1192,12 +1192,12 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { nlaedit_duplicate_exec(C, op); RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION); - WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr); + WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr, event); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 3000b4a1109..1efb91bc99f 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -439,7 +439,7 @@ static void nlaedit_select_leftright(bContext *C, /* if currently in tweak-mode, exit tweak-mode first */ if (scene->flag & SCE_NLA_EDIT_ON) { - WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL, NULL); } /* if select mode is replace, deselect all keyframes (and channels) first */ @@ -600,7 +600,7 @@ static int mouse_nla_strips(bContext *C, * now that we've found our target... */ if (scene->flag & SCE_NLA_EDIT_ON) { - WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL, NULL); } if (select_mode != SELECT_REPLACE) { diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index afb205f9f9e..fab2946ad76 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -304,9 +304,11 @@ static void node_buts_image_user(uiLayout *layout, const bool show_layer_selection, const bool show_color_management) { - if (!imaptr->data) { + Image *image = (Image *)imaptr->data; + if (!image) { return; } + ImageUser *iuser = (ImageUser *)iuserptr->data; uiLayout *col = uiLayoutColumn(layout, false); @@ -318,8 +320,6 @@ static void node_buts_image_user(uiLayout *layout, /* don't use iuser->framenr directly * because it may not be updated if auto-refresh is off */ Scene *scene = CTX_data_scene(C); - ImageUser *iuser = (ImageUser *)iuserptr->data; - /* Image *ima = imaptr->data; */ /* UNUSED */ char numstr[32]; const int framenr = BKE_image_user_frame_get(iuser, CFRA, nullptr); @@ -343,11 +343,20 @@ static void node_buts_image_user(uiLayout *layout, } if (show_color_management) { - uiLayout *split = uiLayoutSplit(layout, 0.5f, true); + uiLayout *split = uiLayoutSplit(layout, 0.33f, true); PointerRNA colorspace_settings_ptr = RNA_pointer_get(imaptr, "colorspace_settings"); uiItemL(split, IFACE_("Color Space"), ICON_NONE); uiItemR(split, &colorspace_settings_ptr, "name", DEFAULT_FLAGS, "", ICON_NONE); + if (image->source != IMA_SRC_GENERATED) { + split = uiLayoutSplit(layout, 0.33f, true); + uiItemL(split, IFACE_("Alpha"), ICON_NONE); + uiItemR(split, imaptr, "alpha_mode", DEFAULT_FLAGS, "", ICON_NONE); + + bool is_data = IMB_colormanagement_space_name_is_data(image->colorspace_settings.name); + uiLayoutSetActive(split, !is_data); + } + /* Avoid losing changes image is painted. */ if (BKE_image_is_dirty((Image *)imaptr->data)) { uiLayoutSetEnabled(split, false); diff --git a/source/blender/editors/space_node/link_drag_search.cc b/source/blender/editors/space_node/link_drag_search.cc index 2484318e612..ccd3333fcc5 100644 --- a/source/blender/editors/space_node/link_drag_search.cc +++ b/source/blender/editors/space_node/link_drag_search.cc @@ -235,7 +235,7 @@ static void link_drag_search_exec_fn(bContext *C, void *arg1, void *arg2) PointerRNA ptr; WM_operator_properties_create_ptr(&ptr, ot); RNA_boolean_set(&ptr, "view2d_edge_pan", true); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); WM_operator_properties_free(&ptr); } diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 1286f6a818c..9976ecf7700 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -720,7 +720,7 @@ static void node_socket_draw_multi_input(const float color[4], { /* The other sockets are drawn with the keyframe shader. There, the outline has a base thickness * that can be varied but always scales with the size the socket is drawn at. Using `U.dpi_fac` - * has the the same effect here. It scales the outline correctly across different screen DPIs + * has the same effect here. It scales the outline correctly across different screen DPI's * and UI scales without being affected by the 'line-width'. */ const float outline_width = NODE_SOCK_OUTLINE_SCALE * U.dpi_fac; @@ -1193,7 +1193,7 @@ static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_ /* Select & activate only the button's node. */ node_select_single(*C, *node); - WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, nullptr); + WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, nullptr, nullptr); } static void node_draw_shadow(const SpaceNode &snode, diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index b30be6ae0af..974e4c2e1cf 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -955,8 +955,10 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) switch (event->type) { case MOUSEMOVE: { + int mval[2]; + WM_event_drag_start_mval(event, region, mval); float mx, my; - UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &mx, &my); + UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &mx, &my); float dx = (mx - nsw->mxstart) / UI_DPI_FAC; float dy = (my - nsw->mystart) / UI_DPI_FAC; @@ -1057,7 +1059,9 @@ static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* convert mouse coordinates to v2d space */ float cursor[2]; - UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]); + int mval[2]; + WM_event_drag_start_mval(event, region, mval); + UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &cursor[0], &cursor[1]); const NodeResizeDirection dir = node_get_resize_direction(node, cursor[0], cursor[1]); if (dir == NODE_RESIZE_NONE) { return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; @@ -1503,7 +1507,7 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op)) /* To keep keyframe positions. */ sce->r.scemode |= R_NO_FRAME_UPDATE; - WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr); + WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr, nullptr); WM_operator_properties_free(&op_ptr); diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index 299e7e5658c..2eae1ce240c 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -1177,8 +1177,11 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) bool detach = RNA_boolean_get(op->ptr, "detach"); + int mval[2]; + WM_event_drag_start_mval(event, ®ion, mval); + float2 cursor; - UI_view2d_region_to_view(®ion.v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]); + UI_view2d_region_to_view(®ion.v2d, mval[0], mval[1], &cursor[0], &cursor[1]); RNA_float_set_array(op->ptr, "drag_start", cursor); RNA_boolean_set(op->ptr, "has_link_picked", false); diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index a355487057c..1d0097068f1 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -185,7 +185,11 @@ static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event) SpaceNode *snode = CTX_wm_space_node(C); ARegion *region = CTX_wm_region(C); float2 mouse; - UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &mouse.x, &mouse.y); + + int mval[2]; + WM_event_drag_start_mval(event, region, mval); + + UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &mouse.x, &mouse.y); return is_position_over_node_or_socket(*snode, mouse); } diff --git a/source/blender/editors/space_outliner/outliner_collections.cc b/source/blender/editors/space_outliner/outliner_collections.cc index f38f6c2855d..7c0ccd7b14c 100644 --- a/source/blender/editors/space_outliner/outliner_collections.cc +++ b/source/blender/editors/space_outliner/outliner_collections.cc @@ -9,6 +9,7 @@ #include "BLI_listbase.h" #include "BLI_utildefines.h" +#include "DNA_ID.h" #include "DNA_collection_types.h" #include "DNA_object_types.h" @@ -275,6 +276,12 @@ struct CollectionEditData { Scene *scene; SpaceOutliner *space_outliner; GSet *collections_to_edit; + + /* Whether the processed operation should be allowed on liboverride collections, or not. */ + bool is_liboverride_allowed; + /* Whether the processed operation should be allowed on hierarchy roots of liboverride + * collections, or not. */ + bool is_liboverride_hierarchy_root_allowed; }; static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *customdata) @@ -287,27 +294,40 @@ static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *c } if (collection->flag & COLLECTION_IS_MASTER) { - /* skip - showing warning/error message might be misleading - * when deleting multiple collections, so just do nothing */ + /* Skip - showing warning/error message might be misleading + * when deleting multiple collections, so just do nothing. */ + return TRAVERSE_CONTINUE; } - else { - /* Delete, duplicate and link don't edit children, those will come along - * with the parents. */ - BLI_gset_add(data->collections_to_edit, collection); - return TRAVERSE_SKIP_CHILDS; + + if (ID_IS_OVERRIDE_LIBRARY_REAL(collection)) { + if (ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(collection)) { + if (!data->is_liboverride_hierarchy_root_allowed) { + return TRAVERSE_SKIP_CHILDS; + } + } + else { + if (!data->is_liboverride_allowed) { + return TRAVERSE_SKIP_CHILDS; + } + } } - return TRAVERSE_CONTINUE; + /* Delete, duplicate and link don't edit children, those will come along + * with the parents. */ + BLI_gset_add(data->collections_to_edit, collection); + return TRAVERSE_SKIP_CHILDS; } void outliner_collection_delete( - bContext *C, Main *bmain, Scene *scene, ReportList *reports, bool hierarchy) + bContext *C, Main *bmain, Scene *scene, ReportList *reports, bool do_hierarchy) { SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); CollectionEditData data{}; data.scene = scene; data.space_outliner = space_outliner; + data.is_liboverride_allowed = false; + data.is_liboverride_hierarchy_root_allowed = do_hierarchy; data.collections_to_edit = BLI_gset_ptr_new(__func__); @@ -356,14 +376,14 @@ void outliner_collection_delete( } if (!skip) { - BKE_collection_delete(bmain, collection, hierarchy); + BKE_collection_delete(bmain, collection, do_hierarchy); } else { - BKE_reportf( - reports, - RPT_WARNING, - "Cannot delete linked collection '%s', it is used by other linked scenes/collections", - collection->id.name + 2); + BKE_reportf(reports, + RPT_WARNING, + "Cannot delete collection '%s', it is either a linked one used by other " + "linked scenes/collections, or a library override one", + collection->id.name + 2); } } } @@ -662,6 +682,8 @@ static int collection_link_exec(bContext *C, wmOperator *op) CollectionEditData data{}; data.scene = scene; data.space_outliner = space_outliner; + data.is_liboverride_allowed = false; /* No linking of non-root collections. */ + data.is_liboverride_hierarchy_root_allowed = true; if ((ID_IS_LINKED(active_collection) || ID_IS_OVERRIDE_LIBRARY(active_collection)) || ((active_collection->flag & COLLECTION_IS_MASTER) && @@ -726,6 +748,8 @@ static int collection_instance_exec(bContext *C, wmOperator *UNUSED(op)) CollectionEditData data{}; data.scene = scene; data.space_outliner = space_outliner; + data.is_liboverride_allowed = false; /* No instancing of non-root collections. */ + data.is_liboverride_hierarchy_root_allowed = true; data.collections_to_edit = BLI_gset_ptr_new(__func__); @@ -825,6 +849,8 @@ static bool collections_view_layer_poll(bContext *C, bool clear, int flag) CollectionEditData data{}; data.scene = scene; data.space_outliner = space_outliner; + data.is_liboverride_allowed = true; + data.is_liboverride_hierarchy_root_allowed = true; data.collections_to_edit = BLI_gset_ptr_new(__func__); bool result = false; @@ -891,6 +917,8 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op) CollectionEditData data{}; data.scene = scene; data.space_outliner = space_outliner; + data.is_liboverride_allowed = true; + data.is_liboverride_hierarchy_root_allowed = true; bool clear = strstr(op->idname, "clear") != nullptr; int flag = strstr(op->idname, "holdout") ? LAYER_COLLECTION_HOLDOUT : strstr(op->idname, "indirect_only") ? LAYER_COLLECTION_INDIRECT_ONLY : @@ -1029,6 +1057,8 @@ static int collection_isolate_exec(bContext *C, wmOperator *op) CollectionEditData data{}; data.scene = scene; data.space_outliner = space_outliner; + data.is_liboverride_allowed = true; + data.is_liboverride_hierarchy_root_allowed = true; data.collections_to_edit = BLI_gset_ptr_new(__func__); outliner_tree_traverse(space_outliner, &space_outliner->tree, @@ -1126,6 +1156,8 @@ static int collection_visibility_exec(bContext *C, wmOperator *op) CollectionEditData data{}; data.scene = scene; data.space_outliner = space_outliner; + data.is_liboverride_allowed = true; + data.is_liboverride_hierarchy_root_allowed = true; data.collections_to_edit = BLI_gset_ptr_new(__func__); outliner_tree_traverse(space_outliner, @@ -1273,6 +1305,8 @@ static int collection_flag_exec(bContext *C, wmOperator *op) CollectionEditData data{}; data.scene = scene; data.space_outliner = space_outliner; + data.is_liboverride_allowed = true; + data.is_liboverride_hierarchy_root_allowed = true; data.collections_to_edit = BLI_gset_ptr_new(__func__); const bool has_layer_collection = space_outliner->outlinevis == SO_VIEW_LAYER; diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.cc b/source/blender/editors/space_outliner/outliner_dragdrop.cc index edd2e5f304f..30b81b2ecb2 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.cc +++ b/source/blender/editors/space_outliner/outliner_dragdrop.cc @@ -46,7 +46,9 @@ static Collection *collection_parent_from_ID(ID *id); -/* ******************** Drop Target Find *********************** */ +/* -------------------------------------------------------------------- */ +/** \name Drop Target Find + * \{ */ static TreeElement *outliner_dropzone_element(TreeElement *te, const float fmval[2], @@ -254,7 +256,11 @@ static int outliner_get_insert_index(TreeElement *drag_te, return BLI_findindex(listbase, drop_te->directdata); } -/* ******************** Parent Drop Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Parent Drop Operator + * \{ */ static bool parent_drop_allowed(TreeElement *te, Object *potential_child) { @@ -443,7 +449,11 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } -/* ******************** Parent Clear Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Parent Clear Operator + * \{ */ static bool parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event) { @@ -527,7 +537,11 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } -/* ******************** Scene Drop Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Scene Drop Operator + * \{ */ static bool scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { @@ -592,7 +606,11 @@ void OUTLINER_OT_scene_drop(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } -/* ******************** Material Drop Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Material Drop Operator + * \{ */ static bool material_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { @@ -641,15 +659,19 @@ void OUTLINER_OT_material_drop(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } -/* ******************** Data Stack Drop Operator *********************** */ +/** \} */ -/* A generic operator to allow drag and drop for modifiers, constraints, +/* -------------------------------------------------------------------- */ +/** \name Data Stack Drop Operator + * + * A generic operator to allow drag and drop for modifiers, constraints, * and shader effects which all share the same UI stack layout. * * The following operations are allowed: * - Reordering within an object. * - Copying a single modifier/constraint/effect to another object. - * - Copying (linking) an object's modifiers/constraints/effects to another. */ + * - Copying (linking) an object's modifiers/constraints/effects to another. + * \{ */ enum eDataStackDropAction { DATA_STACK_DROP_REORDER, @@ -1069,7 +1091,11 @@ void OUTLINER_OT_datastack_drop(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } -/* ******************** Collection Drop Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Collection Drop Operator + * \{ */ struct CollectionDrop { Collection *from; @@ -1350,7 +1376,11 @@ void OUTLINER_OT_collection_drop(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } -/* ********************* Outliner Drag Operator ******************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Outliner Drag Operator + * \{ */ #define OUTLINER_DRAG_SCOLL_OUTSIDE_PAD 7 /* In UI units */ @@ -1358,9 +1388,12 @@ static TreeElement *outliner_item_drag_element_find(SpaceOutliner *space_outline ARegion *region, const wmEvent *event) { - /* NOTE: using EVT_TWEAK_ events to trigger dragging is fine, + /* NOTE: using click-drag events to trigger dragging is fine, * it sends coordinates from where dragging was started */ - const float my = UI_view2d_region_to_view_y(®ion->v2d, event->mval[1]); + int mval[2]; + WM_event_drag_start_mval(event, region, mval); + + const float my = UI_view2d_region_to_view_y(®ion->v2d, mval[1]); return outliner_find_item_at_y(space_outliner, &space_outliner->tree, my); } @@ -1372,6 +1405,9 @@ static int outliner_item_drag_drop_invoke(bContext *C, SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); TreeElement *te = outliner_item_drag_element_find(space_outliner, region, event); + int mval[2]; + WM_event_drag_start_mval(event, region, mval); + if (!te) { return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } @@ -1383,8 +1419,7 @@ static int outliner_item_drag_drop_invoke(bContext *C, } float view_mval[2]; - UI_view2d_region_to_view( - ®ion->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]); if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) { return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } @@ -1399,7 +1434,7 @@ static int outliner_item_drag_drop_invoke(bContext *C, PointerRNA op_ptr; WM_operator_properties_create_ptr(&op_ptr, ot); RNA_float_set(&op_ptr, "outside_padding", OUTLINER_DRAG_SCOLL_OUTSIDE_PAD); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr, event); WM_operator_properties_free(&op_ptr); } @@ -1523,7 +1558,11 @@ void OUTLINER_OT_item_drag_drop(wmOperatorType *ot) #undef OUTLINER_DRAG_SCOLL_OUTSIDE_PAD -/* *************************** Drop Boxes ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Drop Boxes + * \{ */ void outliner_dropboxes(void) { @@ -1546,3 +1585,5 @@ void outliner_dropboxes(void) nullptr, collection_drop_tooltip); } + +/** \} */ diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index 53de7d582b6..7b62b28abc5 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -1721,7 +1721,7 @@ static void outliner_draw_userbuts(uiBlock *block, LISTBASE_FOREACH (TreeElement *, te, lb) { TreeStoreElem *tselem = TREESTORE(te); - if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) { + if (outliner_is_element_in_view(te, ®ion->v2d)) { if (tselem->type == TSE_SOME_ID) { uiBut *bt; ID *id = tselem->id; @@ -1792,8 +1792,7 @@ static bool outliner_draw_overrides_buts(uiBlock *block, LISTBASE_FOREACH (TreeElement *, te, lb) { bool item_has_warnings = false; - const bool do_draw = (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && - te->ys <= region->v2d.cur.ymax); + const bool do_draw = outliner_is_element_in_view(te, ®ion->v2d); int but_flag = UI_BUT_DRAG_LOCK; const char *tip = nullptr; @@ -1903,7 +1902,7 @@ static void outliner_draw_rnabuts( LISTBASE_FOREACH (TreeElement *, te, lb) { TreeStoreElem *tselem = TREESTORE(te); - if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) { + if (outliner_is_element_in_view(te, ®ion->v2d)) { if (TreeElementRNAProperty *te_rna_prop = tree_element_cast<TreeElementRNAProperty>(te)) { ptr = te_rna_prop->getPointerRNA(); prop = te_rna_prop->getPropertyRNA(); @@ -2348,10 +2347,8 @@ static BIFIconID tree_element_get_icon_from_id(const ID *id) if (text->filepath == nullptr || (text->flags & TXT_ISMEM)) { return ICON_FILE_TEXT; } - else { - /* Helps distinguish text-based formats like the file-browser does. */ - return (BIFIconID)ED_file_extension_icon(text->filepath); - } + /* Helps distinguish text-based formats like the file-browser does. */ + return (BIFIconID)ED_file_extension_icon(text->filepath); } case ID_GR: return ICON_OUTLINER_COLLECTION; diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc index 6916f5fe502..a60e082f6a5 100644 --- a/source/blender/editors/space_outliner/outliner_edit.cc +++ b/source/blender/editors/space_outliner/outliner_edit.cc @@ -225,8 +225,11 @@ static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmE const bool toggle_all = RNA_boolean_get(op->ptr, "all"); float view_mval[2]; - UI_view2d_region_to_view( - ®ion->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + + int mval[2]; + WM_event_drag_start_mval(event, region, mval); + + UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]); TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]); @@ -726,7 +729,7 @@ void id_remap_fn(bContext *C, RNA_enum_set(&op_props, "id_type", GS(tselem->id->name)); RNA_enum_set_identifier(C, &op_props, "old_id", tselem->id->name + 2); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props, nullptr); WM_operator_properties_free(&op_props); } @@ -872,10 +875,10 @@ static int lib_relocate( RNA_string_set(&op_props, "directory", dir); RNA_string_set(&op_props, "filename", filename); - ret = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props); + ret = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props, nullptr); } else { - ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props); + ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props, nullptr); } WM_operator_properties_free(&op_props); diff --git a/source/blender/editors/space_outliner/outliner_intern.hh b/source/blender/editors/space_outliner/outliner_intern.hh index 0516758e887..a9bdcc56787 100644 --- a/source/blender/editors/space_outliner/outliner_intern.hh +++ b/source/blender/editors/space_outliner/outliner_intern.hh @@ -33,6 +33,7 @@ struct ViewLayer; struct bContext; struct bContextDataResult; struct bPoseChannel; +struct View2D; struct wmKeyConfig; struct wmOperatorType; @@ -218,8 +219,9 @@ typedef enum { /* is the current element open? if so we also show children */ #define TSELEM_OPEN(telm, sv) \ - (((telm)->flag & TSE_CLOSED) == 0 || \ - (SEARCHING_OUTLINER(sv) && ((telm)->flag & TSE_CHILDSEARCH))) + (CHECK_TYPE_INLINE(telm, TreeStoreElem *), \ + (((telm)->flag & TSE_CLOSED) == 0 || \ + (SEARCHING_OUTLINER(sv) && ((telm)->flag & TSE_CHILDSEARCH)))) /** * Container to avoid passing around these variables to many functions. @@ -545,7 +547,7 @@ void outliner_collection_delete(struct bContext *C, struct Main *bmain, struct Scene *scene, struct ReportList *reports, - bool hierarchy); + bool do_hierarchy); void OUTLINER_OT_collection_new(struct wmOperatorType *ot); void OUTLINER_OT_collection_duplicate_linked(struct wmOperatorType *ot); @@ -642,10 +644,16 @@ float outliner_restrict_columns_width(const struct SpaceOutliner *space_outliner */ TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag); /** - * Find if element is visible in the outliner tree. + * Find if element is visible in the outliner tree, i.e. if all of its parents are expanded. + * Doesn't check if the item is in view-bounds, for that use #outliner_is_element_in_view(). */ bool outliner_is_element_visible(const TreeElement *te); /** + * Check if the element is displayed within the view bounds. Doesn't check if all parents are + * open/uncollapsed. + */ +bool outliner_is_element_in_view(const TreeElement *te, const struct View2D *v2d); +/** * Scroll view vertically while keeping within total bounds. */ void outliner_scroll_view(struct SpaceOutliner *space_outliner, diff --git a/source/blender/editors/space_outliner/outliner_ops.cc b/source/blender/editors/space_outliner/outliner_ops.cc index 69a691aeb50..8baac45666e 100644 --- a/source/blender/editors/space_outliner/outliner_ops.cc +++ b/source/blender/editors/space_outliner/outliner_ops.cc @@ -11,7 +11,9 @@ #include "outliner_intern.hh" -/* ************************** registration **********************************/ +/* -------------------------------------------------------------------- */ +/** \name Registration + * \{ */ void outliner_operatortypes(void) { @@ -97,3 +99,5 @@ void outliner_keymap(wmKeyConfig *keyconf) { WM_keymap_ensure(keyconf, "Outliner", SPACE_OUTLINER, 0); } + +/** \} */ diff --git a/source/blender/editors/space_outliner/outliner_select.cc b/source/blender/editors/space_outliner/outliner_select.cc index c6b9d9577b5..233051f31ff 100644 --- a/source/blender/editors/space_outliner/outliner_select.cc +++ b/source/blender/editors/space_outliner/outliner_select.cc @@ -68,6 +68,10 @@ using namespace blender::ed::outliner; +/* -------------------------------------------------------------------- */ +/** \name Internal Utilities + * \{ */ + /** * \note changes to selection are by convention and not essential. * @@ -199,8 +203,11 @@ void outliner_item_mode_toggle(bContext *C, } } -/* ****************************************************** */ -/* Outliner Element Selection/Activation on Click */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Outliner Element Selection/Activation on Click Operator + * \{ */ static void tree_element_viewlayer_activate(bContext *C, TreeElement *te) { @@ -1662,10 +1669,15 @@ static int outliner_item_do_activate_from_cursor(bContext *C, /* Event can enter-key, then it opens/closes. */ static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + ARegion *region = CTX_wm_region(C); + const bool extend = RNA_boolean_get(op->ptr, "extend"); const bool use_range = RNA_boolean_get(op->ptr, "extend_range"); const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); - return outliner_item_do_activate_from_cursor(C, event->mval, extend, use_range, deselect_all); + + int mval[2]; + WM_event_drag_start_mval(event, region, mval); + return outliner_item_do_activate_from_cursor(C, mval, extend, use_range, deselect_all); } void OUTLINER_OT_item_activate(wmOperatorType *ot) @@ -1695,9 +1707,12 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ****************************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Box Select Operator + * \{ */ -/* **************** Box Select Tool ****************** */ static void outliner_item_box_select(bContext *C, SpaceOutliner *space_outliner, Scene *scene, @@ -1756,8 +1771,9 @@ static int outliner_box_select_invoke(bContext *C, wmOperator *op, const wmEvent float view_mval[2]; const bool tweak = RNA_boolean_get(op->ptr, "tweak"); - UI_view2d_region_to_view( - ®ion->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + int mval[2]; + WM_event_drag_start_mval(event, region, mval); + UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]); /* Find element clicked on */ TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]); @@ -1803,9 +1819,11 @@ void OUTLINER_OT_select_box(wmOperatorType *ot) WM_operator_properties_select_operation_simple(ot); } -/* ****************************************************** */ +/** \} */ -/* **************** Walk Select Tool ****************** */ +/* -------------------------------------------------------------------- */ +/** \name Walk Select Operator + * \{ */ /* Given a tree element return the rightmost child that is visible in the outliner */ static TreeElement *outliner_find_rightmost_visible_child(SpaceOutliner *space_outliner, @@ -2030,4 +2048,4 @@ void OUTLINER_OT_select_walk(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ****************************************************** */ +/** \} */ diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc index 8fcf967bce8..3b14c8542bd 100644 --- a/source/blender/editors/space_outliner/outliner_tools.cc +++ b/source/blender/editors/space_outliner/outliner_tools.cc @@ -1705,7 +1705,16 @@ static TreeTraversalAction outliner_find_objects_to_delete(TreeElement *te, void return TRAVERSE_SKIP_CHILDS; } - BLI_gset_add(objects_to_delete, tselem->id); + ID *id = tselem->id; + + if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + if (!ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(id)) { + /* Only allow deletion of liboverride objects if they are root overrides. */ + return TRAVERSE_SKIP_CHILDS; + } + } + + BLI_gset_add(objects_to_delete, id); return TRAVERSE_CONTINUE; } @@ -2216,14 +2225,14 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) } case OUTLINER_IDOP_COPY: { wm->op_undo_depth++; - WM_operator_name_call(C, "OUTLINER_OT_id_copy", WM_OP_INVOKE_DEFAULT, nullptr); + WM_operator_name_call(C, "OUTLINER_OT_id_copy", WM_OP_INVOKE_DEFAULT, nullptr, nullptr); wm->op_undo_depth--; /* No need for undo, this operation does not change anything... */ break; } case OUTLINER_IDOP_PASTE: { wm->op_undo_depth++; - WM_operator_name_call(C, "OUTLINER_OT_id_paste", WM_OP_INVOKE_DEFAULT, nullptr); + WM_operator_name_call(C, "OUTLINER_OT_id_paste", WM_OP_INVOKE_DEFAULT, nullptr, nullptr); wm->op_undo_depth--; ED_outliner_select_sync_from_all_tag(C); ED_undo_push(C, "Paste"); @@ -2595,7 +2604,8 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) case OUTLINER_ANIMOP_SET_ACT: /* delegate once again... */ wm->op_undo_depth++; - WM_operator_name_call(C, "OUTLINER_OT_action_set", WM_OP_INVOKE_REGION_WIN, nullptr); + WM_operator_name_call( + C, "OUTLINER_OT_action_set", WM_OP_INVOKE_REGION_WIN, nullptr, nullptr); wm->op_undo_depth--; ED_undo_push(C, "Set active action"); break; @@ -2618,7 +2628,7 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) nullptr); WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, nullptr); - /* ED_undo_push(C, "Refresh Drivers"); No undo needed - shouldn't have any impact? */ + // ED_undo_push(C, "Refresh Drivers"); /* No undo needed - shouldn't have any impact? */ break; case OUTLINER_ANIMOP_CLEAR_DRV: diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc index 06a5918f25c..1a772287dfa 100644 --- a/source/blender/editors/space_outliner/outliner_tree.cc +++ b/source/blender/editors/space_outliner/outliner_tree.cc @@ -74,8 +74,9 @@ using namespace blender::ed::outliner; /* prototypes */ static int outliner_exclude_filter_get(const SpaceOutliner *space_outliner); -/* ********************************************************* */ -/* Persistent Data */ +/* -------------------------------------------------------------------- */ +/** \name Persistent Data + * \{ */ static void outliner_storage_cleanup(SpaceOutliner *space_outliner) { @@ -175,8 +176,11 @@ static void check_persistent( BKE_outliner_treehash_add_element(space_outliner->runtime->treehash, tselem); } -/* ********************************************************* */ -/* Tree Management */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tree Management + * \{ */ void outliner_free_tree(ListBase *tree) { @@ -960,10 +964,14 @@ TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outliner, return ten; } +/** \} */ + /* ======================================================= */ /* Generic Tree Building helpers - order these are called is top to bottom */ -/* Sorting ------------------------------------------------------ */ +/* -------------------------------------------------------------------- */ +/** \name Tree Sorting Helper + * \{ */ struct tTreeSort { TreeElement *te; @@ -1195,7 +1203,11 @@ static void outliner_collections_children_sort(ListBase *lb) } } -/* Filtering ----------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tree Filtering Helper + * \{ */ struct OutlinerTreeElementFocus { TreeStoreElem *tselem; @@ -1644,8 +1656,11 @@ static void outliner_clear_newid_from_main(Main *bmain) FOREACH_MAIN_ID_END; } -/* ======================================================= */ -/* Main Tree Building API */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Main Tree Building API + * \{ */ void outliner_build_tree(Main *mainvar, Scene *scene, @@ -1707,3 +1722,5 @@ void outliner_build_tree(Main *mainvar, * as this expects valid IDs in this pointer, not random unknown data. */ outliner_clear_newid_from_main(mainvar); } + +/** \} */ diff --git a/source/blender/editors/space_outliner/outliner_utils.cc b/source/blender/editors/space_outliner/outliner_utils.cc index b49a2416b38..556f87617f6 100644 --- a/source/blender/editors/space_outliner/outliner_utils.cc +++ b/source/blender/editors/space_outliner/outliner_utils.cc @@ -386,6 +386,11 @@ bool outliner_is_element_visible(const TreeElement *te) return true; } +bool outliner_is_element_in_view(const TreeElement *te, const View2D *v2d) +{ + return ((te->ys + UI_UNIT_Y) >= v2d->cur.ymin) && (te->ys <= v2d->cur.ymax); +} + bool outliner_item_is_co_over_name_icons(const TreeElement *te, float view_co_x) { /* Special case: count area left of Scene Collection as empty space */ diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 5ac4363e63d..0d0042c4656 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -476,7 +476,7 @@ static void draw_seq_waveform_overlay(View2D *v2d, bool is_line_strip = (value_max - value_min < 0.05f); - if (was_line_strip != -1 && is_line_strip != was_line_strip) { + if (!ELEM(was_line_strip, -1, is_line_strip)) { /* If the previously added strip type isn't the same as the current one, * add transition areas so they transition smoothly between each other. */ if (is_line_strip) { @@ -2690,12 +2690,7 @@ void draw_timeline_seq(const bContext *C, ARegion *region) GPU_depth_test(GPU_DEPTH_NONE); UI_GetThemeColor3fv(TH_BACK, col); - if (ed && ed->metastack.first) { - GPU_clear_color(col[0], col[1], col[2] - 0.1f, 0.0f); - } - else { - GPU_clear_color(col[0], col[1], col[2], 0.0f); - } + GPU_clear_color(col[0], col[1], col[2], 0.0f); UI_view2d_view_ortho(v2d); draw_seq_timeline_channels(v2d); diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 8fefd258f7a..d3fc3e9d352 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -36,7 +36,9 @@ #include "WM_api.h" #include "WM_types.h" -/******************** text font drawing ******************/ +/* -------------------------------------------------------------------- */ +/** \name Text Font Drawing + * \{ */ typedef struct TextDrawContext { int font_id; @@ -141,7 +143,11 @@ static void format_draw_color(const TextDrawContext *tdc, char formatchar) } } -/************************** draw text *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Draw Text + * \{ */ /** * Notes on word-wrap @@ -556,7 +562,11 @@ static void text_draw(const SpaceText *st, flatten_string_free(&fs); } -/************************ cache utilities *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cache Utilities + * \{ */ typedef struct DrawCache { int *line_height; @@ -766,7 +776,11 @@ void text_free_caches(SpaceText *st) } } -/************************ word-wrap utilities *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Word-Wrap Utilities + * \{ */ /* cache should be updated in caller */ static int text_get_visible_lines_no(const SpaceText *st, int lineno) @@ -845,7 +859,11 @@ int text_get_total_lines(SpaceText *st, ARegion *region) return drawcache->total_lines; } -/************************ draw scrollbar *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Draw Scroll-Bar + * \{ */ static void calc_text_rcts(SpaceText *st, ARegion *region, rcti *scroll, rcti *back) { @@ -1006,7 +1024,11 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back) col); } -/*********************** draw documentation *******************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Draw Documentation + * \{ */ #if 0 static void draw_documentation(const SpaceText *st, ARegion *region) @@ -1086,7 +1108,7 @@ static void draw_documentation(const SpaceText *st, ARegion *region) if (*p == '\r' && *(++p) != '\n') { *(--p) = '\n'; /* Fix line endings */ } - if (*p == ' ' || *p == '\t') { + if (ELEM(*p, ' ', '\t')) { br = i; } else if (*p == '\n') { @@ -1118,7 +1140,11 @@ static void draw_documentation(const SpaceText *st, ARegion *region) } #endif -/*********************** draw suggestion list *******************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Draw Suggestion List + * \{ */ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc, ARegion *region) { @@ -1221,7 +1247,11 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc } } -/*********************** draw cursor ************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Draw Cursor + * \{ */ static void draw_text_decoration(SpaceText *st, ARegion *region) { @@ -1383,7 +1413,11 @@ static void draw_text_decoration(SpaceText *st, ARegion *region) immUnbindProgram(); } -/******************* draw matching brackets *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Draw Matching Brackets + * \{ */ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegion *region) { @@ -1544,7 +1578,11 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi } } -/*********************** main region drawing *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Main Region Drawing + * \{ */ void draw_text_main(SpaceText *st, ARegion *region) { @@ -1707,7 +1745,11 @@ void draw_text_main(SpaceText *st, ARegion *region) text_font_end(&tdc); } -/************************** update ***************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Update & Coordinate Conversion + * \{ */ void text_update_character_width(SpaceText *st) { @@ -1861,3 +1903,5 @@ error: r_pixel_co[0] = r_pixel_co[1] = -1; return false; } + +/** \} */ diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 3c29b32c2fa..15fea301b1c 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -649,13 +649,13 @@ static int text_save_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int text_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int text_save_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Text *text = CTX_data_edit_text(C); /* Internal and texts without a filepath will go to "Save As". */ if (text->filepath == NULL || (text->flags & TXT_ISMEM)) { - WM_operator_name_call(C, "TEXT_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "TEXT_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL, event); return OPERATOR_CANCELLED; } return text_save_exec(C, op); @@ -1098,10 +1098,10 @@ static int text_indent_or_autocomplete_exec(bContext *C, wmOperator *UNUSED(op)) TextLine *line = text->curl; bool text_before_cursor = text->curc != 0 && !ELEM(line->line[text->curc - 1], ' ', '\t'); if (text_before_cursor && (txt_has_sel(text) == false)) { - WM_operator_name_call(C, "TEXT_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "TEXT_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL, NULL); } else { - WM_operator_name_call(C, "TEXT_OT_indent", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "TEXT_OT_indent", WM_OP_EXEC_DEFAULT, NULL, NULL); } return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 4656540c19b..e2a027837a7 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -801,7 +801,7 @@ static void view3d_lightcache_update(bContext *C) RNA_int_set(&op_ptr, "delay", 200); RNA_enum_set_identifier(C, &op_ptr, "subset", "DIRTY"); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr, NULL); WM_operator_properties_free(&op_ptr); } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index b4cf08f69fe..e52ff062302 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -507,19 +507,17 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot) * Wraps walk/fly modes. * \{ */ -static int view3d_navigate_invoke(bContext *C, - wmOperator *UNUSED(op), - const wmEvent *UNUSED(event)) +static int view3d_navigate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { eViewNavigation_Method mode = U.navigation_mode; switch (mode) { case VIEW_NAVIGATION_FLY: - WM_operator_name_call(C, "VIEW3D_OT_fly", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_fly", WM_OP_INVOKE_DEFAULT, NULL, event); break; case VIEW_NAVIGATION_WALK: default: - WM_operator_name_call(C, "VIEW3D_OT_walk", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_walk", WM_OP_INVOKE_DEFAULT, NULL, event); break; } diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index 9b954cd817b..3a8a28dc2a1 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -455,6 +455,19 @@ static bool view3d_ruler_item_mousemove(const bContext *C, return false; } +/** + * When the gizmo-group has been created immediately before running an operator + * to manipulate rulers, it's possible the new gizmo-group has not yet been initialized. + * in 3.0 this happened because left-click drag would both select and add a new ruler, + * significantly increasing the likelihood of this happening. + * Workaround this crash by checking the gizmo's custom-data has not been cleared. + * The key-map has also been modified not to trigger this bug, see T95591. + */ +static bool gizmo_ruler_check_for_operator(const wmGizmoGroup *gzgroup) +{ + return gzgroup->customdata != NULL; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -1069,7 +1082,8 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event) ARegion *region = ruler_info->region; - const float mval_fl[2] = {UNPACK2(event->mval)}; + float mval_fl[2]; + WM_event_drag_start_mval_fl(event, region, mval_fl); #ifdef USE_AXIS_CONSTRAINTS ruler_info->constrain_axis = CONSTRAIN_AXIS_NONE; @@ -1294,13 +1308,21 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *e wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id); const bool use_depth = (v3d->shading.type >= OB_SOLID); + if (!gizmo_ruler_check_for_operator(gzgroup)) { + return OPERATOR_CANCELLED; + } + + int mval[2]; + WM_event_drag_start_mval(event, region, mval); + /* Create new line */ RulerItem *ruler_item; ruler_item = ruler_item_add(gzgroup); /* This is a little weak, but there is no real good way to tweak directly. */ WM_gizmo_highlight_set(gzmap, &ruler_item->gz); - if (WM_operator_name_call(C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_REGION_WIN, NULL) == + if (WM_operator_name_call( + C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_REGION_WIN, NULL, event) == OPERATOR_RUNNING_MODAL) { RulerInfo *ruler_info = gzgroup->customdata; RulerInteraction *inter = ruler_item->gz.interaction_data; @@ -1312,7 +1334,7 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *e depsgraph, ruler_info, ruler_item, - event->mval, + mval, false #ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK , @@ -1327,7 +1349,7 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *e else { negate_v3_v3(inter->drag_start_co, rv3d->ofs); copy_v3_v3(ruler_item->co[0], inter->drag_start_co); - view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval); + view3d_ruler_item_project(ruler_info, ruler_item->co[0], mval); } copy_v3_v3(ruler_item->co[2], ruler_item->co[0]); @@ -1369,6 +1391,9 @@ static int view3d_ruler_remove_invoke(bContext *C, wmOperator *op, const wmEvent wmGizmoMap *gzmap = region->gizmo_map; wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id); if (gzgroup) { + if (!gizmo_ruler_check_for_operator(gzgroup)) { + return OPERATOR_CANCELLED; + } RulerInfo *ruler_info = gzgroup->customdata; if (ruler_info->item_active) { RulerItem *ruler_item = ruler_info->item_active; diff --git a/source/blender/editors/space_view3d/view3d_navigate.c b/source/blender/editors/space_view3d/view3d_navigate.c index daf534ce0ba..50d7626a57d 100644 --- a/source/blender/editors/space_view3d/view3d_navigate.c +++ b/source/blender/editors/space_view3d/view3d_navigate.c @@ -1153,16 +1153,16 @@ static int view_axis_exec(bContext *C, wmOperator *op) float quat_test[4]; if (viewnum == RV3D_VIEW_LEFT) { - axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI / 2.0f); + axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI_2); } else if (viewnum == RV3D_VIEW_RIGHT) { - axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI / 2.0f); + axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI_2); } else if (viewnum == RV3D_VIEW_TOP) { - axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI / 2.0f); + axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI_2); } else if (viewnum == RV3D_VIEW_BOTTOM) { - axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI / 2.0f); + axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI_2); } else if (viewnum == RV3D_VIEW_FRONT) { unit_qt(quat_rotate); diff --git a/source/blender/editors/space_view3d/view3d_navigate_dolly.c b/source/blender/editors/space_view3d/view3d_navigate_dolly.c index 7b6b119294d..29ccc352950 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_dolly.c +++ b/source/blender/editors/space_view3d/view3d_navigate_dolly.c @@ -134,11 +134,11 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event) event_code = VIEW_CONFIRM; break; case VIEWROT_MODAL_SWITCH_MOVE: - WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event); event_code = VIEW_CONFIRM; break; case VIEWROT_MODAL_SWITCH_ROTATE: - WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event); event_code = VIEW_CONFIRM; break; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_move.c b/source/blender/editors/space_view3d/view3d_navigate_move.c index 071643e9314..af8419894b1 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_move.c +++ b/source/blender/editors/space_view3d/view3d_navigate_move.c @@ -76,11 +76,11 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event) event_code = VIEW_CONFIRM; break; case VIEWROT_MODAL_SWITCH_ZOOM: - WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL, event); event_code = VIEW_CONFIRM; break; case VIEWROT_MODAL_SWITCH_ROTATE: - WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event); event_code = VIEW_CONFIRM; break; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_roll.c b/source/blender/editors/space_view3d/view3d_navigate_roll.c index 9c070fb0341..ea21eed6445 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_roll.c +++ b/source/blender/editors/space_view3d/view3d_navigate_roll.c @@ -99,11 +99,11 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event) event_code = VIEW_CONFIRM; break; case VIEWROT_MODAL_SWITCH_MOVE: - WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event); event_code = VIEW_CONFIRM; break; case VIEWROT_MODAL_SWITCH_ROTATE: - WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event); event_code = VIEW_CONFIRM; break; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_rotate.c b/source/blender/editors/space_view3d/view3d_navigate_rotate.c index 11de5463cdb..a53c71bd823 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_rotate.c +++ b/source/blender/editors/space_view3d/view3d_navigate_rotate.c @@ -327,11 +327,11 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event) event_code = VIEW_APPLY; break; case VIEWROT_MODAL_SWITCH_ZOOM: - WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL, event); event_code = VIEW_CONFIRM; break; case VIEWROT_MODAL_SWITCH_MOVE: - WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event); event_code = VIEW_CONFIRM; break; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_zoom.c b/source/blender/editors/space_view3d/view3d_navigate_zoom.c index 5f6f9fde324..c744ef85236 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_zoom.c +++ b/source/blender/editors/space_view3d/view3d_navigate_zoom.c @@ -370,11 +370,11 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event) event_code = VIEW_CONFIRM; break; case VIEWROT_MODAL_SWITCH_MOVE: - WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event); event_code = VIEW_CONFIRM; break; case VIEWROT_MODAL_SWITCH_ROTATE: - WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event); event_code = VIEW_CONFIRM; break; } diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c index 98fb914cda9..05d4372723b 100644 --- a/source/blender/editors/space_view3d/view3d_placement.c +++ b/source/blender/editors/space_view3d/view3d_placement.c @@ -733,9 +733,11 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv * the current cursor location instead of the drag-start. */ if (event->val == KM_CLICK_DRAG) { /* Set this flag so snapping always updated. */ + int mval[2]; + WM_event_drag_start_mval(event, ipd->region, mval); int flag_orig = snap_state_new->flag; snap_state_new->flag |= V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE; - ED_view3d_cursor_snap_data_get(snap_state_new, C, event->mval[0], event->mval[1]); + ED_view3d_cursor_snap_data_get(snap_state_new, C, mval[0], mval[1]); snap_state_new->flag = flag_orig; } } @@ -1151,7 +1153,7 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve RNA_float_set(&op_props, "radius2", 0.0f); } - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props); + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props, NULL); WM_operator_properties_free(&op_props); } else { @@ -1168,7 +1170,8 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve } if (do_cursor_update) { - const float mval_fl[2] = {UNPACK2(event->mval)}; + float mval_fl[2]; + WM_event_drag_start_mval_fl(event, region, mval_fl); /* Calculate the snap location on mouse-move or when toggling snap. */ ipd->is_snap_found = false; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index e380a08dcc7..5d3168908d6 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1628,7 +1628,7 @@ static Base *object_mouse_select_menu(bContext *C, RNA_boolean_set(&ptr, "extend", extend); RNA_boolean_set(&ptr, "deselect", deselect); RNA_boolean_set(&ptr, "toggle", toggle); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL); WM_operator_properties_free(&ptr); BLI_linklist_free(linklist.list, NULL); @@ -1851,7 +1851,7 @@ static bool bone_mouse_select_menu(bContext *C, RNA_boolean_set(&ptr, "extend", extend); RNA_boolean_set(&ptr, "deselect", deselect); RNA_boolean_set(&ptr, "toggle", toggle); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL); WM_operator_properties_free(&ptr); BLI_linklist_free(base_list.list, NULL); diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index bcdc962a860..2f51b2dce3b 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -600,9 +600,9 @@ static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op) const int pivot_point = scene->toolsettings->transform_pivot_point; if (snap_selected_to_location(C, snap_target_global, use_offset, pivot_point, true)) { - return OPERATOR_CANCELLED; + return OPERATOR_FINISHED; } - return OPERATOR_FINISHED; + return OPERATOR_CANCELLED; } void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index fd01f708ed2..92d312cebce 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1513,14 +1513,42 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if (t->flag & T_MODAL) { /* do we check for parameter? */ if (transformModeUseSnap(t)) { - if (!(t->modifiers & MOD_SNAP) != !(ts->snap_flag & SCE_SNAP)) { + if (!(t->modifiers & MOD_SNAP) != !(t->tsnap.flag & SCE_SNAP)) { + char *snap_flag_ptr; + + wmMsgParams_RNA msg_key_params = {{0}}; + RNA_pointer_create(&t->scene->id, &RNA_ToolSettings, ts, &msg_key_params.ptr); + + _WM_MESSAGE_EXTERN_BEGIN; + extern PropertyRNA rna_ToolSettings_use_snap; + extern PropertyRNA rna_ToolSettings_use_snap_node; + extern PropertyRNA rna_ToolSettings_use_snap_sequencer; + extern PropertyRNA rna_ToolSettings_use_snap_uv; + _WM_MESSAGE_EXTERN_END; + if (t->spacetype == SPACE_NODE) { + snap_flag_ptr = &ts->snap_flag_node; + msg_key_params.prop = &rna_ToolSettings_use_snap_node; + } + else if (t->spacetype == SPACE_IMAGE) { + snap_flag_ptr = &ts->snap_uv_flag; + msg_key_params.prop = &rna_ToolSettings_use_snap_uv; + } + else if (t->spacetype == SPACE_SEQ) { + snap_flag_ptr = &ts->snap_flag_seq; + msg_key_params.prop = &rna_ToolSettings_use_snap_sequencer; + } + else { + snap_flag_ptr = &ts->snap_flag; + msg_key_params.prop = &rna_ToolSettings_use_snap; + } + if (t->modifiers & MOD_SNAP) { - ts->snap_flag |= SCE_SNAP; + *snap_flag_ptr |= SCE_SNAP; } else { - ts->snap_flag &= ~SCE_SNAP; + *snap_flag_ptr &= ~SCE_SNAP; } - WM_msg_publish_rna_prop(t->mbus, &t->scene->id, ts, ToolSettings, use_snap); + WM_msg_publish_rna_params(t->mbus, &msg_key_params); } } } @@ -1819,7 +1847,15 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve use_accurate = true; } } - initMouseInput(t, &t->mouse, t->center2d, event->mval, use_accurate); + + int mval[2]; + if (t->flag & T_EVENT_DRAG_START) { + WM_event_drag_start_mval(event, t->region, mval); + } + else { + copy_v2_v2_int(mval, event->mval); + } + initMouseInput(t, &t->mouse, t->center2d, mval, use_accurate); } transform_mode_init(t, op, mode); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 3ee5868d5be..713cf487ac7 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -137,6 +137,9 @@ typedef enum { /** Runs auto-merge & splits. */ T_AUTOSPLIT = 1 << 21, + /** Use drag-start position of the event, otherwise use the cursor coordinates (unmodified). */ + T_EVENT_DRAG_START = (1 << 22), + /** No cursor wrapping on region bounds */ T_NO_CURSOR_WRAP = 1 << 23, } eTFlag; @@ -292,7 +295,8 @@ typedef struct TransSnapPoint { } TransSnapPoint; typedef struct TransSnap { - short mode; + char flag; + char mode; short target; short modePoint; short modeSelect; diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 4a2169b381e..dbe67bd0d66 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -1113,7 +1113,8 @@ static void init_TransDataContainers(TransInfo *t, &objects_len, { .object_mode = object_mode, - .no_dup_data = true, + /* Pose transform operates on `ob->pose` so don't skip duplicate object-data. */ + .no_dup_data = (object_mode & OB_MODE_POSE) == 0, }); free_objects = true; } diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index b8530293d3e..d4b12142162 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -1449,7 +1449,7 @@ static void VertsToTransData(TransInfo *t, td->ext = NULL; td->val = NULL; td->extra = eve; - if (t->mode == TFM_BWEIGHT || t->mode == TFM_VERT_CREASE) { + if (ELEM(t->mode, TFM_BWEIGHT, TFM_VERT_CREASE)) { td->val = bweight; td->ival = *bweight; } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 8987325145c..3b9e2a982dc 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -206,6 +206,12 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->obedit_type = -1; } + if (t->options & CTX_CURSOR) { + /* Cursor should always use the drag start as the combination of click-drag to place & move + * doesn't work well if the click location isn't used when transforming. */ + t->flag |= T_EVENT_DRAG_START; + } + /* Many kinds of transform only use a single handle. */ if (t->data_container == NULL) { t->data_container = MEM_callocN(sizeof(*t->data_container), __func__); @@ -216,7 +222,12 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve int mval[2]; if (event) { - copy_v2_v2_int(mval, event->mval); + if (t->flag & T_EVENT_DRAG_START) { + WM_event_drag_start_mval(event, region, mval); + } + else { + copy_v2_v2_int(mval, event->mval); + } } else { zero_v2_int(mval); diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index f07fadb7fc1..5381785091a 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -1824,7 +1824,7 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgr static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz, - const wmEvent *UNUSED(event)) + const wmEvent *event) { GizmoGroup *ggd = gzgroup->customdata; @@ -1867,9 +1867,8 @@ static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, } if (axis != -1) { - wmWindow *win = CTX_wm_window(C); /* Swap single axis for two-axis constraint. */ - bool flip = (win->eventstate->modifier & KM_SHIFT) != 0; + const bool flip = (event->modifier & KM_SHIFT) != 0; BLI_assert(axis_idx != -1); const short axis_type = gizmo_get_axis_type(axis_idx); if (axis_type != MAN_AXES_ROTATE) { diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index 6162dfc9bb5..2fd81486bb6 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -1212,8 +1212,8 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode) } /* TODO(germano): Some of these operations change the `t->mode`. - * This can be bad for Redo. - * BLI_assert(t->mode == mode); */ + * This can be bad for Redo. */ + // BLI_assert(t->mode == mode); } void transform_mode_default_modal_orientation_set(TransInfo *t, int type) diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 936aca7d2e0..efbb7375af4 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -1311,9 +1311,7 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot) P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER); } -static int transform_from_gizmo_invoke(bContext *C, - wmOperator *UNUSED(op), - const wmEvent *UNUSED(event)) +static int transform_from_gizmo_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { bToolRef *tref = WM_toolsystem_ref_from_context(C); if (tref) { @@ -1343,7 +1341,7 @@ static int transform_from_gizmo_invoke(bContext *C, PointerRNA op_ptr; WM_operator_properties_create_ptr(&op_ptr, ot); RNA_boolean_set(&op_ptr, "release_confirm", true); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr, event); WM_operator_properties_free(&op_ptr); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 2f3c021ba38..7ace6343985 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -561,7 +561,22 @@ static bool bm_face_is_snap_target(BMFace *f, void *UNUSED(user_data)) return true; } -static short snap_mode_from_scene(TransInfo *t) +static char snap_flag_from_spacetype(TransInfo *t) +{ + ToolSettings *ts = t->settings; + if (t->spacetype == SPACE_NODE) { + return ts->snap_flag_node; + } + else if (t->spacetype == SPACE_IMAGE) { + return ts->snap_uv_flag; + } + else if (t->spacetype == SPACE_SEQ) { + return ts->snap_flag_seq; + } + return ts->snap_flag; +} + +static short snap_mode_from_spacetype(TransInfo *t) { ToolSettings *ts = t->settings; short r_snap_mode = SCE_SNAP_MODE_INCREMENT; @@ -580,7 +595,7 @@ static short snap_mode_from_scene(TransInfo *t) else if (t->spacetype == SPACE_SEQ) { r_snap_mode = SEQ_tool_settings_snap_mode_get(t->scene); } - else if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) { + else if ((t->spacetype == SPACE_VIEW3D) && !(t->options & CTX_CAMERA)) { /* All obedit types will match. */ const int obedit_type = t->obedit_type; if ((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) || @@ -652,7 +667,7 @@ static short snap_select_type_get(TransInfo *t) static void initSnappingMode(TransInfo *t) { ToolSettings *ts = t->settings; - t->tsnap.mode = snap_mode_from_scene(t); + t->tsnap.mode = snap_mode_from_spacetype(t); t->tsnap.modeSelect = snap_select_type_get(t); if ((t->spacetype != SPACE_VIEW3D) || !(ts->snap_mode & SCE_SNAP_MODE_FACE)) { @@ -701,10 +716,9 @@ static void initSnappingMode(TransInfo *t) void initSnapping(TransInfo *t, wmOperator *op) { - ToolSettings *ts = t->settings; - short snap_target = t->settings->snap_target; - resetSnapping(t); + t->tsnap.flag = snap_flag_from_spacetype(t); + short snap_target = t->settings->snap_target; /* if snap property exists */ PropertyRNA *prop; @@ -745,19 +759,14 @@ void initSnapping(TransInfo *t, wmOperator *op) } /* use scene defaults only when transform is modal */ else if (t->flag & T_MODAL) { - if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) { - if (transformModeUseSnap(t) && (ts->snap_flag & SCE_SNAP)) { - t->modifiers |= MOD_SNAP; - } - - t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) != 0); - t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0); - t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) != 0); - t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0); - } - else if ((t->spacetype == SPACE_SEQ) && (ts->snap_flag & SCE_SNAP_SEQ)) { + if (transformModeUseSnap(t) && (t->tsnap.flag & SCE_SNAP)) { t->modifiers |= MOD_SNAP; } + + t->tsnap.align = ((t->tsnap.flag & SCE_SNAP_ROTATE) != 0); + t->tsnap.project = ((t->tsnap.flag & SCE_SNAP_PROJECT) != 0); + t->tsnap.snap_self = !((t->tsnap.flag & SCE_SNAP_NO_SELF) != 0); + t->tsnap.peel = ((t->tsnap.flag & SCE_SNAP_PROJECT) != 0); } t->tsnap.target = snap_target; diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index b2a411147a5..b73a02e8de6 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -155,8 +155,8 @@ void UV_OT_shortest_path_select(struct wmOperatorType *ot); /* uvedit_select.c */ -bool uvedit_select_is_any_selected(struct Scene *scene, struct Object *obedit); -bool uvedit_select_is_any_selected_multi(struct Scene *scene, +bool uvedit_select_is_any_selected(const struct Scene *scene, struct Object *obedit); +bool uvedit_select_is_any_selected_multi(const struct Scene *scene, struct Object **objects, uint objects_len); /** diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index bbf84ee74d7..fe6f9f0d513 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1518,11 +1518,11 @@ static int uv_hide_exec(bContext *C, wmOperator *op) BM_face_select_set(em->bm, efa, false); break; } - else if (UV_VERT_SEL_TEST(luv, !swap) && (ts->uv_selectmode == UV_SELECT_VERTEX)) { + if (UV_VERT_SEL_TEST(luv, !swap) && (ts->uv_selectmode == UV_SELECT_VERTEX)) { BM_face_select_set(em->bm, efa, false); break; } - else if (ts->uv_selectmode == UV_SELECT_ISLAND) { + if (ts->uv_selectmode == UV_SELECT_ISLAND) { BM_face_select_set(em->bm, efa, false); break; } @@ -1533,18 +1533,21 @@ static int uv_hide_exec(bContext *C, wmOperator *op) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (UV_EDGE_SEL_TEST(luv, !swap) && (ts->uv_selectmode == UV_SELECT_EDGE)) { - if (em->selectmode == SCE_SELECT_EDGE) + if (em->selectmode == SCE_SELECT_EDGE) { BM_edge_select_set(em->bm, l->e, false); + } else { BM_vert_select_set(em->bm, l->v, false); BM_vert_select_set(em->bm, l->next->v, false); } } else if (UV_VERT_SEL_TEST(luv, !swap) && (ts->uv_selectmode != UV_SELECT_EDGE)) { - if (em->selectmode == SCE_SELECT_EDGE) + if (em->selectmode == SCE_SELECT_EDGE) { BM_edge_select_set(em->bm, l->e, false); - else + } + else { BM_vert_select_set(em->bm, l->v, false); + } } } if (!swap) { diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index 53b8a541dba..3f7c7745bff 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -2039,7 +2039,7 @@ static float p_collapse_cost(PEdge *edge, PEdge *pair) float *co1 = e->next->vert->co; float *co2 = e->next->next->vert->co; - if ((e->face != oldf1) && (e->face != oldf2)) { + if (!ELEM(e->face, oldf1, oldf2)) { float tetrav2[3], tetrav3[3]; /* tetrahedron volume = (1/3!)*|a.(b x c)| */ @@ -2059,7 +2059,7 @@ static float p_collapse_cost(PEdge *edge, PEdge *pair) a1 = a1 - M_PI / 3.0; a2 = a2 - M_PI / 3.0; a3 = a3 - M_PI / 3.0; - shapeold = (a1 * a1 + a2 * a2 + a3 * a3) / ((M_PI / 2) * (M_PI / 2)); + shapeold = (a1 * a1 + a2 * a2 + a3 * a3) / (M_PI_2 * M_PI_2); nshapeold++; } @@ -2068,7 +2068,7 @@ static float p_collapse_cost(PEdge *edge, PEdge *pair) a1 = a1 - M_PI / 3.0; a2 = a2 - M_PI / 3.0; a3 = a3 - M_PI / 3.0; - shapenew = (a1 * a1 + a2 * a2 + a3 * a3) / ((M_PI / 2) * (M_PI / 2)); + shapenew = (a1 * a1 + a2 * a2 + a3 * a3) / (M_PI_2 * M_PI_2); nshapenew++; } @@ -3730,7 +3730,7 @@ static float p_chart_minimum_area_angle(PChart *chart) minarea = 1e10; minangle = 0.0; - while (rotated <= (float)(M_PI / 2.0)) { /* INVESTIGATE: how far to rotate? */ + while (rotated <= (float)M_PI_2) { /* INVESTIGATE: how far to rotate? */ /* rotate with the smallest angle */ i_min = 0; mina = 1e10; @@ -3777,8 +3777,8 @@ static float p_chart_minimum_area_angle(PChart *chart) } /* try keeping rotation as small as possible */ - if (minangle > (float)(M_PI / 4)) { - minangle -= (float)(M_PI / 2.0); + if (minangle > (float)M_PI_4) { + minangle -= (float)M_PI_2; } MEM_freeN(angles); diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index ca66981cd3a..938b798f4b6 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -55,18 +55,21 @@ #include "uvedit_intern.h" -static void uv_select_all_perform(Scene *scene, Object *obedit, int action); - -static void uv_select_all_perform_multi_ex( - Scene *scene, Object **objects, const uint objects_len, int action, const Object *ob_exclude); -static void uv_select_all_perform_multi(Scene *scene, +static void uv_select_all_perform(const Scene *scene, Object *obedit, int action); + +static void uv_select_all_perform_multi_ex(const Scene *scene, + Object **objects, + const uint objects_len, + int action, + const Object *ob_exclude); +static void uv_select_all_perform_multi(const Scene *scene, Object **objects, const uint objects_len, int action); -static void uv_select_flush_from_tag_face(Scene *scene, Object *obedit, const bool select); -static void uv_select_flush_from_tag_loop(Scene *scene, Object *obedit, const bool select); -static void uv_select_flush_from_loop_edge_flag(Scene *scene, BMEditMesh *em); +static void uv_select_flush_from_tag_face(const Scene *scene, Object *obedit, const bool select); +static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, const bool select); +static void uv_select_flush_from_loop_edge_flag(const Scene *scene, BMEditMesh *em); static void uv_select_tag_update_for_object(Depsgraph *depsgraph, const ToolSettings *ts, @@ -435,7 +438,7 @@ void uvedit_edge_select_shared_vert(const Scene *scene, const bool do_history, const int cd_loop_uv_offset) { - BLI_assert((sticky_flag == SI_STICKY_LOC) || (sticky_flag == SI_STICKY_VERTEX)); + BLI_assert(ELEM(sticky_flag, SI_STICKY_LOC, SI_STICKY_VERTEX)); /* Set edge flags. Rely on this for face visibility checks */ uvedit_edge_select_set_noflush(scene, l, select, sticky_flag, cd_loop_uv_offset); @@ -644,7 +647,7 @@ void uvedit_uv_select_shared_vert(const Scene *scene, const bool do_history, const int cd_loop_uv_offset) { - BLI_assert((sticky_flag == SI_STICKY_LOC) || (sticky_flag == SI_STICKY_VERTEX)); + BLI_assert(ELEM(sticky_flag, SI_STICKY_LOC, SI_STICKY_VERTEX)); BMEdge *e_first, *e_iter; e_first = e_iter = l->e; @@ -1200,7 +1203,10 @@ bool uvedit_vert_is_all_other_faces_selected(const Scene *scene, /** * Clear specified UV flag (vert/edge/pinned). */ -static void bm_uv_flag_clear(Scene *scene, BMesh *bm, const int flag, const int cd_loop_uv_offset) +static void bm_uv_flag_clear(const Scene *scene, + BMesh *bm, + const int flag, + const int cd_loop_uv_offset) { BMFace *efa; BMLoop *l; @@ -1223,12 +1229,13 @@ static void bm_uv_flag_clear(Scene *scene, BMesh *bm, const int flag, const int * * \{ */ -void ED_uvedit_selectmode_flush(Scene *scene, BMEditMesh *em) +void ED_uvedit_selectmode_flush(const Scene *scene, BMEditMesh *em) { - ToolSettings *ts = scene->toolsettings; + const ToolSettings *ts = scene->toolsettings; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BLI_assert((ts->uv_flag & UV_SYNC_SELECTION) == 0); + UNUSED_VARS_NDEBUG(ts); /* Vertex Mode only. */ if (ts->uv_selectmode & UV_SELECT_VERTEX) { @@ -1261,14 +1268,15 @@ void ED_uvedit_selectmode_flush(Scene *scene, BMEditMesh *em) /** \name UV Flush selection (up/down) * \{ */ -/* Careful when using this in face select mode. - * For face selections with sticky mode enabled, this can create invalid selection states. */ -void uvedit_select_flush(Scene *scene, BMEditMesh *em) +void uvedit_select_flush(const Scene *scene, BMEditMesh *em) { - ToolSettings *ts = scene->toolsettings; + /* Careful when using this in face select mode. + * For face selections with sticky mode enabled, this can create invalid selection states. */ + const ToolSettings *ts = scene->toolsettings; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BLI_assert((ts->uv_flag & UV_SYNC_SELECTION) == 0); + UNUSED_VARS_NDEBUG(ts); BMFace *efa; BMLoop *l; @@ -1289,12 +1297,13 @@ void uvedit_select_flush(Scene *scene, BMEditMesh *em) } } -void uvedit_deselect_flush(Scene *scene, BMEditMesh *em) +void uvedit_deselect_flush(const Scene *scene, BMEditMesh *em) { - ToolSettings *ts = scene->toolsettings; + const ToolSettings *ts = scene->toolsettings; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BLI_assert((ts->uv_flag & UV_SYNC_SELECTION) == 0); + UNUSED_VARS_NDEBUG(ts); BMFace *efa; BMLoop *l; @@ -1711,7 +1720,7 @@ static int uv_select_edgering(Scene *scene, Object *obedit, UvNearestHit *hit, c if (select && uvedit_edge_select_test(scene, l_step, cd_loop_uv_offset)) { break; } - else if (!select && !uvedit_edge_select_test(scene, l_step, cd_loop_uv_offset)) { + if (!select && !uvedit_edge_select_test(scene, l_step, cd_loop_uv_offset)) { break; } } @@ -2163,7 +2172,7 @@ void UV_OT_select_less(wmOperatorType *ot) /** \name (De)Select All Operator * \{ */ -bool uvedit_select_is_any_selected(Scene *scene, Object *obedit) +bool uvedit_select_is_any_selected(const Scene *scene, Object *obedit) { const ToolSettings *ts = scene->toolsettings; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2191,7 +2200,9 @@ bool uvedit_select_is_any_selected(Scene *scene, Object *obedit) return false; } -bool uvedit_select_is_any_selected_multi(Scene *scene, Object **objects, const uint objects_len) +bool uvedit_select_is_any_selected_multi(const Scene *scene, + Object **objects, + const uint objects_len) { bool found = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -2204,7 +2215,7 @@ bool uvedit_select_is_any_selected_multi(Scene *scene, Object **objects, const u return found; } -static void uv_select_all(Scene *scene, BMEditMesh *em, bool select_all) +static void uv_select_all(const Scene *scene, BMEditMesh *em, bool select_all) { BMFace *efa; BMLoop *l; @@ -2223,7 +2234,7 @@ static void uv_select_all(Scene *scene, BMEditMesh *em, bool select_all) } } -static void uv_select_invert(Scene *scene, BMEditMesh *em) +static void uv_select_invert(const Scene *scene, BMEditMesh *em) { const ToolSettings *ts = scene->toolsettings; BLI_assert((ts->uv_flag & UV_SYNC_SELECTION) == 0); @@ -2240,13 +2251,13 @@ static void uv_select_invert(Scene *scene, BMEditMesh *em) } BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if ((uv_selectmode == UV_SELECT_EDGE) || (uv_selectmode == UV_SELECT_FACE)) { + if (ELEM(uv_selectmode, UV_SELECT_EDGE, UV_SELECT_FACE)) { /* Use #MLOOPUV_EDGESEL to flag edges that must be selected. */ luv->flag ^= MLOOPUV_EDGESEL; luv->flag &= ~MLOOPUV_VERTSEL; } /* Use #MLOOPUV_VERTSEL to flag verts that must be selected. */ - else if ((uv_selectmode == UV_SELECT_VERTEX) || (uv_selectmode == UV_SELECT_ISLAND)) { + else if (ELEM(uv_selectmode, UV_SELECT_VERTEX, UV_SELECT_ISLAND)) { luv->flag ^= MLOOPUV_VERTSEL; luv->flag &= ~MLOOPUV_EDGESEL; } @@ -2254,15 +2265,15 @@ static void uv_select_invert(Scene *scene, BMEditMesh *em) } /* Flush based on uv vert/edge flags and current UV select mode */ - if ((uv_selectmode == UV_SELECT_EDGE) || (uv_selectmode == UV_SELECT_FACE)) { + if (ELEM(uv_selectmode, UV_SELECT_EDGE, UV_SELECT_FACE)) { uv_select_flush_from_loop_edge_flag(scene, em); } - else if ((uv_selectmode == UV_SELECT_VERTEX) || (uv_selectmode == UV_SELECT_ISLAND)) { + else if (ELEM(uv_selectmode, UV_SELECT_VERTEX, UV_SELECT_ISLAND)) { uvedit_select_flush(scene, em); } } -static void uv_select_all_perform(Scene *scene, Object *obedit, int action) +static void uv_select_all_perform(const Scene *scene, Object *obedit, int action) { const ToolSettings *ts = scene->toolsettings; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -2303,8 +2314,11 @@ static void uv_select_all_perform(Scene *scene, Object *obedit, int action) } } -static void uv_select_all_perform_multi_ex( - Scene *scene, Object **objects, const uint objects_len, int action, const Object *ob_exclude) +static void uv_select_all_perform_multi_ex(const Scene *scene, + Object **objects, + const uint objects_len, + int action, + const Object *ob_exclude) { if (action == SEL_TOGGLE) { action = uvedit_select_is_any_selected_multi(scene, objects, objects_len) ? SEL_DESELECT : @@ -2320,7 +2334,7 @@ static void uv_select_all_perform_multi_ex( } } -static void uv_select_all_perform_multi(Scene *scene, +static void uv_select_all_perform_multi(const Scene *scene, Object **objects, const uint objects_len, int action) @@ -3133,7 +3147,7 @@ static void uv_select_tag_update_for_object(Depsgraph *depsgraph, /** * helper function for #uv_select_flush_from_tag_loop and uv_select_flush_from_tag_face */ -static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene, +static void uv_select_flush_from_tag_sticky_loc_internal(const Scene *scene, BMEditMesh *em, UvVertMap *vmap, const uint efa_index, @@ -3191,7 +3205,7 @@ static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene, * \note This function is very similar to #uv_select_flush_from_tag_loop, * be sure to update both upon changing. */ -static void uv_select_flush_from_tag_face(Scene *scene, Object *obedit, const bool select) +static void uv_select_flush_from_tag_face(const Scene *scene, Object *obedit, const bool select) { /* Selecting UV Faces with some modes requires us to change * the selection in other faces (depending on the sticky mode). @@ -3207,7 +3221,7 @@ static void uv_select_flush_from_tag_face(Scene *scene, Object *obedit, const bo const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && - ((ts->uv_sticky == SI_STICKY_VERTEX) || (ts->uv_sticky == SI_STICKY_LOC))) { + ELEM(ts->uv_sticky, SI_STICKY_VERTEX, SI_STICKY_LOC)) { struct UvVertMap *vmap; uint efa_index; @@ -3260,7 +3274,7 @@ static void uv_select_flush_from_tag_face(Scene *scene, Object *obedit, const bo * \note This function is very similar to #uv_select_flush_from_tag_face, * be sure to update both upon changing. */ -static void uv_select_flush_from_tag_loop(Scene *scene, Object *obedit, const bool select) +static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, const bool select) { /* Selecting UV Loops with some modes requires us to change * the selection in other faces (depending on the sticky mode). @@ -3342,7 +3356,7 @@ static void uv_select_flush_from_tag_loop(Scene *scene, Object *obedit, const bo * * \note Current behavior is selecting only; deselecting can be added but the behavior isn't * required anywhere.*/ -static void uv_select_flush_from_loop_edge_flag(Scene *scene, BMEditMesh *em) +static void uv_select_flush_from_loop_edge_flag(const Scene *scene, BMEditMesh *em) { const ToolSettings *ts = scene->toolsettings; BMFace *efa; @@ -3352,7 +3366,7 @@ static void uv_select_flush_from_loop_edge_flag(Scene *scene, BMEditMesh *em) const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && - ((ts->uv_sticky == SI_STICKY_LOC) || (ts->uv_sticky == SI_STICKY_VERTEX))) { + ELEM(ts->uv_sticky, SI_STICKY_LOC, SI_STICKY_VERTEX)) { /* Use the #MLOOPUV_EDGESEL flag to identify which verts must to be selected */ struct UvVertMap *vmap; uint efa_index; @@ -4355,7 +4369,7 @@ void UV_OT_select_overlap(wmOperatorType *ot) * So an edge that has two connected edge loops only assigns one loop in the array. * \{ */ -BMFace **ED_uvedit_selected_faces(Scene *scene, BMesh *bm, int len_max, int *r_faces_len) +BMFace **ED_uvedit_selected_faces(const Scene *scene, BMesh *bm, int len_max, int *r_faces_len) { const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); CLAMP_MAX(len_max, bm->totface); @@ -4383,7 +4397,7 @@ finally: return faces; } -BMLoop **ED_uvedit_selected_edges(Scene *scene, BMesh *bm, int len_max, int *r_edges_len) +BMLoop **ED_uvedit_selected_edges(const Scene *scene, BMesh *bm, int len_max, int *r_edges_len) { const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); CLAMP_MAX(len_max, bm->totloop); @@ -4439,7 +4453,7 @@ finally: return edges; } -BMLoop **ED_uvedit_selected_verts(Scene *scene, BMesh *bm, int len_max, int *r_verts_len) +BMLoop **ED_uvedit_selected_verts(const Scene *scene, BMesh *bm, int len_max, int *r_verts_len) { const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); CLAMP_MAX(len_max, bm->totloop); @@ -4505,7 +4519,9 @@ finally: * * Use only when sync select disabled. */ -static void uv_isolate_selected_islands(Scene *scene, BMEditMesh *em, const int cd_loop_uv_offset) +static void uv_isolate_selected_islands(const Scene *scene, + BMEditMesh *em, + const int cd_loop_uv_offset) { BLI_assert((scene->toolsettings->uv_flag & UV_SYNC_SELECTION) == 0); BMFace *efa; @@ -4553,9 +4569,9 @@ static void uv_isolate_selected_islands(Scene *scene, BMEditMesh *em, const int MEM_freeN(is_island_not_selected); } -void ED_uvedit_selectmode_clean(Scene *scene, Object *obedit) +void ED_uvedit_selectmode_clean(const Scene *scene, Object *obedit) { - ToolSettings *ts = scene->toolsettings; + const ToolSettings *ts = scene->toolsettings; BLI_assert((ts->uv_flag & UV_SYNC_SELECTION) == 0); BMEditMesh *em = BKE_editmesh_from_object(obedit); char sticky = ts->uv_sticky; diff --git a/source/blender/freestyle/intern/geometry/matrix_util.cpp b/source/blender/freestyle/intern/geometry/matrix_util.cpp index ecf5443a957..35503a37685 100644 --- a/source/blender/freestyle/intern/geometry/matrix_util.cpp +++ b/source/blender/freestyle/intern/geometry/matrix_util.cpp @@ -106,7 +106,7 @@ void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, delta = a_ll - a_mm; if (delta == 0.0) { - x = -M_PI / 4; + x = -M_PI_4; } else { x = -atan((a_lm + a_lm) / delta) / 2.0; diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h index 729b31965c8..fe7c2e62d9a 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.h +++ b/source/blender/freestyle/intern/view_map/ViewMap.h @@ -938,7 +938,7 @@ class ViewEdge : public Interface1D { FEdge *_FEdgeB; // last edge of the embedded fedges chain Id _Id; unsigned _ChainingTimeStamp; - // The silhouette view edge separates 2 2D spaces. The one on the left is necessarly the Shape + // The silhouette view edge separates two 2D spaces. The one on the left is necessarily the Shape // _Shape (the one to which this edge belongs to) and _aShape is the one on its right NOT HANDLED // BY THE COPY CONSTRUCTOR ViewShape *_aShape; diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp index fba3110907a..9086593a945 100644 --- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp +++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp @@ -474,10 +474,10 @@ inline static real angle(WOEdge *h) const Vec3r v = h->GetVec(); real sine = (n1 ^ n2) * v / v.norm(); if (sine >= 1.0) { - return M_PI / 2.0; + return M_PI_2; } if (sine <= -1.0) { - return -M_PI / 2.0; + return -M_PI_2; } return ::asin(sine); } diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h index b77381bd4e5..6d39446056f 100644 --- a/source/blender/freestyle/intern/winged_edge/WEdge.h +++ b/source/blender/freestyle/intern/winged_edge/WEdge.h @@ -1400,11 +1400,11 @@ inline void WOEdge::setVecAndAngle() if (_paFace && _pbFace) { float sine = (_pbFace->GetNormal() ^ _paFace->GetNormal()) * _vec / _vec.norm(); if (sine >= 1.0) { - _angle = M_PI / 2.0; + _angle = M_PI_2; return; } if (sine <= -1.0) { - _angle = -M_PI / 2.0; + _angle = -M_PI_2; return; } _angle = ::asin(sine); diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp index a56ac003703..b18d232dbbe 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp @@ -74,7 +74,7 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge() //----------------------------- // We retrieve the 2 edges for which we have opposite signs for each extremity RetrieveCuspEdgesIndices(cuspEdgesIndices); - if (cuspEdgesIndices.size() != 2) { // we necessarly have 2 cusp edges + if (cuspEdgesIndices.size() != 2) { // we necessarily have 2 cusp edges return nullptr; } diff --git a/source/blender/geometry/GEO_mesh_to_curve.hh b/source/blender/geometry/GEO_mesh_to_curve.hh index a99ee9c7fee..c480e4178cf 100644 --- a/source/blender/geometry/GEO_mesh_to_curve.hh +++ b/source/blender/geometry/GEO_mesh_to_curve.hh @@ -2,11 +2,10 @@ #include "BLI_index_mask.hh" -#include "BKE_spline.hh" - #pragma once struct Mesh; +struct Curves; class MeshComponent; /** \file @@ -20,7 +19,6 @@ namespace blender::geometry { * intersections of more than three edges will become breaks in splines. Attributes that * are not built-in on meshes and not curves are transferred to the result curve. */ -std::unique_ptr<CurveEval> mesh_to_curve_convert(const MeshComponent &mesh_component, - const IndexMask selection); +Curves *mesh_to_curve_convert(const MeshComponent &mesh_component, const IndexMask selection); } // namespace blender::geometry diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc index 121a1b5de39..0c2377fde6d 100644 --- a/source/blender/geometry/intern/mesh_to_curve_convert.cc +++ b/source/blender/geometry/intern/mesh_to_curve_convert.cc @@ -2,7 +2,6 @@ #include "BLI_array.hh" #include "BLI_set.hh" -#include "BLI_string_ref.hh" #include "BLI_task.hh" #include "DNA_mesh_types.h" @@ -10,85 +9,48 @@ #include "BKE_attribute_access.hh" #include "BKE_attribute_math.hh" +#include "BKE_curves.hh" #include "BKE_geometry_set.hh" -#include "BKE_spline.hh" #include "GEO_mesh_to_curve.hh" namespace blender::geometry { template<typename T> -static void copy_attribute_to_points(const VArray<T> &source_data, - Span<int> map, - MutableSpan<T> dest_data) +static void copy_with_map(const VArray<T> &src, Span<int> map, MutableSpan<T> dst) { - for (const int point_index : map.index_range()) { - const int vert_index = map[point_index]; - dest_data[point_index] = source_data[vert_index]; - } + devirtualize_varray(src, [&](const auto &src) { + threading::parallel_for(map.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + const int vert_index = map[i]; + dst[i] = src[vert_index]; + } + }); + }); } -static std::unique_ptr<CurveEval> create_curve_from_vert_indices( - const MeshComponent &mesh_component, Span<Vector<int>> vert_indices, IndexRange cyclic_splines) +static Curves *create_curve_from_vert_indices(const MeshComponent &mesh_component, + const Span<int> vert_indices, + const Span<int> curve_offsets, + const IndexRange cyclic_splines) { - std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>(); - curve->resize(vert_indices.size()); - - MutableSpan<SplinePtr> splines = curve->splines(); + Curves *curves_id = bke::curves_new_nomain(vert_indices.size(), curve_offsets.size()); + bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry); + curves.offsets().drop_back(1).copy_from(curve_offsets); + curves.offsets().last() = vert_indices.size(); + curves.curve_types().fill(CURVE_TYPE_POLY); - for (const int i : vert_indices.index_range()) { - splines[i] = std::make_unique<PolySpline>(); - splines[i]->resize(vert_indices[i].size()); - } - for (const int i : cyclic_splines) { - splines[i]->set_cyclic(true); - } + curves.cyclic().fill(false); + curves.cyclic().slice(cyclic_splines).fill(true); Set<bke::AttributeIDRef> source_attribute_ids = mesh_component.attribute_ids(); - /* Copy builtin control point attributes. */ - if (source_attribute_ids.contains("tilt")) { - const VArray<float> tilt_attribute = mesh_component.attribute_get_for_read<float>( - "tilt", ATTR_DOMAIN_POINT, 0.0f); - threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) { - for (const int i : range) { - copy_attribute_to_points<float>(tilt_attribute, vert_indices[i], splines[i]->tilts()); - } - }); - source_attribute_ids.remove_contained("tilt"); - } - else { - for (SplinePtr &spline : splines) { - spline->tilts().fill(0.0f); - } - } - - if (source_attribute_ids.contains("radius")) { - const VArray<float> radius_attribute = mesh_component.attribute_get_for_read<float>( - "radius", ATTR_DOMAIN_POINT, 1.0f); - threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) { - for (const int i : range) { - copy_attribute_to_points<float>(radius_attribute, vert_indices[i], splines[i]->radii()); - } - }); - source_attribute_ids.remove_contained("radius"); - } - else { - for (SplinePtr &spline : splines) { - spline->radii().fill(1.0f); - } - } - - VArray<float3> mesh_positions = mesh_component.attribute_get_for_read( - "position", ATTR_DOMAIN_POINT, float3(0)); - threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { - for (const int i : range) { - copy_attribute_to_points(mesh_positions, vert_indices[i], splines[i]->positions()); - } - }); + CurveComponent curves_component; + curves_component.replace(curves_id, GeometryOwnershipType::Editable); for (const bke::AttributeIDRef &attribute_id : source_attribute_ids) { - if (mesh_component.attribute_is_builtin(attribute_id)) { + if (mesh_component.attribute_is_builtin(attribute_id) && + !curves_component.attribute_is_builtin(attribute_id)) { /* Don't copy attributes that are built-in on meshes but not on curves. */ continue; } @@ -105,33 +67,24 @@ static std::unique_ptr<CurveEval> create_curve_from_vert_indices( continue; } - const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute.type()); - - threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { - for (const int i : range) { - /* Create attribute on the spline points. */ - splines[i]->attributes.create(attribute_id, data_type); - std::optional<fn::GMutableSpan> spline_attribute = splines[i]->attributes.get_for_write( - attribute_id); - BLI_assert(spline_attribute); - - /* Copy attribute based on the map for this spline. */ - attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) { - using T = decltype(dummy); - copy_attribute_to_points<T>( - mesh_attribute.typed<T>(), vert_indices[i], spline_attribute->typed<T>()); - }); - } + /* Copy attribute based on the map for this spline. */ + attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) { + using T = decltype(dummy); + bke::OutputAttribute_Typed<T> attribute = + curves_component.attribute_try_get_for_output_only<T>(attribute_id, ATTR_DOMAIN_POINT); + copy_with_map<T>(mesh_attribute.typed<T>(), vert_indices, attribute.as_span()); + attribute.save(); }); } - curve->assert_valid_point_attributes(); - return curve; + return curves_id; } struct CurveFromEdgesOutput { /** The indices in the mesh for each control point of each result splines. */ - Vector<Vector<int>> vert_indices; + Vector<int> vert_indices; + /** The first index of each curve in the result. */ + Vector<int> curve_offsets; /** A subset of splines that should be set cyclic. */ IndexRange cyclic_splines; }; @@ -139,7 +92,9 @@ struct CurveFromEdgesOutput { static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts, Span<std::pair<int, int>> edges) { - Vector<Vector<int>> vert_indices; + Vector<int> vert_indices; + vert_indices.reserve(edges.size()); + Vector<int> curve_offsets; /* Compute the number of edges connecting to each vertex. */ Array<int> neighbor_count(verts.size(), 0); @@ -191,15 +146,16 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts, continue; } - Vector<int> spline_indices; - spline_indices.append(current_vert); + /* Start a new curve in the output. */ + curve_offsets.append(vert_indices.size()); + vert_indices.append(current_vert); /* Follow connected edges until we read a vertex with more than two connected edges. */ while (true) { int last_vert = current_vert; current_vert = next_vert; - spline_indices.append(current_vert); + vert_indices.append(current_vert); unused_edges[current_vert]--; unused_edges[last_vert]--; @@ -212,13 +168,11 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts, const int next_b = neighbors[offset + 1]; next_vert = (last_vert == next_a) ? next_b : next_a; } - - vert_indices.append(std::move(spline_indices)); } } /* All splines added after this are cyclic. */ - const int cyclic_start = vert_indices.size(); + const int cyclic_start = curve_offsets.size(); /* All remaining edges are part of cyclic splines (we skipped vertices with two edges before). */ for (const int start_vert : verts.index_range()) { @@ -229,16 +183,15 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts, int current_vert = start_vert; int next_vert = neighbors[neighbor_offsets[current_vert]]; - Vector<int> spline_indices; - - spline_indices.append(current_vert); + curve_offsets.append(vert_indices.size()); + vert_indices.append(current_vert); /* Follow connected edges until we loop back to the start vertex. */ while (next_vert != start_vert) { const int last_vert = current_vert; current_vert = next_vert; - spline_indices.append(current_vert); + vert_indices.append(current_vert); unused_edges[current_vert]--; unused_edges[last_vert]--; @@ -247,13 +200,11 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts, const int next_b = neighbors[offset + 1]; next_vert = (last_vert == next_a) ? next_b : next_a; } - - vert_indices.append(std::move(spline_indices)); } - const int final_size = vert_indices.size(); + const IndexRange cyclic_curves = curve_offsets.index_range().drop_front(cyclic_start); - return {std::move(vert_indices), IndexRange(cyclic_start, final_size - cyclic_start)}; + return {std::move(vert_indices), std::move(curve_offsets), cyclic_curves}; } /** @@ -270,8 +221,7 @@ static Vector<std::pair<int, int>> get_selected_edges(const Mesh &mesh, const In return selected_edges; } -std::unique_ptr<CurveEval> mesh_to_curve_convert(const MeshComponent &mesh_component, - const IndexMask selection) +Curves *mesh_to_curve_convert(const MeshComponent &mesh_component, const IndexMask selection) { const Mesh &mesh = *mesh_component.get_for_read(); Vector<std::pair<int, int>> selected_edges = get_selected_edges(*mesh_component.get_for_read(), @@ -280,7 +230,7 @@ std::unique_ptr<CurveEval> mesh_to_curve_convert(const MeshComponent &mesh_compo selected_edges); return create_curve_from_vert_indices( - mesh_component, output.vert_indices, output.cyclic_splines); + mesh_component, output.vert_indices, output.curve_offsets, output.cyclic_splines); } } // namespace blender::geometry diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 4f7024eea82..32bad07de4f 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -121,15 +121,37 @@ struct RealizeMeshTask { struct RealizeCurveInfo { const Curves *curves; /** - * Matches the order in #AllCurvesInfo.attributes. For point attributes, the `std::optional` - * will be empty. + * Matches the order in #AllCurvesInfo.attributes. */ - Array<std::optional<GVArray_GSpan>> spline_attributes; + Array<std::optional<GVArray_GSpan>> attributes; + + /** ID attribute on the curves. If there are no ids, this #Span is empty. */ + Span<int> stored_ids; + + /** + * Handle position attributes must be transformed along with positions. Accessing them in + * advance isn't necessary theoretically, but is done to simplify other code and to avoid + * some overhead. + */ + Span<float3> handle_left; + Span<float3> handle_right; + + /** + * The radius attribute must be filled with a default of 1.0 if it + * doesn't exist on some (but not all) of the input curves data-blocks. + */ + Span<float> radius; +}; + +/** Start indices in the final output curves data-block. */ +struct CurvesElementStartIndices { + int point = 0; + int curve = 0; }; struct RealizeCurveTask { - /* Start index in the final curve. */ - int start_spline_index = 0; + CurvesElementStartIndices start_indices; + const RealizeCurveInfo *curve_info; /* Transformation applied to the position of control points and handles. */ float4x4 transform; @@ -168,6 +190,8 @@ struct AllCurvesInfo { /** Preprocessed data about every original curve. This is ordered by #order. */ Array<RealizeCurveInfo> realize_info; bool create_id_attribute = false; + bool create_handle_postion_attributes = false; + bool create_radius_attribute = false; }; /** Collects all tasks that need to be executed to realize all instances. */ @@ -185,7 +209,7 @@ struct GatherTasks { struct GatherOffsets { int pointcloud_offset = 0; MeshElementStartIndices mesh_offsets; - int spline_offset = 0; + CurvesElementStartIndices curves_offsets; }; struct GatherTasksInfo { @@ -230,6 +254,92 @@ struct InstanceContext { } }; +static void copy_transformed_positions(const Span<float3> src, + const float4x4 &transform, + MutableSpan<float3> dst) +{ + threading::parallel_for(src.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + dst[i] = transform * src[i]; + } + }); +} + +static void threaded_copy(const GSpan src, GMutableSpan dst) +{ + BLI_assert(src.size() == dst.size()); + BLI_assert(src.type() == dst.type()); + threading::parallel_for(IndexRange(src.size()), 1024, [&](const IndexRange range) { + src.type().copy_construct_n(src.slice(range).data(), dst.slice(range).data(), range.size()); + }); +} + +static void threaded_fill(const fn::GPointer value, GMutableSpan dst) +{ + BLI_assert(*value.type() == dst.type()); + threading::parallel_for(IndexRange(dst.size()), 1024, [&](const IndexRange range) { + value.type()->fill_construct_n(value.get(), dst.slice(range).data(), range.size()); + }); +} + +static void copy_generic_attributes_to_result( + const Span<std::optional<GVArray_GSpan>> src_attributes, + const AttributeFallbacksArray &attribute_fallbacks, + const OrderedAttributes &ordered_attributes, + const FunctionRef<IndexRange(AttributeDomain)> &range_fn, + MutableSpan<GMutableSpan> dst_attributes) +{ + threading::parallel_for(dst_attributes.index_range(), 10, [&](const IndexRange attribute_range) { + for (const int attribute_index : attribute_range) { + const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain; + const IndexRange element_slice = range_fn(domain); + + GMutableSpan dst_span = dst_attributes[attribute_index].slice(element_slice); + if (src_attributes[attribute_index].has_value()) { + threaded_copy(*src_attributes[attribute_index], dst_span); + } + else { + const CPPType &cpp_type = dst_span.type(); + const void *fallback = attribute_fallbacks.array[attribute_index] == nullptr ? + cpp_type.default_value() : + attribute_fallbacks.array[attribute_index]; + threaded_fill({cpp_type, fallback}, dst_span); + } + } + }); +} + +static void create_result_ids(const RealizeInstancesOptions &options, + Span<int> stored_ids, + const int task_id, + MutableSpan<int> dst_ids) +{ + if (options.keep_original_ids) { + if (stored_ids.is_empty()) { + dst_ids.fill(0); + } + else { + dst_ids.copy_from(stored_ids); + } + } + else { + if (stored_ids.is_empty()) { + threading::parallel_for(dst_ids.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + dst_ids[i] = noise::hash(task_id, i); + } + }); + } + else { + threading::parallel_for(dst_ids.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + dst_ids[i] = noise::hash(task_id, stored_ids[i]); + } + }); + } + } +} + /* -------------------------------------------------------------------- */ /** \name Gather Realize Tasks * \{ */ @@ -448,12 +558,13 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info, if (curves != nullptr && curves->geometry.curve_size > 0) { const int curve_index = gather_info.curves.order.index_of(curves); const RealizeCurveInfo &curve_info = gather_info.curves.realize_info[curve_index]; - gather_info.r_tasks.curve_tasks.append({gather_info.r_offsets.spline_offset, + gather_info.r_tasks.curve_tasks.append({gather_info.r_offsets.curves_offsets, &curve_info, base_transform, base_instance_context.curves, base_instance_context.id}); - gather_info.r_offsets.spline_offset += curves->geometry.curve_size; + gather_info.r_offsets.curves_offsets.point += curves->geometry.point_size; + gather_info.r_offsets.curves_offsets.curve += curves->geometry.curve_size; } break; } @@ -559,6 +670,7 @@ static AllPointCloudsInfo preprocess_pointclouds(const GeometrySet &geometry_set static void execute_realize_pointcloud_task(const RealizeInstancesOptions &options, const RealizePointCloudTask &task, + const OrderedAttributes &ordered_attributes, PointCloud &dst_pointcloud, MutableSpan<GMutableSpan> dst_attribute_spans, MutableSpan<int> all_dst_ids) @@ -569,68 +681,25 @@ static void execute_realize_pointcloud_task(const RealizeInstancesOptions &optio const IndexRange point_slice{task.start_index, pointcloud.totpoint}; MutableSpan<float3> dst_positions{(float3 *)dst_pointcloud.co + task.start_index, pointcloud.totpoint}; - MutableSpan<int> dst_ids = all_dst_ids.slice(task.start_index, pointcloud.totpoint); - /* Copy transformed positions. */ - threading::parallel_for(IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) { - for (const int i : range) { - dst_positions[i] = task.transform * src_positions[i]; - } - }); + copy_transformed_positions(src_positions, task.transform, dst_positions); + /* Create point ids. */ if (!all_dst_ids.is_empty()) { - if (options.keep_original_ids) { - if (pointcloud_info.stored_ids.is_empty()) { - dst_ids.fill(0); - } - else { - dst_ids.copy_from(pointcloud_info.stored_ids); - } - } - else { - threading::parallel_for(IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) { - if (pointcloud_info.stored_ids.is_empty()) { - for (const int i : range) { - dst_ids[i] = noise::hash(task.id, i); - } - } - else { - for (const int i : range) { - dst_ids[i] = noise::hash(task.id, pointcloud_info.stored_ids[i]); - } - } - }); - } + create_result_ids( + options, pointcloud_info.stored_ids, task.id, all_dst_ids.slice(point_slice)); } - /* Copy generic attributes. */ - threading::parallel_for( - dst_attribute_spans.index_range(), 10, [&](const IndexRange attribute_range) { - for (const int attribute_index : attribute_range) { - GMutableSpan dst_span = dst_attribute_spans[attribute_index].slice(point_slice); - const CPPType &cpp_type = dst_span.type(); - const void *attribute_fallback = task.attribute_fallbacks.array[attribute_index]; - if (pointcloud_info.attributes[attribute_index].has_value()) { - /* Copy attribute from the original point cloud. */ - const GSpan src_span = *pointcloud_info.attributes[attribute_index]; - threading::parallel_for( - IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) { - cpp_type.copy_assign_n( - src_span.slice(range).data(), dst_span.slice(range).data(), range.size()); - }); - } - else { - if (attribute_fallback == nullptr) { - attribute_fallback = cpp_type.default_value(); - } - /* As the fallback value for the attribute. */ - threading::parallel_for( - IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) { - cpp_type.fill_assign_n( - attribute_fallback, dst_span.slice(range).data(), range.size()); - }); - } - } - }); + + copy_generic_attributes_to_result( + pointcloud_info.attributes, + task.attribute_fallbacks, + ordered_attributes, + [&](const AttributeDomain domain) { + BLI_assert(domain == ATTR_DOMAIN_POINT); + UNUSED_VARS_NDEBUG(domain); + return point_slice; + }, + dst_attribute_spans); } static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &options, @@ -678,7 +747,7 @@ static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &opti for (const int task_index : task_range) { const RealizePointCloudTask &task = tasks[task_index]; execute_realize_pointcloud_task( - options, task, *dst_pointcloud, dst_attribute_spans, point_ids_span); + options, task, ordered_attributes, *dst_pointcloud, dst_attribute_spans, point_ids_span); } }); @@ -810,9 +879,6 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, MutableSpan<MLoop> dst_loops{dst_mesh.mloop + task.start_indices.loop, mesh.totloop}; MutableSpan<MPoly> dst_polys{dst_mesh.mpoly + task.start_indices.poly, mesh.totpoly}; - MutableSpan<int> dst_vertex_ids = all_dst_vertex_ids.slice(task.start_indices.vertex, - mesh.totvert); - const Span<int> material_index_map = mesh_info.material_index_map; threading::parallel_for(IndexRange(mesh.totvert), 1024, [&](const IndexRange vert_range) { @@ -856,78 +922,34 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, } } }); - /* Create id attribute. */ + if (!all_dst_vertex_ids.is_empty()) { - if (options.keep_original_ids) { - if (mesh_info.stored_vertex_ids.is_empty()) { - dst_vertex_ids.fill(0); - } - else { - dst_vertex_ids.copy_from(mesh_info.stored_vertex_ids); - } - } - else { - threading::parallel_for(IndexRange(mesh.totvert), 1024, [&](const IndexRange vert_range) { - if (mesh_info.stored_vertex_ids.is_empty()) { - for (const int i : vert_range) { - dst_vertex_ids[i] = noise::hash(task.id, i); - } - } - else { - for (const int i : vert_range) { - const int original_id = mesh_info.stored_vertex_ids[i]; - dst_vertex_ids[i] = noise::hash(task.id, original_id); - } - } - }); - } + create_result_ids(options, + mesh_info.stored_vertex_ids, + task.id, + all_dst_vertex_ids.slice(task.start_indices.vertex, mesh.totvert)); } - /* Copy generic attributes. */ - threading::parallel_for( - dst_attribute_spans.index_range(), 10, [&](const IndexRange attribute_range) { - for (const int attribute_index : attribute_range) { - const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain; - IndexRange element_slice; - switch (domain) { - case ATTR_DOMAIN_POINT: - element_slice = IndexRange(task.start_indices.vertex, mesh.totvert); - break; - case ATTR_DOMAIN_EDGE: - element_slice = IndexRange(task.start_indices.edge, mesh.totedge); - break; - case ATTR_DOMAIN_CORNER: - element_slice = IndexRange(task.start_indices.loop, mesh.totloop); - break; - case ATTR_DOMAIN_FACE: - element_slice = IndexRange(task.start_indices.poly, mesh.totpoly); - break; - default: - BLI_assert_unreachable(); - } - GMutableSpan dst_span = dst_attribute_spans[attribute_index].slice(element_slice); - const CPPType &cpp_type = dst_span.type(); - const void *attribute_fallback = task.attribute_fallbacks.array[attribute_index]; - if (mesh_info.attributes[attribute_index].has_value()) { - const GSpan src_span = *mesh_info.attributes[attribute_index]; - threading::parallel_for( - IndexRange(element_slice.size()), 1024, [&](const IndexRange sub_range) { - cpp_type.copy_assign_n(src_span.slice(sub_range).data(), - dst_span.slice(sub_range).data(), - sub_range.size()); - }); - } - else { - if (attribute_fallback == nullptr) { - attribute_fallback = cpp_type.default_value(); - } - threading::parallel_for( - IndexRange(element_slice.size()), 1024, [&](const IndexRange sub_range) { - cpp_type.fill_assign_n( - attribute_fallback, dst_span.slice(sub_range).data(), sub_range.size()); - }); - } + + copy_generic_attributes_to_result( + mesh_info.attributes, + task.attribute_fallbacks, + ordered_attributes, + [&](const AttributeDomain domain) { + switch (domain) { + case ATTR_DOMAIN_POINT: + return IndexRange(task.start_indices.vertex, mesh.totvert); + case ATTR_DOMAIN_EDGE: + return IndexRange(task.start_indices.edge, mesh.totedge); + case ATTR_DOMAIN_CORNER: + return IndexRange(task.start_indices.loop, mesh.totloop); + case ATTR_DOMAIN_FACE: + return IndexRange(task.start_indices.poly, mesh.totpoly); + default: + BLI_assert_unreachable(); + return IndexRange(); } - }); + }, + dst_attribute_spans); } static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options, @@ -1007,7 +1029,7 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options, /** \} */ /* -------------------------------------------------------------------- */ -/** \name Curve +/** \name Curves * \{ */ static OrderedAttributes gather_generic_curve_attributes_to_propagate( @@ -1023,9 +1045,6 @@ static OrderedAttributes gather_generic_curve_attributes_to_propagate( in_geometry_set.gather_attributes_for_propagation( src_component_types, GEO_COMPONENT_TYPE_CURVE, true, attributes_to_propagate); attributes_to_propagate.remove("position"); - attributes_to_propagate.remove("cyclic"); - attributes_to_propagate.remove("resolution"); - attributes_to_propagate.remove("tilt"); attributes_to_propagate.remove("radius"); attributes_to_propagate.remove("handle_right"); attributes_to_propagate.remove("handle_left"); @@ -1071,19 +1090,43 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set, /* Access attributes. */ CurveComponent component; component.replace(const_cast<Curves *>(curves), GeometryOwnershipType::ReadOnly); - curve_info.spline_attributes.reinitialize(info.attributes.size()); + curve_info.attributes.reinitialize(info.attributes.size()); for (const int attribute_index : info.attributes.index_range()) { const AttributeDomain domain = info.attributes.kinds[attribute_index].domain; - if (domain != ATTR_DOMAIN_CURVE) { - continue; - } const AttributeIDRef &attribute_id = info.attributes.ids[attribute_index]; const CustomDataType data_type = info.attributes.kinds[attribute_index].data_type; if (component.attribute_exists(attribute_id)) { GVArray attribute = component.attribute_get_for_read(attribute_id, domain, data_type); - curve_info.spline_attributes[attribute_index].emplace(std::move(attribute)); + curve_info.attributes[attribute_index].emplace(std::move(attribute)); } } + if (info.create_id_attribute) { + ReadAttributeLookup ids_lookup = component.attribute_try_get_for_read("id"); + if (ids_lookup) { + curve_info.stored_ids = ids_lookup.varray.get_internal_span().typed<int>(); + } + } + + /* Retrieve the radius attribute, if it exists. */ + if (component.attribute_exists("radius")) { + curve_info.radius = component + .attribute_get_for_read<float>("radius", ATTR_DOMAIN_POINT, 0.0f) + .get_internal_span(); + info.create_radius_attribute = true; + } + + /* Retrieve handle position attributes, if they exist. */ + if (component.attribute_exists("handle_right")) { + curve_info.handle_left = component + .attribute_get_for_read<float3>( + "handle_left", ATTR_DOMAIN_POINT, float3(0)) + .get_internal_span(); + curve_info.handle_right = component + .attribute_get_for_read<float3>( + "handle_right", ATTR_DOMAIN_POINT, float3(0)) + .get_internal_span(); + info.create_handle_postion_attributes = true; + } } return info; } @@ -1092,108 +1135,81 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options, const AllCurvesInfo &all_curves_info, const RealizeCurveTask &task, const OrderedAttributes &ordered_attributes, - MutableSpan<SplinePtr> dst_splines, - MutableSpan<GMutableSpan> dst_spline_attributes) + bke::CurvesGeometry &dst_curves, + MutableSpan<GMutableSpan> dst_attribute_spans, + MutableSpan<int> all_dst_ids, + MutableSpan<float3> all_handle_left, + MutableSpan<float3> all_handle_right, + MutableSpan<float> all_radii) { - const RealizeCurveInfo &curve_info = *task.curve_info; - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_info.curves); - - const Span<SplinePtr> src_splines = curve->splines(); - - /* Initialize point attributes. */ - threading::parallel_for(src_splines.index_range(), 100, [&](const IndexRange src_spline_range) { - for (const int src_spline_index : src_spline_range) { - const int dst_spline_index = src_spline_index + task.start_spline_index; - const Spline &src_spline = *src_splines[src_spline_index]; - SplinePtr dst_spline = src_spline.copy_without_attributes(); - dst_spline->transform(task.transform); - const int spline_size = dst_spline->size(); - - const CustomDataAttributes &src_point_attributes = src_spline.attributes; - CustomDataAttributes &dst_point_attributes = dst_spline->attributes; - - /* Create point ids. */ - if (all_curves_info.create_id_attribute) { - dst_point_attributes.create("id", CD_PROP_INT32); - MutableSpan<int> dst_point_ids = dst_point_attributes.get_for_write("id")->typed<int>(); - std::optional<GSpan> src_point_ids_opt = src_point_attributes.get_for_read("id"); - if (options.keep_original_ids) { - if (src_point_ids_opt.has_value()) { - const Span<int> src_point_ids = src_point_ids_opt->typed<int>(); - dst_point_ids.copy_from(src_point_ids); - } - else { - dst_point_ids.fill(0); - } - } - else { - if (src_point_ids_opt.has_value()) { - const Span<int> src_point_ids = src_point_ids_opt->typed<int>(); - for (const int i : IndexRange(dst_spline->size())) { - dst_point_ids[i] = noise::hash(task.id, src_point_ids[i]); - } - } - else { - for (const int i : IndexRange(dst_spline->size())) { - /* Mix spline index into the id, because otherwise points on different splines will - * get the same id. */ - dst_point_ids[i] = noise::hash(task.id, src_spline_index, i); - } - } - } - } + const RealizeCurveInfo &curves_info = *task.curve_info; + const Curves &curves_id = *curves_info.curves; + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); - /* Copy generic point attributes. */ - for (const int attribute_index : ordered_attributes.index_range()) { - const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain; - if (domain != ATTR_DOMAIN_POINT) { - continue; - } - const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type; - const CPPType &cpp_type = *custom_data_type_to_cpp_type(data_type); - const AttributeIDRef &attribute_id = ordered_attributes.ids[attribute_index]; - const void *attribute_fallback = task.attribute_fallbacks.array[attribute_index]; - const std::optional<GSpan> src_span_opt = src_point_attributes.get_for_read(attribute_id); - void *dst_buffer = MEM_malloc_arrayN(spline_size, cpp_type.size(), "Curve Attribute"); - if (src_span_opt.has_value()) { - const GSpan src_span = *src_span_opt; - cpp_type.copy_construct_n(src_span.data(), dst_buffer, spline_size); - } - else { - if (attribute_fallback == nullptr) { - attribute_fallback = cpp_type.default_value(); - } - cpp_type.fill_construct_n(attribute_fallback, dst_buffer, spline_size); - } - dst_point_attributes.create_by_move(attribute_id, data_type, dst_buffer); - } + const IndexRange dst_point_range{task.start_indices.point, curves.points_size()}; + const IndexRange dst_curve_range{task.start_indices.curve, curves.curves_size()}; + + copy_transformed_positions( + curves.positions(), task.transform, dst_curves.positions().slice(dst_point_range)); - dst_splines[dst_spline_index] = std::move(dst_spline); + /* Copy and transform handle positions if necessary. */ + if (all_curves_info.create_handle_postion_attributes) { + if (curves_info.handle_left.is_empty()) { + all_handle_left.slice(dst_point_range).fill(float3(0)); } - }); - /* Initialize spline attributes. */ - for (const int attribute_index : ordered_attributes.index_range()) { - const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain; - if (domain != ATTR_DOMAIN_CURVE) { - continue; + else { + copy_transformed_positions( + curves_info.handle_left, task.transform, all_handle_left.slice(dst_point_range)); } - const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type; - const CPPType &cpp_type = *custom_data_type_to_cpp_type(data_type); + if (curves_info.handle_right.is_empty()) { + all_handle_right.slice(dst_point_range).fill(float3(0)); + } + else { + copy_transformed_positions( + curves_info.handle_right, task.transform, all_handle_right.slice(dst_point_range)); + } + } - GMutableSpan dst_span = dst_spline_attributes[attribute_index].slice(task.start_spline_index, - src_splines.size()); - if (curve_info.spline_attributes[attribute_index].has_value()) { - const GSpan src_span = *curve_info.spline_attributes[attribute_index]; - cpp_type.copy_construct_n(src_span.data(), dst_span.data(), src_splines.size()); + /* Copy radius attribute with 1.0 default if it doesn't exist. */ + if (all_curves_info.create_radius_attribute) { + if (curves_info.radius.is_empty()) { + all_radii.slice(dst_point_range).fill(1.0f); } else { - const void *attribute_fallback = task.attribute_fallbacks.array[attribute_index]; - if (attribute_fallback == nullptr) { - attribute_fallback = cpp_type.default_value(); - } - cpp_type.fill_construct_n(attribute_fallback, dst_span.data(), src_splines.size()); + all_radii.slice(dst_point_range).copy_from(curves_info.radius); + } + } + + /* Copy curve offsets. */ + const Span<int> src_offsets = curves.offsets(); + const MutableSpan<int> dst_offsets = dst_curves.offsets().slice(dst_curve_range); + threading::parallel_for(curves.curves_range(), 2048, [&](const IndexRange range) { + for (const int i : range) { + dst_offsets[i] = task.start_indices.point + src_offsets[i]; } + }); + + if (!all_dst_ids.is_empty()) { + create_result_ids( + options, curves_info.stored_ids, task.id, all_dst_ids.slice(dst_point_range)); } + + copy_generic_attributes_to_result( + curves_info.attributes, + task.attribute_fallbacks, + ordered_attributes, + [&](const AttributeDomain domain) { + switch (domain) { + case ATTR_DOMAIN_POINT: + return IndexRange(task.start_indices.point, curves.points_size()); + case ATTR_DOMAIN_CURVE: + return IndexRange(task.start_indices.curve, curves.curves_size()); + default: + BLI_assert_unreachable(); + return IndexRange(); + } + }, + dst_attribute_spans); } static void execute_realize_curve_tasks(const RealizeInstancesOptions &options, @@ -1208,42 +1224,90 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options, const RealizeCurveTask &last_task = tasks.last(); const Curves &last_curves = *last_task.curve_info->curves; - const int tot_splines = last_task.start_spline_index + last_curves.geometry.curve_size; + const int points_size = last_task.start_indices.point + last_curves.geometry.point_size; + const int curves_size = last_task.start_indices.curve + last_curves.geometry.curve_size; - Array<SplinePtr> dst_splines(tot_splines); + /* Allocate new curves data-block. */ + Curves *dst_curves_id = bke::curves_new_nomain(points_size, curves_size); + bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry); + dst_curves.offsets().last() = points_size; + CurveComponent &dst_component = r_realized_geometry.get_component_for_write<CurveComponent>(); + dst_component.replace(dst_curves_id); - std::unique_ptr<CurveEval> dst_curve = std::make_unique<CurveEval>(); - dst_curve->attributes.reallocate(tot_splines); - CustomDataAttributes &spline_attributes = dst_curve->attributes; + /* Prepare id attribute. */ + OutputAttribute_Typed<int> point_ids; + MutableSpan<int> point_ids_span; + if (all_curves_info.create_id_attribute) { + point_ids = dst_component.attribute_try_get_for_output_only<int>("id", ATTR_DOMAIN_POINT); + point_ids_span = point_ids.as_span(); + } - /* Prepare spline attributes. */ - Vector<GMutableSpan> dst_spline_attributes; + /* Prepare generic output attributes. */ + Vector<OutputAttribute> dst_attributes; + Vector<GMutableSpan> dst_attribute_spans; for (const int attribute_index : ordered_attributes.index_range()) { const AttributeIDRef &attribute_id = ordered_attributes.ids[attribute_index]; - const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type; const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain; - if (domain == ATTR_DOMAIN_CURVE) { - spline_attributes.create(attribute_id, data_type); - dst_spline_attributes.append(*spline_attributes.get_for_write(attribute_id)); - } - else { - dst_spline_attributes.append({CPPType::get<float>()}); - } + const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type; + OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( + attribute_id, domain, data_type); + dst_attribute_spans.append(dst_attribute.as_span()); + dst_attributes.append(std::move(dst_attribute)); + } + + /* Prepare handle position attributes if necessary. */ + OutputAttribute_Typed<float3> handle_left; + OutputAttribute_Typed<float3> handle_right; + MutableSpan<float3> handle_left_span; + MutableSpan<float3> handle_right_span; + if (all_curves_info.create_handle_postion_attributes) { + handle_left = dst_component.attribute_try_get_for_output_only<float3>("handle_left", + ATTR_DOMAIN_POINT); + handle_right = dst_component.attribute_try_get_for_output_only<float3>("handle_right", + ATTR_DOMAIN_POINT); + handle_left_span = handle_left.as_span(); + handle_right_span = handle_right.as_span(); + } + + /* Prepare radius attribute if necessary. */ + OutputAttribute_Typed<float> radius; + MutableSpan<float> radius_span; + if (all_curves_info.create_radius_attribute) { + radius = dst_component.attribute_try_get_for_output_only<float>("radius", ATTR_DOMAIN_POINT); + radius_span = radius.as_span(); } /* Actually execute all tasks. */ threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) { for (const int task_index : task_range) { const RealizeCurveTask &task = tasks[task_index]; - execute_realize_curve_task( - options, all_curves_info, task, ordered_attributes, dst_splines, dst_spline_attributes); + execute_realize_curve_task(options, + all_curves_info, + task, + ordered_attributes, + dst_curves, + dst_attribute_spans, + point_ids_span, + handle_left_span, + handle_right_span, + radius_span); } }); - dst_curve->add_splines(dst_splines); - - CurveComponent &dst_component = r_realized_geometry.get_component_for_write<CurveComponent>(); - dst_component.replace(curve_eval_to_curves(*dst_curve)); + /* Save modified attributes. */ + for (OutputAttribute &dst_attribute : dst_attributes) { + dst_attribute.save(); + } + if (point_ids) { + point_ids.save(); + } + if (radius) { + radius.save(); + } + if (all_curves_info.create_handle_postion_attributes) { + handle_left.save(); + handle_right.save(); + } } /** \} */ diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c index 45c7bd5b4e0..288ae9c0c5f 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c @@ -59,7 +59,7 @@ static void gpencil_modifier_reorder(bContext *C, Panel *panel, int new_index) WM_operator_properties_create_ptr(&props_ptr, ot); RNA_string_set(&props_ptr, "modifier", md->name); RNA_int_set(&props_ptr, "index", new_index); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL); WM_operator_properties_free(&props_ptr); } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h index bbc0a3d26b6..57eac4d77bf 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h @@ -41,8 +41,8 @@ PanelType *gpencil_modifier_panel_register(struct ARegionType *region_type, /** * Add a child panel to the parent. * - * \note To create the panel type's idname, it appends the \a name argument to the \a parent's - * idname. + * \note To create the panel type's #PanelType.idname, + * it appends the \a name argument to the \a parent's `idname`. */ struct PanelType *gpencil_modifier_subpanel_register(struct ARegionType *region_type, const char *name, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c index b1447bcaccb..1a69a6a8a38 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c @@ -180,23 +180,42 @@ typedef struct tStrokeBuildDetails { int totpoints; } tStrokeBuildDetails; -/* Sequential - Show strokes one after the other */ -static void build_sequential(BuildGpencilModifierData *mmd, - bGPdata *gpd, - bGPDframe *gpf, - float fac) +/* Sequential and additive - Show strokes one after the other. */ +static void build_sequential( + BuildGpencilModifierData *mmd, bGPdata *gpd, bGPDframe *gpf, float fac, bool additive) { - const size_t tot_strokes = BLI_listbase_count(&gpf->strokes); + size_t tot_strokes = BLI_listbase_count(&gpf->strokes); + size_t start_stroke; bGPDstroke *gps; size_t i; - /* 1) Compute proportion of time each stroke should occupy */ + /* 1) Determine which strokes to start with & total strokes to build. */ + + if (additive) { + if (gpf->prev) { + start_stroke = BLI_listbase_count(&gpf->prev->strokes); + } + else { + start_stroke = 0; + } + if (start_stroke <= tot_strokes) { + tot_strokes = tot_strokes - start_stroke; + } + else { + start_stroke = 0; + } + } + else { + start_stroke = 0; + } + + /* 2) Compute proportion of time each stroke should occupy */ /* NOTE: This assumes that the total number of points won't overflow! */ tStrokeBuildDetails *table = MEM_callocN(sizeof(tStrokeBuildDetails) * tot_strokes, __func__); size_t totpoints = 0; - /* 1.1) First pass - Tally up points */ - for (gps = gpf->strokes.first, i = 0; gps; gps = gps->next, i++) { + /* 2.1) First pass - Tally up points */ + for (gps = BLI_findlink(&gpf->strokes, start_stroke), i = 0; gps; gps = gps->next, i++) { tStrokeBuildDetails *cell = &table[i]; cell->gps = gps; @@ -205,7 +224,7 @@ static void build_sequential(BuildGpencilModifierData *mmd, totpoints += cell->totpoints; } - /* 1.2) Second pass - Compute the overall indices for points */ + /* 2.2) Second pass - Compute the overall indices for points */ for (i = 0; i < tot_strokes; i++) { tStrokeBuildDetails *cell = &table[i]; @@ -218,7 +237,7 @@ static void build_sequential(BuildGpencilModifierData *mmd, cell->end_idx = cell->start_idx + cell->totpoints - 1; } - /* 2) Determine the global indices for points that should be visible */ + /* 3) Determine the global indices for points that should be visible */ size_t first_visible = 0; size_t last_visible = 0; @@ -248,7 +267,7 @@ static void build_sequential(BuildGpencilModifierData *mmd, break; } - /* 3) Go through all strokes, deciding which to keep, and/or how much of each to keep */ + /* 4) Go through all strokes, deciding which to keep, and/or how much of each to keep */ for (i = 0; i < tot_strokes; i++) { tStrokeBuildDetails *cell = &table[i]; @@ -386,10 +405,14 @@ static void build_concurrent(BuildGpencilModifierData *mmd, } /* --------------------------------------------- */ + static void generate_geometry( GpencilModifierData *md, Depsgraph *depsgraph, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf) { BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md; + if (mmd->mode == GP_BUILD_MODE_ADDITIVE) { + mmd->transition = GP_BUILD_TRANSITION_GROW; + } const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW); const bool is_percentage = (mmd->flag & GP_BUILD_PERCENTAGE); @@ -494,13 +517,17 @@ static void generate_geometry( /* Time management mode */ switch (mmd->mode) { case GP_BUILD_MODE_SEQUENTIAL: - build_sequential(mmd, gpd, gpf, fac); + build_sequential(mmd, gpd, gpf, fac, false); break; case GP_BUILD_MODE_CONCURRENT: build_concurrent(mmd, gpd, gpf, fac); break; + case GP_BUILD_MODE_ADDITIVE: + build_sequential(mmd, gpd, gpf, fac, true); + break; + default: printf("Unsupported build mode (%d) for GP Build Modifier: '%s'\n", mmd->mode, @@ -544,7 +571,9 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemS(layout); - uiItemR(layout, ptr, "transition", 0, NULL, ICON_NONE); + if (ELEM(mode, GP_BUILD_MODE_SEQUENTIAL, GP_BUILD_MODE_CONCURRENT)) { + uiItemR(layout, ptr, "transition", 0, NULL, ICON_NONE); + } row = uiLayoutRow(layout, true); uiLayoutSetActive(row, !use_percentage); uiItemR(row, ptr, "start_delay", 0, NULL, ICON_NONE); diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c index b2fd60a62e5..cf8837ab26e 100644 --- a/source/blender/gpu/intern/gpu_immediate_util.c +++ b/source/blender/gpu/intern/gpu_immediate_util.c @@ -181,7 +181,7 @@ static void imm_draw_circle_partial(GPUPrimType prim_type, float sweep) { /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ - const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2); + const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2; const float angle_end = -(DEG2RADF(sweep) - angle_start); nsegments += 1; immBegin(prim_type, nsegments); @@ -215,7 +215,7 @@ static void imm_draw_disk_partial(GPUPrimType prim_type, CLAMP(sweep, -max_angle, max_angle); /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ - const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2); + const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2; const float angle_end = -(DEG2RADF(sweep) - angle_start); nsegments += 1; immBegin(prim_type, nsegments * 2); diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh index bf74d44d9a7..da63d372669 100644 --- a/source/blender/gpu/intern/gpu_shader_create_info.hh +++ b/source/blender/gpu/intern/gpu_shader_create_info.hh @@ -22,7 +22,7 @@ namespace blender::gpu::shader { #ifndef GPU_SHADER_CREATE_INFO -/* Helps intelisense / auto-completion. */ +/* Helps intellisense / auto-completion. */ # define GPU_SHADER_INTERFACE_INFO(_interface, _inst_name) \ StageInterfaceInfo _interface(#_interface, _inst_name); \ _interface diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc index eedd660d0a9..a9ac191754b 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.cc +++ b/source/blender/gpu/intern/gpu_vertex_format.cc @@ -133,7 +133,7 @@ uint GPU_vertformat_attr_add(GPUVertFormat *format, case GPU_COMP_I10: /* 10_10_10 format intended for normals (xyz) or colors (rgb) * extra component packed.w can be manually set to { -2, -1, 0, 1 } */ - assert(comp_len == 3 || comp_len == 4); + assert(ELEM(comp_len, 3, 4)); /* Not strictly required, may relax later. */ assert(fetch_mode == GPU_FETCH_INT_TO_FLOAT_UNIT); @@ -143,7 +143,7 @@ uint GPU_vertformat_attr_add(GPUVertFormat *format, /* integer types can be kept as int or converted/normalized to float */ assert(fetch_mode != GPU_FETCH_FLOAT); /* only support float matrices (see Batch_update_program_bindings) */ - assert(comp_len != 8 && comp_len != 12 && comp_len != 16); + assert(!ELEM(comp_len, 8, 12, 16)); } #endif format->name_len++; /* Multi-name support. */ diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 302d8249914..f0d7a23ef82 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -270,6 +270,11 @@ static void detect_workarounds() GCaps.shader_image_load_store_support = false; GCaps.broken_amd_driver = true; } + /* Compute shaders have some issues with those versions (see T94936). */ + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) && + (strstr(version, "4.5.14831") || strstr(version, "4.5.14760"))) { + GCaps.compute_shader_support = false; + } /* We have issues with this specific renderer. (see T74024) */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && (strstr(renderer, "AMD VERDE") || strstr(renderer, "AMD KAVERI") || diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 31f657a63b2..256702b60c5 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -175,7 +175,7 @@ static const char *to_string(const eGPUTextureFormat &type) case GPU_R16: return "r16"; default: - return "unkown"; + return "unknown"; } } diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl index ff77b0beea2..607cf119b36 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl @@ -4,12 +4,14 @@ void node_object_info(mat4 obmat, float mat_index, out vec3 location, out vec4 color, + out float alpha, out float object_index, out float material_index, out float random) { location = obmat[3].xyz; color = obcolor; + alpha = obcolor.w; object_index = info.x; material_index = mat_index; random = info.z; diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl index 20a65f23c05..434e07e7b86 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl @@ -4,9 +4,9 @@ void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec) worldvec = worldPosition; #else vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); + vec4 co_homogeneous = (ProjectionMatrixInverse * v); - vec3 co = co_homogenous.xyz / co_homogenous.w; + vec3 co = co_homogeneous.xyz / co_homogeneous.w; # if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) worldvec = mat3(ViewMatrixInverse) * co; # else diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl index 08d566224bf..a8ef9687b0a 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl @@ -19,8 +19,8 @@ void generated_from_orco(vec3 orco, out vec3 generated) void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated) { vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + vec4 co_homogeneous = (ProjectionMatrixInverse * v); + vec4 co = vec4(co_homogeneous.xyz / co_homogeneous.w, 0.0); co.xyz = normalize(co.xyz); #if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) generated = (ViewMatrixInverse * co).xyz; @@ -68,9 +68,9 @@ void node_tex_coord_background(vec3 I, out vec3 reflection) { vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); + vec4 co_homogeneous = (ProjectionMatrixInverse * v); - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + vec4 co = vec4(co_homogeneous.xyz / co_homogeneous.w, 0.0); co = normalize(co); diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index d0cb7f00df8..6d99fde9df6 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -255,8 +255,10 @@ static void where_is_ik_bone(bPoseChannel *pchan, pchan->flag |= POSE_DONE; } -/* called from within the core BKE_pose_where_is loop, all animsystems and constraints - * were executed & assigned. Now as last we do an IK pass */ +/** + * Called from within the core #BKE_pose_where_is loop, all animation-systems and constraints + * were executed & assigned. Now as last we do an IK pass. + */ static void execute_posetree(struct Depsgraph *depsgraph, struct Scene *scene, Object *ob, diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h index 70ff0ad83cd..623a3b2b5f4 100644 --- a/source/blender/imbuf/IMB_thumbs.h +++ b/source/blender/imbuf/IMB_thumbs.h @@ -71,7 +71,7 @@ void IMB_thumb_delete(const char *path, ThumbSize size); struct ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source); /** - * Create the necessary dirs to store the thumbnails. + * Create the necessary directories to store the thumbnails. */ void IMB_thumb_makedirs(void); diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 7cde49f44b7..096089d4c41 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -874,6 +874,8 @@ static int ffmpeg_read_video_frame(struct anim *anim, AVPacket *packet) if (packet->stream_index == anim->videoStream) { break; } + av_packet_unref(packet); + packet->stream_index = -1; } return ret; diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 9173b5a9d49..ce5dd4927be 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -34,6 +34,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ +#include "BLI_utildefines.h" +#undef CLAMP + #include <BlockDXT.h> #include <DirectDrawSurface.h> #include <PixelFormat.h> @@ -596,7 +599,7 @@ void DDSHeader::setDepth(uint d) void DDSHeader::setMipmapCount(uint count) { - if (count == 0 || count == 1) { + if (ELEM(count, 0, 1)) { this->flags &= ~DDSD_MIPMAPCOUNT; this->mipmapcount = 1; @@ -904,11 +907,12 @@ bool DirectDrawSurface::isValid() const bool DirectDrawSurface::isSupported() const { if (header.hasDX10Header()) { - if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM || - header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) { + if (ELEM(header.header10.dxgiFormat, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC2_UNORM, + DXGI_FORMAT_BC3_UNORM, + DXGI_FORMAT_BC4_UNORM, + DXGI_FORMAT_BC5_UNORM)) { return true; } @@ -916,10 +920,15 @@ bool DirectDrawSurface::isSupported() const } if (header.pf.flags & DDPF_FOURCC) { - if (header.pf.fourcc != FOURCC_DXT1 && header.pf.fourcc != FOURCC_DXT2 && - header.pf.fourcc != FOURCC_DXT3 && header.pf.fourcc != FOURCC_DXT4 && - header.pf.fourcc != FOURCC_DXT5 && header.pf.fourcc != FOURCC_RXGB && - header.pf.fourcc != FOURCC_ATI1 && header.pf.fourcc != FOURCC_ATI2) { + if (!ELEM(header.pf.fourcc, + FOURCC_DXT1, + FOURCC_DXT2, + FOURCC_DXT3, + FOURCC_DXT4, + FOURCC_DXT5, + FOURCC_RXGB, + FOURCC_ATI1, + FOURCC_ATI2)) { /* Unknown fourcc code. */ return false; } diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp index b14de8be7df..8f5d2742b0e 100644 --- a/source/blender/io/collada/AnimationImporter.cpp +++ b/source/blender/io/collada/AnimationImporter.cpp @@ -719,7 +719,7 @@ void AnimationImporter::Assign_float_animations(const COLLADAFW::UniqueId &listi fcurve_deg_to_rad(fcu); } } - /** XXX What About animtype "rotation" ? */ + /** XXX What About animation-type "rotation" ? */ BLI_addtail(AnimCurves, fcu); fcurve_is_used(fcu); @@ -1938,7 +1938,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, return false; } - /* TODO: support other animclasses. */ + /* TODO: support other animation-classes. */ if (animclass != COLLADAFW::AnimationList::ANGLE) { report_class_type_unsupported(path, animclass, type); return false; diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index 6515f7553ad..2ce97bc8b5d 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -396,8 +396,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, anim_importer.read_node_transform(instance_node, obn); /* if we also have a source_node (always ;), take its * transformation matrix and apply it to the newly instantiated - * object to account for node hierarchy transforms in - * .dae */ + * object to account for node hierarchy transforms in `.dae`. */ if (source_node) { COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix(); COLLADABU::Math::Matrix4 bmat4 = diff --git a/source/blender/io/collada/SceneExporter.cpp b/source/blender/io/collada/SceneExporter.cpp index 6cdfce5f35a..ea95729666a 100644 --- a/source/blender/io/collada/SceneExporter.cpp +++ b/source/blender/io/collada/SceneExporter.cpp @@ -189,7 +189,7 @@ void SceneExporter::writeNode(Object *ob) "blender", con_tag, "lin_error", con->lin_error); /* not ideal: add the target object name as another parameter. - * No real mapping in the .dae + * No real mapping in the `.dae`. * Need support for multiple target objects also. */ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {nullptr, nullptr}; diff --git a/source/blender/io/collada/collada_internal.cpp b/source/blender/io/collada/collada_internal.cpp index db27236b885..da9a4cd4a9b 100644 --- a/source/blender/io/collada/collada_internal.cpp +++ b/source/blender/io/collada/collada_internal.cpp @@ -14,8 +14,8 @@ UnitConverter::UnitConverter() : up_axis(COLLADAFW::FileInfo::Z_UP) { - axis_angle_to_mat4_single(x_up_mat4, 'Y', -0.5 * M_PI); - axis_angle_to_mat4_single(y_up_mat4, 'X', 0.5 * M_PI); + axis_angle_to_mat4_single(x_up_mat4, 'Y', -M_PI_2); + axis_angle_to_mat4_single(y_up_mat4, 'X', M_PI_2); unit_m4(z_up_mat4); unit_m4(scale_mat4); diff --git a/source/blender/io/usd/intern/usd_capi_import.cc b/source/blender/io/usd/intern/usd_capi_import.cc index f2963c87e41..3054641de2a 100644 --- a/source/blender/io/usd/intern/usd_capi_import.cc +++ b/source/blender/io/usd/intern/usd_capi_import.cc @@ -102,7 +102,7 @@ static void convert_to_z_up(pxr::UsdStageRefPtr stage, ImportSettings *r_setting /* Rotate 90 degrees about the X-axis. */ float rmat[3][3]; float axis[3] = {1.0f, 0.0f, 0.0f}; - axis_angle_normalized_to_mat3(rmat, axis, M_PI / 2.0f); + axis_angle_normalized_to_mat3(rmat, axis, M_PI_2); unit_m4(r_settings->conversion_mat); copy_m4_m3(r_settings->conversion_mat, rmat); diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 011f3618e15..c3132eeab3d 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -573,6 +573,10 @@ typedef struct PreviewImage { #define ID_IS_OVERRIDE_LIBRARY(_id) \ (ID_IS_OVERRIDE_LIBRARY_REAL(_id) || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(_id)) +#define ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(_id) \ + (!ID_IS_OVERRIDE_LIBRARY_REAL(_id) || \ + ((ID *)(_id))->override_library->hierarchy_root == ((ID *)(_id))) + #define ID_IS_OVERRIDE_LIBRARY_TEMPLATE(_id) \ (((ID *)(_id))->override_library != NULL && ((ID *)(_id))->override_library->reference == NULL) @@ -605,7 +609,7 @@ typedef struct PreviewImage { /** id->flag (persistent). */ enum { - /** Don't delete the datablock even if unused. */ + /** Don't delete the data-block even if unused. */ LIB_FAKEUSER = 1 << 9, /** * The data-block is a sub-data of another one. @@ -613,14 +617,14 @@ enum { */ LIB_EMBEDDED_DATA = 1 << 10, /** - * Datablock is from a library and linked indirectly, with LIB_TAG_INDIRECT + * Data-block is from a library and linked indirectly, with LIB_TAG_INDIRECT * tag set. But the current .blend file also has a weak pointer to it that * we want to restore if possible, and silently drop if it's missing. */ LIB_INDIRECT_WEAK_LINK = 1 << 11, /** * The data-block is a sub-data of another one, which is an override. - * Note that this also applies to shapekeys, even though they are not 100% embedded data... + * Note that this also applies to shape-keys, even though they are not 100% embedded data. */ LIB_EMBEDDED_DATA_LIB_OVERRIDE = 1 << 12, /** diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index fa0898e6ea5..516d3ce94f9 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -875,27 +875,27 @@ typedef enum eSAction_Flag { SACTION_SHOW_MARKERS = (1 << 14), } eSAction_Flag; -/* SpaceAction_Runtime.flag */ +/** #SpaceAction_Runtime.flag */ typedef enum eSAction_Runtime_Flag { /** Temporary flag to force channel selections to be synced with main */ SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC = (1 << 0), } eSAction_Runtime_Flag; -/* SpaceAction Mode Settings */ +/** #SpaceAction.mode */ typedef enum eAnimEdit_Context { - /* action on the active object */ + /** Action on the active object. */ SACTCONT_ACTION = 0, - /* list of all shapekeys on the active object, linked with their F-Curves */ + /** List of all shape-keys on the active object, linked with their F-Curves. */ SACTCONT_SHAPEKEY = 1, - /* editing of gpencil data */ + /** Editing of grease-pencil data. */ SACTCONT_GPENCIL = 2, - /* dopesheet (default) */ + /** Dope-sheet (default). */ SACTCONT_DOPESHEET = 3, - /* mask */ + /** Mask. */ SACTCONT_MASK = 4, - /* cache file */ + /** Cache file */ SACTCONT_CACHEFILE = 5, - /* timeline - replacement for the standalone "timeline editor" */ + /** Timeline - replacement for the standalone "timeline editor". */ SACTCONT_TIMELINE = 6, } eAnimEdit_Context; diff --git a/source/blender/makesdna/DNA_brush_enums.h b/source/blender/makesdna/DNA_brush_enums.h index 88be670457a..f8ffe6a0a47 100644 --- a/source/blender/makesdna/DNA_brush_enums.h +++ b/source/blender/makesdna/DNA_brush_enums.h @@ -457,9 +457,11 @@ typedef enum eBrushUVSculptTool { /* Brush.curves_sculpt_tool. */ typedef enum eBrushCurvesSculptTool { - CURVES_SCULPT_TOOL_TEST1 = 0, - CURVES_SCULPT_TOOL_TEST2 = 1, - CURVES_SCULPT_TOOL_TEST3 = 2, + CURVES_SCULPT_TOOL_COMB = 0, + CURVES_SCULPT_TOOL_DELETE = 1, + CURVES_SCULPT_TOOL_SNAKE_HOOK = 2, + CURVES_SCULPT_TOOL_TEST1 = 3, + CURVES_SCULPT_TOOL_TEST2 = 4, } eBrushCurvesSculptTool; /** When #BRUSH_ACCUMULATE is used */ diff --git a/source/blender/makesdna/DNA_curves_types.h b/source/blender/makesdna/DNA_curves_types.h index 98d2aa4b295..f1626781fc6 100644 --- a/source/blender/makesdna/DNA_curves_types.h +++ b/source/blender/makesdna/DNA_curves_types.h @@ -40,6 +40,14 @@ typedef enum HandleType { BEZIER_HANDLE_ALIGN = 3, } HandleType; +/** Method used to calculate a NURBS curve's knot vector. */ +typedef enum KnotsMode { + NURBS_KNOT_MODE_NORMAL = 0, + NURBS_KNOT_MODE_ENDPOINT = 1, + NURBS_KNOT_MODE_BEZIER = 2, + NURBS_KNOT_MODE_ENDPOINT_BEZIER = 3, +} KnotsMode; + /** * A reusable data structure for geometry consisting of many curves. All control point data is * stored contiguously for better efficiency. Data for each curve is stored as a slice of the @@ -69,7 +77,8 @@ typedef struct CurvesGeometry { /** * The start index of each curve in the point data. The size of each curve can be calculated by * subtracting the offset from the next offset. That is valid even for the last curve because - * this array is allocated with a length one larger than the number of splines. + * this array is allocated with a length one larger than the number of splines. This is allowed + * to be null when there are no curves. * * \note This is *not* stored in #CustomData because its size is one larger than #curve_data. */ @@ -77,6 +86,7 @@ typedef struct CurvesGeometry { /** * All attributes stored on control points (#ATTR_DOMAIN_POINT). + * This might not contain a layer for positions if there are no points. */ CustomData point_data; diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index e30dd4e1c8f..0539b84e093 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -401,6 +401,8 @@ typedef enum eBuildGpencil_Mode { GP_BUILD_MODE_SEQUENTIAL = 0, /* All strokes start at the same time */ GP_BUILD_MODE_CONCURRENT = 1, + /* Only the new strokes are built */ + GP_BUILD_MODE_ADDITIVE = 2, } eBuildGpencil_Mode; typedef enum eBuildGpencil_Transition { diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index 41cc8048de1..299ac4e2fbe 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -145,7 +145,7 @@ .compression_damp = 5.0f, \ .shear_damp = 5.0f, \ .internal_spring_max_length = 0.0f, \ - .internal_spring_max_diversion = M_PI / 4.0f, \ + .internal_spring_max_diversion = M_PI_4, \ .vgroup_intern = 0, \ .internal_tension = 15.0f, \ .internal_compression = 15.0f, \ diff --git a/source/blender/makesdna/DNA_scene_defaults.h b/source/blender/makesdna/DNA_scene_defaults.h index 82f788e0623..74db1d14bbc 100644 --- a/source/blender/makesdna/DNA_scene_defaults.h +++ b/source/blender/makesdna/DNA_scene_defaults.h @@ -360,6 +360,10 @@ /* GP Stroke Placement */ \ .gpencil_v3d_align = GP_PROJECT_VIEWSPACE, \ .gpencil_v2d_align = GP_PROJECT_VIEWSPACE, \ + \ + /* UV painting */ \ + .uv_sculpt_settings = 0, \ + .uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN, \ } /* clang-format off */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 512be41ce2c..2f8d1c5eafe 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1469,13 +1469,18 @@ typedef struct ToolSettings { /* Transform */ char transform_pivot_point; char transform_flag; + /** Snap elements (per spacetype). */ char snap_mode; char snap_node_mode; char snap_uv_mode; + /** Generic flags (per spacetype). */ char snap_flag; - /** UV equivalent of `snap_flag`, limited to: #SCE_SNAP_ABS_GRID. */ + char snap_flag_node; + char snap_flag_seq; char snap_uv_flag; + /** Default snap source. */ char snap_target; + /** Snap mask for transform modes. */ char snap_transform_mode_flag; char proportional_edit, prop_mode; @@ -1505,16 +1510,14 @@ typedef struct ToolSettings { char gpencil_selectmode_vertex; /* UV painting */ - char _pad2[1]; char uv_sculpt_settings; char uv_relax_method; - /* XXX: these sculpt_paint_* fields are deprecated, use the - * unified_paint_settings field instead! */ - short sculpt_paint_settings DNA_DEPRECATED; char workspace_tool_type; - char _pad5[1]; + /* XXX: these sculpt_paint_* fields are deprecated, use the + * unified_paint_settings field instead! */ + short sculpt_paint_settings DNA_DEPRECATED; int sculpt_paint_unified_size DNA_DEPRECATED; float sculpt_paint_unified_unprojected_radius DNA_DEPRECATED; float sculpt_paint_unified_alpha DNA_DEPRECATED; @@ -2055,7 +2058,6 @@ enum { #define SCE_SNAP_NO_SELF (1 << 4) #define SCE_SNAP_ABS_GRID (1 << 5) #define SCE_SNAP_BACKFACE_CULLING (1 << 6) -#define SCE_SNAP_SEQ (1 << 7) /** #ToolSettings.snap_target */ #define SCE_SNAP_TARGET_CLOSEST 0 diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 42c94832a43..ade0fcdb13f 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -294,6 +294,8 @@ typedef struct wmWindow { /** Storage for event system. */ struct wmEvent *eventstate; + /** Keep the last handled event in `event_queue` here (owned and must be freed). */ + struct wmEvent *event_last_handled; /* Input Method Editor data - complex character input (especially for Asian character input) * Currently WIN32 and APPLE, runtime-only data. */ diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index 74bcc95d1dd..d4c38060e1b 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -258,7 +258,7 @@ typedef enum PropertyFlag { /** * flag contains multiple enums. - * NOTE: not to be confused with prop->enumbitflags + * NOTE: not to be confused with `prop->enumbitflags` * this exposes the flag as multiple options in python and the UI. * * \note These can't be animated so use with care. diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 01a6108fd8c..3ea7f8e0df6 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -724,10 +724,10 @@ static char *rna_def_property_get_func( } else { const PropertySubType subtype = prop->subtype; - const char *string_copy_func = (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH || - subtype == PROP_FILENAME || subtype == PROP_BYTESTRING) ? - "BLI_strncpy" : - "BLI_strncpy_utf8"; + const char *string_copy_func = + ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING) ? + "BLI_strncpy" : + "BLI_strncpy_utf8"; rna_print_data_get(f, dp); @@ -1073,10 +1073,10 @@ static char *rna_def_property_set_func( } else { const PropertySubType subtype = prop->subtype; - const char *string_copy_func = (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH || - subtype == PROP_FILENAME || subtype == PROP_BYTESTRING) ? - "BLI_strncpy" : - "BLI_strncpy_utf8"; + const char *string_copy_func = + ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING) ? + "BLI_strncpy" : + "BLI_strncpy_utf8"; rna_print_data_get(f, dp); @@ -2362,7 +2362,12 @@ static void rna_def_struct_function_prototype_cpp(FILE *f, pout = (flag_parameter & PARM_OUTPUT); if (flag & PROP_DYNAMIC) { - ptrstr = pout ? "**" : "*"; + if (type == PROP_STRING) { + ptrstr = pout ? "*" : ""; + } + else { + ptrstr = pout ? "**" : "*"; + } } else if (type == PROP_POINTER) { ptrstr = pout ? "*" : ""; @@ -2853,7 +2858,12 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA /* XXX only arrays and strings are allowed to be dynamic, is this checked anywhere? */ } else if (cptr || (flag & PROP_DYNAMIC)) { - ptrstr = pout ? "**" : "*"; + if (type == PROP_STRING) { + ptrstr = pout ? "*" : ""; + } + else { + ptrstr = pout ? "**" : "*"; + } /* Fixed size arrays and RNA pointers are pre-allocated on the ParameterList stack, * pass a pointer to it. */ } @@ -2933,8 +2943,14 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA else { const char *data_str; if (cptr || (flag & PROP_DYNAMIC)) { - ptrstr = "**"; - valstr = "*"; + if (type == PROP_STRING) { + ptrstr = "*"; + valstr = ""; + } + else { + ptrstr = "**"; + valstr = "*"; + } } else if ((type == PROP_POINTER) && !(flag & PROP_THICK_WRAP)) { ptrstr = "**"; @@ -3531,7 +3547,12 @@ static void rna_generate_static_parameter_prototypes(FILE *f, } if (cptr || (flag & PROP_DYNAMIC)) { - ptrstr = pout ? "**" : "*"; + if (type == PROP_STRING) { + ptrstr = pout ? "*" : ""; + } + else { + ptrstr = pout ? "**" : "*"; + } } else if (type == PROP_POINTER || dparm->prop->arraydimension) { ptrstr = "*"; diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 94ffa330064..a9725da7841 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -744,6 +744,11 @@ static void rna_ID_override_library_operations_update(ID *id, return; } + if (ID_IS_LINKED(id)) { + BKE_reportf(reports, RPT_ERROR, "ID '%s' is linked, cannot edit its overrides", id->name); + return; + } + BKE_lib_override_library_operations_create(bmain, id); WM_main_add_notifier(NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 7ccb8181b51..a6fa369dc73 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -2437,7 +2437,7 @@ void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value) BLI_assert(RNA_property_type(prop) == PROP_INT); BLI_assert(RNA_property_array_check(prop) == false); /* useful to check on bad values but set function should clamp */ - /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */ + // BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); if ((idprop = rna_idproperty_check(&prop, ptr))) { RNA_property_int_clamp(ptr, prop, &value); @@ -3812,7 +3812,7 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA } IDP_AppendArray(idprop, item); /* IDP_AppendArray does a shallow copy (memcpy), only free memory. */ - /* IDP_FreePropertyContent(item); */ + // IDP_FreePropertyContent(item); MEM_freeN(item); rna_idproperty_touch(idprop); } diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index e282b474d8d..6052a742ad5 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -244,9 +244,11 @@ const EnumPropertyItem rna_enum_brush_gpencil_weight_types_items[] = { }; const EnumPropertyItem rna_enum_brush_curves_sculpt_tool_items[] = { + {CURVES_SCULPT_TOOL_COMB, "COMB", ICON_NONE, "Comb", ""}, + {CURVES_SCULPT_TOOL_DELETE, "DELETE", ICON_NONE, "Delete", ""}, + {CURVES_SCULPT_TOOL_SNAKE_HOOK, "SNAKE_HOOK", ICON_NONE, "Snake Hook", ""}, {CURVES_SCULPT_TOOL_TEST1, "TEST1", ICON_NONE, "Test 1", ""}, {CURVES_SCULPT_TOOL_TEST2, "TEST2", ICON_NONE, "Test 2", ""}, - {CURVES_SCULPT_TOOL_TEST3, "TEST3", ICON_NONE, "Test 3", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -2982,7 +2984,7 @@ static void rna_def_brush(BlenderRNA *brna) prop = RNA_def_property(srna, "falloff_angle", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "falloff_angle"); - RNA_def_property_range(prop, 0, M_PI / 2); + RNA_def_property_range(prop, 0, M_PI_2); RNA_def_property_ui_text( prop, "Falloff Angle", diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 0378e64290b..118589332ea 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -136,7 +136,7 @@ static void rna_CameraDOFSettings_aperture_blades_set(PointerRNA *ptr, const int { CameraDOFSettings *dofsettings = (CameraDOFSettings *)ptr->data; - if (value == 1 || value == 2) { + if (ELEM(value, 1, 2)) { if (dofsettings->aperture_blades == 0) { dofsettings->aperture_blades = 3; } @@ -392,13 +392,13 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); prop = RNA_def_property(srna, "pole_merge_angle_from", PROP_FLOAT, PROP_ANGLE); - RNA_def_property_range(prop, 0.0f, M_PI / 2.0); + RNA_def_property_range(prop, 0.0f, M_PI_2); RNA_def_property_ui_text( prop, "Pole Merge Start Angle", "Angle at which interocular distance starts to fade to 0"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); prop = RNA_def_property(srna, "pole_merge_angle_to", PROP_FLOAT, PROP_ANGLE); - RNA_def_property_range(prop, 0.0f, M_PI / 2.0); + RNA_def_property_range(prop, 0.0f, M_PI_2); RNA_def_property_ui_text( prop, "Pole Merge End Angle", "Angle at which interocular distance is 0"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 4ee57017841..3ad901e5397 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -922,7 +922,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "internal_spring_max_diversion", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "internal_spring_max_diversion"); - RNA_def_property_range(prop, 0.0f, M_PI / 4.0f); + RNA_def_property_range(prop, 0.0f, M_PI_4); RNA_def_property_ui_text(prop, "Internal Spring Max Diversion", "How much the rays used to connect the internal points can diverge " diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 114fe30acf7..63d8876ec8b 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -1209,6 +1209,9 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna) prop = RNA_def_property(srna, "chain_count", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "rootbone"); + /* Changing the IK chain length requires a rebuild of depsgraph relations. This makes it + * unsuitable for animation. */ + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 0, 255); RNA_def_property_ui_text( prop, "Chain Length", "How many bones are included in the IK effect - 0 uses all bones"); @@ -3020,6 +3023,9 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) prop = RNA_def_property(srna, "chain_count", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "chainlen"); + /* Changing the IK chain length requires a rebuild of depsgraph relations. This makes it + * unsuitable for animation. */ + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* TODO: this should really check the max length of the chain the constraint is attached to */ RNA_def_property_range(prop, 1, 255); RNA_def_property_ui_text(prop, "Chain Length", "How many bones are included in the chain"); diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 891de95a2a2..fb911725836 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -1995,24 +1995,20 @@ static void rna_def_curve_nurb(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Cyclic V", "Make this surface a closed loop in the V direction"); RNA_def_property_update(prop, 0, "rna_Nurb_update_cyclic_v"); - /* NOTE: endpoint and bezier flags should never be on at the same time! */ prop = RNA_def_property(srna, "use_endpoint_u", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flagu", CU_NURB_ENDPOINT); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text( prop, "Endpoint U", - "Make this nurbs curve or surface meet the endpoints in the U direction " - "(Cyclic U must be disabled)"); + "Make this nurbs curve or surface meet the endpoints in the U direction"); RNA_def_property_update(prop, 0, "rna_Nurb_update_knot_u"); prop = RNA_def_property(srna, "use_endpoint_v", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flagv", CU_NURB_ENDPOINT); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, - "Endpoint V", - "Make this nurbs surface meet the endpoints in the V direction " - "(Cyclic V must be disabled)"); + RNA_def_property_ui_text( + prop, "Endpoint V", "Make this nurbs surface meet the endpoints in the V direction "); RNA_def_property_update(prop, 0, "rna_Nurb_update_knot_v"); prop = RNA_def_property(srna, "use_bezier_u", PROP_BOOLEAN, PROP_NONE); @@ -2021,17 +2017,14 @@ static void rna_def_curve_nurb(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Bezier U", - "Make this nurbs curve or surface act like a Bezier spline in the U direction " - "(Order U must be 3 or 4, Cyclic U must be disabled)"); + "Make this nurbs curve or surface act like a Bezier spline in the U direction"); RNA_def_property_update(prop, 0, "rna_Nurb_update_knot_u"); prop = RNA_def_property(srna, "use_bezier_v", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flagv", CU_NURB_BEZIER); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, - "Bezier V", - "Make this nurbs surface act like a Bezier spline in the V direction " - "(Order V must be 3 or 4, Cyclic V must be disabled)"); + RNA_def_property_ui_text( + prop, "Bezier V", "Make this nurbs surface act like a Bezier spline in the V direction"); RNA_def_property_update(prop, 0, "rna_Nurb_update_knot_v"); prop = RNA_def_property(srna, "use_smooth", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_curve_api.c b/source/blender/makesrna/intern/rna_curve_api.c index d0086a425a2..f31e72ce652 100644 --- a/source/blender/makesrna/intern/rna_curve_api.c +++ b/source/blender/makesrna/intern/rna_curve_api.c @@ -36,6 +36,39 @@ static float rna_Nurb_calc_length(Nurb *nu, int resolution_u) return BKE_nurb_calc_length(nu, resolution_u); } +static void rna_Nurb_valid_message(Nurb *nu, int direction, int *result_len, const char **r_result) +{ + const bool is_surf = nu->pntsv > 1; + const short type = nu->type; + + int pnts; + short order, flag; + const char *dir; + if (direction == 0) { + pnts = nu->pntsu; + order = nu->orderu; + flag = nu->flagu; + dir = "U"; + } + else { + pnts = nu->pntsv; + order = nu->orderv; + flag = nu->flagv; + dir = "V"; + } + + char buf[64]; + if (BKE_nurb_valid_message(pnts, order, flag, type, is_surf, dir, buf, sizeof(buf))) { + const int buf_len = strlen(buf); + *r_result = BLI_strdupn(buf, buf_len); + *result_len = buf_len; + } + else { + *r_result = NULL; + *result_len = 0; + } +} + #else void RNA_api_curve(StructRNA *srna) @@ -86,6 +119,22 @@ void RNA_api_curve_nurb(StructRNA *srna) 0.0f, FLT_MAX); RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "valid_message", "rna_Nurb_valid_message"); + RNA_def_function_ui_description(func, "Return the message"); + parm = RNA_def_int( + func, "direction", 0, 0, 1, "Direction", "The direction where 0-1 maps to U-V", 0, 1); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + /* return value */ + parm = RNA_def_string(func, + "result", + "nothing", + 64, + "Return value", + "The message or an empty string when there is no error"); + + RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_OUTPUT); + RNA_def_property_clear_flag(parm, PROP_NEVER_NULL); } #endif diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 5127b418b7f..8e2b9c1d937 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -2394,8 +2394,7 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const iprop->hardmax = iprop->softmax = INT8_MAX; } - if (prop->subtype == PROP_UNSIGNED || prop->subtype == PROP_PERCENTAGE || - prop->subtype == PROP_FACTOR) { + if (ELEM(prop->subtype, PROP_UNSIGNED, PROP_PERCENTAGE, PROP_FACTOR)) { iprop->hardmin = iprop->softmin = 0; } diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c index d81e44791f4..ed6d4996c1e 100644 --- a/source/blender/makesrna/intern/rna_dynamicpaint.c +++ b/source/blender/makesrna/intern/rna_dynamicpaint.c @@ -237,8 +237,7 @@ static const EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *UNU RNA_enum_item_add(&item, &totitem, &tmp); /* Displace */ - if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX || - surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { + if (ELEM(surface->format, MOD_DPAINT_SURFACE_F_VERTEX, MOD_DPAINT_SURFACE_F_IMAGESEQ)) { tmp.value = MOD_DPAINT_SURFACE_T_DISPLACE; tmp.identifier = "DISPLACE"; tmp.name = "Displace"; diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index a619d179a33..33c0b29f6d0 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -2070,6 +2070,11 @@ static void rna_def_modifier_gpencilbuild(BlenderRNA *brna) ICON_PARTICLE_TIP, "Concurrent", "Multiple strokes appear/disappear at once"}, + {GP_BUILD_MODE_ADDITIVE, + "ADDITIVE", + ICON_PARTICLE_PATH, + "Additive", + "Builds only new strokes (assuming 'additive' drawing)"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index 7687dcbb11f..50b25157989 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -153,10 +153,10 @@ static void rna_ShapeKey_slider_max_set(PointerRNA *ptr, float value) # undef SHAPEKEY_SLIDER_TOL -/* ***** Normals accessors for shapekeys. ***** */ +/* ***** Normals accessors for shape-keys. ***** */ /* NOTE: with this we may recompute several times the same data, should we want to access verts, * then polys, then loops normals... However, - * such case looks rather unlikely - and not worth adding some kind of caching in KeyBlocks. + * such case looks rather unlikely - and not worth adding some kind of caching in key-blocks. */ static Mesh *rna_KeyBlock_normals_get_mesh(PointerRNA *ptr, ID *id) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index cc97dca9387..640fe3b919b 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4520,6 +4520,25 @@ static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA rna_Node_update(bmain, scene, ptr); } +static void rna_ShaderNode_is_active_output_set(PointerRNA *ptr, bool value) +{ + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; + bNode *node = ptr->data; + if (value) { + /* If this node becomes the active output, the others of the same type can't be the active + * output anymore. */ + LISTBASE_FOREACH (bNode *, other_node, &ntree->nodes) { + if (other_node->type == node->type) { + other_node->flag &= ~NODE_DO_OUTPUT; + } + } + node->flag |= NODE_DO_OUTPUT; + } + else { + node->flag &= ~NODE_DO_OUTPUT; + } +} + static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr) { bNode *node = ptr->data; @@ -5288,6 +5307,7 @@ static void def_sh_output(StructRNA *srna) RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_DO_OUTPUT); RNA_def_property_ui_text( prop, "Active Output", "True if this node is used as the active output"); + RNA_def_property_boolean_funcs(prop, NULL, "rna_ShaderNode_is_active_output_set"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "target", PROP_ENUM, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index f61d5456974..2770255802d 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -438,8 +438,7 @@ static void rna_ParticleSystem_co_hair( return; } - if (part->ren_as == PART_DRAW_OB || part->ren_as == PART_DRAW_GR || - part->ren_as == PART_DRAW_NOT) { + if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR, PART_DRAW_NOT)) { return; } @@ -836,7 +835,7 @@ static void rna_Particle_target_reset(Main *bmain, Scene *UNUSED(scene), Pointer ParticleTarget *pt = (ParticleTarget *)ptr->data; ParticleSystem *kpsys = NULL, *psys = rna_particle_system_for_target(ob, pt); - if (pt->ob == ob || pt->ob == NULL) { + if (ELEM(pt->ob, ob, NULL)) { kpsys = BLI_findlink(&ob->particlesystem, pt->psys - 1); if (kpsys) { @@ -1334,7 +1333,7 @@ static const EnumPropertyItem *rna_Particle_type_itemf(bContext *UNUSED(C), { ParticleSettings *part = (ParticleSettings *)ptr->owner_id; - if (part->type == PART_HAIR || part->type == PART_EMITTER) { + if (ELEM(part->type, PART_HAIR, PART_EMITTER)) { return part_type_items; } else { diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index e7c3d90573f..8f1847c00f4 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -1451,7 +1451,7 @@ static int rna_property_override_diff_propptr(Main *bmain, *r_override_changed = true; } - if (extended_rna_path != extended_rna_path_buffer && extended_rna_path != rna_path) { + if (!ELEM(extended_rna_path, extended_rna_path_buffer, rna_path)) { MEM_freeN(extended_rna_path); } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 145746cdce4..d398dadbec7 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1425,7 +1425,7 @@ static const EnumPropertyItem *rna_ImageFormatSettings_exr_codec_itemf(bContext } for (i = 0; i < R_IMF_EXR_CODEC_MAX; i++) { - if ((i == R_IMF_EXR_CODEC_B44 || i == R_IMF_EXR_CODEC_B44A)) { + if (ELEM(i, R_IMF_EXR_CODEC_B44, R_IMF_EXR_CODEC_B44A)) { continue; /* B44 and B44A are not defined for 32 bit floats */ } @@ -3149,6 +3149,25 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "use_snap_node", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "snap_flag_node", SCE_SNAP); + RNA_def_property_ui_text(prop, "Snap", "Snap Node during transform"); + RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + + prop = RNA_def_property(srna, "use_snap_sequencer", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "snap_flag_seq", SCE_SNAP); + RNA_def_property_ui_text(prop, "Use Snapping", "Snap to strip edges or current frame"); + RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1); + RNA_def_property_boolean_default(prop, true); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* Publish message-bus. */ + + prop = RNA_def_property(srna, "use_snap_uv", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "snap_uv_flag", SCE_SNAP); + RNA_def_property_ui_text(prop, "Snap", "Snap UV during transform"); + RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "use_snap_align_rotation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_ROTATE); RNA_def_property_ui_text( @@ -3163,13 +3182,6 @@ static void rna_def_tool_settings(BlenderRNA *brna) "Absolute grid alignment while translating (based on the pivot center)"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - prop = RNA_def_property(srna, "use_snap_sequencer", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_SEQ); - RNA_def_property_ui_text(prop, "Use Snapping", "Snap to strip edges or current frame"); - RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1); - RNA_def_property_boolean_default(prop, true); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* Publish message-bus. */ - prop = RNA_def_property(srna, "snap_elements", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_mode"); RNA_def_property_enum_items(prop, rna_enum_snap_element_items); diff --git a/source/blender/makesrna/intern/rna_text_api.c b/source/blender/makesrna/intern/rna_text_api.c index 67e93add549..0c0b8a85023 100644 --- a/source/blender/makesrna/intern/rna_text_api.c +++ b/source/blender/makesrna/intern/rna_text_api.c @@ -32,6 +32,17 @@ static void rna_Text_write(Text *text, const char *str) WM_main_add_notifier(NC_TEXT | NA_EDITED, text); } +static void rna_Text_from_string(Text *text, const char *str) +{ + BKE_text_clear(text); + BKE_text_write(text, str); +} + +static void rna_Text_as_string(Text *text, int *r_result_len, const char **result) +{ + *result = txt_to_buf(text, r_result_len); +} + static void rna_Text_select_set(Text *text, int startl, int startc, int endl, int endc) { txt_sel_set(text, startl, startc, endl, endc); @@ -60,6 +71,16 @@ void RNA_api_text(StructRNA *srna) parm = RNA_def_string(func, "text", "Text", 0, "", "New text for this data-block"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + func = RNA_def_function(srna, "from_string", "rna_Text_from_string"); + RNA_def_function_ui_description(func, "Replace text with this string."); + parm = RNA_def_string(func, "text", "Text", 0, "", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + + func = RNA_def_function(srna, "as_string", "rna_Text_as_string"); + RNA_def_function_ui_description(func, "Return the text as a string"); + parm = RNA_def_string(func, "text", "Text", 0, "", ""); + RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_OUTPUT); + func = RNA_def_function( srna, "is_syntax_highlight_supported", "ED_text_is_syntax_highlight_supported"); RNA_def_function_return(func, diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 00fb48b489a..1d0723851ad 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -549,7 +549,7 @@ static void uilist_filter_items(uiList *ui_list, parm = RNA_function_find_parameter(NULL, func, "filter_flags"); ret_len = RNA_parameter_dynamic_length_get(&list, parm); - if (ret_len != len && ret_len != 0) { + if (!ELEM(ret_len, len, 0)) { printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n", __func__, RNA_parameter_dynamic_length_get(&list, parm), @@ -565,7 +565,7 @@ static void uilist_filter_items(uiList *ui_list, parm = RNA_function_find_parameter(NULL, func, "filter_neworder"); ret_len = RNA_parameter_dynamic_length_get(&list, parm); - if (ret_len != len && ret_len != 0) { + if (!ELEM(ret_len, len, 0)) { printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n", __func__, RNA_parameter_dynamic_length_get(&list, parm), diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 339d0bf380c..3b9632342ec 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -638,7 +638,7 @@ static void rna_userdef_autosave_update(Main *bmain, Scene *scene, PointerRNA *p wmWindowManager *wm = bmain->wm.first; if (wm) { - WM_autosave_init(wm); + WM_file_autosave_init(wm); } rna_userdef_update(bmain, scene, ptr); } diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 8835591f303..a850f8862bc 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -98,11 +98,13 @@ static const EnumPropertyItem event_ndof_type_items[] = { {NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""}, {NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""}, {NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""}, +# if 0 /* Never used (converted to keyboard events by GHOST). */ /* keyboard emulation */ {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"}, {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "Alt"}, {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "Shift"}, {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "Ctrl"}, +# endif /* general-purpose buttons */ {NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""}, {NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""}, @@ -311,11 +313,13 @@ const EnumPropertyItem rna_enum_event_type_items[] = { {NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "NDOF Dominant", "NdofDom"}, {NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "NDOF Plus", "Ndof+"}, {NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "NDOF Minus", "Ndof-"}, +#if 0 /* Never used (converted to keyboard events by GHOST). */ /* keyboard emulation */ {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "NDOF Esc", "NdofEsc"}, {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "NDOF Alt", "NdofAlt"}, {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "NDOF Shift", "NdofShift"}, {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "NDOF Ctrl", "NdofCtrl"}, +#endif /* general-purpose buttons */ {NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "NDOF Button 1", "NdofB1"}, {NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "NDOF Button 2", "NdofB2"}, @@ -2098,6 +2102,20 @@ static void rna_def_event(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Mouse Previous Y Position", "The window relative vertical location of the mouse"); + prop = RNA_def_property(srna, "mouse_prev_press_x", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "prev_press_xy[0]"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, + "Mouse Previous X Press Position", + "The window relative horizontal location of the last press event"); + + prop = RNA_def_property(srna, "mouse_prev_press_y", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "prev_press_xy[1]"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, + "Mouse Previous Y Press Position", + "The window relative vertical location of the last press event"); + prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c index 9fe3153eb1e..d8be9b7e80d 100644 --- a/source/blender/makesrna/intern/rna_xr.c +++ b/source/blender/makesrna/intern/rna_xr.c @@ -33,7 +33,7 @@ static wmXrData *rna_XrSession_wm_xr_data_get(PointerRNA *ptr) /* Callers could also get XrSessionState pointer through ptr->data, but prefer if we just * consistently pass wmXrData pointers to the WM_xr_xxx() API. */ - BLI_assert((ptr->type == &RNA_XrSessionSettings) || (ptr->type == &RNA_XrSessionState)); + BLI_assert(ELEM(ptr->type, &RNA_XrSessionSettings, &RNA_XrSessionState)); wmWindowManager *wm = (wmWindowManager *)ptr->owner_id; BLI_assert(wm && (GS(wm->id.name) == ID_WM)); @@ -739,7 +739,7 @@ static bool rna_XrSessionState_action_create(bContext *C, return false; } - const bool is_float_action = (ami->type == XR_FLOAT_INPUT || ami->type == XR_VECTOR2F_INPUT); + const bool is_float_action = ELEM(ami->type, XR_FLOAT_INPUT, XR_VECTOR2F_INPUT); const bool is_button_action = (is_float_action || ami->type == XR_BOOLEAN_INPUT); wmOperatorType *ot = NULL; IDProperty *op_properties = NULL; @@ -791,7 +791,7 @@ static bool rna_XrSessionState_action_binding_create(bContext *C, return false; } - const bool is_float_action = (ami->type == XR_FLOAT_INPUT || ami->type == XR_VECTOR2F_INPUT); + const bool is_float_action = ELEM(ami->type, XR_FLOAT_INPUT, XR_VECTOR2F_INPUT); const bool is_button_action = (is_float_action || ami->type == XR_BOOLEAN_INPUT); const bool is_pose_action = (ami->type == XR_POSE_INPUT); float float_thresholds[2]; diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 9450a444042..b19caefae29 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -94,7 +94,8 @@ Mesh *doEdgeSplit(const Mesh *mesh, EdgeSplitModifierData *emd) BM_mesh_edgesplit(bm, false, true, false); - /* BM_mesh_validate(bm); */ /* for troubleshooting */ + /* Uncomment for troubleshooting. */ + // BM_mesh_validate(bm); result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); BM_mesh_free(bm); diff --git a/source/blender/modifiers/intern/MOD_ui_common.c b/source/blender/modifiers/intern/MOD_ui_common.c index 90652c180c6..eddf4bd03e1 100644 --- a/source/blender/modifiers/intern/MOD_ui_common.c +++ b/source/blender/modifiers/intern/MOD_ui_common.c @@ -63,7 +63,7 @@ static void modifier_reorder(bContext *C, Panel *panel, int new_index) WM_operator_properties_create_ptr(&props_ptr, ot); RNA_string_set(&props_ptr, "modifier", md->name); RNA_int_set(&props_ptr, "index", new_index); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL); WM_operator_properties_free(&props_ptr); } diff --git a/source/blender/modifiers/intern/MOD_ui_common.h b/source/blender/modifiers/intern/MOD_ui_common.h index 16e9dd25253..6548a897be9 100644 --- a/source/blender/modifiers/intern/MOD_ui_common.h +++ b/source/blender/modifiers/intern/MOD_ui_common.h @@ -51,8 +51,8 @@ struct PanelType *modifier_panel_register(struct ARegionType *region_type, /** * Add a child panel to the parent. * - * \note To create the panel type's idname, it appends the \a name argument to the \a parent's - * idname. + * \note To create the panel type's #PanelType.idname, + * it appends the \a name argument to the \a parent's `idname`. */ struct PanelType *modifier_subpanel_register(struct ARegionType *region_type, const char *name, diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc index 2fe06a17adf..2c801642bd7 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc @@ -41,7 +41,7 @@ static void node_geo_exec(GeoNodeExecParams params) } }); - geometry_set.replace_curve(curve_eval_to_curves(*curve)); + geometry_set.replace_curves(curve_eval_to_curves(*curve)); params.set_output("Curve", geometry_set); } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc index 537c7c42610..56e9068882b 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc @@ -101,7 +101,7 @@ static void node_geo_exec(GeoNodeExecParams params) bezier_spline.mark_cache_invalid(); } - geometry_set.replace_curve(curve_eval_to_curves(*curve)); + geometry_set.replace_curves(curve_eval_to_curves(*curve)); if (!has_bezier_spline) { params.error_message_add(NodeWarningType::Info, TIP_("No Bezier splines in input curve")); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc index 4e3b0839da7..002c42c4c82 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc @@ -100,7 +100,7 @@ static SplinePtr poly_to_nurbs(const Spline &input) output->set_resolution(12); output->set_order(4); Spline::copy_base_settings(input, *output); - output->knots_mode = NURBSpline::KnotsMode::Bezier; + output->knots_mode = NURBS_KNOT_MODE_BEZIER; output->attributes = input.attributes; return output; } @@ -128,7 +128,7 @@ static SplinePtr bezier_to_nurbs(const Spline &input) output->set_resolution(12); output->set_order(4); output->set_cyclic(input.is_cyclic()); - output->knots_mode = NURBSpline::KnotsMode::Bezier; + output->knots_mode = NURBS_KNOT_MODE_BEZIER; output->attributes.reallocate(output->size()); copy_attributes(input, *output, [](GSpan src, GMutableSpan dst) { attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc index 8991261a21a..72cb540df4a 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc @@ -45,10 +45,8 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - std::unique_ptr<CurveEval> curve = geometry::mesh_to_curve_convert( - component, IndexMask(selected_edge_indices)); - - params.set_output("Curve", GeometrySet::create_with_curves(curve_eval_to_curves(*curve))); + Curves *curves = geometry::mesh_to_curve_convert(component, IndexMask(selected_edge_indices)); + params.set_output("Curve", GeometrySet::create_with_curves(curves)); } } // namespace blender::nodes::node_geo_legacy_mesh_to_curve_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc index 6702ee6c0aa..08aa7415073 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc @@ -120,7 +120,7 @@ static void curve_fill_calculate(GeometrySet &geometry_set, const GeometryNodeCu const std::unique_ptr<CurveEval> curve = curves_to_curve_eval( *geometry_set.get_curves_for_read()); if (curve->splines().is_empty()) { - geometry_set.replace_curve(nullptr); + geometry_set.replace_curves(nullptr); return; } @@ -132,7 +132,7 @@ static void curve_fill_calculate(GeometrySet &geometry_set, const GeometryNodeCu Mesh *mesh = cdt_to_mesh(results); geometry_set.replace_mesh(mesh); - geometry_set.replace_curve(nullptr); + geometry_set.replace_curves(nullptr); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc index 24d72ad553b..81ca87eec25 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc @@ -283,7 +283,7 @@ static void limit_radii(FilletData &fd, const bool cyclic) /* Assign the max_radii to the fillet data's radii. */ for (const int i : IndexRange(size)) { - radii[i] = max_radii[i]; + radii[i] = std::min(radii[i], max_radii[i]); } } @@ -606,7 +606,7 @@ static void calculate_curve_fillet(GeometrySet &geometry_set, const std::unique_ptr<CurveEval> input_curve = curves_to_curve_eval(*component.get_for_read()); std::unique_ptr<CurveEval> output_curve = fillet_curve(*input_curve, fillet_param); - geometry_set.replace_curve(curve_eval_to_curves(*output_curve)); + geometry_set.replace_curves(curve_eval_to_curves(*output_curve)); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc index ccd3a587e63..0aa603a7736 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc @@ -112,7 +112,6 @@ class HandleTypeFieldInput final : public GeometryFieldInput { bool is_equal_to(const fn::FieldNode &other) const override { - return dynamic_cast<const HandleTypeFieldInput *>(&other) != nullptr; if (const HandleTypeFieldInput *other_handle_selection = dynamic_cast<const HandleTypeFieldInput *>(&other)) { return mode_ == other_handle_selection->mode_ && type_ == other_handle_selection->type_; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc index 874e29dda86..2fb9f724130 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc @@ -176,7 +176,7 @@ static void node_geo_exec(GeoNodeExecParams params) const GeometryNodeCurvePrimitiveCircleMode mode = (GeometryNodeCurvePrimitiveCircleMode) storage.mode; - Curves *curves; + Curves *curves = nullptr; if (mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS) { float3 center_point; curves = create_point_circle_curve(params.extract_input<float3>("Point 1"), diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc index c5814a9a1dd..5a4c2ad1660 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc @@ -242,7 +242,7 @@ static void geometry_set_curve_resample(GeometrySet &geometry_set, std::unique_ptr<CurveEval> output_curve = resample_curve( geometry_set.get_component_for_read<CurveComponent>(), mode_param); - geometry_set.replace_curve(curve_eval_to_curves(*output_curve)); + geometry_set.replace_curves(curve_eval_to_curves(*output_curve)); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc index 55610ec86ab..4118448b237 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc @@ -58,21 +58,22 @@ static void scale_output_assign(const Span<T> input, template<class T> static void nurbs_to_bezier_assign(const Span<T> input, const MutableSpan<T> r_output, - const NURBSpline::KnotsMode knotsMode) + const KnotsMode knotsMode) { const int input_size = input.size(); const int output_size = r_output.size(); switch (knotsMode) { - case NURBSpline::KnotsMode::Bezier: + case NURBS_KNOT_MODE_BEZIER: scale_input_assign<T>(input, 3, 1, r_output); break; - case NURBSpline::KnotsMode::Normal: + case NURBS_KNOT_MODE_NORMAL: for (const int i : IndexRange(output_size)) { r_output[i] = input[(i + 1) % input_size]; } break; - case NURBSpline::KnotsMode::EndPoint: + case NURBS_KNOT_MODE_ENDPOINT_BEZIER: + case NURBS_KNOT_MODE_ENDPOINT: for (const int i : IndexRange(1, output_size - 2)) { r_output[i] = input[i + 1]; } @@ -107,11 +108,11 @@ static void copy_attributes(const Spline &input_spline, Spline &output_spline, C } static Vector<float3> create_nurbs_to_bezier_handles(const Span<float3> nurbs_positions, - const NURBSpline::KnotsMode knots_mode) + const KnotsMode knots_mode) { const int nurbs_positions_size = nurbs_positions.size(); Vector<float3> handle_positions; - if (knots_mode == NURBSpline::KnotsMode::Bezier) { + if (knots_mode == NURBS_KNOT_MODE_BEZIER) { for (const int i : IndexRange(nurbs_positions_size)) { if (i % 3 == 1) { continue; @@ -127,7 +128,7 @@ static Vector<float3> create_nurbs_to_bezier_handles(const Span<float3> nurbs_po } } else { - const bool is_periodic = knots_mode == NURBSpline::KnotsMode::Normal; + const bool is_periodic = knots_mode == NURBS_KNOT_MODE_NORMAL; if (is_periodic) { handle_positions.append(nurbs_positions[1] + ((nurbs_positions[0] - nurbs_positions[1]) / 3)); @@ -169,9 +170,9 @@ static Vector<float3> create_nurbs_to_bezier_handles(const Span<float3> nurbs_po static Array<float3> create_nurbs_to_bezier_positions(const Span<float3> nurbs_positions, const Span<float3> handle_positions, - const NURBSpline::KnotsMode knots_mode) + const KnotsMode knots_mode) { - if (knots_mode == NURBSpline::KnotsMode::Bezier) { + if (knots_mode == NURBS_KNOT_MODE_BEZIER) { /* Every third NURBS position (starting from index 1) should be converted to Bezier position */ const int scale = 3; const int offset = 1; @@ -211,7 +212,7 @@ static SplinePtr poly_to_nurbs(const Spline &input) output->set_resolution(12); output->set_order(4); Spline::copy_base_settings(input, *output); - output->knots_mode = NURBSpline::KnotsMode::Bezier; + output->knots_mode = NURBS_KNOT_MODE_BEZIER; output->attributes = input.attributes; return output; } @@ -239,7 +240,7 @@ static SplinePtr bezier_to_nurbs(const Spline &input) output->set_resolution(12); output->set_order(4); output->set_cyclic(input.is_cyclic()); - output->knots_mode = NURBSpline::KnotsMode::Bezier; + output->knots_mode = NURBS_KNOT_MODE_BEZIER; output->attributes.reallocate(output->size()); copy_attributes(input, *output, [](GSpan src, GMutableSpan dst) { attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { @@ -272,13 +273,13 @@ static SplinePtr nurbs_to_bezier(const Spline &input) const NURBSpline &nurbs_spline = static_cast<const NURBSpline &>(input); Span<float3> nurbs_positions; Vector<float3> nurbs_positions_vector; - NURBSpline::KnotsMode knots_mode; + KnotsMode knots_mode; if (nurbs_spline.is_cyclic()) { nurbs_positions_vector = nurbs_spline.positions(); nurbs_positions_vector.append(nurbs_spline.positions()[0]); nurbs_positions_vector.append(nurbs_spline.positions()[1]); nurbs_positions = nurbs_positions_vector; - knots_mode = NURBSpline::KnotsMode::Normal; + knots_mode = NURBS_KNOT_MODE_NORMAL; } else { nurbs_positions = nurbs_spline.positions(); @@ -403,7 +404,7 @@ static void node_geo_exec(GeoNodeExecParams params) } }); new_curve->attributes = curve->attributes; - geometry_set.replace_curve(curve_eval_to_curves(*new_curve)); + geometry_set.replace_curves(curve_eval_to_curves(*new_curve)); }); params.set_output("Curve", std::move(geometry_set)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc index bbe57b2b3fa..371556c04f1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc @@ -206,6 +206,10 @@ static void subdivide_bezier_spline(const BezierSpline &src, } else { dst_positions.last() = src_positions.last(); + dst_type_left.first() = src.handle_types_left().first(); + dst_type_right.last() = src.handle_types_right().last(); + dst_handles_left.first() = src_handles_left.first(); + dst_handles_right.last() = src_handles_right.last(); } } @@ -342,7 +346,7 @@ static void node_geo_exec(GeoNodeExecParams params) } std::unique_ptr<CurveEval> output_curve = subdivide_curve( *curves_to_curve_eval(*component.get_for_read()), cuts); - geometry_set.replace_curve(curve_eval_to_curves(*output_curve)); + geometry_set.replace_curves(curve_eval_to_curves(*output_curve)); }); params.set_output("Curve", geometry_set); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc index a3dab1b50fe..df360818313 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc @@ -566,7 +566,7 @@ static void geometry_set_curve_trim(GeometrySet &geometry_set, } }); - geometry_set.replace_curve(curve_eval_to_curves(*curve)); + geometry_set.replace_curves(curve_eval_to_curves(*curve)); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index 3baee8a25bb..cf6837817c2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -477,10 +477,10 @@ static void separate_curve_selection(GeometrySet &geometry_set, std::unique_ptr<CurveEval> r_curve = curve_separate( *curves_to_curve_eval(*src_component.get_for_read()), selection, selection_domain, invert); if (r_curve) { - geometry_set.replace_curve(curve_eval_to_curves(*r_curve)); + geometry_set.replace_curves(curve_eval_to_curves(*r_curve)); } else { - geometry_set.replace_curve(nullptr); + geometry_set.replace_curves(nullptr); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index 1ceab18c01b..eb216c08289 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -599,7 +599,7 @@ static void duplicate_splines(GeometrySet &geometry_set, dst_component, ATTR_DOMAIN_CURVE, selection, attributes, curve_offsets); } - geometry_set.replace_curve(dst_component.get_for_write()); + geometry_set.replace_curves(dst_component.get_for_write()); } static void duplicate_faces(GeometrySet &geometry_set, diff --git a/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc b/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc index a87aef358e1..33802d00d2b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc @@ -257,8 +257,8 @@ class ImageFieldsFunction : public fn::MultiFunction { const int width = ibuf->x; const int height = ibuf->y; int ix, iy; - const float tx = frac(px * (float)width - 0.5f, &ix); - const float ty = frac(py * (float)height - 0.5f, &iy); + const float tx = frac(px * (float)width, &ix); + const float ty = frac(py * (float)height, &iy); switch (extension) { case SHD_IMAGE_EXTENSION_REPEAT: { diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc index f952e15fbbe..c3d87055745 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc @@ -25,13 +25,16 @@ static VArray<float> construct_spline_length_gvarray(const CurveComponent &compo const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read()); Span<SplinePtr> splines = curve->splines(); - auto length_fn = [splines](int i) { return splines[i]->length(); }; + Array<float> spline_lenghts(splines.size()); + for (const int i : splines.index_range()) { + spline_lenghts[i] = splines[i]->length(); + } if (domain == ATTR_DOMAIN_CURVE) { - return VArray<float>::ForFunc(splines.size(), length_fn); + return VArray<float>::ForContainer(std::move(spline_lenghts)); } if (domain == ATTR_DOMAIN_POINT) { - VArray<float> length = VArray<float>::ForFunc(splines.size(), length_fn); + VArray<float> length = VArray<float>::ForContainer(std::move(spline_lenghts)); return component.attribute_try_adapt_domain<float>( std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc index d84a2e73172..b882d4bdf09 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc @@ -510,11 +510,11 @@ static void calculate_selection_outputs(Mesh *mesh, if (config.bottom_is_point) { selection[config.last_vert] = true; } + else if (face) { + selection.slice(config.bottom_faces_start, config.bottom_faces_len).fill(true); + } else { - selection - .slice(config.bottom_faces_start, - face ? config.bottom_faces_len : config.circle_segments) - .fill(true); + selection.slice(config.last_ring_verts_start + 1, config.circle_segments).fill(true); } attribute.save(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc index 4a09fd8d1d2..4e0e5c7c912 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc @@ -76,10 +76,10 @@ static void calculate_sphere_vertex_data(MutableSpan<MVert> verts, int vert_index = 1; for (const int ring : IndexRange(1, rings - 1)) { const float theta = ring * delta_theta; + const float sin_theta = std::sin(theta); const float z = std::cos(theta); for (const int segment : IndexRange(1, segments)) { const float phi = segment * delta_phi; - const float sin_theta = std::sin(theta); const float x = sin_theta * std::cos(phi); const float y = sin_theta * std::sin(phi); copy_v3_v3(verts[vert_index].co, float3(x, y, z) * radius); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc index 91cde52f9eb..f6ee3d00dee 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc @@ -34,8 +34,7 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - std::unique_ptr<CurveEval> curve = geometry::mesh_to_curve_convert(component, selection); - geometry_set.replace_curve(curve_eval_to_curves(*curve)); + geometry_set.replace_curves(geometry::mesh_to_curve_convert(component, selection)); geometry_set.keep_only({GEO_COMPONENT_TYPE_CURVE, GEO_COMPONENT_TYPE_INSTANCES}); }); diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc index 95cec8eab11..9159ac081e0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc @@ -129,7 +129,7 @@ static void translate_geometry_set(GeometrySet &geometry, if (Curves *curves = geometry.get_curves_for_write()) { std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curves); curve->translate(translation); - geometry.replace_curve(curve_eval_to_curves(*curve)); + geometry.replace_curves(curve_eval_to_curves(*curve)); } if (Mesh *mesh = geometry.get_mesh_for_write()) { translate_mesh(*mesh, translation); @@ -152,7 +152,7 @@ void transform_geometry_set(GeometrySet &geometry, if (Curves *curves = geometry.get_curves_for_write()) { std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curves); curve->transform(transform); - geometry.replace_curve(curve_eval_to_curves(*curve)); + geometry.replace_curves(curve_eval_to_curves(*curve)); } if (Mesh *mesh = geometry.get_mesh_for_write()) { transform_mesh(*mesh, transform); diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc index 6c2f38fc723..ba98a797f2a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -43,7 +43,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Float>(N_("Specular Tint")) - .default_value(0.5f) + .default_value(0.0f) .min(0.0f) .max(1.0f) .subtype(PROP_FACTOR); diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.cc b/source/blender/nodes/shader/nodes/node_shader_object_info.cc index 6ed5a7b715d..03c1a018d37 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.cc +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.cc @@ -9,6 +9,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_output<decl::Vector>(N_("Location")); b.add_output<decl::Color>(N_("Color")); + b.add_output<decl::Float>(N_("Alpha")); b.add_output<decl::Float>(N_("Object Index")); b.add_output<decl::Float>(N_("Material Index")); b.add_output<decl::Float>(N_("Random")); diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index c05c003b176..2fbb6b8ee05 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -756,7 +756,16 @@ static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject static PyObject *BPy_IDGroup_iter(BPy_IDProperty *self) { - return BPy_IDGroup_ViewKeys_CreatePyObject(self); + PyObject *iterable = BPy_IDGroup_ViewKeys_CreatePyObject(self); + PyObject *ret; + if (iterable) { + ret = PyObject_GetIter(iterable); + Py_DECREF(iterable); + } + else { + ret = NULL; + } + return ret; } PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop) diff --git a/source/blender/python/gpu/gpu_py_texture.c b/source/blender/python/gpu/gpu_py_texture.c index ab038423878..0ad55aeac78 100644 --- a/source/blender/python/gpu/gpu_py_texture.c +++ b/source/blender/python/gpu/gpu_py_texture.c @@ -545,11 +545,11 @@ static struct PyMethodDef pygpu_texture__m_methods[] = { {NULL, NULL, 0, NULL}, }; -PyDoc_STRVAR(pygpu_texure__m_doc, "This module provides utils for textures."); +PyDoc_STRVAR(pygpu_texture__m_doc, "This module provides utils for textures."); static PyModuleDef pygpu_texture_module_def = { PyModuleDef_HEAD_INIT, .m_name = "gpu.texture", - .m_doc = pygpu_texure__m_doc, + .m_doc = pygpu_texture__m_doc, .m_methods = pygpu_texture__m_methods, }; diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 3155f3a63bd..ba3e6a3d74b 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -64,6 +64,8 @@ static PyStructSequence_Field app_cb_info_fields[] = { {"load_factory_preferences_post", "on loading factory preferences (after)"}, {"load_factory_startup_post", "on loading factory startup (after)"}, {"xr_session_start_pre", "on starting an xr session (before)"}, + {"annotation_pre", "on drawing an annotation (before)"}, + {"annotation_post", "on drawing an annotation (after)"}, /* sets the permanent tag */ #define APP_CB_OTHER_FIELDS 1 @@ -276,7 +278,7 @@ void BPY_app_handlers_reset(const short do_all) } else { /* remove */ - /* PySequence_DelItem(ls, i); */ /* more obvious but slower */ + // PySequence_DelItem(ls, i); /* more obvious but slower */ PyList_SetSlice(ls, i, i + 1, NULL); } } diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 61bb183068d..68018d22753 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -162,9 +162,11 @@ static struct { /* borrowed reference to the 'self' in 'bpy_pydriver_Dict' * keep for as long as the same self is used. */ PyObject *self; + BPy_StructRNA *depsgraph; } g_pydriver_state_prev = { .evaltime = FLT_MAX, .self = NULL, + .depsgraph = NULL, }; static void bpy_pydriver_namespace_update_frame(const float evaltime) @@ -199,6 +201,38 @@ static void bpy_pydriver_namespace_clear_self(void) } } +static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph) +{ + struct PointerRNA depsgraph_ptr; + RNA_pointer_create(NULL, &RNA_Depsgraph, depsgraph, &depsgraph_ptr); + return pyrna_struct_CreatePyObject(&depsgraph_ptr); +} + +/** + * Adds a variable 'depsgraph' to the name-space. This can then be used to obtain evaluated + * data-blocks, and the current view layer and scene. See T75553. + */ +static void bpy_pydriver_namespace_update_depsgraph(struct Depsgraph *depsgraph) +{ + /* This should never happen, but it's probably better to have None in Python + * than a NULL-wrapping Depsgraph Python struct. */ + BLI_assert(depsgraph != NULL); + if (UNLIKELY(depsgraph == NULL)) { + PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_depsgraph, Py_None); + g_pydriver_state_prev.depsgraph = NULL; + return; + } + + if ((g_pydriver_state_prev.depsgraph == NULL) || + ((depsgraph != g_pydriver_state_prev.depsgraph->ptr.data))) { + PyObject *item = bpy_pydriver_depsgraph_as_pyobject(depsgraph); + PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_depsgraph, item); + Py_DECREF(item); + + g_pydriver_state_prev.depsgraph = (BPy_StructRNA *)item; + } +} + void BPY_driver_reset(void) { PyGILState_STATE gilstate; @@ -226,6 +260,7 @@ void BPY_driver_reset(void) /* freed when clearing driver dict */ g_pydriver_state_prev.self = NULL; + g_pydriver_state_prev.depsgraph = NULL; if (use_gil) { PyGILState_Release(gilstate); @@ -369,40 +404,6 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d } #endif /* USE_BYTECODE_WHITELIST */ - -static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph) -{ - /* This should never happen, but it's probably better to have None in Python - * than a NULL-wrapping Depsgraph py struct. */ - BLI_assert(depsgraph != NULL); - if (depsgraph == NULL) { - Py_RETURN_NONE; - } - - struct PointerRNA depsgraph_ptr; - RNA_pointer_create(NULL, &RNA_Depsgraph, depsgraph, &depsgraph_ptr); - return pyrna_struct_CreatePyObject(&depsgraph_ptr); -} - -/** - * Adds a variable 'depsgraph' to the driver variables. This can then be used to obtain evaluated - * data-blocks, and the current view layer and scene. See T75553. - */ -static void bpy_pydriver_namespace_add_depsgraph(PyObject *driver_vars, - struct Depsgraph *depsgraph) -{ - PyObject *py_depsgraph = bpy_pydriver_depsgraph_as_pyobject(depsgraph); - const char *depsgraph_variable_name = "depsgraph"; - - if (PyDict_SetItemString(driver_vars, depsgraph_variable_name, py_depsgraph) == -1) { - fprintf(stderr, - "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", - depsgraph_variable_name); - PyErr_Print(); - PyErr_Clear(); - } -} - float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, @@ -488,6 +489,8 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, bpy_pydriver_namespace_clear_self(); } + bpy_pydriver_namespace_update_depsgraph(anim_eval_context->depsgraph); + if (driver_orig->expr_comp == NULL) { driver_orig->flag |= DRIVER_FLAG_RECOMPILE; } @@ -612,8 +615,6 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, } #endif /* USE_BYTECODE_WHITELIST */ - bpy_pydriver_namespace_add_depsgraph(driver_vars, anim_eval_context->depsgraph); - #if 0 /* slow, with this can avoid all Py_CompileString above. */ /* execute expression to get a value */ retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars); diff --git a/source/blender/python/intern/bpy_interface_run.c b/source/blender/python/intern/bpy_interface_run.c index 01db0efecfd..500221c3c50 100644 --- a/source/blender/python/intern/bpy_interface_run.c +++ b/source/blender/python/intern/bpy_interface_run.c @@ -102,7 +102,8 @@ static bool python_script_exec( fn_dummy_py = PyC_UnicodeFromByte(fn_dummy); - buf = txt_to_buf(text, NULL); + int buf_len_dummy; + buf = txt_to_buf(text, &buf_len_dummy); text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1); MEM_freeN(buf); diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c index 1cf8f3b65a0..817494cb70a 100644 --- a/source/blender/python/intern/bpy_intern_string.c +++ b/source/blender/python/intern/bpy_intern_string.c @@ -14,7 +14,7 @@ #include "BLI_utildefines.h" -static PyObject *bpy_intern_str_arr[16]; +static PyObject *bpy_intern_str_arr[17]; PyObject *bpy_intern_str___annotations__; PyObject *bpy_intern_str___doc__; @@ -31,6 +31,7 @@ PyObject *bpy_intern_str_frame; PyObject *bpy_intern_str_properties; PyObject *bpy_intern_str_register; PyObject *bpy_intern_str_self; +PyObject *bpy_intern_str_depsgraph; PyObject *bpy_intern_str_unregister; void bpy_intern_string_init(void) @@ -58,6 +59,7 @@ void bpy_intern_string_init(void) BPY_INTERN_STR(bpy_intern_str_properties, "properties"); BPY_INTERN_STR(bpy_intern_str_register, "register"); BPY_INTERN_STR(bpy_intern_str_self, "self"); + BPY_INTERN_STR(bpy_intern_str_depsgraph, "depsgraph"); BPY_INTERN_STR(bpy_intern_str_unregister, "unregister"); #undef BPY_INTERN_STR diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h index 1d74e8c31c5..cc8bf8a6f3b 100644 --- a/source/blender/python/intern/bpy_intern_string.h +++ b/source/blender/python/intern/bpy_intern_string.h @@ -28,6 +28,7 @@ extern PyObject *bpy_intern_str_frame; extern PyObject *bpy_intern_str_properties; extern PyObject *bpy_intern_str_register; extern PyObject *bpy_intern_str_self; +extern PyObject *bpy_intern_str_depsgraph; extern PyObject *bpy_intern_str_unregister; #ifdef __cplusplus diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 61de15b07f5..159ac23bf95 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -313,7 +313,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) return NULL; } - WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL, NULL); } #endif } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 316cfe4d8b1..16e90a55844 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -5897,28 +5897,37 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat break; case PROP_STRING: { const char *data_ch; - PyObject *value_coerce = NULL; const int subtype = RNA_property_subtype(prop); + size_t data_ch_len; - if (flag & PROP_THICK_WRAP) { - data_ch = (char *)data; + if (flag & PROP_DYNAMIC) { + ParameterDynAlloc *data_alloc = data; + data_ch = data_alloc->array; + data_ch_len = data_alloc->array_tot; + BLI_assert((data_ch == NULL) || strlen(data_ch) == data_ch_len); } else { - data_ch = *(char **)data; + data_ch = (flag & PROP_THICK_WRAP) ? (char *)data : *(char **)data; + data_ch_len = data_ch ? strlen(data_ch) : 0; } + if (UNLIKELY(data_ch == NULL)) { + BLI_assert((flag & PROP_NEVER_NULL) == 0); + ret = Py_None; + Py_INCREF(ret); + } #ifdef USE_STRING_COERCE - if (subtype == PROP_BYTESTRING) { - ret = PyBytes_FromString(data_ch); + else if (subtype == PROP_BYTESTRING) { + ret = PyBytes_FromStringAndSize(data_ch, data_ch_len); } else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - ret = PyC_UnicodeFromByte(data_ch); + ret = PyC_UnicodeFromByteAndSize(data_ch, data_ch_len); } else { - ret = PyUnicode_FromString(data_ch); + ret = PyUnicode_FromStringAndSize(data_ch, data_ch_len); } #else - if (subtype == PROP_BYTESTRING) { + else if (subtype == PROP_BYTESTRING) { ret = PyBytes_FromString(buf); } else { @@ -5926,10 +5935,6 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat } #endif -#ifdef USE_STRING_COERCE - Py_XDECREF(value_coerce); -#endif - break; } case PROP_ENUM: { @@ -6229,7 +6234,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject arg_name = PyUnicode_AsUTF8(key); found = false; - if (arg_name == NULL) { /* Unlikely the argname is not a string, but ignore if it is. */ + if (arg_name == NULL) { /* Unlikely the `arg_name` is not a string, but ignore if it is. */ PyErr_Clear(); } else { diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h index 2d43aa7b27f..f532c705534 100644 --- a/source/blender/render/RE_pipeline.h +++ b/source/blender/render/RE_pipeline.h @@ -322,9 +322,13 @@ bool RE_WriteRenderViewsMovie(struct ReportList *reports, bool preview); /** - * Only #RE_NewRender() needed, main Blender render calls. - * * General Blender frame render call. + * + * \note Only #RE_NewRender() needed, main Blender render calls. + * + * \param write_still: Saves frames to disk (typically disabled). Useful for batch-operations + * (rendering from Python for e.g.) when an additional save action for is inconvenient. + * This is the default behavior for #RE_RenderAnim. */ void RE_RenderFrame(struct Render *re, struct Main *bmain, @@ -334,7 +338,7 @@ void RE_RenderFrame(struct Render *re, int frame, bool write_still); /** - * Saves images to disk. + * A version of #RE_RenderFrame that saves images to disk. */ void RE_RenderAnim(struct Render *re, struct Main *bmain, diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c index 2a93fb2c46b..aa006713755 100644 --- a/source/blender/render/intern/pipeline.c +++ b/source/blender/render/intern/pipeline.c @@ -116,14 +116,20 @@ * - save file or append in movie */ -/* ********* globals ******** */ +/* -------------------------------------------------------------------- */ +/** \name Globals + * \{ */ /* here we store all renders */ static struct { ListBase renderlist; } RenderGlobal = {{NULL, NULL}}; -/* ********* callbacks ******** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Callbacks + * \{ */ static void render_callback_exec_null(Render *re, Main *bmain, eCbEvent evt) { @@ -141,7 +147,11 @@ static void render_callback_exec_id(Render *re, Main *bmain, ID *id, eCbEvent ev BKE_callback_exec_id(bmain, id, evt); } -/* ********* alloc and free ******** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Allocation & Free + * \{ */ static int do_write_image_or_movie(Render *re, Main *bmain, @@ -308,7 +318,11 @@ static bool render_scene_has_layers_to_render(Scene *scene, ViewLayer *single_la return false; } -/* *************************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public Render API + * \{ */ Render *RE_GetRender(const char *name) { @@ -686,7 +700,11 @@ void RE_FreePersistentData(const Scene *scene) } } -/* ********* initialize state ******** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Initialize State + * \{ */ static void re_init_resolution(Render *re, Render *source, int winx, int winy, rcti *disprect) { @@ -905,7 +923,11 @@ void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle)) re->tbh = handle; } -/* ********* GL Context ******** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name OpenGL Context + * \{ */ void RE_gl_context_create(Render *re) { @@ -944,6 +966,16 @@ void *RE_gpu_context_get(Render *re) return re->gpu_context; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Render & Composite Scenes (Implementation & Public API) + * + * Main high-level functions defined here are: + * - #RE_RenderFrame + * - #RE_RenderAnim + * \{ */ + /* ************ This part uses API, for rendering Blender scenes ********** */ /* make sure disprect is not affected by the render border */ @@ -1940,6 +1972,12 @@ void RE_RenderFreestyleExternal(Render *re) } #endif +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Read/Write Render Result (Images & Movies) + * \{ */ + bool RE_WriteRenderViewsImage( ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name) { @@ -2600,11 +2638,6 @@ bool RE_ReadRenderResult(Scene *scene, Scene *scenode) return success; } -void RE_init_threadcount(Render *re) -{ - re->r.threads = BKE_render_num_threads(&re->r); -} - void RE_layer_load_from_file( RenderLayer *layer, ReportList *reports, const char *filename, int x, int y) { @@ -2785,6 +2818,12 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha return render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, viewname, "RGBA", true); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Miscellaneous Public Render API + * \{ */ + bool RE_allow_render_generic_object(Object *ob) { /* override not showing object when duplis are used with particles */ @@ -2796,3 +2835,10 @@ bool RE_allow_render_generic_object(Object *ob) } return true; } + +void RE_init_threadcount(Render *re) +{ + re->r.threads = BKE_render_num_threads(&re->r); +} + +/** \} */ diff --git a/source/blender/render/intern/texture_procedural.c b/source/blender/render/intern/texture_procedural.c index 4b1439529c1..73dbcfdfeab 100644 --- a/source/blender/render/intern/texture_procedural.c +++ b/source/blender/render/intern/texture_procedural.c @@ -102,10 +102,10 @@ static int blend(const Tex *tex, const float texvec[3], TexResult *texres) y = texvec[1]; } - if (tex->stype == TEX_LIN) { /* lin */ + if (tex->stype == TEX_LIN) { /* Linear. */ texres->tin = (1.0f + x) / 2.0f; } - else if (tex->stype == TEX_QUAD) { /* quad */ + else if (tex->stype == TEX_QUAD) { /* Quadratic. */ texres->tin = (1.0f + x) / 2.0f; if (texres->tin < 0.0f) { texres->tin = 0.0f; @@ -114,7 +114,7 @@ static int blend(const Tex *tex, const float texvec[3], TexResult *texres) texres->tin *= texres->tin; } } - else if (tex->stype == TEX_EASE) { /* ease */ + else if (tex->stype == TEX_EASE) { /* Ease. */ texres->tin = (1.0f + x) / 2.0f; if (texres->tin <= 0.0f) { texres->tin = 0.0f; @@ -127,10 +127,10 @@ static int blend(const Tex *tex, const float texvec[3], TexResult *texres) texres->tin = (3.0f * t - 2.0f * t * texres->tin); } } - else if (tex->stype == TEX_DIAG) { /* diag */ + else if (tex->stype == TEX_DIAG) { /* Diagonal. */ texres->tin = (2.0f + x + y) / 4.0f; } - else if (tex->stype == TEX_RAD) { /* radial */ + else if (tex->stype == TEX_RAD) { /* Radial. */ texres->tin = (atan2f(y, x) / (float)(2 * M_PI) + 0.5f); } else { /* sphere TEX_SPHERE */ @@ -139,7 +139,7 @@ static int blend(const Tex *tex, const float texvec[3], TexResult *texres) texres->tin = 0.0f; } if (tex->stype == TEX_HALO) { - texres->tin *= texres->tin; /* halo */ + texres->tin *= texres->tin; /* Halo. */ } } diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c index aa433eeed09..01211aeeec6 100644 --- a/source/blender/sequencer/intern/effects.c +++ b/source/blender/sequencer/intern/effects.c @@ -58,6 +58,10 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type); +/* -------------------------------------------------------------------- */ +/** \name Internal Utilities + * \{ */ + static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, @@ -108,7 +112,11 @@ static void slice_get_float_buffers(const SeqRenderData *context, } } -/*********************** Glow effect *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Glow Effect + * \{ */ enum { GlowR = 0, @@ -178,7 +186,11 @@ static ImBuf *prepare_effect_imbufs(const SeqRenderData *context, return out; } -/*********************** Alpha Over *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Alpha Over Effect + * \{ */ static void init_alpha_over_or_under(Sequence *seq) { @@ -288,7 +300,11 @@ static void do_alphaover_effect(const SeqRenderData *context, } } -/*********************** Alpha Under *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Alpha Under Effect + * \{ */ static void do_alphaunder_effect_byte( float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) @@ -405,7 +421,11 @@ static void do_alphaunder_effect(const SeqRenderData *context, } } -/*********************** Cross *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cross Effect + * \{ */ static void do_cross_effect_byte( float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) @@ -482,7 +502,11 @@ static void do_cross_effect(const SeqRenderData *context, } } -/*********************** Gamma Cross *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Gamma Cross + * \{ */ /* copied code from initrender.c */ static unsigned short gamtab[65536]; @@ -726,7 +750,11 @@ static void do_gammacross_effect(const SeqRenderData *context, } } -/*********************** Add *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Color Add Effect + * \{ */ static void do_add_effect_byte( float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) @@ -802,7 +830,11 @@ static void do_add_effect(const SeqRenderData *context, } } -/*********************** Sub *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Color Subtract Effect + * \{ */ static void do_sub_effect_byte( float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) @@ -880,7 +912,11 @@ static void do_sub_effect(const SeqRenderData *context, } } -/*********************** Drop *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Drop Effect + * \{ */ /* Must be > 0 or add precopy, etc to the function */ #define XOFF 8 @@ -954,7 +990,11 @@ static void do_drop_effect_float( memcpy(out, rt1, sizeof(*out) * yoff * 4 * x); } -/*********************** Mul *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Multiply Effect + * \{ */ static void do_mul_effect_byte( float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) @@ -1035,7 +1075,12 @@ static void do_mul_effect(const SeqRenderData *context, } } -/*********************** Blend Mode ***************************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Blend Mode Effect + * \{ */ + typedef void (*IMB_blend_func_byte)(unsigned char *dst, const unsigned char *src1, const unsigned char *src2); @@ -1268,7 +1313,13 @@ static void do_blend_mode_effect(const SeqRenderData *context, fac, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out); } } -/*********************** Color Mix Effect *************************/ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Color Mix Effect + * \{ */ + static void init_colormix_effect(Sequence *seq) { ColorMixVars *data; @@ -1314,7 +1365,11 @@ static void do_colormix_effect(const SeqRenderData *context, } } -/*********************** Wipe *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Wipe Effect + * \{ */ typedef struct WipeZone { float angle; @@ -1334,7 +1389,9 @@ static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo wipezone->pythangle = 1.0f / sqrtf(wipezone->angle * wipezone->angle + 1.0f); } -/* This function calculates the blur band for the wipe effects */ +/** + * This function calculates the blur band for the wipe effects. + */ static float in_band(float width, float dist, int side, int dir) { float alpha; @@ -1757,7 +1814,11 @@ static ImBuf *do_wipe_effect(const SeqRenderData *context, return out; } -/*********************** Transform *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform Effect + * \{ */ static void init_transform_effect(Sequence *seq) { @@ -1909,7 +1970,11 @@ static void do_transform_effect(const SeqRenderData *context, transform->interpolation); } -/*********************** Glow *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Glow Effect + * \{ */ static void RVBlurBitmap2_float(float *map, int width, int height, float blur, int quality) { @@ -2229,7 +2294,11 @@ static ImBuf *do_glow_effect(const SeqRenderData *context, return out; } -/*********************** Solid color *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Solid Color Effect + * \{ */ static void init_solid_color(Sequence *seq) { @@ -2324,9 +2393,13 @@ static ImBuf *do_solid_color(const SeqRenderData *context, return out; } -/*********************** Mulitcam *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Multi-Camera Effect + * \{ */ -/* no effect inputs for multicam, we use give_ibuf_seq */ +/** No effect inputs for multi-camera, we use #give_ibuf_seq. */ static int num_inputs_multicam(void) { return 0; @@ -2367,9 +2440,13 @@ static ImBuf *do_multicam(const SeqRenderData *context, return out; } -/*********************** Adjustment *************************/ +/** \} */ -/* no effect inputs for adjustment, we use give_ibuf_seq */ +/* -------------------------------------------------------------------- */ +/** \name Adjustment Effect + * \{ */ + +/** No effect inputs for adjustment, we use #give_ibuf_seq. */ static int num_inputs_adjustment(void) { return 0; @@ -2438,7 +2515,11 @@ static ImBuf *do_adjustment(const SeqRenderData *context, return out; } -/*********************** Speed *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Speed Effect + * \{ */ static void init_speed_effect(Sequence *seq) { @@ -2639,7 +2720,11 @@ static ImBuf *do_speed_effect(const SeqRenderData *context, return IMB_dupImBuf(ibuf1); } -/*********************** overdrop *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Over-Drop Effect + * \{ */ static void do_overdrop_effect(const SeqRenderData *context, Sequence *UNUSED(seq), @@ -2675,7 +2760,11 @@ static void do_overdrop_effect(const SeqRenderData *context, } } -/*********************** Gaussian Blur *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Gaussian Blur + * \{ */ /* NOTE: This gaussian blur implementation accumulates values in the square * kernel rather that doing X direction and then Y direction because of the @@ -3099,7 +3188,11 @@ static ImBuf *do_gaussian_blur_effect(const SeqRenderData *context, return out; } -/*********************** text *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Text Effect + * \{ */ static void init_text_effect(Sequence *seq) { @@ -3341,7 +3434,11 @@ static ImBuf *do_text_effect(const SeqRenderData *context, return out; } -/*********************** sequence effect factory *************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sequence Effect Factory + * \{ */ static void init_noop(Sequence *UNUSED(seq)) { @@ -3592,6 +3689,12 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) return rval; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public Sequencer Effect API + * \{ */ + struct SeqEffectHandle SEQ_effect_handle_get(Sequence *seq) { struct SeqEffectHandle rval = {false, false, NULL}; @@ -3639,3 +3742,5 @@ int SEQ_effect_get_num_inputs(int seq_type) } return 0; } + +/** \} */ diff --git a/source/blender/sequencer/intern/effects.h b/source/blender/sequencer/intern/effects.h index 573f8df4352..c15701a2047 100644 --- a/source/blender/sequencer/intern/effects.h +++ b/source/blender/sequencer/intern/effects.h @@ -15,13 +15,6 @@ struct Scene; struct SeqRenderData; struct Sequence; -/* ********************************************************************** - * sequencer.c - * - * Sequencer editing functions - * ********************************************************************** - */ - struct SeqEffectHandle seq_effect_get_sequence_blend(struct Sequence *seq); /** * Build frame map when speed in mode #SEQ_SPEED_MULTIPLY is animated. diff --git a/source/blender/shader_fx/intern/FX_ui_common.c b/source/blender/shader_fx/intern/FX_ui_common.c index 3770b796c4d..4c9eaa11ab6 100644 --- a/source/blender/shader_fx/intern/FX_ui_common.c +++ b/source/blender/shader_fx/intern/FX_ui_common.c @@ -50,7 +50,7 @@ static void shaderfx_reorder(bContext *C, Panel *panel, int new_index) WM_operator_properties_create_ptr(&props_ptr, ot); RNA_string_set(&props_ptr, "shaderfx", fx->name); RNA_int_set(&props_ptr, "index", new_index); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL); WM_operator_properties_free(&props_ptr); } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index aa380928082..7959c3d6f0b 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -242,11 +242,12 @@ void WM_window_set_dpi(const wmWindow *win); bool WM_stereo3d_enabled(struct wmWindow *win, bool only_fullscreen_test); -/* files */ +/* wm_files.c */ + void WM_file_autoexec_init(const char *filepath); bool WM_file_read(struct bContext *C, const char *filepath, struct ReportList *reports); -void WM_autosave_init(struct wmWindowManager *wm); -bool WM_recover_last_session(struct bContext *C, struct ReportList *reports); +void WM_file_autosave_init(struct wmWindowManager *wm); +bool WM_file_recover_last_session(struct bContext *C, struct ReportList *reports); void WM_file_tag_modified(void); /** @@ -615,7 +616,8 @@ bool WM_operator_poll_context(struct bContext *C, struct wmOperatorType *ot, sho /** * For running operators with frozen context (modal handlers, menus). * - * \param store: Store settings for re-use. + * \param store: Store properties for re-use when an operator has finished + * (unless #PROP_SKIP_SAVE is set). * * \warning do not use this within an operator to call itself! T29537. */ @@ -644,19 +646,29 @@ bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op bool WM_operator_name_poll(struct bContext *C, const char *opstring); /** * Invokes operator in context. + * + * \param event: Optionally pass in an event to use when context uses one of the + * `WM_OP_INVOKE_*` values. When left unset the #wmWindow.eventstate will be used, + * this can cause problems for operators that read the events type - for example, + * storing the key that was pressed so as to be able to detect it's release. + * In these cases it's necessary to forward the current event being handled. */ int WM_operator_name_call_ptr(struct bContext *C, struct wmOperatorType *ot, wmOperatorCallContext context, - struct PointerRNA *properties); + struct PointerRNA *properties, + const wmEvent *event); +/** See #WM_operator_name_call_ptr */ int WM_operator_name_call(struct bContext *C, const char *opstring, wmOperatorCallContext context, - struct PointerRNA *properties); + struct PointerRNA *properties, + const wmEvent *event); int WM_operator_name_call_with_properties(struct bContext *C, const char *opstring, wmOperatorCallContext context, - struct IDProperty *properties); + struct IDProperty *properties, + const wmEvent *event); /** * Similar to #WM_operator_name_call called with #WM_OP_EXEC_DEFAULT context. * @@ -675,6 +687,7 @@ void WM_operator_name_call_ptr_with_depends_on_cursor(struct bContext *C, wmOperatorType *ot, wmOperatorCallContext opcontext, PointerRNA *properties, + const wmEvent *event, const char *drawstr); /** @@ -1453,6 +1466,9 @@ bool WM_cursor_test_motion_and_update(const int mval[2]) ATTR_NONNULL(1) ATTR_WA int WM_event_drag_threshold(const struct wmEvent *event); bool WM_event_drag_test(const struct wmEvent *event, const int prev_xy[2]); bool WM_event_drag_test_with_delta(const struct wmEvent *event, const int delta[2]); +void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2]); +void WM_event_drag_start_mval_fl(const wmEvent *event, const ARegion *region, float r_mval[2]); +void WM_event_drag_start_xy(const wmEvent *event, int r_xy[2]); /** * Event map that takes preferences into account. diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index d7fe34a3b4c..9edbafafdd3 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -238,6 +238,7 @@ enum { KM_SHIFT = (1 << 0), KM_CTRL = (1 << 1), KM_ALT = (1 << 2), + /** Use for Windows-Key on MS-Windows, Command-key on macOS and Super on Linux. */ KM_OSKEY = (1 << 3), /* Used for key-map item creation function arguments. */ @@ -267,6 +268,10 @@ enum { KM_RELEASE = 2, KM_CLICK = 3, KM_DBL_CLICK = 4, + /** + * \note The cursor location at the point dragging starts is set to #wmEvent.prev_press_xy + * some operators such as box selection should use this location instead of #wmEvent.xy. + */ KM_CLICK_DRAG = 5, }; @@ -605,6 +610,11 @@ typedef enum eWM_EventFlag { * See #KMI_REPEAT_IGNORE for details on how key-map handling uses this. */ WM_EVENT_IS_REPEAT = (1 << 1), + /** + * Mouse-move events may have this flag set to force creating a click-drag event + * even when the threshold has not been met. + */ + WM_EVENT_FORCE_DRAG_THRESHOLD = (1 << 2), } eWM_EventFlag; typedef struct wmTabletData { @@ -625,23 +635,39 @@ typedef struct wmTabletData { * event comes from event manager and from keymap. * * - * Previous State - * ============== - * - * Events hold information about the previous event, - * this is used for detecting click and double-click events (the timer is needed for double-click). - * See #wm_event_add_ghostevent for implementation details. + * Previous State (`prev_*`) + * ========================= * - * Notes: + * Events hold information about the previous event. * - * - The previous values are only set for mouse button and keyboard events. - * See: #ISMOUSE_BUTTON & #ISKEYBOARD macros. + * - Previous values are only set for events types that generate #KM_PRESS. + * See: #ISKEYBOARD_OR_BUTTON. * * - Previous x/y are exceptions: #wmEvent.prev * these are set on mouse motion, see #MOUSEMOVE & track-pad events. * * - Modal key-map handling sets `prev_val` & `prev_type` to `val` & `type`, * this allows modal keys-maps to check the original values (needed in some cases). + * + * + * Press State (`prev_press_*`) + * ============================ + * + * Events hold information about the state when the last #KM_PRESS event was added. + * This is used for generating #KM_CLICK, #KM_DBL_CLICK & #KM_CLICK_DRAG events. + * See #wm_handlers_do for the implementation. + * + * - Previous values are only set when a #KM_PRESS event is detected. + * See: #ISKEYBOARD_OR_BUTTON. + * + * - The reason to differentiate between "press" and the previous event state is + * the previous event may be set by key-release events. In the case of a single key click + * this isn't a problem however releasing other keys such as modifiers prevents click/click-drag + * events from being detected, see: T89989. + * + * - Mouse-wheel events are excluded even though they generate #KM_PRESS + * as clicking and dragging don't make sense for mouse wheel events. + * */ typedef struct wmEvent { struct wmEvent *next, *prev; @@ -663,38 +689,16 @@ typedef struct wmEvent { /** From ghost, fallback if utf8 isn't set. */ char ascii; - /** The previous value of `type`. */ - short prev_type; - /** The previous value of `val`. */ - short prev_val; - /** - * The previous value of #wmEvent.xy, - * Unlike other previous state variables, this is set on any mouse motion. - * Use `prev_click` for the value at time of pressing. - */ - int prev_xy[2]; - - /** The `type` at the point of the click action. */ - short prev_click_type; - /** The time when the key is pressed, see #PIL_check_seconds_timer. */ - double prev_click_time; - /** The location when the key is pressed (used to enforce drag thresholds). */ - int prev_click_xy[2]; - /** The `modifier` at the point of the click action. */ - uint8_t prev_click_modifier; - /** The `keymodifier` at the point of the click action. */ - short prev_click_keymodifier; - - /** - * Modifier states. - * #KM_SHIFT, #KM_CTRL, #KM_ALT & #KM_OSKEY is apple or windows-key. - */ + /** Modifier states: #KM_SHIFT, #KM_CTRL, #KM_ALT & #KM_OSKEY. */ uint8_t modifier; /** The direction (for #KM_CLICK_DRAG events only). */ int8_t direction; - /** Raw-key modifier (allow using any key as a modifier). */ + /** + * Raw-key modifier (allow using any key as a modifier). + * Compatible with values in `type`. + */ short keymodifier; /** Tablet info, available for mouse move and button events. */ @@ -703,11 +707,44 @@ typedef struct wmEvent { eWM_EventFlag flag; /* Custom data. */ - /** Custom data type, stylus, 6dof, see wm_event_types.h */ + + /** Custom data type, stylus, 6-DOF, see `wm_event_types.h`. */ short custom; short customdata_free; /** Ascii, unicode, mouse-coords, angles, vectors, NDOF data, drag-drop info. */ void *customdata; + + /* Previous State. */ + + /** The previous value of `type`. */ + short prev_type; + /** The previous value of `val`. */ + short prev_val; + /** + * The previous value of #wmEvent.xy, + * Unlike other previous state variables, this is set on any mouse motion. + * Use `prev_press_*` for the value at time of pressing. + */ + int prev_xy[2]; + + /* Previous Press State (when `val == KM_PRESS`). */ + + /** The `type` at the point of the press action. */ + short prev_press_type; + /** + * The location when the key is pressed. + * used to enforce drag threshold & calculate the `direction`. + */ + int prev_press_xy[2]; + /** The `modifier` at the point of the press action. */ + uint8_t prev_press_modifier; + /** The `keymodifier` at the point of the press action. */ + short prev_press_keymodifier; + /** + * The time when the key is pressed, see #PIL_check_seconds_timer. + * Used to detect double-click events. + */ + double prev_press_time; } wmEvent; /** diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_api.h b/source/blender/windowmanager/gizmo/WM_gizmo_api.h index 6b497c7462a..fe73daeed29 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_api.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_api.h @@ -92,7 +92,10 @@ struct PointerRNA *WM_gizmo_operator_set(struct wmGizmo *gz, int part_index, struct wmOperatorType *ot, struct IDProperty *properties); -int WM_gizmo_operator_invoke(struct bContext *C, struct wmGizmo *gz, struct wmGizmoOpElem *gzop); +int WM_gizmo_operator_invoke(struct bContext *C, + struct wmGizmo *gz, + struct wmGizmoOpElem *gzop, + const struct wmEvent *event); /* Callbacks. */ diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c index 05564f3bd0a..db4926f3430 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c @@ -225,7 +225,7 @@ PointerRNA *WM_gizmo_operator_set(wmGizmo *gz, return &gzop->ptr; } -int WM_gizmo_operator_invoke(bContext *C, wmGizmo *gz, wmGizmoOpElem *gzop) +int WM_gizmo_operator_invoke(bContext *C, wmGizmo *gz, wmGizmoOpElem *gzop, const wmEvent *event) { if (gz->flag & WM_GIZMO_OPERATOR_TOOL_INIT) { /* Merge toolsettings into the gizmo properties. */ @@ -239,7 +239,7 @@ int WM_gizmo_operator_invoke(bContext *C, wmGizmo *gz, wmGizmoOpElem *gzop) IDP_MergeGroup(gzop->ptr.data, tref_ptr.data, false); } } - return WM_operator_name_call_ptr(C, gzop->type, WM_OP_INVOKE_DEFAULT, &gzop->ptr); + return WM_operator_name_call_ptr(C, gzop->type, WM_OP_INVOKE_DEFAULT, &gzop->ptr, event); } static void wm_gizmo_set_matrix_rotation_from_z_axis__internal(float matrix[4][4], @@ -425,7 +425,7 @@ void WM_gizmo_modal_set_from_setup(struct wmGizmoMap *gzmap, } else { /* WEAK: but it works. */ - WM_operator_name_call(C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_DEFAULT, NULL, event); } } diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c index b3ef9b27667..00615d9d662 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c @@ -441,7 +441,7 @@ static bool gizmo_tweak_start_and_finish( gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz, event); } /* Allow for 'button' gizmos, single click to run an action. */ - WM_gizmo_operator_invoke(C, gz, gzop); + WM_gizmo_operator_invoke(C, gz, gzop, event); } return true; } @@ -1137,7 +1137,7 @@ void WM_gizmo_group_refresh(const bContext *C, wmGizmoGroup *gzgroup) BLI_assert(region->gizmo_map == gzmap); /* Check if the tweak event originated from this region. */ if ((win->eventstate != NULL) && (win->event_queue_check_drag) && - BLI_rcti_isect_pt_v(®ion->winrct, win->eventstate->prev_click_xy)) { + BLI_rcti_isect_pt_v(®ion->winrct, win->eventstate->prev_press_xy)) { /* We need to run refresh again. */ gzgroup->init_flag &= ~WM_GIZMOGROUP_INIT_REFRESH; WM_gizmomap_tag_refresh_drawstep(gzmap, WM_gizmomap_drawstep_from_gizmo_group(gzgroup)); diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index f1ac19f4651..d9f4050c8f1 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -815,6 +815,14 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap, BLI_buffer_declare_static(wmGizmo *, visible_3d_gizmos, BLI_BUFFER_NOP, 128); bool do_step[WM_GIZMOMAP_DRAWSTEP_MAX]; + int mval[2]; + if (event->val == KM_CLICK_DRAG) { + WM_event_drag_start_mval(event, CTX_wm_region(C), mval); + } + else { + copy_v2_v2_int(mval, event->mval); + } + for (int i = 0; i < ARRAY_SIZE(do_step); i++) { do_step[i] = WM_gizmo_context_check_drawstep(C, i); } @@ -841,7 +849,7 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap, } else if (step == WM_GIZMOMAP_DRAWSTEP_2D) { if ((gz = wm_gizmogroup_find_intersected_gizmo( - wm, gzgroup, C, event->modifier, event->mval, r_part))) { + wm, gzgroup, C, event->modifier, mval, r_part))) { break; } } @@ -853,7 +861,7 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap, /* 2D gizmos get priority. */ if (gz == NULL) { gz = gizmo_find_intersected_3d( - C, event->mval, visible_3d_gizmos.data, visible_3d_gizmos.count, r_part); + C, mval, visible_3d_gizmos.data, visible_3d_gizmos.count, r_part); } } BLI_buffer_free(&visible_3d_gizmos); @@ -1149,7 +1157,7 @@ void wm_gizmomap_modal_set( struct wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, gz->highlight_part); if (gzop && gzop->type) { - const int retval = WM_gizmo_operator_invoke(C, gz, gzop); + const int retval = WM_gizmo_operator_invoke(C, gz, gzop, event); if ((retval & OPERATOR_RUNNING_MODAL) == 0) { wm_gizmomap_modal_set(gzmap, C, gz, event, false); } diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index a55f5af03d1..40d9b0b9a35 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -155,6 +155,7 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id) win->ghostwin = NULL; win->gpuctx = NULL; win->eventstate = NULL; + win->event_last_handled = NULL; win->cursor_keymap_status = NULL; #if defined(WIN32) || defined(__APPLE__) win->ime_data = NULL; @@ -484,7 +485,7 @@ void WM_check(bContext *C) /* Case: file-read. */ if ((wm->initialized & WM_WINDOW_IS_INIT) == 0) { WM_keyconfig_init(C); - WM_autosave_init(wm); + WM_file_autosave_init(wm); } /* Case: no open windows at all, for old file reads. */ diff --git a/source/blender/windowmanager/intern/wm_event_query.c b/source/blender/windowmanager/intern/wm_event_query.c index ee13e1832ed..9a7d31f8bb8 100644 --- a/source/blender/windowmanager/intern/wm_event_query.c +++ b/source/blender/windowmanager/intern/wm_event_query.c @@ -227,8 +227,8 @@ bool WM_event_is_mouse_drag_or_press(const wmEvent *event) int WM_event_drag_direction(const wmEvent *event) { const int delta[2] = { - event->xy[0] - event->prev_click_xy[0], - event->xy[1] - event->prev_click_xy[1], + event->xy[0] - event->prev_press_xy[0], + event->xy[1] - event->prev_press_xy[1], }; int theta = round_fl_to_int(4.0f * atan2f((float)delta[1], (float)delta[0]) / (float)M_PI); @@ -306,8 +306,8 @@ bool WM_cursor_test_motion_and_update(const int mval[2]) int WM_event_drag_threshold(const struct wmEvent *event) { int drag_threshold; - if (ISMOUSE(event->prev_click_type)) { - BLI_assert(event->prev_click_type != MOUSEMOVE); + if (ISMOUSE(event->prev_press_type)) { + BLI_assert(event->prev_press_type != MOUSEMOVE); /* Using the previous type is important is we want to check the last pressed/released button, * The `event->type` would include #MOUSEMOVE which is always the case when dragging * and does not help us know which threshold to use. */ @@ -338,6 +338,25 @@ bool WM_event_drag_test(const wmEvent *event, const int prev_xy[2]) return WM_event_drag_test_with_delta(event, drag_delta); } +void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2]) +{ + const int *xy = (event->val == KM_CLICK_DRAG) ? event->prev_press_xy : event->xy; + r_mval[0] = xy[0] - region->winrct.xmin; + r_mval[1] = xy[1] - region->winrct.ymin; +} + +void WM_event_drag_start_mval_fl(const wmEvent *event, const ARegion *region, float r_mval[2]) +{ + const int *xy = (event->val == KM_CLICK_DRAG) ? event->prev_press_xy : event->xy; + r_mval[0] = xy[0] - region->winrct.xmin; + r_mval[1] = xy[1] - region->winrct.ymin; +} + +void WM_event_drag_start_xy(const wmEvent *event, int r_xy[2]) +{ + copy_v2_v2_int(r_xy, (event->val == KM_CLICK_DRAG) ? event->prev_press_xy : event->xy); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 0e262f8c388..62aeb8a2928 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -97,9 +97,10 @@ static int wm_operator_call_internal(bContext *C, ReportList *reports, const wmOperatorCallContext context, const bool poll_only, - wmEvent *event); + const wmEvent *event); static bool wm_operator_check_locked_interface(bContext *C, wmOperatorType *ot); +static wmEvent *wm_event_add_mousemove_to_head(wmWindow *win); /* -------------------------------------------------------------------- */ /** \name Event Management @@ -145,7 +146,7 @@ wmEvent *WM_event_add_simulate(wmWindow *win, const wmEvent *event_to_add) copy_v2_v2_int(win->eventstate->prev_xy, win->eventstate->xy); copy_v2_v2_int(event->prev_xy, win->eventstate->xy); } - else if (ISMOUSE_BUTTON(event->type) || ISKEYBOARD(event->type)) { + else if (ISKEYBOARD_OR_BUTTON(event->type)) { win->eventstate->prev_val = event->prev_val = win->eventstate->val; win->eventstate->prev_type = event->prev_type = win->eventstate->type; @@ -154,13 +155,36 @@ wmEvent *WM_event_add_simulate(wmWindow *win, const wmEvent *event_to_add) if (event->val == KM_PRESS) { if ((event->flag & WM_EVENT_IS_REPEAT) == 0) { - copy_v2_v2_int(win->eventstate->prev_click_xy, event->xy); + copy_v2_v2_int(win->eventstate->prev_press_xy, event->xy); } } } return event; } +static void wm_event_custom_free(wmEvent *event) +{ + if ((event->customdata && event->customdata_free) == 0) { + return; + } + + /* NOTE: pointer to #ListBase struct elsewhere. */ + if (event->custom == EVT_DATA_DRAGDROP) { + ListBase *lb = event->customdata; + WM_drag_free_list(lb); + } + else { + MEM_freeN(event->customdata); + } +} + +static void wm_event_custom_clear(wmEvent *event) +{ + event->custom = 0; + event->customdata = NULL; + event->customdata_free = false; +} + void wm_event_free(wmEvent *event) { #ifndef NDEBUG @@ -172,22 +196,35 @@ void wm_event_free(wmEvent *event) } #endif - if (event->customdata) { - if (event->customdata_free) { - /* NOTE: pointer to #ListBase struct elsewhere. */ - if (event->custom == EVT_DATA_DRAGDROP) { - ListBase *lb = event->customdata; - WM_drag_free_list(lb); - } - else { - MEM_freeN(event->customdata); - } - } - } + wm_event_custom_free(event); MEM_freeN(event); } +/** A version of #wm_event_free that holds the last handled event. */ +static void wm_event_free_last_handled(wmWindow *win, wmEvent *event) +{ + /* Don't rely on this pointer being valid, + * callers should behave as if the memory has been freed. + * As this function should be interchangeable with #wm_event_free. */ +#ifndef NDEBUG + { + wmEvent *event_copy = MEM_dupallocN(event); + MEM_freeN(event); + event = event_copy; + } +#endif + + if (win->event_last_handled) { + wm_event_free(win->event_last_handled); + } + /* Don't store custom data in the last handled event as we don't have control how long this event + * will be stored and the referenced data may become invalid (also it's not needed currently). */ + wm_event_custom_free(event); + wm_event_custom_clear(event); + win->event_last_handled = event; +} + static void wm_event_free_last(wmWindow *win) { wmEvent *event = BLI_poptail(&win->event_queue); @@ -1276,7 +1313,7 @@ static void wm_region_mouse_co(bContext *C, wmEvent *event) */ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, - wmEvent *event, + const wmEvent *event, PointerRNA *properties, ReportList *reports, const bool poll_only, @@ -1317,7 +1354,9 @@ static int wm_operator_invoke(bContext *C, } if (op->type->invoke && event) { - wm_region_mouse_co(C, event); + /* Temporarily write into `mval` (not technically `const` correct) but this is restored. */ + int mval_prev[2] = {UNPACK2(event->mval)}; + wm_region_mouse_co(C, (wmEvent *)event); if (op->type->flag & OPTYPE_UNDO) { wm->op_undo_depth++; @@ -1329,6 +1368,8 @@ static int wm_operator_invoke(bContext *C, if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) { wm->op_undo_depth--; } + + copy_v2_v2_int(((wmEvent *)event)->mval, mval_prev); } else if (op->type->exec) { if (op->type->flag & OPTYPE_UNDO) { @@ -1440,7 +1481,7 @@ static int wm_operator_call_internal(bContext *C, ReportList *reports, const wmOperatorCallContext context, const bool poll_only, - wmEvent *event) + const wmEvent *event) { int retval; @@ -1572,19 +1613,21 @@ static int wm_operator_call_internal(bContext *C, int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, - PointerRNA *properties) + PointerRNA *properties, + const wmEvent *event) { BLI_assert(ot == WM_operatortype_find(ot->idname, true)); - return wm_operator_call_internal(C, ot, properties, NULL, context, false, NULL); + return wm_operator_call_internal(C, ot, properties, NULL, context, false, event); } int WM_operator_name_call(bContext *C, const char *opstring, wmOperatorCallContext context, - PointerRNA *properties) + PointerRNA *properties, + const wmEvent *event) { wmOperatorType *ot = WM_operatortype_find(opstring, 0); if (ot) { - return WM_operator_name_call_ptr(C, ot, context, properties); + return WM_operator_name_call_ptr(C, ot, context, properties, event); } return 0; @@ -1603,12 +1646,13 @@ bool WM_operator_name_poll(bContext *C, const char *opstring) int WM_operator_name_call_with_properties(struct bContext *C, const char *opstring, wmOperatorCallContext context, - struct IDProperty *properties) + struct IDProperty *properties, + const wmEvent *event) { PointerRNA props_ptr; wmOperatorType *ot = WM_operatortype_find(opstring, false); RNA_pointer_create(G_MAIN->wm.first, ot->srna, properties, &props_ptr); - return WM_operator_name_call_ptr(C, ot, context, &props_ptr); + return WM_operator_name_call_ptr(C, ot, context, &props_ptr, event); } void WM_menu_name_call(bContext *C, const char *menu_name, short context) @@ -1617,7 +1661,7 @@ void WM_menu_name_call(bContext *C, const char *menu_name, short context) PointerRNA ptr; WM_operator_properties_create_ptr(&ptr, ot); RNA_string_set(&ptr, "name", menu_name); - WM_operator_name_call_ptr(C, ot, context, &ptr); + WM_operator_name_call_ptr(C, ot, context, &ptr, NULL); WM_operator_properties_free(&ptr); } @@ -1729,7 +1773,8 @@ static int ui_handler_wait_for_input(bContext *C, const wmEvent *event, void *us WM_operator_name_call_ptr(C, opwait->optype_params.optype, opwait->optype_params.opcontext, - opwait->optype_params.opptr); + opwait->optype_params.opptr, + event); CTX_store_set(C, NULL); } @@ -1751,6 +1796,7 @@ void WM_operator_name_call_ptr_with_depends_on_cursor(bContext *C, wmOperatorType *ot, wmOperatorCallContext opcontext, PointerRNA *properties, + const wmEvent *event, const char *drawstr) { int flag = ot->flag; @@ -1763,7 +1809,7 @@ void WM_operator_name_call_ptr_with_depends_on_cursor(bContext *C, } if ((flag & OPTYPE_DEPENDS_ON_CURSOR) == 0) { - WM_operator_name_call_ptr(C, ot, opcontext, properties); + WM_operator_name_call_ptr(C, ot, opcontext, properties, event); return; } @@ -3062,8 +3108,7 @@ static int wm_handlers_do_intern(bContext *C, wmWindow *win, wmEvent *event, Lis WM_drag_free_list(lb); WM_drag_free_list(&single_lb); - event->customdata = NULL; - event->custom = 0; + wm_event_custom_clear(event); wm_drop_end(C, drag, drop); @@ -3165,21 +3210,22 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) * in `action` setting #WM_HANDLER_HANDLED, but not #WM_HANDLER_BREAK. */ if ((action & WM_HANDLER_BREAK) == 0 || wm_action_not_handled(action)) { if (win->event_queue_check_drag) { - if (WM_event_drag_test(event, event->prev_click_xy)) { + if ((event->flag & WM_EVENT_FORCE_DRAG_THRESHOLD) || + WM_event_drag_test(event, event->prev_press_xy)) { win->event_queue_check_drag_handled = true; const int direction = WM_event_drag_direction(event); - const int prev_xy[2] = {UNPACK2(event->xy)}; + /* Intentionally leave `event->xy` as-is, event users are expected to use + * `event->prev_press_xy` if they need to access the drag start location. */ const short prev_val = event->val; const short prev_type = event->type; const uint8_t prev_modifier = event->modifier; const short prev_keymodifier = event->keymodifier; - copy_v2_v2_int(event->xy, event->prev_click_xy); event->val = KM_CLICK_DRAG; - event->type = event->prev_click_type; - event->modifier = event->prev_click_modifier; - event->keymodifier = event->prev_click_keymodifier; + event->type = event->prev_press_type; + event->modifier = event->prev_press_modifier; + event->keymodifier = event->prev_press_keymodifier; event->direction = direction; CLOG_INFO(WM_LOG_HANDLERS, 1, "handling PRESS_DRAG"); @@ -3191,7 +3237,6 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) event->modifier = prev_modifier; event->val = prev_val; event->type = prev_type; - copy_v2_v2_int(event->xy, prev_xy); win->event_queue_check_click = false; if (!((action & WM_HANDLER_BREAK) == 0 || wm_action_not_handled(action))) { @@ -3205,7 +3250,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) win->event_queue_check_drag = false; } } - else if (ISMOUSE_BUTTON(event->type) || ISKEYBOARD(event->type)) { + else if (ISKEYBOARD_OR_BUTTON(event->type)) { /* All events that don't set #wmEvent.prev_type must be ignored. */ /* Test for CLICK events. */ @@ -3222,8 +3267,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) } else if (event->val == KM_RELEASE) { if (win->event_queue_check_drag) { - if ((event->prev_click_type != event->type) && - (ISKEYMODIFIER(event->type) || (event->type == event->prev_click_keymodifier))) { + if ((event->prev_press_type != event->type) && + (ISKEYMODIFIER(event->type) || (event->type == event->prev_press_keymodifier))) { /* Support releasing modifier keys without canceling the drag event, see T89989. */ } else { @@ -3232,12 +3277,12 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) } } - if (event->prev_click_type == event->type) { + if (event->prev_press_type == event->type) { if (event->val == KM_RELEASE) { if (event->prev_val == KM_PRESS) { if (win->event_queue_check_click == true) { - if (WM_event_drag_test(event, event->prev_click_xy)) { + if (WM_event_drag_test(event, event->prev_press_xy)) { win->event_queue_check_click = false; win->event_queue_check_drag = false; } @@ -3246,7 +3291,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) * accurate selecting in case the mouse drifts a little. */ int xy[2] = {UNPACK2(event->xy)}; - copy_v2_v2_int(event->xy, event->prev_click_xy); + copy_v2_v2_int(event->xy, event->prev_press_xy); event->val = KM_CLICK; CLOG_INFO(WM_LOG_HANDLERS, 1, "handling CLICK"); @@ -3406,11 +3451,8 @@ static void wm_event_drag_and_drop_test(wmWindowManager *wm, wmWindow *win, wmEv event->type = EVT_DROP; /* Create custom-data, first free existing. */ - if (event->customdata) { - if (event->customdata_free) { - MEM_freeN(event->customdata); - } - } + wm_event_custom_free(event); + wm_event_custom_clear(event); event->custom = EVT_DATA_DRAGDROP; event->customdata = &wm->drags; @@ -3653,6 +3695,19 @@ void wm_event_do_handlers(bContext *C) while ((event = win->event_queue.first)) { int action = WM_HANDLER_CONTINUE; + /* Force handling drag if a key is pressed even if the drag threshold has not been met. + * Needed so tablet actions (which typically use a larger threshold) can click-drag + * then press keys - activating the drag action early. + * Limit to mouse-buttons drag actions interrupted by pressing any non-mouse button. + * Otherwise pressing two keys on the keyboard will interpret this as a drag action. */ + if (win->event_queue_check_drag) { + if ((event->val == KM_PRESS) && ((event->flag & WM_EVENT_IS_REPEAT) == 0) && + ISKEYBOARD_OR_BUTTON(event->type) && ISMOUSE_BUTTON(event->prev_press_type)) { + event = wm_event_add_mousemove_to_head(win); + event->flag |= WM_EVENT_FORCE_DRAG_THRESHOLD; + } + } + /* Active screen might change during handlers, update pointer. */ screen = WM_window_get_active_screen(win); @@ -3668,7 +3723,7 @@ void wm_event_do_handlers(bContext *C) CLOG_INFO(WM_LOG_HANDLERS, 1, "event filtered due to pie button pressed"); } BLI_remlink(&win->event_queue, event); - wm_event_free(event); + wm_event_free_last_handled(win, event); continue; } @@ -3678,7 +3733,7 @@ void wm_event_do_handlers(bContext *C) if (event->type == EVT_XR_ACTION) { wm_event_handle_xrevent(C, wm, win, event); BLI_remlink(&win->event_queue, event); - wm_event_free(event); + wm_event_free_last_handled(win, event); /* Skip mouse event handling below, which is unnecessary for XR events. */ continue; } @@ -3816,7 +3871,7 @@ void wm_event_do_handlers(bContext *C) /* Un-link and free here, Blender-quit then frees all. */ BLI_remlink(&win->event_queue, event); - wm_event_free(event); + wm_event_free_last_handled(win, event); } /* Only add mouse-move when the event queue was read entirely. */ @@ -4692,11 +4747,11 @@ static bool wm_event_is_double_click(const wmEvent *event) { if ((event->type == event->prev_type) && (event->prev_val == KM_RELEASE) && (event->val == KM_PRESS)) { - if (ISMOUSE(event->type) && WM_event_drag_test(event, event->prev_click_xy)) { + if (ISMOUSE(event->type) && WM_event_drag_test(event, event->prev_press_xy)) { /* Pass. */ } else { - if ((PIL_check_seconds_timer() - event->prev_click_time) * 1000 < U.dbl_click_time) { + if ((PIL_check_seconds_timer() - event->prev_press_time) * 1000 < U.dbl_click_time) { return true; } } @@ -4714,14 +4769,14 @@ static void wm_event_prev_values_set(wmEvent *event, wmEvent *event_state) event->prev_type = event_state->prev_type = event_state->type; } -static void wm_event_prev_click_set(wmEvent *event, wmEvent *event_state) +static void wm_event_prev_click_set(wmEvent *event_state) { - event->prev_click_time = event_state->prev_click_time = PIL_check_seconds_timer(); - event->prev_click_type = event_state->prev_click_type = event_state->type; - event->prev_click_modifier = event_state->prev_click_modifier = event_state->modifier; - event->prev_click_keymodifier = event_state->prev_click_keymodifier = event_state->keymodifier; - event->prev_click_xy[0] = event_state->prev_click_xy[0] = event_state->xy[0]; - event->prev_click_xy[1] = event_state->prev_click_xy[1] = event_state->xy[1]; + event_state->prev_press_time = PIL_check_seconds_timer(); + event_state->prev_press_type = event_state->type; + event_state->prev_press_modifier = event_state->modifier; + event_state->prev_press_keymodifier = event_state->keymodifier; + event_state->prev_press_xy[0] = event_state->xy[0]; + event_state->prev_press_xy[1] = event_state->xy[1]; } static wmEvent *wm_event_add_mousemove(wmWindow *win, const wmEvent *event) @@ -4745,6 +4800,38 @@ static wmEvent *wm_event_add_mousemove(wmWindow *win, const wmEvent *event) return event_new; } +static wmEvent *wm_event_add_mousemove_to_head(wmWindow *win) +{ + /* Use the last handled event instead of `win->eventstate` because the state of the modifiers + * and previous values should be set based on the last state, not using values from the future. + * So this gives an accurate simulation of mouse motion before the next event is handled. */ + const wmEvent *event_last = win->event_last_handled; + + wmEvent tevent; + if (event_last) { + tevent = *event_last; + + tevent.flag = 0; + tevent.ascii = '\0'; + tevent.utf8_buf[0] = '\0'; + + wm_event_custom_clear(&tevent); + } + else { + memset(&tevent, 0x0, sizeof(tevent)); + } + + tevent.type = MOUSEMOVE; + copy_v2_v2_int(tevent.prev_xy, tevent.xy); + + wmEvent *event_new = wm_event_add(win, &tevent); + BLI_remlink(&win->event_queue, event_new); + BLI_addhead(&win->event_queue, event_new); + + copy_v2_v2_int(event_new->prev_xy, event_last->xy); + return event_new; +} + static wmEvent *wm_event_add_trackpad(wmWindow *win, const wmEvent *event, int deltax, int deltay) { /* Ignore in between track-pad events for performance, we only need high accuracy @@ -4765,6 +4852,46 @@ static wmEvent *wm_event_add_trackpad(wmWindow *win, const wmEvent *event, int d return event_new; } +/** + * Update the event-state for any kind of event that supports #KM_PRESS / #KM_RELEASE. + */ +static void wm_event_state_update_and_click_set(const GHOST_TEventType type, + wmEvent *event, + wmEvent *event_state) +{ + BLI_assert(ISKEYBOARD_OR_BUTTON(event->type)); + BLI_assert(ELEM(event->val, KM_PRESS, KM_RELEASE)); + + /* Only copy these flags into the `event_state`. */ + const eWM_EventFlag event_state_flag_mask = WM_EVENT_IS_REPEAT; + + wm_event_prev_values_set(event, event_state); + + /* Copy to event state. */ + event_state->val = event->val; + event_state->type = event->type; + /* It's important only to write into the `event_state` modifier for keyboard + * events because emulate MMB clears one of the modifiers in `event->modifier`, + * making the second press not behave as if the modifier is pressed, see T96279. */ + if (ELEM(type, GHOST_kEventKeyDown, GHOST_kEventKeyUp)) { + event_state->modifier = event->modifier; + } + event_state->flag = (event->flag & event_state_flag_mask); + /* NOTE: It's important that `keymodifier` is handled in the keyboard event handling logic + * since the `event_state` and the `event` are not kept in sync. */ + + /* Double click test. */ + if (wm_event_is_double_click(event)) { + CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click"); + event->val = KM_DBL_CLICK; + } + else if (event->val == KM_PRESS) { + if ((event->flag & WM_EVENT_IS_REPEAT) == 0) { + wm_event_prev_click_set(event_state); + } + } +} + void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void *customdata) { if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) { @@ -4806,15 +4933,13 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void * while not common, avoid a false alarm. */ #ifndef NDEBUG if ((event_state->type || event_state->val) && /* Ignore cleared event state. */ - !(ISMOUSE_BUTTON(event_state->type) || ISKEYBOARD(event_state->type) || - (event_state->type == EVENT_NONE))) { + !(ISKEYBOARD_OR_BUTTON(event_state->type) || (event_state->type == EVENT_NONE))) { CLOG_WARN(WM_LOG_HANDLERS, "Non-keyboard/mouse button found in 'win->eventstate->type = %d'", event_state->type); } if ((event_state->prev_type || event_state->prev_val) && /* Ignore cleared event state. */ - !(ISMOUSE_BUTTON(event_state->prev_type) || ISKEYBOARD(event_state->prev_type) || - (event_state->type == EVENT_NONE))) { + !(ISKEYBOARD_OR_BUTTON(event_state->prev_type) || (event_state->type == EVENT_NONE))) { CLOG_WARN(WM_LOG_HANDLERS, "Non-keyboard/mouse button found in 'win->eventstate->prev_type = %d'", event_state->prev_type); @@ -4924,20 +5049,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void wm_tablet_data_from_ghost(&bd->tablet, &event.tablet); wm_eventemulation(&event, false); - wm_event_prev_values_set(&event, event_state); - - /* Copy to event state. */ - event_state->val = event.val; - event_state->type = event.type; - - /* Double click test. */ - if (wm_event_is_double_click(&event)) { - CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click"); - event.val = KM_DBL_CLICK; - } - if (event.val == KM_PRESS) { - wm_event_prev_click_set(&event, event_state); - } + wm_event_state_update_and_click_set(type, &event, event_state); /* Add to other window if event is there (not to both!). */ wmWindow *win_other = wm_event_cursor_other_windows(wm, win, &event); @@ -4966,9 +5078,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void case GHOST_kEventKeyDown: case GHOST_kEventKeyUp: { GHOST_TEventKeyData *kd = customdata; - /* Only copy these flags into the `event_state`. */ - const eWM_EventFlag event_state_flag_mask = WM_EVENT_IS_REPEAT; - bool keymodifier = 0; event.type = convert_key(kd->key); event.ascii = kd->ascii; /* Might be not NULL terminated. */ @@ -4979,12 +5088,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE; wm_eventemulation(&event, false); - wm_event_prev_values_set(&event, event_state); - - /* Copy to event state. */ - event_state->val = event.val; - event_state->type = event.type; - event_state->flag = (event.flag & event_state_flag_mask); /* Exclude arrow keys, escape, etc from text input. */ if (type == GHOST_kEventKeyUp) { @@ -5017,108 +5120,68 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void switch (event.type) { case EVT_LEFTSHIFTKEY: - case EVT_RIGHTSHIFTKEY: - if (event.val == KM_PRESS) { - keymodifier = true; - } - if (keymodifier) { - event.modifier |= KM_SHIFT; - event_state->modifier |= KM_SHIFT; - } - else { - event.modifier &= ~KM_SHIFT; - event_state->modifier &= ~KM_SHIFT; - } + case EVT_RIGHTSHIFTKEY: { + SET_FLAG_FROM_TEST(event.modifier, (event.val == KM_PRESS), KM_SHIFT); break; + } case EVT_LEFTCTRLKEY: - case EVT_RIGHTCTRLKEY: - if (event.val == KM_PRESS) { - keymodifier = true; - } - if (keymodifier) { - event.modifier |= KM_CTRL; - event_state->modifier |= KM_CTRL; - } - else { - event.modifier &= ~KM_CTRL; - event_state->modifier &= ~KM_CTRL; - } + case EVT_RIGHTCTRLKEY: { + SET_FLAG_FROM_TEST(event.modifier, (event.val == KM_PRESS), KM_CTRL); break; + } case EVT_LEFTALTKEY: - case EVT_RIGHTALTKEY: - if (event.val == KM_PRESS) { - keymodifier = true; - } - if (keymodifier) { - event.modifier |= KM_ALT; - event_state->modifier |= KM_ALT; - } - else { - event.modifier &= ~KM_ALT; - event_state->modifier &= ~KM_ALT; - } + case EVT_RIGHTALTKEY: { + SET_FLAG_FROM_TEST(event.modifier, (event.val == KM_PRESS), KM_ALT); + break; + } + case EVT_OSKEY: { + SET_FLAG_FROM_TEST(event.modifier, (event.val == KM_PRESS), KM_OSKEY); break; - case EVT_OSKEY: + } + default: { if (event.val == KM_PRESS) { - keymodifier = true; - } - if (keymodifier) { - event.modifier |= KM_OSKEY; - event_state->modifier |= KM_OSKEY; + if (event.keymodifier == 0) { + /* Only set in `eventstate`, for next event. */ + event_state->keymodifier = event.type; + } } else { - event.modifier &= ~KM_OSKEY; - event_state->modifier &= ~KM_OSKEY; + BLI_assert(event.val == KM_RELEASE); + if (event.keymodifier == event.type) { + event.keymodifier = event_state->keymodifier = 0; + } } - break; - default: - if (event.val == KM_PRESS && event.keymodifier == 0) { - /* Only set in `eventstate`, for next event. */ - event_state->keymodifier = event.type; + + /* This case happens on holding a key pressed, + * it should not generate press events with the same key as modifier. */ + if (event.keymodifier == event.type) { + event.keymodifier = 0; } - else if (event.val == KM_RELEASE && event.keymodifier == event.type) { - event.keymodifier = event_state->keymodifier = 0; + else if (event.keymodifier == EVT_UNKNOWNKEY) { + /* This case happens with an external number-pad, and also when using 'dead keys' + * (to compose complex latin characters e.g.), it's not really clear why. + * Since it's impossible to map a key modifier to an unknown key, + * it shouldn't harm to clear it. */ + event_state->keymodifier = event.keymodifier = 0; } break; + } } - /* Double click test. */ - /* If previous event was same type, and previous was release, and now it presses... */ - if (wm_event_is_double_click(&event)) { - CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click"); - event.val = KM_DBL_CLICK; - } - - /* This case happens on holding a key pressed, - * it should not generate press events with the same key as modifier. */ - if (event.keymodifier == event.type) { - event.keymodifier = 0; - } - - /* This case happens with an external number-pad, and also when using 'dead keys' - * (to compose complex latin characters e.g.), it's not really clear why. - * Since it's impossible to map a key modifier to an unknown key, - * it shouldn't harm to clear it. */ - if (event.keymodifier == EVT_UNKNOWNKEY) { - event_state->keymodifier = event.keymodifier = 0; - } + /* It's important `event.modifier` has been initialized first. */ + wm_event_state_update_and_click_set(type, &event, event_state); /* If test_break set, it catches this. Do not set with modifier presses. - * XXX Keep global for now? */ - if ((event.type == EVT_ESCKEY && event.val == KM_PRESS) && - /* Check other modifiers because ms-windows uses these to bring up the task manager. */ - ((event.modifier & (KM_SHIFT | KM_CTRL | KM_ALT)) == 0)) { + * Exclude modifiers because MS-Windows uses these to bring up the task manager. + * + * NOTE: in general handling events here isn't great design as + * event handling should be managed by the event handling loop. + * Make an exception for `G.is_break` as it ensures we can always cancel operations + * such as rendering or baking no matter which operation is currently handling events. */ + if ((event.type == EVT_ESCKEY) && (event.val == KM_PRESS) && (event.modifier == 0)) { G.is_break = true; } - /* Double click test - only for press. */ - if (event.val == KM_PRESS) { - /* Don't reset timer & location when holding the key generates repeat events. */ - if ((event.flag & WM_EVENT_IS_REPEAT) == 0) { - wm_event_prev_click_set(&event, event_state); - } - } - wm_event_add(win, &event); break; @@ -5173,11 +5236,15 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void case GHOST_kRelease: event.val = KM_RELEASE; break; + default: + BLI_assert_unreachable(); } event.custom = 0; event.customdata = NULL; + wm_event_state_update_and_click_set(type, &event, event_state); + wm_event_add(win, &event); break; @@ -5230,7 +5297,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void #ifdef WITH_XR_OPENXR void wm_event_add_xrevent(wmWindow *win, wmXrActionData *actiondata, short val) { - BLI_assert(val == KM_PRESS || val == KM_RELEASE); + BLI_assert(ELEM(val, KM_PRESS, KM_RELEASE)); wmEvent event = { .type = EVT_XR_ACTION, diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 7471d41b44c..04ce7bcb520 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -246,7 +246,9 @@ static void wm_window_substitute_old(wmWindowManager *oldwm, oldwin->gpuctx = NULL; win->eventstate = oldwin->eventstate; + win->event_last_handled = oldwin->event_last_handled; oldwin->eventstate = NULL; + oldwin->event_last_handled = NULL; /* Ensure proper screen re-scaling. */ win->sizex = oldwin->sizex; @@ -1966,7 +1968,7 @@ void wm_autosave_timer_end(wmWindowManager *wm) } } -void WM_autosave_init(wmWindowManager *wm) +void WM_file_autosave_init(wmWindowManager *wm) { wm_autosave_timer_begin(wm); } @@ -2422,7 +2424,7 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) static void wm_homefile_read_after_dialog_callback(bContext *C, void *user_data) { WM_operator_name_call_with_properties( - C, "WM_OT_read_homefile", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data); + C, "WM_OT_read_homefile", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data, NULL); } static int wm_homefile_read_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) @@ -2575,7 +2577,7 @@ static int wm_open_mainfile_dispatch(bContext *C, wmOperator *op); static void wm_open_mainfile_after_dialog_callback(bContext *C, void *user_data) { WM_operator_name_call_with_properties( - C, "WM_OT_open_mainfile", WM_OP_INVOKE_DEFAULT, (IDProperty *)user_data); + C, "WM_OT_open_mainfile", WM_OP_INVOKE_DEFAULT, (IDProperty *)user_data, NULL); } static int wm_open_mainfile__discard_changes(bContext *C, wmOperator *op) @@ -2860,7 +2862,7 @@ void WM_OT_revert_mainfile(wmOperatorType *ot) /** \name Recover Last Session Operator * \{ */ -bool WM_recover_last_session(bContext *C, ReportList *reports) +bool WM_file_recover_last_session(bContext *C, ReportList *reports) { char filepath[FILE_MAX]; BLI_join_dirfile(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE); @@ -2874,7 +2876,7 @@ static int wm_recover_last_session_exec(bContext *C, wmOperator *op) { wm_open_init_use_scripts(op, true); SET_FLAG_FROM_TEST(G.f, RNA_boolean_get(op->ptr, "use_scripts"), G_FLAG_SCRIPT_AUTOEXEC); - if (WM_recover_last_session(C, op->reports)) { + if (WM_file_recover_last_session(C, op->reports)) { if (!G.background) { wmOperatorType *ot = op->type; PointerRNA *props_ptr = MEM_callocN(sizeof(PointerRNA), __func__); @@ -2890,7 +2892,7 @@ static int wm_recover_last_session_exec(bContext *C, wmOperator *op) static void wm_recover_last_session_after_dialog_callback(bContext *C, void *user_data) { WM_operator_name_call_with_properties( - C, "WM_OT_recover_last_session", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data); + C, "WM_OT_recover_last_session", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data, NULL); } static int wm_recover_last_session_invoke(bContext *C, @@ -3288,7 +3290,7 @@ static void wm_block_autorun_warning_reload_with_scripts(bContext *C, /* Save user preferences for permanent execution. */ if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) { - WM_operator_name_call(C, "WM_OT_save_userpref", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "WM_OT_save_userpref", WM_OP_EXEC_DEFAULT, NULL, NULL); } /* Load file again with scripts enabled. @@ -3307,7 +3309,7 @@ static void wm_block_autorun_warning_enable_scripts(bContext *C, /* Save user preferences for permanent execution. */ if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) { - WM_operator_name_call(C, "WM_OT_save_userpref", WM_OP_EXEC_DEFAULT, NULL); + WM_operator_name_call(C, "WM_OT_save_userpref", WM_OP_EXEC_DEFAULT, NULL, NULL); } /* Force a full refresh, but without reloading the file. */ @@ -3476,7 +3478,7 @@ void wm_test_autorun_revert_action_exec(bContext *C) wm_test_autorun_revert_action_set(ot, ptr); } - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, ptr, NULL); wm_test_autorun_revert_action_set(NULL, NULL); } @@ -3557,13 +3559,13 @@ static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_dat bool file_has_been_saved_before = BKE_main_blendfile_path(bmain)[0] != '\0'; if (file_has_been_saved_before) { - if (WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL) & + if (WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL, NULL) & OPERATOR_CANCELLED) { execute_callback = false; } } else { - WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_INVOKE_DEFAULT, NULL, NULL); execute_callback = false; } diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index a6fbad8b171..ec01e097e98 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -49,6 +49,9 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent gesture->modal_state = GESTURE_MODAL_NOP; gesture->move = false; + int xy[2]; + WM_event_drag_start_xy(event, xy); + if (ELEM(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, @@ -57,14 +60,14 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent rcti *rect = MEM_callocN(sizeof(rcti), "gesture rect new"); gesture->customdata = rect; - rect->xmin = event->xy[0] - gesture->winrct.xmin; - rect->ymin = event->xy[1] - gesture->winrct.ymin; + rect->xmin = xy[0] - gesture->winrct.xmin; + rect->ymin = xy[1] - gesture->winrct.ymin; if (type == WM_GESTURE_CIRCLE) { /* caller is responsible for initializing 'xmax' to radius. */ } else { - rect->xmax = event->xy[0] - gesture->winrct.xmin; - rect->ymax = event->xy[1] - gesture->winrct.ymin; + rect->xmax = xy[0] - gesture->winrct.xmin; + rect->ymax = xy[1] - gesture->winrct.ymin; } } else if (ELEM(type, WM_GESTURE_LINES, WM_GESTURE_LASSO)) { @@ -72,8 +75,8 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent gesture->points_alloc = 1024; gesture->customdata = lasso = MEM_mallocN(sizeof(short[2]) * gesture->points_alloc, "lasso points"); - lasso[0] = event->xy[0] - gesture->winrct.xmin; - lasso[1] = event->xy[1] - gesture->winrct.ymin; + lasso[0] = xy[0] - gesture->winrct.xmin; + lasso[1] = xy[1] - gesture->winrct.ymin; gesture->points = 1; } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 70e54e3e69d..6a9776c6933 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -365,7 +365,7 @@ void WM_init_splash(bContext *C) if (wm->windows.first) { CTX_wm_window_set(C, wm->windows.first); - WM_operator_name_call(C, "WM_OT_splash", WM_OP_INVOKE_DEFAULT, NULL); + WM_operator_name_call(C, "WM_OT_splash", WM_OP_INVOKE_DEFAULT, NULL, NULL); CTX_wm_window_set(C, prevwin); } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 0dce8b8f000..7b18d7659e2 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -383,7 +383,7 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr * since there is no convenient way to calculate partial RNA paths. * * \note While the path to the ID is typically sufficient to calculate the remainder of the path, - * in practice this would cause #WM_context_path_resolve_property_full to crate a path such as: + * in practice this would cause #WM_context_path_resolve_property_full to create a path such as: * `object.data.bones["Bones"].use_deform` such paths are not useful for key-shortcuts, * so this function supports returning data-paths directly to context members that aren't ID types. */ @@ -956,8 +956,13 @@ int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event) int WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - RNA_int_set(op->ptr, "mouse_x", event->mval[0]); - RNA_int_set(op->ptr, "mouse_y", event->mval[1]); + ARegion *region = CTX_wm_region(C); + + int mval[2]; + WM_event_drag_start_mval(event, region, mval); + + RNA_int_set(op->ptr, "mouse_x", mval[0]); + RNA_int_set(op->ptr, "mouse_y", mval[1]); op->customdata = POINTER_FROM_INT(0); @@ -3592,8 +3597,11 @@ static int doc_view_manual_ui_context_exec(bContext *C, wmOperator *UNUSED(op)) WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); RNA_string_set(&ptr_props, "doc_id", buf); - retval = WM_operator_name_call_ptr( - C, WM_operatortype_find("WM_OT_doc_view_manual", false), WM_OP_EXEC_DEFAULT, &ptr_props); + retval = WM_operator_name_call_ptr(C, + WM_operatortype_find("WM_OT_doc_view_manual", false), + WM_OP_EXEC_DEFAULT, + &ptr_props, + NULL); WM_operator_properties_free(&ptr_props); } diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c index 51e4bc9faa8..bc4bbc86367 100644 --- a/source/blender/windowmanager/intern/wm_toolsystem.c +++ b/source/blender/windowmanager/intern/wm_toolsystem.c @@ -611,7 +611,7 @@ bToolRef *WM_toolsystem_ref_set_by_id_ex( RNA_enum_set(&op_props, "space_type", tkey->space_type); RNA_boolean_set(&op_props, "cycle", cycle); - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props); + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props, NULL); WM_operator_properties_free(&op_props); bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); @@ -664,7 +664,7 @@ static const char *toolsystem_default_tool(const bToolKey *tkey) case CTX_MODE_VERTEX_GPENCIL: return "builtin_brush.Draw"; case CTX_MODE_SCULPT_CURVES: - return "builtin_brush.Test 1"; + return "builtin_brush.Comb"; /* end temporary hack. */ case CTX_MODE_PARTICLE: diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 6c90e0603a5..cbebb856660 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -209,6 +209,9 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win) if (win->eventstate) { MEM_freeN(win->eventstate); } + if (win->event_last_handled) { + MEM_freeN(win->event_last_handled); + } if (win->cursor_keymap_status) { MEM_freeN(win->cursor_keymap_status); @@ -1325,7 +1328,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr WM_operator_properties_create_ptr(&props_ptr, ot); RNA_string_set(&props_ptr, "filepath", path); RNA_boolean_set(&props_ptr, "display_file_selector", false); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL); WM_operator_properties_free(&props_ptr); CTX_wm_window_set(C, NULL); diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index d5c8c5022cc..0a0fdfa769a 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -244,6 +244,7 @@ enum { NDOF_MOTION = 0x0190, /* 400 */ #define _NDOF_MIN NDOF_MOTION +#define _NDOF_BUTTON_MIN NDOF_BUTTON_MENU /* used internally, never sent */ NDOF_BUTTON_NONE = NDOF_MOTION, @@ -274,11 +275,17 @@ enum { NDOF_BUTTON_DOMINANT = 0x01a3, /* 419 */ NDOF_BUTTON_PLUS = 0x01a4, /* 420 */ NDOF_BUTTON_MINUS = 0x01a5, /* 421 */ + +/* Disabled as GHOST converts these to keyboard events + * which use regular keyboard event handling logic. */ +#if 0 /* keyboard emulation */ NDOF_BUTTON_ESC = 0x01a6, /* 422 */ NDOF_BUTTON_ALT = 0x01a7, /* 423 */ NDOF_BUTTON_SHIFT = 0x01a8, /* 424 */ NDOF_BUTTON_CTRL = 0x01a9, /* 425 */ +#endif + /* general-purpose buttons */ NDOF_BUTTON_1 = 0x01aa, /* 426 */ NDOF_BUTTON_2 = 0x01ab, /* 427 */ @@ -296,6 +303,7 @@ enum { NDOF_BUTTON_C = 0x01b6, /* 438 */ #define _NDOF_MAX NDOF_BUTTON_C +#define _NDOF_BUTTON_MAX NDOF_BUTTON_C /* ********** End of Input devices. ********** */ @@ -361,6 +369,17 @@ enum { (((event_type) >= _EVT_KEYBOARD_MIN && (event_type) <= _EVT_KEYBOARD_MAX) || \ ((event_type) >= EVT_F1KEY && (event_type) <= EVT_F24KEY)) +/** + * Test whether the event is a key on the keyboard + * or any other kind of button that supports press & release + * (use for click & click-drag detection). + * + * \note Mouse wheel events are excluded from this macro, while they do generate press events it + * doesn't make sense to have click & click-drag events for a mouse-wheel as it can't be held down. + */ +#define ISKEYBOARD_OR_BUTTON(event_type) \ + (ISMOUSE_BUTTON(event_type) || ISKEYBOARD(event_type) || ISNDOF_BUTTON(event_type)) + /** Test whether the event is a modifier key. */ #define ISKEYMODIFIER(event_type) \ (((event_type) >= EVT_LEFTCTRLKEY && (event_type) <= EVT_LEFTSHIFTKEY) || \ @@ -386,13 +405,16 @@ enum { /** Test whether the event is a NDOF event. */ #define ISNDOF(event_type) ((event_type) >= _NDOF_MIN && (event_type) <= _NDOF_MAX) +#define ISNDOF_BUTTON(event_type) \ + ((event_type) >= _NDOF_BUTTON_MIN && (event_type) <= _NDOF_BUTTON_MAX) #define IS_EVENT_ACTIONZONE(event_type) \ ELEM(event_type, EVT_ACTIONZONE_AREA, EVT_ACTIONZONE_REGION, EVT_ACTIONZONE_FULLSCREEN) /** Test whether event type is acceptable as hotkey (excluding modifiers). */ #define ISHOTKEY(event_type) \ - ((ISKEYBOARD(event_type) || ISMOUSE(event_type) || ISNDOF(event_type)) && \ + ((ISKEYBOARD(event_type) || ISMOUSE_BUTTON(event_type) || ISMOUSE_WHEEL(event_type) || \ + ISNDOF_BUTTON(event_type)) && \ (ISKEYMODIFIER(event_type) == false)) enum eEventType_Mask { diff --git a/source/blender/windowmanager/xr/intern/wm_xr_operators.c b/source/blender/windowmanager/xr/intern/wm_xr_operators.c index 54800a5cd35..3c090423c41 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_operators.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_operators.c @@ -867,7 +867,7 @@ static void wm_xr_fly_compute_turn(eXrFlyMode mode, const float nav_inv[4][4], float r_delta[4][4]) { - BLI_assert(mode == XR_FLY_TURNLEFT || mode == XR_FLY_TURNRIGHT); + BLI_assert(ELEM(mode, XR_FLY_TURNLEFT, XR_FLY_TURNRIGHT)); float z_axis[3], m[3][3], prev[4][4], curr[4][4]; diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 736f1c34de6..6651aa77725 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -262,7 +262,7 @@ static int *parse_int_relative_clamp_n( int i = 0; while (true) { const char *str_end = strchr(str, sep); - if ((*str == sep) || (*str == '\0')) { + if (ELEM(*str, sep, '\0')) { static const char *msg = "incorrect comma use"; *r_err_msg = msg; goto fail; diff --git a/tests/python/bl_pyapi_idprop.py b/tests/python/bl_pyapi_idprop.py index 0e93ba0b690..ac1bd618570 100644 --- a/tests/python/bl_pyapi_idprop.py +++ b/tests/python/bl_pyapi_idprop.py @@ -172,6 +172,14 @@ class TestIdPropertyGroupView(TestHelper, unittest.TestCase): self.assertEqual(list(self.id.items()), [(k, v) for v, k in enumerate(text)]) self.assertEqual(list(reversed(self.id.items())), list(reversed([(k, v) for v, k in enumerate(text)]))) + # Check direct iteration is working as expected. + self.id["group"] = {ch: i for i, ch in enumerate(text)} + group = self.id["group"] + + self.assertEqual(len(group), len(text)) + self.assertEqual(list(iter(group)), text) + + def test_contains(self): # Check `idprop.types.IDPropertyGroupView{Keys/Values/Items}.__contains__` text = ["A", "B", "C"] |