Merge branch 'master' into xr-dev

This commit is contained in:
Peter Kim 2022-02-27 18:56:36 +09:00
commit 23c5e05267
186 changed files with 3387 additions and 949 deletions

View File

@ -244,7 +244,7 @@ void RenderScheduler::render_work_reschedule_on_cancel(RenderWork &render_work)
render_work.tile.write = tile_write;
render_work.full.write = full_write;
/* Do not write tile if it has zero samples it, treat it similarly to all other tiles which
/* Do not write tile if it has zero samples in it, treat it similarly to all other tiles which
* got canceled. */
if (!state_.tile_result_was_written && has_rendered_samples) {
render_work.tile.write = true;

View File

@ -5,27 +5,6 @@
CCL_NAMESPACE_BEGIN
/* Ray offset to avoid self intersection.
*
* This function should be used to compute a modified ray start position for
* rays leaving from a surface. This is from "A Fast and Robust Method for Avoiding
* Self-Intersection" see https://research.nvidia.com/publication/2019-03_A-Fast-and
*/
ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
{
const float int_scale = 256.0f;
int3 of_i = make_int3((int)(int_scale * Ng.x), (int)(int_scale * Ng.y), (int)(int_scale * Ng.z));
float3 p_i = make_float3(__int_as_float(__float_as_int(P.x) + ((P.x < 0) ? -of_i.x : of_i.x)),
__int_as_float(__float_as_int(P.y) + ((P.y < 0) ? -of_i.y : of_i.y)),
__int_as_float(__float_as_int(P.z) + ((P.z < 0) ? -of_i.z : of_i.z)));
const float origin = 1.0f / 32.0f;
const float float_scale = 1.0f / 65536.0f;
return make_float3(fabsf(P.x) < origin ? P.x + float_scale * Ng.x : p_i.x,
fabsf(P.y) < origin ? P.y + float_scale * Ng.y : p_i.y,
fabsf(P.z) < origin ? P.z + float_scale * Ng.z : p_i.z);
}
#if defined(__KERNEL_CPU__)
ccl_device int intersections_compare(const void *a, const void *b)
{

View File

@ -128,9 +128,10 @@ ccl_device float point_radius(KernelGlobals kg, ccl_private const ShaderData *sd
return r;
}
else {
float3 dir = make_float3(r, r, r);
const float normalized_r = r * (1.0f / M_SQRT3_F);
float3 dir = make_float3(normalized_r, normalized_r, normalized_r);
object_dir_transform(kg, sd, &dir);
return average(dir);
return len(dir);
}
}

View File

@ -30,6 +30,50 @@ ccl_device_inline float bake_clamp_mirror_repeat(float u, float max)
return ((((int)fu) & 1) ? 1.0f - u : u) * max;
}
/* Offset towards center of triangle to avoid ray-tracing precision issues. */
ccl_device const float2 bake_offset_towards_center(KernelGlobals kg,
const int prim,
const float u,
const float v)
{
float3 tri_verts[3];
triangle_vertices(kg, prim, tri_verts);
/* Empirically determined values, by no means perfect. */
const float position_offset = 1e-4f;
const float uv_offset = 1e-5f;
/* Offset position towards center, amount relative to absolute size of position coordinates. */
const float3 P = u * tri_verts[0] + v * tri_verts[1] + (1.0f - u - v) * tri_verts[2];
const float3 center = (tri_verts[0] + tri_verts[1] + tri_verts[2]) / 3.0f;
const float3 to_center = center - P;
const float3 offset_P = P + normalize(to_center) *
min(len(to_center), max(max3(fabs(P)), 1.0f) * position_offset);
/* Compute barycentric coordinates at new position. */
const float3 v1 = tri_verts[1] - tri_verts[0];
const float3 v2 = tri_verts[2] - tri_verts[0];
const float3 vP = offset_P - tri_verts[0];
const float d11 = dot(v1, v1);
const float d12 = dot(v1, v2);
const float d22 = dot(v2, v2);
const float dP1 = dot(vP, v1);
const float dP2 = dot(vP, v2);
const float denom = d11 * d22 - d12 * d12;
if (denom == 0.0f) {
return make_float2(0.0f, 0.0f);
}
const float offset_v = clamp((d22 * dP1 - d12 * dP2) / denom, uv_offset, 1.0f - uv_offset);
const float offset_w = clamp((d11 * dP2 - d12 * dP1) / denom, uv_offset, 1.0f - uv_offset);
const float offset_u = clamp(1.0f - offset_v - offset_w, uv_offset, 1.0f - uv_offset);
return make_float2(offset_u, offset_v);
}
/* Return false to indicate that this pixel is finished.
* Used by CPU implementation to not attempt to sample pixel for multiple samples once its known
* that the pixel did converge. */
@ -87,7 +131,7 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
/* Initialize path state for path integration. */
path_state_init_integrator(kg, state, sample, rng_hash);
/* Barycentric UV with sub-pixel offset. */
/* Barycentric UV. */
float u = primitive[2];
float v = primitive[3];
@ -96,6 +140,14 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
float dvdx = differential[2];
float dvdy = differential[3];
/* Exactly at vertex? Nudge inwards to avoid self-intersection. */
if ((u == 0.0f || u == 1.0f) && (v == 0.0f || v == 1.0f)) {
const float2 uv = bake_offset_towards_center(kg, prim, u, v);
u = uv.x;
v = uv.y;
}
/* Sub-pixel offset. */
if (sample > 0) {
u = bake_clamp_mirror_repeat(u + dudx * (filter_x - 0.5f) + dudy * (filter_y - 0.5f), 1.0f);
v = bake_clamp_mirror_repeat(v + dvdx * (filter_x - 0.5f) + dvdy * (filter_y - 0.5f),

View File

@ -352,12 +352,8 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
float ao_pdf;
sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
if (!(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f)) {
return;
}
Ray ray ccl_optional_struct_init;
ray.P = sd->P;
ray.P = shadow_ray_offset(kg, sd, ao_D);
ray.D = ao_D;
ray.t = kernel_data.integrator.ao_bounces_distance;
ray.time = sd->time;

View File

@ -1638,12 +1638,16 @@ bool OSLRenderServices::trace(TraceOpt &options,
ray.D = TO_FLOAT3(R);
ray.t = (options.maxdist == 1.0e30f) ? FLT_MAX : options.maxdist - options.mindist;
ray.time = sd->time;
ray.self.object = OBJECT_NONE;
ray.self.prim = PRIM_NONE;
ray.self.light_object = OBJECT_NONE;
ray.self.light_prim = PRIM_NONE;
if (options.mindist == 0.0f) {
/* avoid self-intersections */
if (ray.P == sd->P) {
bool transmit = (dot(sd->Ng, ray.D) < 0.0f);
ray.P = ray_offset(sd->P, (transmit) ? -sd->Ng : sd->Ng);
ray.self.object = sd->object;
ray.self.prim = sd->prim;
}
}
else {

View File

@ -58,8 +58,8 @@ ccl_device_noinline void svm_node_light_path(KernelGlobals kg,
info = (float)integrator_state_bounce(state, path_flag);
}
/* For background, light emission and shadow evaluation we from a
* surface or volume we are effective one bounce further. */
/* For background, light emission and shadow evaluation from a
* surface or volume we are effectively one bounce further. */
if (path_flag & (PATH_RAY_SHADOW | PATH_RAY_EMISSION)) {
info += 1.0f;
}

View File

@ -67,6 +67,9 @@ CCL_NAMESPACE_BEGIN
#ifndef M_SQRT2_F
# define M_SQRT2_F (1.4142135623730950f) /* sqrt(2) */
#endif
#ifndef M_SQRT3_F
# define M_SQRT3_F (1.7320508075688772f) /* sqrt(3) */
#endif
#ifndef M_LN2_F
# define M_LN2_F (0.6931471805599453f) /* ln(2) */
#endif

View File

@ -307,6 +307,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
case ']':
return GHOST_kKeyRightBracket;
case '`':
case '<': /* The position of '`' is equivalent to this symbol in the French layout. */
return GHOST_kKeyAccentGrave;
default:
return GHOST_kKeyUnknown;

View File

@ -53,9 +53,6 @@
#ifndef VK_COMMA
# define VK_COMMA 0xBC
#endif // VK_COMMA
#ifndef VK_QUOTE
# define VK_QUOTE 0xDE
#endif // VK_QUOTE
#ifndef VK_BACK_QUOTE
# define VK_BACK_QUOTE 0xC0
#endif // VK_BACK_QUOTE
@ -635,14 +632,32 @@ GHOST_TKey GHOST_SystemWin32::hardKey(RAWINPUT const &raw,
GHOST_TKey GHOST_SystemWin32::processSpecialKey(short vKey, short scanCode) const
{
GHOST_TKey key = GHOST_kKeyUnknown;
switch (PRIMARYLANGID(m_langId)) {
case LANG_FRENCH:
if (vKey == VK_OEM_8)
key = GHOST_kKeyF13; // oem key; used purely for shortcuts .
char ch = (char)MapVirtualKeyA(vKey, MAPVK_VK_TO_CHAR);
switch (ch) {
case u'\"':
case u'\'':
key = GHOST_kKeyQuote;
break;
case LANG_ENGLISH:
if (SUBLANGID(m_langId) == SUBLANG_ENGLISH_UK && vKey == VK_OEM_8) // "`¬"
key = GHOST_kKeyAccentGrave;
case u'.':
key = GHOST_kKeyNumpadPeriod;
break;
case u'/':
key = GHOST_kKeySlash;
break;
case u'`':
case u'²':
key = GHOST_kKeyAccentGrave;
break;
default:
if (vKey == VK_OEM_7) {
key = GHOST_kKeyQuote;
}
else if (vKey == VK_OEM_8) {
if (PRIMARYLANGID(m_langId) == LANG_FRENCH) {
/* oem key; used purely for shortcuts. */
key = GHOST_kKeyF13;
}
}
break;
}
@ -777,9 +792,6 @@ GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short exten
case VK_CLOSE_BRACKET:
key = GHOST_kKeyRightBracket;
break;
case VK_QUOTE:
key = GHOST_kKeyQuote;
break;
case VK_GR_LESS:
key = GHOST_kKeyGrLess;
break;
@ -821,9 +833,6 @@ GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short exten
case VK_CAPITAL:
key = GHOST_kKeyCapsLock;
break;
case VK_OEM_8:
key = ((GHOST_SystemWin32 *)getSystem())->processSpecialKey(vKey, scanCode);
break;
case VK_MEDIA_PLAY_PAUSE:
key = GHOST_kKeyMediaPlay;
break;
@ -836,8 +845,10 @@ GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short exten
case VK_MEDIA_NEXT_TRACK:
key = GHOST_kKeyMediaLast;
break;
case VK_OEM_7:
case VK_OEM_8:
default:
key = GHOST_kKeyUnknown;
key = ((GHOST_SystemWin32 *)getSystem())->processSpecialKey(vKey, scanCode);
break;
}
}

View File

@ -324,7 +324,7 @@ static bool addGPULut2D(OCIO_GPUTextures &textures,
GPU_R16F;
OCIO_GPULutTexture lut;
lut.texture = GPU_texture_create_2d(texture_name, width, height, 0, format, values);
lut.texture = GPU_texture_create_2d(texture_name, width, height, 1, format, values);
if (lut.texture == nullptr) {
return false;
}
@ -356,7 +356,7 @@ static bool addGPULut3D(OCIO_GPUTextures &textures,
OCIO_GPULutTexture lut;
lut.texture = GPU_texture_create_3d(
texture_name, edgelen, edgelen, edgelen, 0, GPU_RGB16F, GPU_DATA_FLOAT, values);
texture_name, edgelen, edgelen, edgelen, 1, GPU_RGB16F, GPU_DATA_FLOAT, values);
if (lut.texture == nullptr) {
return false;
}

View File

@ -144,7 +144,7 @@ const UserDef U_default = {
* so invert this by default, see: T67579. */
NDOF_ROTX_INVERT_AXIS | NDOF_ROTY_INVERT_AXIS | NDOF_ROTZ_INVERT_AXIS |
NDOF_PANX_INVERT_AXIS | NDOF_PANY_INVERT_AXIS | NDOF_PANZ_INVERT_AXIS |
NDOF_ZOOM_INVERT),
NDOF_ZOOM_INVERT | NDOF_CAMERA_PAN_ZOOM),
.image_draw_method = IMAGE_DRAW_METHOD_AUTO,
.glalphaclip = 0.004,
.autokey_mode = (AUTOKEY_MODE_NORMAL & ~AUTOKEY_ON),

View File

@ -489,12 +489,7 @@ def disable_all():
def _blender_manual_url_prefix():
if _bpy.app.version_cycle in {"rc", "release"}:
manual_version = "%d.%d" % _bpy.app.version[:2]
else:
manual_version = "dev"
return "https://docs.blender.org/manual/en/" + manual_version
return "https://docs.blender.org/manual/en/%d.%d" % _bpy.app.version[:2]
def module_bl_info(mod, *, info_basis=None):

View File

@ -3,10 +3,7 @@
import bpy
if bpy.app.version_cycle in {'rc', 'release'}:
manual_version = '%d.%d' % bpy.app.version[:2]
else:
manual_version = 'dev'
manual_version = '%d.%d' % bpy.app.version[:2]
url_manual_prefix = "https://docs.blender.org/manual/en/" + manual_version + "/"
@ -50,7 +47,6 @@ url_manual_mapping = (
("bpy.types.lineartgpencilmodifier.use_offset_towards_custom_camera*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-offset-towards-custom-camera"),
("bpy.types.movietrackingsettings.refine_intrinsics_principal_point*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingsettings-refine-intrinsics-principal-point"),
("bpy.types.cyclesobjectsettings.shadow_terminator_geometry_offset*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesobjectsettings-shadow-terminator-geometry-offset"),
("bpy.types.cyclesrenderlayersettings.denoising_optix_input_passes*", "render/layers/denoising.html#bpy-types-cyclesrenderlayersettings-denoising-optix-input-passes"),
("bpy.types.sequencertoolsettings.use_snap_current_frame_to_strips*", "video_editing/sequencer/editing.html#bpy-types-sequencertoolsettings-use-snap-current-frame-to-strips"),
("bpy.types.fluiddomainsettings.sndparticle_potential_max_energy*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-potential-max-energy"),
("bpy.types.fluiddomainsettings.sndparticle_potential_min_energy*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-potential-min-energy"),
@ -114,6 +110,7 @@ url_manual_mapping = (
("bpy.types.gpencilsculptsettings.intersection_threshold*", "grease_pencil/modes/draw/tools/cutter.html#bpy-types-gpencilsculptsettings-intersection-threshold"),
("bpy.types.gpencilsculptsettings.use_multiframe_falloff*", "grease_pencil/multiframe.html#bpy-types-gpencilsculptsettings-use-multiframe-falloff"),
("bpy.types.lineartgpencilmodifier.use_intersection_mask*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-intersection-mask"),
("bpy.types.lineartgpencilmodifier.use_invert_collection*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-invert-collection"),
("bpy.types.movietrackingsettings.use_keyframe_selection*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingsettings-use-keyframe-selection"),
("bpy.types.rendersettings.simplify_gpencil_antialiasing*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-antialiasing"),
("bpy.types.sequencertimelineoverlay.show_strip_duration*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-strip-duration"),
@ -123,7 +120,6 @@ url_manual_mapping = (
("bpy.types.brush.show_multiplane_scrape_planes_preview*", "sculpt_paint/sculpting/tools/multiplane_scrape.html#bpy-types-brush-show-multiplane-scrape-planes-preview"),
("bpy.types.brushgpencilsettings.eraser_strength_factor*", "grease_pencil/modes/draw/tools/erase.html#bpy-types-brushgpencilsettings-eraser-strength-factor"),
("bpy.types.cyclesmaterialsettings.volume_interpolation*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-volume-interpolation"),
("bpy.types.cyclesrendersettings.debug_optix_curves_api*", "render/cycles/render_settings/debug.html#bpy-types-cyclesrendersettings-debug-optix-curves-api"),
("bpy.types.cyclesrendersettings.denoising_input_passes*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-denoising-input-passes"),
("bpy.types.cyclesrendersettings.film_transparent_glass*", "render/cycles/render_settings/film.html#bpy-types-cyclesrendersettings-film-transparent-glass"),
("bpy.types.cyclesrendersettings.offscreen_dicing_scale*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-offscreen-dicing-scale"),
@ -358,6 +354,7 @@ url_manual_mapping = (
("bpy.types.toolsettings.use_keyframe_insert_auto*", "editors/timeline.html#bpy-types-toolsettings-use-keyframe-insert-auto"),
("bpy.types.viewlayer.use_pass_cryptomatte_object*", "render/layers/passes.html#bpy-types-viewlayer-use-pass-cryptomatte-object"),
("bpy.ops.armature.rigify_apply_selection_colors*", "addons/rigging/rigify/metarigs.html#bpy-ops-armature-rigify-apply-selection-colors"),
("bpy.ops.ed.lib_id_generate_preview_from_object*", "editors/asset_browser.html#bpy-ops-ed-lib-id-generate-preview-from-object"),
("bpy.types.brushgpencilsettings.fill_layer_mode*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-layer-mode"),
("bpy.types.brushgpencilsettings.random_strength*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-random-strength"),
("bpy.types.brushgpencilsettings.simplify_factor*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-simplify-factor"),
@ -379,6 +376,7 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.use_split_pattern*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-split-pattern"),
("bpy.types.freestylesettings.use_view_map_cache*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-use-view-map-cache"),
("bpy.types.geometrynodecurvehandletypeselection*", "modeling/geometry_nodes/curve/handle_type_selection.html#bpy-types-geometrynodecurvehandletypeselection"),
("bpy.types.geometrynodeinputmeshvertexneighbors*", "modeling/geometry_nodes/mesh/vertex_neighbors.html#bpy-types-geometrynodeinputmeshvertexneighbors"),
("bpy.types.greasepencil.curve_edit_corner_angle*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-corner-angle"),
("bpy.types.lineartgpencilmodifier.source_camera*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-source-camera"),
("bpy.types.lineartgpencilmodifier.use_face_mark*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-face-mark"),
@ -405,7 +403,6 @@ url_manual_mapping = (
("bpy.types.brushgpencilsettings.use_fill_limit*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-use-fill-limit"),
("bpy.types.clothsettings.vertex_group_pressure*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-vertex-group-pressure"),
("bpy.types.cyclesmaterialsettings.displacement*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-displacement"),
("bpy.types.cyclesrendersettings.debug_bvh_type*", "render/cycles/render_settings/debug.html#bpy-types-cyclesrendersettings-debug-bvh-type"),
("bpy.types.cyclesrendersettings.fast_gi_method*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-fast-gi-method"),
("bpy.types.cyclesrendersettings.glossy_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-glossy-bounces"),
("bpy.types.cyclesrendersettings.volume_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-volume-bounces"),
@ -458,6 +455,7 @@ url_manual_mapping = (
("bpy.types.cyclescamerasettings.panorama_type*", "render/cycles/object_settings/cameras.html#bpy-types-cyclescamerasettings-panorama-type"),
("bpy.types.cyclesrendersettings.dicing_camera*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-dicing-camera"),
("bpy.types.cyclesrendersettings.film_exposure*", "render/cycles/render_settings/film.html#bpy-types-cyclesrendersettings-film-exposure"),
("bpy.types.cyclesrendersettings.sample_offset*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-sample-offset"),
("bpy.types.cyclesrendersettings.texture_limit*", "render/cycles/render_settings/simplify.html#bpy-types-cyclesrendersettings-texture-limit"),
("bpy.types.cyclesrendersettings.use_denoising*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-use-denoising"),
("bpy.types.editbone.bbone_custom_handle_start*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-custom-handle-start"),
@ -483,6 +481,8 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.use_dashed_line*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-dashed-line"),
("bpy.types.freestylelinestyle.use_same_object*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-same-object"),
("bpy.types.functionnodeinputspecialcharacters*", "modeling/geometry_nodes/text/special_characters.html#bpy-types-functionnodeinputspecialcharacters"),
("bpy.types.geometrynodeinputmeshedgeneighbors*", "modeling/geometry_nodes/mesh/edge_neighbors.html#bpy-types-geometrynodeinputmeshedgeneighbors"),
("bpy.types.geometrynodeinputmeshfaceneighbors*", "modeling/geometry_nodes/mesh/face_neighbors.html#bpy-types-geometrynodeinputmeshfaceneighbors"),
("bpy.types.gpencilsculptguide.reference_point*", "grease_pencil/modes/draw/guides.html#bpy-types-gpencilsculptguide-reference-point"),
("bpy.types.greasepencil.edit_curve_resolution*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-edit-curve-resolution"),
("bpy.types.linestylegeometrymodifier_2doffset*", "render/freestyle/view_layer/line_style/modifiers/geometry/2d_offset.html#bpy-types-linestylegeometrymodifier-2doffset"),
@ -495,6 +495,7 @@ url_manual_mapping = (
("bpy.types.sequencertimelineoverlay.show_grid*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-grid"),
("bpy.types.sequencertoolsettings.overlap_mode*", "video_editing/sequencer/editing.html#bpy-types-sequencertoolsettings-overlap-mode"),
("bpy.types.spaceclipeditor.show_green_channel*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-show-green-channel"),
("bpy.types.spacenodeoverlay.show_context_path*", "interface/controls/nodes/introduction.html#bpy-types-spacenodeoverlay-show-context-path"),
("bpy.types.spaceoutliner.show_restrict_column*", "editors/outliner/interface.html#bpy-types-spaceoutliner-show-restrict-column"),
("bpy.types.spacespreadsheet.object_eval_state*", "editors/spreadsheet.html#bpy-types-spacespreadsheet-object-eval-state"),
("bpy.types.spaceuveditor.display_stretch_type*", "editors/uv/overlays.html#bpy-types-spaceuveditor-display-stretch-type"),
@ -522,6 +523,7 @@ url_manual_mapping = (
("bpy.types.freestylelineset.select_edge_mark*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-select-edge-mark"),
("bpy.types.freestylelinestyle.use_length_max*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-length-max"),
("bpy.types.freestylelinestyle.use_length_min*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-length-min"),
("bpy.types.geometrynodeinputmeshedgevertices*", "modeling/geometry_nodes/mesh/edge_vertices.html#bpy-types-geometrynodeinputmeshedgevertices"),
("bpy.types.geometrynodeinputsplineresolution*", "modeling/geometry_nodes/curve/spline_resolution.html#bpy-types-geometrynodeinputsplineresolution"),
("bpy.types.greasepencil.curve_edit_threshold*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-threshold"),
("bpy.types.materialgpencilstyle.stroke_style*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-stroke-style"),
@ -617,6 +619,7 @@ url_manual_mapping = (
("bpy.types.brush.surface_smooth_iterations*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-surface-smooth-iterations"),
("bpy.types.brushgpencilsettings.pen_jitter*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-pen-jitter"),
("bpy.types.brushgpencilsettings.show_lasso*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-show-lasso"),
("bpy.types.compositornodeconvertcolorspace*", "compositing/types/converter/color_space.html#bpy-types-compositornodeconvertcolorspace"),
("bpy.types.cyclescurverendersettings.shape*", "render/cycles/render_settings/hair.html#bpy-types-cyclescurverendersettings-shape"),
("bpy.types.cyclesrendersettings.ao_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-ao-bounces"),
("bpy.types.cyclesrendersettings.time_limit*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-time-limit"),
@ -713,7 +716,9 @@ url_manual_mapping = (
("bpy.types.geometrynodealigneulertovector*", "modeling/geometry_nodes/utilities/align_euler_to_vector.html#bpy-types-geometrynodealigneulertovector"),
("bpy.types.geometrynodeattributestatistic*", "modeling/geometry_nodes/attribute/attribute_statistic.html#bpy-types-geometrynodeattributestatistic"),
("bpy.types.geometrynodecurvequadrilateral*", "modeling/geometry_nodes/curve_primitives/quadrilateral.html#bpy-types-geometrynodecurvequadrilateral"),
("bpy.types.geometrynodegeometrytoinstance*", "modeling/geometry_nodes/geometry/geometry_to_instance.html#bpy-types-geometrynodegeometrytoinstance"),
("bpy.types.geometrynodeinputmaterialindex*", "modeling/geometry_nodes/material/material_index.html#bpy-types-geometrynodeinputmaterialindex"),
("bpy.types.geometrynodeinputmeshedgeangle*", "modeling/geometry_nodes/mesh/edge_angle.html#bpy-types-geometrynodeinputmeshedgeangle"),
("bpy.types.geometrynodeseparatecomponents*", "modeling/geometry_nodes/geometry/separate_components.html#bpy-types-geometrynodeseparatecomponents"),
("bpy.types.geometrynodesubdivisionsurface*", "modeling/geometry_nodes/mesh/subdivision_surface.html#bpy-types-geometrynodesubdivisionsurface"),
("bpy.types.geometrynodetranslateinstances*", "modeling/geometry_nodes/instances/translate_instances.html#bpy-types-geometrynodetranslateinstances"),
@ -793,6 +798,7 @@ url_manual_mapping = (
("bpy.types.freestylesettings.use_culling*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-use-culling"),
("bpy.types.geometrynodeendpointselection*", "modeling/geometry_nodes/curve/endpoint_selection.html#bpy-types-geometrynodeendpointselection"),
("bpy.types.geometrynodegeometryproximity*", "modeling/geometry_nodes/geometry/geometry_proximity.html#bpy-types-geometrynodegeometryproximity"),
("bpy.types.geometrynodeinputmeshfacearea*", "modeling/geometry_nodes/mesh/face_area.html#bpy-types-geometrynodeinputmeshfacearea"),
("bpy.types.geometrynodeinputsplinecyclic*", "modeling/geometry_nodes/curve/is_spline_cyclic.html#bpy-types-geometrynodeinputsplinecyclic"),
("bpy.types.geometrynodeinstancestopoints*", "modeling/geometry_nodes/instances/instances_to_points.html#bpy-types-geometrynodeinstancestopoints"),
("bpy.types.geometrynodetransferattribute*", "modeling/geometry_nodes/attribute/transfer_attribute.html#bpy-types-geometrynodetransferattribute"),
@ -822,6 +828,7 @@ url_manual_mapping = (
("bpy.types.toolsettings.mesh_select_mode*", "modeling/meshes/selecting/introduction.html#bpy-types-toolsettings-mesh-select-mode"),
("bpy.types.toolsettings.use_snap_project*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-project"),
("bpy.types.transformorientationslot.type*", "editors/3dview/controls/orientation.html#bpy-types-transformorientationslot-type"),
("bpy.types.unitsettings.temperature_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-temperature-unit"),
("bpy.types.vertexweightproximitymodifier*", "modeling/modifiers/modify/weight_proximity.html#bpy-types-vertexweightproximitymodifier"),
("bpy.types.view3doverlay.show_wireframes*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-show-wireframes"),
("bpy.types.view3dshading.background_type*", "editors/3dview/display/shading.html#bpy-types-view3dshading-background-type"),
@ -879,6 +886,7 @@ url_manual_mapping = (
("bpy.types.spacetexteditor.use_find_all*", "editors/text_editor.html#bpy-types-spacetexteditor-use-find-all"),
("bpy.types.toolsettings.snap_uv_element*", "editors/uv/controls/snapping.html#bpy-types-toolsettings-snap-uv-element"),
("bpy.types.toolsettings.use_snap_rotate*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-rotate"),
("bpy.types.unitsettings.system_rotation*", "scene_layout/scene/properties.html#bpy-types-unitsettings-system-rotation"),
("bpy.types.view3doverlay.display_handle*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-display-handle"),
("bpy.types.volumedisplay.wireframe_type*", "modeling/volumes/properties.html#bpy-types-volumedisplay-wireframe-type"),
("bpy.ops.anim.channels_editable_toggle*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-editable-toggle"),
@ -923,11 +931,15 @@ url_manual_mapping = (
("bpy.types.freestylelineset.visibility*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-visibility"),
("bpy.types.freestylelinestyle.chaining*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-chaining"),
("bpy.types.freestylelinestyle.sort_key*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-sort-key"),
("bpy.types.geometrynodeaccumulatefield*", "modeling/geometry_nodes/utilities/accumulate_field.html#bpy-types-geometrynodeaccumulatefield"),
("bpy.types.geometrynodecurvesethandles*", "modeling/geometry_nodes/curve/set_handle_type.html#bpy-types-geometrynodecurvesethandles"),
("bpy.types.geometrynodecurvesplinetype*", "modeling/geometry_nodes/curve/set_spline_type.html#bpy-types-geometrynodecurvesplinetype"),
("bpy.types.geometrynodeinputmeshisland*", "modeling/geometry_nodes/mesh/mesh_island.html#bpy-types-geometrynodeinputmeshisland"),
("bpy.types.geometrynodemergebydistance*", "modeling/geometry_nodes/geometry/merge_by_distance.html#bpy-types-geometrynodemergebydistance"),
("bpy.types.geometrynodereplacematerial*", "modeling/geometry_nodes/material/replace_material.html#bpy-types-geometrynodereplacematerial"),
("bpy.types.geometrynoderotateinstances*", "modeling/geometry_nodes/instances/rotate_instances.html#bpy-types-geometrynoderotateinstances"),
("bpy.types.geometrynodesetsplinecyclic*", "modeling/geometry_nodes/curve/set_spline_cyclic.html#bpy-types-geometrynodesetsplinecyclic"),
("bpy.types.geometrynodesplineparameter*", "modeling/geometry_nodes/curve/spline_parameter.html#bpy-types-geometrynodesplineparameter"),
("bpy.types.gpencillayer.use_mask_layer*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-use-mask-layer"),
("bpy.types.greasepencil.use_curve_edit*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-use-curve-edit"),
("bpy.types.imagepaint.screen_grab_size*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-types-imagepaint-screen-grab-size"),
@ -997,9 +1009,9 @@ url_manual_mapping = (
("bpy.types.fluidflowsettings.use_flow*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-flow"),
("bpy.types.fmodifierfunctiongenerator*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierfunctiongenerator"),
("bpy.types.geometrynodecollectioninfo*", "modeling/geometry_nodes/input/collection_info.html#bpy-types-geometrynodecollectioninfo"),
("bpy.types.geometrynodecurveparameter*", "modeling/geometry_nodes/curve/curve_parameter.html#bpy-types-geometrynodecurveparameter"),
("bpy.types.geometrynodedeletegeometry*", "modeling/geometry_nodes/geometry/delete_geometry.html#bpy-types-geometrynodedeletegeometry"),
("bpy.types.geometrynodeinputcurvetilt*", "modeling/geometry_nodes/curve/curve_tilt.html#bpy-types-geometrynodeinputcurvetilt"),
("bpy.types.geometrynodeinputscenetime*", "modeling/geometry_nodes/input/scene_time.html#bpy-types-geometrynodeinputscenetime"),
("bpy.types.geometrynodepointstovolume*", "modeling/geometry_nodes/point/points_to_volume.html#bpy-types-geometrynodepointstovolume"),
("bpy.types.geometrynodescaleinstances*", "modeling/geometry_nodes/instances/scale_instances.html#bpy-types-geometrynodescaleinstances"),
("bpy.types.geometrynodesetcurveradius*", "modeling/geometry_nodes/curve/set_curve_radius.html#bpy-types-geometrynodesetcurveradius"),
@ -1079,7 +1091,6 @@ url_manual_mapping = (
("bpy.types.fluidflowsettings.density*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-density"),
("bpy.types.freestylelineset.qi_start*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-qi-start"),
("bpy.types.freestylelinestyle.rounds*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-rounds"),
("bpy.types.functionnodecomparefloats*", "modeling/geometry_nodes/utilities/compare_floats.html#bpy-types-functionnodecomparefloats"),
("bpy.types.geometrynodecurvetopoints*", "modeling/geometry_nodes/curve/curve_to_points.html#bpy-types-geometrynodecurvetopoints"),
("bpy.types.geometrynodeinputmaterial*", "modeling/geometry_nodes/input/material.html#bpy-types-geometrynodeinputmaterial"),
("bpy.types.geometrynodeinputposition*", "modeling/geometry_nodes/input/position.html#bpy-types-geometrynodeinputposition"),
@ -1087,6 +1098,7 @@ url_manual_mapping = (
("bpy.types.geometrynodemeshicosphere*", "modeling/geometry_nodes/mesh_primitives/icosphere.html#bpy-types-geometrynodemeshicosphere"),
("bpy.types.geometrynodereplacestring*", "modeling/geometry_nodes/text/replace_string.html#bpy-types-geometrynodereplacestring"),
("bpy.types.geometrynoderesamplecurve*", "modeling/geometry_nodes/curve/resample_curve.html#bpy-types-geometrynoderesamplecurve"),
("bpy.types.geometrynodescaleelements*", "modeling/geometry_nodes/mesh/scale_elements.html#bpy-types-geometrynodescaleelements"),
("bpy.types.geometrynodesubdividemesh*", "modeling/geometry_nodes/mesh/subdivide_mesh.html#bpy-types-geometrynodesubdividemesh"),
("bpy.types.geometrynodevaluetostring*", "modeling/geometry_nodes/text/value_to_string.html#bpy-types-geometrynodevaluetostring"),
("bpy.types.keyframe.handle_left_type*", "editors/graph_editor/fcurves/properties.html#bpy-types-keyframe-handle-left-type"),
@ -1110,6 +1122,7 @@ url_manual_mapping = (
("bpy.types.shadernodebsdftranslucent*", "render/shader_nodes/shader/translucent.html#bpy-types-shadernodebsdftranslucent"),
("bpy.types.shadernodebsdftransparent*", "render/shader_nodes/shader/transparent.html#bpy-types-shadernodebsdftransparent"),
("bpy.types.shadernodevectortransform*", "render/shader_nodes/vector/transform.html#bpy-types-shadernodevectortransform"),
("bpy.types.shrinkwrapgpencilmodifier*", "grease_pencil/modifiers/deform/shrinkwrap.html#bpy-types-shrinkwrapgpencilmodifier"),
("bpy.types.spaceclipeditor.show_grid*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-show-grid"),
("bpy.types.spaceoutliner.filter_text*", "editors/outliner/interface.html#bpy-types-spaceoutliner-filter-text"),
("bpy.types.spacetexteditor.find_text*", "editors/text_editor.html#bpy-types-spacetexteditor-find-text"),
@ -1118,6 +1131,8 @@ url_manual_mapping = (
("bpy.types.spaceuveditor.lock_bounds*", "modeling/meshes/uv/editing.html#bpy-types-spaceuveditor-lock-bounds"),
("bpy.types.spline.tilt_interpolation*", "modeling/curves/properties/active_spline.html#bpy-types-spline-tilt-interpolation"),
("bpy.types.transformorientation.name*", "editors/3dview/controls/orientation.html#bpy-types-transformorientation-name"),
("bpy.types.unitsettings.scale_length*", "scene_layout/scene/properties.html#bpy-types-unitsettings-scale-length"),
("bpy.types.unitsettings.use_separate*", "scene_layout/scene/properties.html#bpy-types-unitsettings-use-separate"),
("bpy.types.viewlayer.use_motion_blur*", "render/layers/introduction.html#bpy-types-viewlayer-use-motion-blur"),
("bpy.types.volumedisplay.slice_depth*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-depth"),
("bpy.types.worldmistsettings.falloff*", "render/cycles/world_settings.html#bpy-types-worldmistsettings-falloff"),
@ -1150,13 +1165,14 @@ url_manual_mapping = (
("bpy.ops.wm.previews_batch_generate*", "files/blend/previews.html#bpy-ops-wm-previews-batch-generate"),
("bpy.types.assetmetadata.active_tag*", "editors/asset_browser.html#bpy-types-assetmetadata-active-tag"),
("bpy.types.bakesettings.cage_object*", "render/cycles/baking.html#bpy-types-bakesettings-cage-object"),
("bpy.types.bakesettings.margin_type*", "render/cycles/baking.html#bpy-types-bakesettings-margin-type"),
("bpy.types.bone.use_relative_parent*", "animation/armatures/bones/properties/relations.html#bpy-types-bone-use-relative-parent"),
("bpy.types.brush.auto_smooth_factor*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-auto-smooth-factor"),
("bpy.types.brush.smooth_deform_type*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-smooth-deform-type"),
("bpy.types.brush.use_connected_only*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-use-connected-only"),
("bpy.types.brush.use_cursor_overlay*", "sculpt_paint/brush/cursor.html#bpy-types-brush-use-cursor-overlay"),
("bpy.types.camera.show_passepartout*", "render/cameras.html#bpy-types-camera-show-passepartout"),
("bpy.types.collection.lineart_usage*", "scene_layout/collections/properties.html#bpy-types-collection-lineart-usage"),
("bpy.types.collection.lineart_usage*", "scene_layout/collections/collections.html#bpy-types-collection-lineart-usage"),
("bpy.types.colormanagedviewsettings*", "render/color_management.html#bpy-types-colormanagedviewsettings"),
("bpy.types.compositornodebokehimage*", "compositing/types/input/bokeh_image.html#bpy-types-compositornodebokehimage"),
("bpy.types.compositornodecolormatte*", "compositing/types/matte/color_key.html#bpy-types-compositornodecolormatte"),
@ -1172,6 +1188,7 @@ url_manual_mapping = (
("bpy.types.freestylelineset.exclude*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-exclude"),
("bpy.types.freestylelinestyle.alpha*", "render/freestyle/view_layer/line_style/alpha.html#bpy-types-freestylelinestyle-alpha"),
("bpy.types.freestylelinestyle.color*", "render/freestyle/view_layer/line_style/color.html#bpy-types-freestylelinestyle-color"),
("bpy.types.geometrynodefieldatindex*", "modeling/geometry_nodes/utilities/field_at_index.html#bpy-types-geometrynodefieldatindex"),
("bpy.types.geometrynodeinputtangent*", "modeling/geometry_nodes/curve/curve_tangent.html#bpy-types-geometrynodeinputtangent"),
("bpy.types.geometrynodejoingeometry*", "modeling/geometry_nodes/geometry/join_geometry.html#bpy-types-geometrynodejoingeometry"),
("bpy.types.geometrynodemeshcylinder*", "modeling/geometry_nodes/mesh_primitives/cylinder.html#bpy-types-geometrynodemeshcylinder"),
@ -1207,6 +1224,7 @@ url_manual_mapping = (
("bpy.types.thicknessgpencilmodifier*", "grease_pencil/modifiers/deform/thickness.html#bpy-types-thicknessgpencilmodifier"),
("bpy.types.toolsettings.snap_target*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-snap-target"),
("bpy.types.transformcacheconstraint*", "animation/constraints/transform/transform_cache.html#bpy-types-transformcacheconstraint"),
("bpy.types.unitsettings.length_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-length-unit"),
("bpy.types.vertexweighteditmodifier*", "modeling/modifiers/modify/weight_edit.html#bpy-types-vertexweighteditmodifier"),
("bpy.types.volumedisplay.slice_axis*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-axis"),
("bpy.ops.anim.channels_clean_empty*", "editors/nla/editing.html#bpy-ops-anim-channels-clean-empty"),
@ -1229,7 +1247,7 @@ url_manual_mapping = (
("bpy.ops.object.vertex_group_clean*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-clean"),
("bpy.ops.poselib.create_pose_asset*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-create-pose-asset"),
("bpy.ops.preferences.theme_install*", "editors/preferences/themes.html#bpy-ops-preferences-theme-install"),
("bpy.ops.render.play-rendered-anim*", "render/output/animation_player.html#bpy-ops-render-play-rendered-anim"),
("bpy.ops.render.play_rendered_anim*", "render/output/animation_player.html#bpy-ops-render-play-rendered-anim"),
("bpy.ops.sculpt.set_pivot_position*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-sculpt-set-pivot-position"),
("bpy.ops.sequencer.image_strip_add*", "video_editing/sequencer/strips/image.html#bpy-ops-sequencer-image-strip-add"),
("bpy.ops.sequencer.movie_strip_add*", "video_editing/sequencer/strips/movie.html#bpy-ops-sequencer-movie-strip-add"),
@ -1253,6 +1271,7 @@ url_manual_mapping = (
("bpy.types.compositornodemovieclip*", "compositing/types/input/movie_clip.html#bpy-types-compositornodemovieclip"),
("bpy.types.compositornodenormalize*", "compositing/types/vector/normalize.html#bpy-types-compositornodenormalize"),
("bpy.types.compositornodepremulkey*", "compositing/types/converter/alpha_convert.html#bpy-types-compositornodepremulkey"),
("bpy.types.compositornodescenetime*", "compositing/types/input/scene_time.html#bpy-types-compositornodescenetime"),
("bpy.types.compositornodestabilize*", "compositing/types/distort/stabilize_2d.html#bpy-types-compositornodestabilize"),
("bpy.types.compositornodetransform*", "compositing/types/distort/transform.html#bpy-types-compositornodetransform"),
("bpy.types.compositornodetranslate*", "compositing/types/distort/translate.html#bpy-types-compositornodetranslate"),
@ -1273,6 +1292,7 @@ url_manual_mapping = (
("bpy.types.geometrynodecurvelength*", "modeling/geometry_nodes/curve/curve_length.html#bpy-types-geometrynodecurvelength"),
("bpy.types.geometrynodecurvespiral*", "modeling/geometry_nodes/curve_primitives/curve_spiral.html#bpy-types-geometrynodecurvespiral"),
("bpy.types.geometrynodecurvetomesh*", "modeling/geometry_nodes/curve/curve_to_mesh.html#bpy-types-geometrynodecurvetomesh"),
("bpy.types.geometrynodeextrudemesh*", "modeling/geometry_nodes/mesh/extrude_mesh.html#bpy-types-geometrynodeextrudemesh"),
("bpy.types.geometrynodefilletcurve*", "modeling/geometry_nodes/curve/fillet_curve.html#bpy-types-geometrynodefilletcurve"),
("bpy.types.geometrynodeinputnormal*", "modeling/geometry_nodes/input/normal.html#bpy-types-geometrynodeinputnormal"),
("bpy.types.geometrynodeinputradius*", "modeling/geometry_nodes/input/radius.html#bpy-types-geometrynodeinputradius"),
@ -1332,6 +1352,7 @@ url_manual_mapping = (
("bpy.ops.mesh.primitive_plane_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-plane-add"),
("bpy.ops.mesh.primitive_torus_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-torus-add"),
("bpy.ops.mesh.select_non_manifold*", "modeling/meshes/selecting/all_by_trait.html#bpy-ops-mesh-select-non-manifold"),
("bpy.ops.object.attribute_convert*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-object-attribute-convert"),
("bpy.ops.object.constraints_clear*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraints-clear"),
("bpy.ops.object.quadriflow_remesh*", "modeling/meshes/retopology.html#bpy-ops-object-quadriflow-remesh"),
("bpy.ops.object.vertex_group_copy*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-copy"),
@ -1388,6 +1409,7 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.gap*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-gap"),
("bpy.types.freestylesettings.mode*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-mode"),
("bpy.types.geometrynodeconvexhull*", "modeling/geometry_nodes/geometry/convex_hull.html#bpy-types-geometrynodeconvexhull"),
("bpy.types.geometrynodedomainsize*", "modeling/geometry_nodes/attribute/domain_size.html#bpy-types-geometrynodedomainsize"),
("bpy.types.geometrynodefloattoint*", "modeling/geometry_nodes/utilities/float_to_integer.html#bpy-types-geometrynodefloattoint"),
("bpy.types.geometrynodeinputcolor*", "modeling/geometry_nodes/input/color.html#bpy-types-geometrynodeinputcolor"),
("bpy.types.geometrynodeinputindex*", "modeling/geometry_nodes/input/input_index.html#bpy-types-geometrynodeinputindex"),
@ -1418,6 +1440,8 @@ url_manual_mapping = (
("bpy.types.sound.use_memory_cache*", "video_editing/sequencer/sidebar/strip.html#bpy-types-sound-use-memory-cache"),
("bpy.types.spaceview3d.show_gizmo*", "editors/3dview/display/gizmo.html#bpy-types-spaceview3d-show-gizmo"),
("bpy.types.texturegpencilmodifier*", "grease_pencil/modifiers/modify/texture_mapping.html#bpy-types-texturegpencilmodifier"),
("bpy.types.unitsettings.mass_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-mass-unit"),
("bpy.types.unitsettings.time_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-time-unit"),
("bpy.types.volumedisplacemodifier*", "modeling/modifiers/deform/volume_displace.html#bpy-types-volumedisplacemodifier"),
("bpy.types.volumerender.step_size*", "modeling/volumes/properties.html#bpy-types-volumerender-step-size"),
("bpy.types.weightednormalmodifier*", "modeling/modifiers/modify/weighted_normal.html#bpy-types-weightednormalmodifier"),
@ -1435,6 +1459,7 @@ url_manual_mapping = (
("bpy.ops.gpencil.stroke_caps_set*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-caps-set"),
("bpy.ops.gpencil.stroke_separate*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-stroke-separate"),
("bpy.ops.gpencil.stroke_simplify*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-simplify"),
("bpy.ops.graph.blend_to_neighbor*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-blend-to-neighbor"),
("bpy.ops.graph.snap_cursor_value*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-snap-cursor-value"),
("bpy.ops.image.save_all_modified*", "editors/image/editing.html#bpy-ops-image-save-all-modified"),
("bpy.ops.mesh.extrude_edges_move*", "modeling/meshes/editing/edge/extrude_edges.html#bpy-ops-mesh-extrude-edges-move"),
@ -1447,6 +1472,7 @@ url_manual_mapping = (
("bpy.ops.mesh.subdivide_edgering*", "modeling/meshes/editing/edge/subdivide_edge_ring.html#bpy-ops-mesh-subdivide-edgering"),
("bpy.ops.node.hide_socket_toggle*", "interface/controls/nodes/editing.html#bpy-ops-node-hide-socket-toggle"),
("bpy.ops.node.tree_socket_remove*", "interface/controls/nodes/groups.html#bpy-ops-node-tree-socket-remove"),
("bpy.ops.object.attribute_remove*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-object-attribute-remove"),
("bpy.ops.object.constraints_copy*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraints-copy"),
("bpy.ops.object.gpencil_modifier*", "grease_pencil/modifiers/index.html#bpy-ops-object-gpencil-modifier"),
("bpy.ops.object.make_links_scene*", "scene_layout/object/editing/link_transfer/link_scene.html#bpy-ops-object-make-links-scene"),
@ -1509,6 +1535,7 @@ url_manual_mapping = (
("bpy.types.geometrynodecurvestar*", "modeling/geometry_nodes/curve_primitives/star.html#bpy-types-geometrynodecurvestar"),
("bpy.types.geometrynodeedgesplit*", "modeling/geometry_nodes/mesh/split_edges.html#bpy-types-geometrynodeedgesplit"),
("bpy.types.geometrynodefillcurve*", "modeling/geometry_nodes/curve/fill_curve.html#bpy-types-geometrynodefillcurve"),
("bpy.types.geometrynodeflipfaces*", "modeling/geometry_nodes/mesh/flip_faces.html#bpy-types-geometrynodeflipfaces"),
("bpy.types.geometrynodetransform*", "modeling/geometry_nodes/geometry/transform.html#bpy-types-geometrynodetransform"),
("bpy.types.geometrynodetrimcurve*", "modeling/geometry_nodes/curve/trim_curve.html#bpy-types-geometrynodetrimcurve"),
("bpy.types.gpencilsculptsettings*", "grease_pencil/properties/index.html#bpy-types-gpencilsculptsettings"),
@ -1552,6 +1579,7 @@ url_manual_mapping = (
("bpy.ops.curve.switch_direction*", "modeling/curves/editing/segments.html#bpy-ops-curve-switch-direction"),
("bpy.ops.gpencil.duplicate_move*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-duplicate-move"),
("bpy.ops.gpencil.stroke_arrange*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-arrange"),
("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"),
("bpy.ops.mesh.bridge-edge-loops*", "modeling/meshes/editing/edge/bridge_edge_loops.html#bpy-ops-mesh-bridge-edge-loops"),
("bpy.ops.mesh.intersect_boolean*", "modeling/meshes/editing/face/intersect_boolean.html#bpy-ops-mesh-intersect-boolean"),
("bpy.ops.mesh.loop_multi_select*", "modeling/meshes/selecting/loops.html#bpy-ops-mesh-loop-multi-select"),
@ -1616,6 +1644,7 @@ url_manual_mapping = (
("bpy.types.motionpath.frame_end*", "animation/motion_paths.html#bpy-types-motionpath-frame-end"),
("bpy.types.noisegpencilmodifier*", "grease_pencil/modifiers/deform/noise.html#bpy-types-noisegpencilmodifier"),
("bpy.types.object.hide_viewport*", "scene_layout/object/properties/visibility.html#bpy-types-object-hide-viewport"),
("bpy.types.object.rotation_mode*", "scene_layout/object/properties/transforms.html#bpy-types-object-rotation-mode"),
("bpy.types.object.show_in_front*", "scene_layout/object/properties/display.html#bpy-types-object-show-in-front"),
("bpy.types.posebone.rigify_type*", "addons/rigging/rigify/rig_types/index.html#bpy-types-posebone-rigify-type"),
("bpy.types.preferencesfilepaths*", "editors/preferences/file_paths.html#bpy-types-preferencesfilepaths"),
@ -1718,6 +1747,7 @@ url_manual_mapping = (
("bpy.types.cyclesworldsettings*", "render/cycles/world_settings.html#bpy-types-cyclesworldsettings"),
("bpy.types.dashgpencilmodifier*", "grease_pencil/modifiers/generate/dash.html#bpy-types-dashgpencilmodifier"),
("bpy.types.fluiddomainsettings*", "physics/fluid/type/domain/index.html#bpy-types-fluiddomainsettings"),
("bpy.types.functionnodecompare*", "modeling/geometry_nodes/utilities/compare.html#bpy-types-functionnodecompare"),
("bpy.types.geometrynodeboolean*", "modeling/geometry_nodes/input/boolean.html#bpy-types-geometrynodeboolean"),
("bpy.types.geometrynodeinputid*", "modeling/geometry_nodes/input/id.html#bpy-types-geometrynodeinputid"),
("bpy.types.geometrynodeinteger*", "modeling/geometry_nodes/input/integer.html#bpy-types-geometrynodeinteger"),
@ -1744,6 +1774,7 @@ url_manual_mapping = (
("bpy.types.shadernodelightpath*", "render/shader_nodes/input/light_path.html#bpy-types-shadernodelightpath"),
("bpy.types.shadernodemixshader*", "render/shader_nodes/shader/mix.html#bpy-types-shadernodemixshader"),
("bpy.types.shadernodenormalmap*", "render/shader_nodes/vector/normal_map.html#bpy-types-shadernodenormalmap"),
("bpy.types.shadernodepointinfo*", "render/shader_nodes/input/point_info.html#bpy-types-shadernodepointinfo"),
("bpy.types.shadernodewireframe*", "render/shader_nodes/input/wireframe.html#bpy-types-shadernodewireframe"),
("bpy.types.spacesequenceeditor*", "video_editing/index.html#bpy-types-spacesequenceeditor"),
("bpy.types.spline.resolution_u*", "modeling/curves/properties/active_spline.html#bpy-types-spline-resolution-u"),
@ -1756,6 +1787,7 @@ url_manual_mapping = (
("bpy.types.tintgpencilmodifier*", "grease_pencil/modifiers/color/tint.html#bpy-types-tintgpencilmodifier"),
("bpy.types.transformconstraint*", "animation/constraints/transform/transformation.html#bpy-types-transformconstraint"),
("bpy.types.triangulatemodifier*", "modeling/modifiers/generate/triangulate.html#bpy-types-triangulatemodifier"),
("bpy.types.unitsettings.system*", "scene_layout/scene/properties.html#bpy-types-unitsettings-system"),
("bpy.types.viewlayer.use_solid*", "render/layers/introduction.html#bpy-types-viewlayer-use-solid"),
("bpy.types.volume.frame_offset*", "modeling/volumes/properties.html#bpy-types-volume-frame-offset"),
("bpy.types.windowmanager.addon*", "editors/preferences/addons.html#bpy-types-windowmanager-addon"),
@ -1788,6 +1820,7 @@ url_manual_mapping = (
("bpy.ops.node.node_copy_color*", "interface/controls/nodes/sidebar.html#bpy-ops-node-node-copy-color"),
("bpy.ops.node.read_viewlayers*", "interface/controls/nodes/editing.html#bpy-ops-node-read-viewlayers"),
("bpy.ops.node.tree_socket_add*", "interface/controls/nodes/groups.html#bpy-ops-node-tree-socket-add"),
("bpy.ops.object.attribute_add*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-object-attribute-add"),
("bpy.ops.object.data_transfer*", "scene_layout/object/editing/link_transfer/transfer_mesh_data.html#bpy-ops-object-data-transfer"),
("bpy.ops.object.modifier_copy*", "modeling/modifiers/introduction.html#bpy-ops-object-modifier-copy"),
("bpy.ops.object.select_camera*", "scene_layout/object/selecting.html#bpy-ops-object-select-camera"),
@ -1819,12 +1852,12 @@ url_manual_mapping = (
("bpy.types.armature.show_axes*", "animation/armatures/properties/display.html#bpy-types-armature-show-axes"),
("bpy.types.armatureconstraint*", "animation/constraints/relationship/armature.html#bpy-types-armatureconstraint"),
("bpy.types.compositornodeblur*", "compositing/types/filter/blur_node.html#bpy-types-compositornodeblur"),
("bpy.types.compositornodecomb*", "editors/texture_node/types/color/combine_separate.html#bpy-types-compositornodecomb"),
("bpy.types.compositornodecomb*", "compositing/types/converter/combine_separate.html#bpy-types-compositornodecomb"),
("bpy.types.compositornodecrop*", "compositing/types/distort/crop.html#bpy-types-compositornodecrop"),
("bpy.types.compositornodeflip*", "compositing/types/distort/flip.html#bpy-types-compositornodeflip"),
("bpy.types.compositornodemask*", "compositing/types/input/mask.html#bpy-types-compositornodemask"),
("bpy.types.compositornodemath*", "compositing/types/converter/math.html#bpy-types-compositornodemath"),
("bpy.types.compositornodetime*", "compositing/types/input/time.html#bpy-types-compositornodetime"),
("bpy.types.compositornodetime*", "compositing/types/input/time_curve.html#bpy-types-compositornodetime"),
("bpy.types.constraint.enabled*", "animation/constraints/interface/header.html#bpy-types-constraint-enabled"),
("bpy.types.curve.bevel_object*", "modeling/curves/properties/geometry.html#bpy-types-curve-bevel-object"),
("bpy.types.curve.resolution_u*", "modeling/curves/properties/shape.html#bpy-types-curve-resolution-u"),
@ -1860,7 +1893,6 @@ url_manual_mapping = (
("bpy.types.shadernodeemission*", "render/shader_nodes/shader/emission.html#bpy-types-shadernodeemission"),
("bpy.types.shadernodegeometry*", "render/shader_nodes/input/geometry.html#bpy-types-shadernodegeometry"),
("bpy.types.shadernodehairinfo*", "render/shader_nodes/input/hair_info.html#bpy-types-shadernodehairinfo"),
("bpy.types.shadernodepointinfo*", "render/shader_nodes/input/point_info.html#bpy-types-shadernodepointinfo"),
("bpy.types.shadernodemaprange*", "render/shader_nodes/converter/map_range.html#bpy-types-shadernodemaprange"),
("bpy.types.shadernodergbcurve*", "modeling/geometry_nodes/color/rgb_curves.html#bpy-types-shadernodergbcurve"),
("bpy.types.shadernodeseparate*", "render/shader_nodes/converter/combine_separate.html#bpy-types-shadernodeseparate"),
@ -1892,6 +1924,7 @@ url_manual_mapping = (
("bpy.ops.curve.smooth_weight*", "modeling/curves/editing/control_points.html#bpy-ops-curve-smooth-weight"),
("bpy.ops.file.pack_libraries*", "files/blend/packed_data.html#bpy-ops-file-pack-libraries"),
("bpy.ops.font.change_spacing*", "modeling/texts/editing.html#bpy-ops-font-change-spacing"),
("bpy.ops.gpencil.layer_merge*", "grease_pencil/properties/layers.html#bpy-ops-gpencil-layer-merge"),
("bpy.ops.gpencil.stroke_flip*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-flip"),
("bpy.ops.gpencil.stroke_join*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-join"),
("bpy.ops.gpencil.stroke_trim*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-trim"),
@ -1949,7 +1982,7 @@ url_manual_mapping = (
("bpy.types.collisionmodifier*", "physics/collision.html#bpy-types-collisionmodifier"),
("bpy.types.collisionsettings*", "physics/collision.html#bpy-types-collisionsettings"),
("bpy.types.compositornodergb*", "compositing/types/input/rgb.html#bpy-types-compositornodergb"),
("bpy.types.compositornodesep*", "editors/texture_node/types/color/combine_separate.html#bpy-types-compositornodesep"),
("bpy.types.compositornodesep*", "compositing/types/converter/combine_separate.html#bpy-types-compositornodesep"),
("bpy.types.curve.bevel_depth*", "modeling/curves/properties/geometry.html#bpy-types-curve-bevel-depth"),
("bpy.types.curve.use_stretch*", "modeling/curves/properties/shape.html#bpy-types-curve-use-stretch"),
("bpy.types.edgesplitmodifier*", "modeling/modifiers/generate/edge_split.html#bpy-types-edgesplitmodifier"),
@ -2172,6 +2205,7 @@ url_manual_mapping = (
("bpy.types.floorconstraint*", "animation/constraints/relationship/floor.html#bpy-types-floorconstraint"),
("bpy.types.fmodifiercycles*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifiercycles"),
("bpy.types.fmodifierlimits*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierlimits"),
("bpy.types.geometrynodearc*", "modeling/geometry_nodes/curve_primitives/arc.html#bpy-types-geometrynodearc"),
("bpy.types.imagepaint.mode*", "sculpt_paint/texture_paint/tool_settings/texture_slots.html#bpy-types-imagepaint-mode"),
("bpy.types.latticemodifier*", "modeling/modifiers/deform/lattice.html#bpy-types-latticemodifier"),
("bpy.types.materiallineart*", "render/materials/line_art.html#bpy-types-materiallineart"),
@ -2289,6 +2323,7 @@ url_manual_mapping = (
("bpy.ops.fluid.free_mesh*", "physics/fluid/type/domain/liquid/mesh.html#bpy-ops-fluid-free-mesh"),
("bpy.ops.font.select_all*", "modeling/texts/selecting.html#bpy-ops-font-select-all"),
("bpy.ops.gpencil.convert*", "grease_pencil/modes/object/convert_to_geometry.html#bpy-ops-gpencil-convert"),
("bpy.ops.graph.breakdown*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-breakdown"),
("bpy.ops.mask.parent_set*", "movie_clip/masking/editing.html#bpy-ops-mask-parent-set"),
("bpy.ops.mask.select_all*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-all"),
("bpy.ops.mask.select_box*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-box"),
@ -2475,6 +2510,7 @@ url_manual_mapping = (
("bpy.ops.sculpt.expand*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-sculpt-expand"),
("bpy.ops.view3d.select*", "editors/3dview/selecting.html#bpy-ops-view3d-select"),
("bpy.ops.wm.debug_menu*", "advanced/operators.html#bpy-ops-wm-debug-menu"),
("bpy.ops.wm.obj_export*", "files/import_export/obj.html#bpy-ops-wm-obj-export"),
("bpy.ops.wm.properties*", "files/data_blocks.html#bpy-ops-wm-properties"),
("bpy.ops.wm.usd_export*", "files/import_export/usd.html#bpy-ops-wm-usd-export"),
("bpy.types.addsequence*", "video_editing/sequencer/strips/effects/add.html#bpy-types-addsequence"),
@ -2578,6 +2614,7 @@ url_manual_mapping = (
("bpy.types.node.name*", "interface/controls/nodes/sidebar.html#bpy-types-node-name"),
("bpy.types.nodeframe*", "interface/controls/nodes/frame.html#bpy-types-nodeframe"),
("bpy.types.nodegroup*", "interface/controls/nodes/groups.html#bpy-types-nodegroup"),
("bpy.types.scene.muv*", "addons/uv/magic_uv.html#bpy-types-scene-muv"),
("bpy.types.spotlight*", "render/lights/light_object.html#bpy-types-spotlight"),
("bpy.types.textcurve*", "modeling/texts/index.html#bpy-types-textcurve"),
("bpy.types.udimtiles*", "modeling/meshes/uv/workflows/udims.html#bpy-types-udimtiles"),
@ -2713,6 +2750,7 @@ url_manual_mapping = (
("bpy.ops.render*", "render/index.html#bpy-ops-render"),
("bpy.ops.script*", "advanced/scripting/index.html#bpy-ops-script"),
("bpy.ops.sculpt*", "sculpt_paint/sculpting/index.html#bpy-ops-sculpt"),
("bpy.ops.uv.muv*", "addons/uv/magic_uv.html#bpy-ops-uv-muv"),
("bpy.ops.uv.pin*", "modeling/meshes/uv/editing.html#bpy-ops-uv-pin"),
("bpy.ops.uv.rip*", "modeling/meshes/uv/tools/rip.html#bpy-ops-uv-rip"),
("bpy.ops.view3d*", "editors/3dview/index.html#bpy-ops-view3d"),

View File

@ -208,6 +208,9 @@ class Params:
# ------------------------------------------------------------------------------
# Constants
from math import pi
pi_2 = pi / 2.0
# Physical layout.
NUMBERS_1 = ('ONE', 'TWO', 'THREE', 'FOUR', 'FIVE', 'SIX', 'SEVEN', 'EIGHT', 'NINE', 'ZERO')
# Numeric order.
@ -1409,7 +1412,7 @@ def km_view3d(params):
("view3d.view_roll", {"type": 'NUMPAD_6', "value": 'PRESS', "shift": True, "repeat": True},
{"properties": [("type", 'RIGHT')]}),
("view3d.view_orbit", {"type": 'NUMPAD_9', "value": 'PRESS'},
{"properties": [("angle", 3.1415927), ("type", 'ORBITRIGHT')]}),
{"properties": [("angle", pi), ("type", 'ORBITRIGHT')]}),
("view3d.view_axis", {"type": 'NUMPAD_1', "value": 'PRESS', "shift": True},
{"properties": [("type", 'FRONT'), ("align_active", True)]}),
("view3d.view_axis", {"type": 'NUMPAD_3', "value": 'PRESS', "shift": True},
@ -1453,10 +1456,10 @@ def km_view3d(params):
("view3d.ndof_all", {"type": 'NDOF_MOTION', "value": 'ANY', "shift": True, "ctrl": True}, None),
("view3d.view_selected", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'},
{"properties": [("use_all_regions", False)]}),
("view3d.view_roll", {"type": 'NDOF_BUTTON_ROLL_CW', "value": 'PRESS'},
{"properties": [("angle", pi_2)]}),
("view3d.view_roll", {"type": 'NDOF_BUTTON_ROLL_CCW', "value": 'PRESS'},
{"properties": [("type", 'LEFT')]}),
("view3d.view_roll", {"type": 'NDOF_BUTTON_ROLL_CCW', "value": 'PRESS'},
{"properties": [("type", 'RIGHT')]}),
{"properties": [("angle", -pi_2)]}),
("view3d.view_axis", {"type": 'NDOF_BUTTON_FRONT', "value": 'PRESS'},
{"properties": [("type", 'FRONT')]}),
("view3d.view_axis", {"type": 'NDOF_BUTTON_BACK', "value": 'PRESS'},

View File

@ -995,11 +995,10 @@ class WM_OT_url_open_preset(Operator):
return "https://www.blender.org/download/releases/%d-%d/" % bpy.app.version[:2]
def _url_from_manual(self, _context):
if bpy.app.version_cycle in {"rc", "release"}:
manual_version = "%d.%d" % bpy.app.version[:2]
else:
manual_version = "dev"
return "https://docs.blender.org/manual/en/" + manual_version + "/"
return "https://docs.blender.org/manual/en/%d.%d/" % bpy.app.version[:2]
def _url_from_api(self, _context):
return "https://docs.blender.org/api/%d.%d/" % bpy.app.version[:2]
# This list is: (enum_item, url) pairs.
# Allow dynamically extending.
@ -1014,9 +1013,12 @@ class WM_OT_url_open_preset(Operator):
(('RELEASE_NOTES', "Release Notes",
"Read about what's new in this version of Blender"),
_url_from_release_notes),
(('MANUAL', "Manual",
(('MANUAL', "User Manual",
"The reference manual for this version of Blender"),
_url_from_manual),
(('API', "Python API Reference",
"The API reference manual for this version of Blender"),
_url_from_api),
# Static URL's.
(('FUND', "Development Fund",
@ -1231,11 +1233,7 @@ class WM_OT_doc_view(Operator):
bl_label = "View Documentation"
doc_id: doc_id
if bpy.app.version_cycle in {"release", "rc", "beta"}:
_prefix = ("https://docs.blender.org/api/%d.%d" %
(bpy.app.version[0], bpy.app.version[1]))
else:
_prefix = ("https://docs.blender.org/api/master")
_prefix = "https://docs.blender.org/api/%d.%d" % bpy.app.version[:2]
def execute(self, _context):
url = _wm_doc_get_id(self.doc_id, do_url=True, url_prefix=self._prefix, report=self.report)

View File

@ -35,6 +35,17 @@ class DATA_PT_context_curves(DataButtonsPanel, Panel):
layout.template_ID(space, "pin_id")
class DATA_PT_curves_surface(DataButtonsPanel, Panel):
bl_label = "Surface"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
ob = context.object
layout.prop(ob.data, "surface")
class CURVES_MT_add_attribute(Menu):
bl_label = "Add Attribute"
@ -115,6 +126,7 @@ class DATA_PT_custom_props_curves(DataButtonsPanel, PropertyPanel, Panel):
classes = (
DATA_PT_context_curves,
DATA_PT_CURVES_attributes,
DATA_PT_curves_surface,
DATA_PT_custom_props_curves,
CURVES_MT_add_attribute,
CURVES_UL_attributes,

View File

@ -688,8 +688,8 @@ class TOPBAR_MT_help(Menu):
layout.separator()
layout.operator(
"wm.url_open", text="Python API Reference", icon='URL',
).url = bpy.types.WM_OT_doc_view._prefix
"wm.url_open_preset", text="Python API Reference", icon='URL',
).type = 'API'
if show_developer:
layout.operator(

View File

@ -1718,6 +1718,7 @@ class USERPREF_PT_ndof_settings(Panel):
if show_3dview_settings:
col.prop(props, "ndof_show_guide")
col.prop(props, "ndof_zoom_invert")
col.prop(props, "ndof_lock_camera_pan_zoom")
row = col.row(heading="Pan")
row.prop(props, "ndof_pan_yz_swap_axis", text="Swap Y and Z Axes")

View File

@ -142,6 +142,7 @@ def mesh_node_items(context):
yield NodeItem("GeometryNodeInputMeshEdgeVertices")
yield NodeItem("GeometryNodeInputMeshFaceArea")
yield NodeItem("GeometryNodeInputMeshFaceNeighbors")
yield NodeItem("GeometryNodeInputMeshFaceIsPlanar")
yield NodeItem("GeometryNodeInputMeshIsland")
yield NodeItem("GeometryNodeInputShadeSmooth")
yield NodeItem("GeometryNodeInputMeshVertexNeighbors")
@ -164,6 +165,7 @@ def geometry_node_items(context):
yield NodeItem("GeometryNodeBoundBox")
yield NodeItem("GeometryNodeConvexHull")
yield NodeItem("GeometryNodeDeleteGeometry")
yield NodeItem("GeometryNodeDuplicateElements")
yield NodeItem("GeometryNodeGeometryToInstance")
yield NodeItem("GeometryNodeMergeByDistance")
yield NodeItem("GeometryNodeProximity")

View File

@ -31,7 +31,7 @@ extern "C" {
* version. Older Blender versions will test this and show a warning if the file
* was written with too new a version. */
#define BLENDER_FILE_MIN_VERSION 300
#define BLENDER_FILE_MIN_SUBVERSION 42
#define BLENDER_FILE_MIN_SUBVERSION 43
/** User readable version string. */
const char *BKE_blender_version_string(void);

View File

@ -8,13 +8,13 @@
* General operations for brushes.
*/
#include "DNA_color_types.h"
#include "DNA_object_enums.h"
#ifdef __cplusplus
extern "C" {
#endif
enum eCurveMappingPreset;
struct Brush;
struct ImBuf;
struct ImagePool;

View File

@ -82,6 +82,8 @@ class CurvesGeometry : public ::CurvesGeometry {
int points_size() const;
int curves_size() const;
IndexRange points_range() const;
IndexRange curves_range() const;
/**
* The total number of points in the evaluated poly curve.

View File

@ -92,7 +92,13 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
*
* \param id_hierarchy_root: the override ID that is the root of the hierarchy. May be NULL, in
* which case it is assumed that the given `id_root_reference` is tagged for override, and its
* newly created override will be used as hierarchy root.
* newly created override will be used as hierarchy root. Must be NULL if
* `id_hierarchy_root_reference` is not NULL.
*
* \param id_hierarchy_root_reference: the linked ID that is the root of the hierarchy. Must be
* tagged for override. May be NULL, in which case it is assumed that the given `id_root_reference`
* is tagged for override, and its newly created override will be used as hierarchy root. Must be
* NULL if `id_hierarchy_root` is not NULL.
*
* \param do_no_main: Create the new override data outside of Main database.
* Used for resyncing of linked overrides.
@ -103,6 +109,7 @@ bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
struct Library *owner_library,
const struct ID *id_root_reference,
struct ID *id_hierarchy_root,
const struct ID *id_hierarchy_root_reference,
bool do_no_main);
/**
* Advanced 'smart' function to create fully functional overrides.
@ -119,11 +126,18 @@ bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
* \param owner_library: the library in which the overrides should be created. Besides versioning
* and resync code path, this should always be NULL (i.e. the local .blend file).
*
* \param id_root: The root ID to create an override from.
* \param id_root_reference: The linked root ID to create an override from. May be a sub-root of
* the overall hierarchy, in which case calling code is expected to have already tagged required
* 'path' of IDs leading from the given `id_hierarchy_root` to the given `id_root`.
*
* \param id_reference: Some reference ID used to do some post-processing after overrides have been
* created, may be NULL. Typically, the Empty object instantiating the linked collection we
* override, currently.
* \param id_hierarchy_root_reference: The ID to be used a hierarchy root of the overrides to be
* created. Can be either the linked root ID of the whole override hierarchy, (typically the same
* as `id_root`, unless a sub-part only of the hierarchy is overridden), or the already existing
* override hierarchy root if part of the hierarchy is already overridden.
*
* \param id_instance_hint: Some ID used as hint/reference to do some post-processing after
* overrides have been created, may be NULL. Typically, the Empty object instantiating the linked
* collection we override, currently.
*
* \param r_id_root_override: if not NULL, the override generated for the given \a id_root.
*
@ -133,8 +147,9 @@ bool BKE_lib_override_library_create(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
struct Library *owner_library,
struct ID *id_root,
struct ID *id_reference,
struct ID *id_root_reference,
struct ID *id_hierarchy_root_reference,
struct ID *id_instance_hint,
struct ID **r_id_root_override);
/**
* Create a library override template.

View File

@ -405,6 +405,9 @@ void BKE_mesh_assert_normals_dirty_or_calculated(const struct Mesh *mesh);
* \note In order to clear the dirty flag, this function should be followed by a call to
* #BKE_mesh_vertex_normals_clear_dirty. This is separate so that normals are still tagged dirty
* while they are being assigned.
*
* \warning The memory returned by this function is not initialized if it was not previously
* allocated.
*/
float (*BKE_mesh_vertex_normals_for_write(struct Mesh *mesh))[3];
@ -415,6 +418,9 @@ float (*BKE_mesh_vertex_normals_for_write(struct Mesh *mesh))[3];
* \note In order to clear the dirty flag, this function should be followed by a call to
* #BKE_mesh_poly_normals_clear_dirty. This is separate so that normals are still tagged dirty
* while they are being assigned.
*
* \warning The memory returned by this function is not initialized if it was not previously
* allocated.
*/
float (*BKE_mesh_poly_normals_for_write(struct Mesh *mesh))[3];

View File

@ -1514,6 +1514,8 @@ struct TexResult;
#define GEO_NODE_SCALE_ELEMENTS 1151
#define GEO_NODE_EXTRUDE_MESH 1152
#define GEO_NODE_MERGE_BY_DISTANCE 1153
#define GEO_NODE_DUPLICATE_ELEMENTS 1154
#define GEO_NODE_INPUT_MESH_FACE_IS_PLANAR 1155
/** \} */

View File

@ -24,18 +24,30 @@ void BKE_subsurf_modifier_subdiv_settings_init(struct SubdivSettings *settings,
const struct SubsurfModifierData *smd,
bool use_render_params);
bool BKE_subsurf_modifier_use_custom_loop_normals(const struct SubsurfModifierData *smd,
const struct Mesh *mesh);
/**
* Return true if GPU subdivision evaluation is disabled by force due to incompatible mesh or
* modifier settings. This will only return true if GPU subdivision is enabled in the preferences
* and supported by the GPU. It is mainly useful for showing UI messages.
*/
bool BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(
const struct SubsurfModifierData *smd, const struct Mesh *mesh);
/**
* \param skip_check_is_last: When true, we assume that the modifier passed is the last enabled
* modifier in the stack.
*/
bool BKE_subsurf_modifier_can_do_gpu_subdiv_ex(const struct Scene *scene,
const struct Object *ob,
const struct Mesh *mesh,
const struct SubsurfModifierData *smd,
int required_mode,
bool skip_check_is_last);
bool BKE_subsurf_modifier_can_do_gpu_subdiv(const struct Scene *scene,
const struct Object *ob,
const struct Mesh *mesh,
int required_mode);
extern void (*BKE_subsurf_modifier_free_gpu_cache_cb)(struct Subdiv *subdiv);

View File

@ -114,6 +114,7 @@ static void curves_foreach_id(ID *id, LibraryForeachIDData *data)
for (int i = 0; i < curves->totcol; i++) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, curves->mat[i], IDWALK_CB_USER);
}
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, curves->surface, IDWALK_CB_NOP);
}
static void curves_blend_write(BlendWriter *writer, ID *id, const void *id_address)
@ -186,6 +187,7 @@ static void curves_blend_read_lib(BlendLibReader *reader, ID *id)
for (int a = 0; a < curves->totcol; a++) {
BLO_read_id_address(reader, curves->id.lib, &curves->mat[a]);
}
BLO_read_id_address(reader, curves->id.lib, &curves->surface);
}
static void curves_blend_read_expand(BlendExpander *expander, ID *id)
@ -194,6 +196,7 @@ static void curves_blend_read_expand(BlendExpander *expander, ID *id)
for (int a = 0; a < curves->totcol; a++) {
BLO_expand(expander, curves->mat[a]);
}
BLO_expand(expander, curves->surface);
}
IDTypeInfo IDType_ID_CV = {

View File

@ -106,6 +106,15 @@ int CurvesGeometry::curves_size() const
{
return this->curve_size;
}
IndexRange CurvesGeometry::points_range() const
{
return IndexRange(this->points_size());
}
IndexRange CurvesGeometry::curves_range() const
{
return IndexRange(this->curves_size());
}
int CurvesGeometry::evaluated_points_size() const
{
/* TODO: Implement when there are evaluated points. */
@ -136,7 +145,6 @@ MutableSpan<int8_t> CurvesGeometry::curve_types()
nullptr,
this->curve_size,
ATTR_CURVE_TYPE.c_str());
BLI_assert(data != nullptr);
return {data, this->curve_size};
}

View File

@ -1777,7 +1777,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 44: CD_RADIUS */
{sizeof(float), "MFloatProperty", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 45: CD_PROP_INT8 */
{sizeof(int8_t), "MInt8Property", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
{sizeof(int8_t), "MInt8Property", 1, N_("Int8"), nullptr, nullptr, nullptr, nullptr, nullptr},
/* 46: CD_HAIRMAPPING */ /* UNUSED */
{-1, "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 47: CD_PROP_COLOR */

View File

@ -263,7 +263,6 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
/* This should be ensured by cddata_masks we pass to code generating/giving us me_src now. */
BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != NULL);
BLI_assert(CustomData_get_layer(&me_src->pdata, CD_NORMAL) != NULL);
(void)me_src;
float(*loop_nors_dst)[3];
@ -318,15 +317,12 @@ static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src),
const int num_polys_dst = me_dst->totpoly;
MLoop *loops_dst = me_dst->mloop;
const int num_loops_dst = me_dst->totloop;
CustomData *pdata_dst = &me_dst->pdata;
CustomData *ldata_dst = &me_dst->ldata;
const float(*poly_nors_dst)[3] = CustomData_get_layer(pdata_dst, CD_NORMAL);
const float(*poly_nors_dst)[3] = BKE_mesh_poly_normals_ensure(me_dst);
float(*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL);
short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
BLI_assert(poly_nors_dst);
if (!custom_nors_dst) {
custom_nors_dst = CustomData_add_layer(
ldata_dst, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops_dst);

View File

@ -880,15 +880,7 @@ class VArrayImpl_For_SplinePosition final : public VMutableArrayImpl<float3> {
{
const PointIndices indices = lookup_point_indices(offsets_, index);
Spline &spline = *splines_[indices.spline_index];
if (BezierSpline *bezier_spline = dynamic_cast<BezierSpline *>(&spline)) {
const float3 delta = value - bezier_spline->positions()[indices.point_index];
bezier_spline->handle_positions_left()[indices.point_index] += delta;
bezier_spline->handle_positions_right()[indices.point_index] += delta;
bezier_spline->positions()[indices.point_index] = value;
}
else {
spline.positions()[indices.point_index] = value;
}
spline.positions()[indices.point_index] = value;
}
void set_all(Span<float3> src) final
@ -897,20 +889,7 @@ class VArrayImpl_For_SplinePosition final : public VMutableArrayImpl<float3> {
Spline &spline = *splines_[spline_index];
const int offset = offsets_[spline_index];
const int next_offset = offsets_[spline_index + 1];
if (BezierSpline *bezier_spline = dynamic_cast<BezierSpline *>(&spline)) {
MutableSpan<float3> positions = bezier_spline->positions();
MutableSpan<float3> handle_positions_left = bezier_spline->handle_positions_left();
MutableSpan<float3> handle_positions_right = bezier_spline->handle_positions_right();
for (const int i : IndexRange(next_offset - offset)) {
const float3 delta = src[offset + i] - positions[i];
handle_positions_left[i] += delta;
handle_positions_right[i] += delta;
positions[i] = src[offset + i];
}
}
else {
spline.positions().copy_from(src.slice(offset, next_offset - offset));
}
spline.positions().copy_from(src.slice(offset, next_offset - offset));
}
}
@ -973,10 +952,10 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> {
if (spline.type() == CURVE_TYPE_BEZIER) {
BezierSpline &bezier_spline = static_cast<BezierSpline &>(spline);
if (is_right_) {
bezier_spline.set_handle_position_right(indices.point_index, value);
bezier_spline.handle_positions_right()[indices.point_index] = value;
}
else {
bezier_spline.set_handle_position_left(indices.point_index, value);
bezier_spline.handle_positions_left()[indices.point_index] = value;
}
bezier_spline.mark_cache_invalid();
}
@ -992,12 +971,12 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> {
BezierSpline &bezier_spline = static_cast<BezierSpline &>(spline);
if (is_right_) {
for (const int i : IndexRange(bezier_spline.size())) {
bezier_spline.set_handle_position_right(i, src[offset + i]);
bezier_spline.handle_positions_right()[i] = src[offset + i];
}
}
else {
for (const int i : IndexRange(bezier_spline.size())) {
bezier_spline.set_handle_position_left(i, src[offset + i]);
bezier_spline.handle_positions_left()[i] = src[offset + i];
}
}
bezier_spline.mark_cache_invalid();

View File

@ -321,17 +321,36 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
return local_id;
}
/* TODO: Make this static local function instead? API is becoming complex, and it's not used
* outside of this file anyway. */
bool BKE_lib_override_library_create_from_tag(Main *bmain,
Library *owner_library,
const ID *id_root_reference,
ID *id_hierarchy_root,
const ID *id_hierarchy_root_reference,
const bool do_no_main)
{
BLI_assert(id_root_reference != NULL);
BLI_assert(id_hierarchy_root != NULL || (id_root_reference->tag & LIB_TAG_DOIT) != 0);
BLI_assert(id_hierarchy_root == NULL ||
(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root) &&
id_hierarchy_root->override_library->reference == id_root_reference));
BLI_assert(id_root_reference != NULL && ID_IS_LINKED(id_root_reference));
/* If we do not have any hierarchy root given, then the root reference must be tagged for
* override. */
BLI_assert(id_hierarchy_root != NULL || id_hierarchy_root_reference != NULL ||
(id_root_reference->tag & LIB_TAG_DOIT) != 0);
/* At least one of the hierarchy root pointers must be NULL, passing both is useless and can
* create confusion. */
BLI_assert(ELEM(NULL, id_hierarchy_root, id_hierarchy_root_reference));
if (id_hierarchy_root != NULL) {
/* If the hierarchy root is given, it must be a valid existing override (used during partial
* resync process mainly). */
BLI_assert((ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root) &&
id_hierarchy_root->override_library->reference->lib == id_root_reference->lib));
}
if (!ELEM(id_hierarchy_root_reference, NULL, id_root_reference)) {
/* If the reference hierarchy root is given, it must be from the same library as the reference
* root, and also tagged for override. */
BLI_assert((id_hierarchy_root_reference->lib == id_root_reference->lib &&
(id_hierarchy_root_reference->tag & LIB_TAG_DOIT) != 0));
}
const Library *reference_library = id_root_reference->lib;
@ -387,7 +406,12 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
/* Only remap new local ID's pointers, we don't want to force our new overrides onto our whole
* existing linked IDs usages. */
if (success) {
if (id_root_reference->newid != NULL) {
if (id_hierarchy_root_reference != NULL) {
id_hierarchy_root = id_hierarchy_root_reference->newid;
}
else if (id_root_reference->newid != NULL &&
(id_hierarchy_root == NULL ||
id_hierarchy_root->override_library->reference == id_root_reference)) {
id_hierarchy_root = id_root_reference->newid;
}
BLI_assert(id_hierarchy_root != NULL);
@ -887,12 +911,13 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data)
static bool lib_override_library_create_do(Main *bmain,
Scene *scene,
Library *owner_library,
ID *id_root)
ID *id_root_reference,
ID *id_hierarchy_root_reference)
{
BKE_main_relations_create(bmain, 0);
LibOverrideGroupTagData data = {.bmain = bmain,
.scene = scene,
.id_root = id_root,
.id_root = id_root_reference,
.tag = LIB_TAG_DOIT,
.missing_tag = LIB_TAG_MISSING,
.is_override = false,
@ -906,8 +931,18 @@ static bool lib_override_library_create_do(Main *bmain,
BKE_main_relations_free(bmain);
lib_override_group_tag_data_clear(&data);
const bool success = BKE_lib_override_library_create_from_tag(
bmain, owner_library, id_root, NULL, false);
bool success = false;
if (id_hierarchy_root_reference->lib != id_root_reference->lib) {
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root_reference));
BLI_assert(id_hierarchy_root_reference->override_library->reference->lib ==
id_root_reference->lib);
success = BKE_lib_override_library_create_from_tag(
bmain, owner_library, id_root_reference, id_hierarchy_root_reference, NULL, false);
}
else {
success = BKE_lib_override_library_create_from_tag(
bmain, owner_library, id_root_reference, NULL, id_hierarchy_root_reference, false);
}
return success;
}
@ -917,7 +952,7 @@ static void lib_override_library_create_post_process(Main *bmain,
ViewLayer *view_layer,
const Library *owner_library,
ID *id_root,
ID *id_reference,
ID *id_instance_hint,
Collection *residual_storage,
const bool is_resync)
{
@ -941,8 +976,8 @@ static void lib_override_library_create_post_process(Main *bmain,
(!ID_IS_LINKED(id_root->newid) || id_root->newid->lib == owner_library)) {
switch (GS(id_root->name)) {
case ID_GR: {
Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ?
(Object *)id_reference :
Object *ob_reference = id_instance_hint != NULL && GS(id_instance_hint->name) == ID_OB ?
(Object *)id_instance_hint :
NULL;
Collection *collection_new = ((Collection *)id_root->newid);
if (is_resync && BKE_collection_is_in_scene(collection_new)) {
@ -951,10 +986,10 @@ static void lib_override_library_create_post_process(Main *bmain,
if (ob_reference != NULL) {
BKE_collection_add_from_object(bmain, scene, ob_reference, collection_new);
}
else if (id_reference != NULL) {
BLI_assert(GS(id_reference->name) == ID_GR);
else if (id_instance_hint != NULL) {
BLI_assert(GS(id_instance_hint->name) == ID_GR);
BKE_collection_add_from_collection(
bmain, scene, ((Collection *)id_reference), collection_new);
bmain, scene, ((Collection *)id_instance_hint), collection_new);
}
else {
BKE_collection_add_from_collection(
@ -1047,26 +1082,32 @@ bool BKE_lib_override_library_create(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
Library *owner_library,
ID *id_root,
ID *id_reference,
ID *id_root_reference,
ID *id_hierarchy_root_reference,
ID *id_instance_hint,
ID **r_id_root_override)
{
if (r_id_root_override != NULL) {
*r_id_root_override = NULL;
}
const bool success = lib_override_library_create_do(bmain, scene, owner_library, id_root);
if (id_hierarchy_root_reference == NULL) {
id_hierarchy_root_reference = id_root_reference;
}
const bool success = lib_override_library_create_do(
bmain, scene, owner_library, id_root_reference, id_hierarchy_root_reference);
if (!success) {
return success;
}
if (r_id_root_override != NULL) {
*r_id_root_override = id_root->newid;
*r_id_root_override = id_root_reference->newid;
}
lib_override_library_create_post_process(
bmain, scene, view_layer, owner_library, id_root, id_reference, NULL, false);
bmain, scene, view_layer, owner_library, id_root_reference, id_instance_hint, NULL, false);
/* Cleanup. */
BKE_main_id_newptr_and_tag_clear(bmain);
@ -1527,7 +1568,7 @@ static bool lib_override_library_resync(Main *bmain,
* override IDs (including within the old overrides themselves, since those are tagged too
* above). */
const bool success = BKE_lib_override_library_create_from_tag(
bmain, NULL, id_root_reference, id_root->override_library->hierarchy_root, true);
bmain, NULL, id_root_reference, id_root->override_library->hierarchy_root, NULL, true);
if (!success) {
BLI_ghash_free(linkedref_to_old_override, NULL, NULL);

View File

@ -42,7 +42,7 @@ bool BKE_lib_override_library_proxy_convert(Main *bmain,
const bool is_override_instancing_object = ob_proxy_group != NULL;
ID *id_root = is_override_instancing_object ? &ob_proxy_group->instance_collection->id :
&ob_proxy->proxy->id;
ID *id_reference = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id;
ID *id_instance_hint = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id;
/* In some cases the instance collection of a proxy object may be local (see e.g. T83875). Not
* sure this is a valid state, but for now just abort the overriding process. */
@ -81,7 +81,7 @@ bool BKE_lib_override_library_proxy_convert(Main *bmain,
FOREACH_MAIN_ID_END;
return BKE_lib_override_library_create(
bmain, scene, view_layer, ob_proxy->id.lib, id_root, id_reference, NULL);
bmain, scene, view_layer, ob_proxy->id.lib, id_root, id_root, id_instance_hint, NULL);
}
static void lib_override_library_proxy_convert_do(Main *bmain,

View File

@ -448,7 +448,7 @@ uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner)
case ID_WS:
return FILTER_ID_SCE;
case ID_CV:
return FILTER_ID_MA;
return FILTER_ID_MA | FILTER_ID_OB;
case ID_PT:
return FILTER_ID_MA;
case ID_VO:

View File

@ -220,14 +220,13 @@ void BKE_mesh_calc_normals_poly(const MVert *mvert,
* \{ */
struct MeshCalcNormalsData_PolyAndVertex {
/** Write into vertex normals #MVert.no. */
MVert *mvert;
const MVert *mvert;
const MLoop *mloop;
const MPoly *mpoly;
/** Polygon normal output. */
float (*pnors)[3];
/** Vertex normal output (may be freed, copied into #MVert.no). */
/** Vertex normal output. */
float (*vnors)[3];
};
@ -298,7 +297,7 @@ static void mesh_calc_normals_poly_and_vertex_finalize_fn(
{
MeshCalcNormalsData_PolyAndVertex *data = (MeshCalcNormalsData_PolyAndVertex *)userdata;
MVert *mv = &data->mvert[vidx];
const MVert *mv = &data->mvert[vidx];
float *no = data->vnors[vidx];
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
@ -307,7 +306,7 @@ static void mesh_calc_normals_poly_and_vertex_finalize_fn(
}
}
static void mesh_calc_normals_poly_and_vertex(MVert *mvert,
static void mesh_calc_normals_poly_and_vertex(const MVert *mvert,
const int mvert_len,
const MLoop *mloop,
const int UNUSED(mloop_len),
@ -320,36 +319,22 @@ static void mesh_calc_normals_poly_and_vertex(MVert *mvert,
BLI_parallel_range_settings_defaults(&settings);
settings.min_iter_per_thread = 1024;
float(*vnors)[3] = r_vert_normals;
bool free_vnors = false;
/* First go through and calculate normals for all the polys. */
if (vnors == nullptr) {
vnors = (float(*)[3])MEM_calloc_arrayN((size_t)mvert_len, sizeof(*vnors), __func__);
free_vnors = true;
}
else {
memset(vnors, 0, sizeof(*vnors) * (size_t)mvert_len);
}
memset(r_vert_normals, 0, sizeof(*r_vert_normals) * (size_t)mvert_len);
MeshCalcNormalsData_PolyAndVertex data = {};
data.mpoly = mpoly;
data.mloop = mloop;
data.mvert = mvert;
data.pnors = r_poly_normals;
data.vnors = vnors;
data.vnors = r_vert_normals;
/* Compute poly normals (`pnors`), accumulating them into vertex normals (`vnors`). */
/* Compute poly normals, accumulating them into vertex normals. */
BLI_task_parallel_range(
0, mpoly_len, &data, mesh_calc_normals_poly_and_vertex_accum_fn, &settings);
/* Normalize and validate computed vertex normals (`vnors`). */
/* Normalize and validate computed vertex normals. */
BLI_task_parallel_range(
0, mvert_len, &data, mesh_calc_normals_poly_and_vertex_finalize_fn, &settings);
if (free_vnors) {
MEM_freeN(vnors);
}
}
/** \} */

View File

@ -4751,6 +4751,7 @@ static void registerGeometryNodes()
register_node_type_geo_curve_to_points();
register_node_type_geo_curve_trim();
register_node_type_geo_delete_geometry();
register_node_type_geo_duplicate_elements();
register_node_type_geo_distribute_points_on_faces();
register_node_type_geo_dual_mesh();
register_node_type_geo_edge_split();
@ -4769,6 +4770,7 @@ static void registerGeometryNodes()
register_node_type_geo_input_mesh_edge_neighbors();
register_node_type_geo_input_mesh_edge_vertices();
register_node_type_geo_input_mesh_face_area();
register_node_type_geo_input_mesh_face_is_planar();
register_node_type_geo_input_mesh_face_neighbors();
register_node_type_geo_input_mesh_island();
register_node_type_geo_input_mesh_vertex_neighbors();

View File

@ -54,23 +54,20 @@ static ModifierData *modifier_get_last_enabled_for_mode(const Scene *scene,
return md;
}
bool BKE_subsurf_modifier_can_do_gpu_subdiv_ex(const Scene *scene,
const Object *ob,
const SubsurfModifierData *smd,
int required_mode,
bool skip_check_is_last)
bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd, const Mesh *mesh)
{
if ((U.gpu_flag & USER_GPU_FLAG_SUBDIVISION_EVALUATION) == 0) {
return false;
}
return (smd->flags & eSubsurfModifierFlag_UseCustomNormals) && (mesh->flag & ME_AUTOSMOOTH) &&
CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
}
if (!skip_check_is_last) {
ModifierData *md = modifier_get_last_enabled_for_mode(scene, ob, required_mode);
if (md != (const ModifierData *)smd) {
return false;
}
}
static bool subsurf_modifier_use_autosmooth_or_split_normals(const SubsurfModifierData *smd,
const Mesh *mesh)
{
return (mesh->flag & ME_AUTOSMOOTH) || BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh);
}
static bool is_subdivision_evaluation_possible_on_gpu(void)
{
/* Only OpenGL is supported for OpenSubdiv evaluation for now. */
if (GPU_backend_get_type() != GPU_BACKEND_OPENGL) {
return false;
@ -88,8 +85,52 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv_ex(const Scene *scene,
return true;
}
bool BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(const SubsurfModifierData *smd,
const Mesh *mesh)
{
if ((U.gpu_flag & USER_GPU_FLAG_SUBDIVISION_EVALUATION) == 0) {
/* GPU subdivision is explicitely disabled, so we don't force it. */
return false;
}
if (!is_subdivision_evaluation_possible_on_gpu()) {
/* The GPU type is not compatible with the subdivision. */
return false;
}
return subsurf_modifier_use_autosmooth_or_split_normals(smd, mesh);
}
bool BKE_subsurf_modifier_can_do_gpu_subdiv_ex(const Scene *scene,
const Object *ob,
const Mesh *mesh,
const SubsurfModifierData *smd,
int required_mode,
bool skip_check_is_last)
{
if ((U.gpu_flag & USER_GPU_FLAG_SUBDIVISION_EVALUATION) == 0) {
return false;
}
/* Deactivate GPU subdivision if autosmooth or custom split normals are used as those are
* complicated to support on GPU, and should really be separate workflows. */
if (subsurf_modifier_use_autosmooth_or_split_normals(smd, mesh)) {
return false;
}
if (!skip_check_is_last) {
ModifierData *md = modifier_get_last_enabled_for_mode(scene, ob, required_mode);
if (md != (const ModifierData *)smd) {
return false;
}
}
return is_subdivision_evaluation_possible_on_gpu();
}
bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene,
const Object *ob,
const Mesh *mesh,
int required_mode)
{
ModifierData *md = modifier_get_last_enabled_for_mode(scene, ob, required_mode);
@ -103,7 +144,7 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene,
}
return BKE_subsurf_modifier_can_do_gpu_subdiv_ex(
scene, ob, (SubsurfModifierData *)md, required_mode, true);
scene, ob, mesh, (SubsurfModifierData *)md, required_mode, true);
}
void (*BKE_subsurf_modifier_free_gpu_cache_cb)(Subdiv *subdiv) = NULL;

View File

@ -811,8 +811,8 @@ static bool vfont_to_curve(Object *ob,
#define MARGIN_X_MIN (xof_scale + tb_scale.x)
#define MARGIN_Y_MIN (yof_scale + tb_scale.y)
/* remark: do calculations including the trailing '\0' of a string
* because the cursor can be at that location */
/* NOTE: do calculations including the trailing '\0' of a string
* because the cursor can be at that location. */
BLI_assert(ob == NULL || ob->type == OB_FONT);
@ -905,8 +905,8 @@ static bool vfont_to_curve(Object *ob,
custrinfo[i].flag &= ~(CU_CHINFO_WRAP | CU_CHINFO_SMALLCAPS_CHECK | CU_CHINFO_OVERFLOW);
}
for (i = 0; i <= slen; i++) {
makebreak:
i = 0;
while (i <= slen) {
/* Characters in the list */
info = &custrinfo[i];
ascii = mem[i];
@ -941,19 +941,16 @@ static bool vfont_to_curve(Object *ob,
che = find_vfont_char(vfd, ascii);
BLI_rw_mutex_unlock(&vfont_rwlock);
/*
* The character wasn't in the current curve base so load it
/* The character wasn't in the current curve base so load it.
* But if the font is built-in then do not try loading since
* whole font is in the memory already
*/
* whole font is in the memory already. */
if (che == NULL && BKE_vfont_is_builtin(vfont) == false) {
BLI_rw_mutex_lock(&vfont_rwlock, THREAD_LOCK_WRITE);
/* Check it once again, char might have been already load
* between previous BLI_rw_mutex_unlock() and this BLI_rw_mutex_lock().
* between previous #BLI_rw_mutex_unlock() and this #BLI_rw_mutex_lock().
*
* Such a check should not be a bottleneck since it wouldn't
* happen often once all the chars are load.
*/
* happen often once all the chars are load. */
if ((che = find_vfont_char(vfd, ascii)) == NULL) {
che = BKE_vfontdata_char_from_freetypefont(vfont, ascii);
}
@ -985,8 +982,23 @@ static bool vfont_to_curve(Object *ob,
}
else if (x_used > x_available) {
// CLOG_WARN(&LOG, "linewidth exceeded: %c%c%c...", mem[i], mem[i+1], mem[i+2]);
for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
bool dobreak = false;
bool dobreak = false;
for (j = i; (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
/* Special case when there are no breaks possible. */
if (UNLIKELY(j == 0)) {
if (i == slen) {
/* Use the behavior of zero a height text-box when a break cannot be inserted.
*
* Typically when a text-box has any height and overflow is set to scale
* the text will wrap to fit the width as necessary. When wrapping isn't
* possible it's important to use the same code-path as zero-height lines.
* Without this exception a single word will not scale-to-fit (see: T95116). */
tb_scale.h = 0.0f;
}
break;
}
if (ELEM(mem[j], ' ', '-')) {
ct -= (i - (j - 1));
cnr -= (i - (j - 1));
@ -1001,24 +1013,18 @@ static bool vfont_to_curve(Object *ob,
ct[1].dobreak = 1;
custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
dobreak = true;
break;
}
else if (chartransdata[j].dobreak) {
// CLOG_WARN(&LOG, "word too long: %c%c%c...", mem[j], mem[j+1], mem[j+2]);
ct->dobreak = 1;
custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
ct -= 1;
cnr -= 1;
i--;
xof = ct->xof;
dobreak = true;
}
if (dobreak) {
if (tb_scale.h == 0.0f) {
/* NOTE: If underlined text is truncated away, the extra space is also truncated. */
custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW;
}
goto makebreak;
BLI_assert(chartransdata[j].dobreak == 0);
}
if (dobreak) {
if (tb_scale.h == 0.0f) {
/* NOTE: If underlined text is truncated away, the extra space is also truncated. */
custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW;
}
/* Since a break was added, re-run this loop with `i` at it's new value. */
continue;
}
}
}
@ -1063,22 +1069,12 @@ static bool vfont_to_curve(Object *ob,
current_line_length = 0.0f;
}
/* XXX(campbell): has been unused for years, need to check if this is useful, r4613 r5282. */
#if 0
if (ascii == '\n') {
xof = xof_scale;
}
else {
xof = MARGIN_X_MIN;
}
#else
xof = MARGIN_X_MIN;
#endif
lnr++;
cnr = 0;
wsnr = 0;
}
else if (ascii == 9) { /* TAB */
else if (ascii == '\t') { /* Tab character. */
float tabfac;
ct->xof = xof;
@ -1106,7 +1102,7 @@ static bool vfont_to_curve(Object *ob,
sb->w = xof * font_size;
}
if (ascii == 32) {
if (ascii == ' ') { /* Space character. */
wsfac = cu->wordspace;
wsnr++;
}
@ -1114,7 +1110,7 @@ static bool vfont_to_curve(Object *ob,
wsfac = 1.0f;
}
/* Set the width of the character */
/* Set the width of the character. */
twidth = char_width(cu, che, info);
xof += (twidth * wsfac * (1.0f + (info->kern / 40.0f))) + xtrax;
@ -1124,7 +1120,9 @@ static bool vfont_to_curve(Object *ob,
}
}
ct++;
i++;
}
current_line_length += xof + twidth - MARGIN_X_MIN;
longest_line_length = MAX2(current_line_length, longest_line_length);
@ -1213,7 +1211,7 @@ static bool vfont_to_curve(Object *ob,
}
}
/* top-baseline is default, in this case, do nothing */
/* Top-baseline is default, in this case, do nothing. */
if (cu->align_y != CU_ALIGN_Y_TOP_BASELINE) {
if (tb_scale.h != 0.0f) {
/* We need to loop all the text-boxes even the "full" ones.
@ -1238,7 +1236,7 @@ static bool vfont_to_curve(Object *ob,
}
textbox_scale(&tb_scale, &cu->tb[tb_index], 1.0f / font_size);
/* The initial Y origin of the textbox is hardcoded to 1.0f * text scale. */
/* The initial Y origin of the text-box is hard-coded to 1.0f * text scale. */
const float textbox_y_origin = 1.0f;
float yoff = 0.0f;
@ -1302,7 +1300,7 @@ static bool vfont_to_curve(Object *ob,
MEM_freeN(i_textbox_array);
/* TEXT ON CURVE */
/* NOTE: Only OB_CURVES_LEGACY objects could have a path. */
/* NOTE: Only #OB_CURVES_LEGACY objects could have a path. */
if (cu->textoncurve && cu->textoncurve->type == OB_CURVES_LEGACY) {
BLI_assert(cu->textoncurve->runtime.curve_cache != NULL);
if (cu->textoncurve->runtime.curve_cache != NULL &&
@ -1393,8 +1391,8 @@ static bool vfont_to_curve(Object *ob,
ctime = timeofs + distfac * (ct->xof - minx);
CLAMP(ctime, 0.0f, 1.0f);
/* calc the right loc AND the right rot separately */
/* vec, tvec need 4 items */
/* Calculate the right loc AND the right rot separately. */
/* `vec`, `tvec` need 4 items. */
BKE_where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL, NULL);
BKE_where_on_path(cu->textoncurve, ctime + dtime, tvec, rotvec, NULL, NULL, NULL);
@ -1455,7 +1453,7 @@ static bool vfont_to_curve(Object *ob,
break;
}
cnr = ct->charnr;
/* seek for char with lnr en cnr */
/* Seek for char with `lnr` & `cnr`. */
ef->pos = 0;
ct = chartransdata;
for (i = 0; i < slen; i++) {
@ -1473,7 +1471,7 @@ static bool vfont_to_curve(Object *ob,
}
}
/* cursor first */
/* Cursor first. */
if (ef) {
float si, co;
@ -1519,13 +1517,13 @@ static bool vfont_to_curve(Object *ob,
}
/* Only do that check in case we do have an object, otherwise all materials get erased every
* time that code is called without an object... */
* time that code is called without an object. */
if (ob != NULL && (info->mat_nr > (ob->totcol))) {
// CLOG_ERROR(
// &LOG, "Illegal material index (%d) in text object, setting to 0", info->mat_nr);
info->mat_nr = 0;
}
/* We do not want to see any character for \n or \r */
/* We don't want to see any character for '\n'. */
if (cha != '\n') {
BKE_vfont_build_char(cu, r_nubase, cha, info, ct->xof, ct->yof, ct->rot, i, font_size);
}
@ -1601,8 +1599,7 @@ static bool vfont_to_curve(Object *ob,
*
* Keep in mind that there is no single number that will make all fit to the end.
* In a way, our ultimate goal is to get the highest scale that still leads to the
* number of extra lines to zero.
*/
* number of extra lines to zero. */
if (iter_data->status == VFONT_TO_CURVE_INIT) {
bool valid = true;
@ -1635,7 +1632,7 @@ static bool vfont_to_curve(Object *ob,
iter_data->bisect.max = iter_data->scale_to_fit;
}
else {
/* It fits inside the textbox, scale it up. */
/* It fits inside the text-box, scale it up. */
iter_data->bisect.min = iter_data->scale_to_fit;
valid = true;
}
@ -1697,7 +1694,7 @@ finally:
}
}
/* Store the effective scale, to use for the textbox lines. */
/* Store the effective scale, to use for the text-box lines. */
cu->fsize_realtime = font_size;
return ok;

View File

@ -278,18 +278,20 @@ class Array {
}
/**
* Return a reference to the last element in the array.
* This invokes undefined behavior when the array is empty.
* Return a reference to the nth last element.
* This invokes undefined behavior when the array is too short.
*/
const T &last() const
const T &last(const int64_t n = 0) const
{
BLI_assert(size_ > 0);
return *(data_ + size_ - 1);
BLI_assert(n >= 0);
BLI_assert(n < size_);
return *(data_ + size_ - 1 - n);
}
T &last()
T &last(const int64_t n = 0)
{
BLI_assert(size_ > 0);
return *(data_ + size_ - 1);
BLI_assert(n >= 0);
BLI_assert(n < size_);
return *(data_ + size_ - 1 - n);
}
/**

View File

@ -3,7 +3,25 @@
#pragma once
#ifdef WITH_TBB
# include <tbb/enumerable_thread_specific.h>
# ifdef WITH_TBB
/* Quiet top level deprecation message, unrelated to API usage here. */
# if defined(WIN32) && !defined(NOMINMAX)
/* TBB includes Windows.h which will define min/max macros causing issues
* when we try to use std::min and std::max later on. */
# define NOMINMAX
# define TBB_MIN_MAX_CLEANUP
# endif
# include <tbb/enumerable_thread_specific.h>
# ifdef WIN32
/* We cannot keep this defined, since other parts of the code deal with this on their own, leading
* to multiple define warnings unless we un-define this, however we can only undefine this if we
* were the ones that made the definition earlier. */
# ifdef TBB_MIN_MAX_CLEANUP
# undef NOMINMAX
# endif
# endif
# endif
#endif
#include <atomic>

View File

@ -8,6 +8,7 @@
* This file contains code that can be shared between different hash table implementations.
*/
#include <algorithm>
#include <cmath>
#include "BLI_allocator.hh"

View File

@ -209,6 +209,18 @@ class IndexMask {
return indices_.is_empty();
}
bool contained_in(const IndexRange range) const
{
if (indices_.is_empty()) {
return true;
}
if (range.size() < indices_.size()) {
return false;
}
return indices_.first() >= range.first() && indices_.last() <= range.last();
}
IndexMask slice(int64_t start, int64_t size) const;
IndexMask slice(IndexRange slice) const;
/**
* Create a sub-mask that is also shifted to the beginning.
@ -229,6 +241,30 @@ class IndexMask {
* so that the first index in the output is zero.
*/
IndexMask slice_and_offset(IndexRange slice, Vector<int64_t> &r_new_indices) const;
/**
* Get a new mask that contains all the indices that are not in the current mask.
* If necessary, the indices referenced by the new mask are inserted in #r_new_indices.
*/
IndexMask invert(const IndexRange full_range, Vector<int64_t> &r_new_indices) const;
/**
* Get all contiguous index ranges within the mask.
*/
Vector<IndexRange> extract_ranges() const;
/**
* Similar to #extract ranges, but works on the inverted mask. So the returned ranges are
* in-between the indices in the mask.
*
* Using this method is generally more efficient than first inverting the index mask and then
* extracting the ranges.
*
* If #r_skip_amounts is passed in, it will contain the number of indices that have been skipped
* before each range in the return value starts.
*/
Vector<IndexRange> extract_ranges_invert(const IndexRange full_range,
Vector<int64_t> *r_skip_amounts) const;
};
} // namespace blender

View File

@ -0,0 +1,60 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bli
*
* This is separate from `BLI_index_mask.hh` because it includes headers just `IndexMask` shouldn't
* depend on.
*/
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_index_mask.hh"
#include "BLI_task.hh"
#include "BLI_vector.hh"
namespace blender::index_mask_ops {
namespace detail {
IndexMask find_indices_based_on_predicate__merge(
IndexMask indices_to_check,
threading::EnumerableThreadSpecific<Vector<Vector<int64_t>>> &sub_masks,
Vector<int64_t> &r_indices);
} // namespace detail
/**
* Evaluate the #predicate for all indices in #indices_to_check and return a mask that contains all
* indices where the predicate was true.
*
* #r_indices indices is only used if necessary.
*/
template<typename Predicate>
inline IndexMask find_indices_based_on_predicate(const IndexMask indices_to_check,
const int64_t parallel_grain_size,
Vector<int64_t> &r_indices,
const Predicate &predicate)
{
/* Evaluate predicate in parallel. Since the size of the final mask is not known yet, many
* smaller vectors have to be filled with all indices where the predicate is true. Those smaller
* vectors are joined afterwards. */
threading::EnumerableThreadSpecific<Vector<Vector<int64_t>>> sub_masks;
threading::parallel_for(
indices_to_check.index_range(), parallel_grain_size, [&](const IndexRange range) {
const IndexMask sub_mask = indices_to_check.slice(range);
Vector<int64_t> masked_indices;
for (const int64_t i : sub_mask) {
if (predicate(i)) {
masked_indices.append(i);
}
}
if (!masked_indices.is_empty()) {
sub_masks.local().append(std::move(masked_indices));
}
});
/* This part doesn't have to be in the header. */
return detail::find_indices_based_on_predicate__merge(indices_to_check, sub_masks, r_indices);
}
} // namespace blender::index_mask_ops

View File

@ -303,6 +303,9 @@ float dist_squared_to_projected_aabb_simple(const float projmat[4][4],
const float bbmin[3],
const float bbmax[3]);
/** Returns the distance between two 2D line segments. */
float dist_seg_seg_v2(const float a1[3], const float a2[3], const float b1[3], const float b2[3]);
float closest_to_ray_v3(float r_close[3],
const float p[3],
const float ray_orig[3],

View File

@ -307,13 +307,14 @@ template<typename T> class Span {
}
/**
* Returns a reference to the last element in the array. This invokes undefined behavior when the
* array is empty.
* Returns a reference to the nth last element. This invokes undefined behavior when the span is
* too short.
*/
constexpr const T &last() const
constexpr const T &last(const int64_t n = 0) const
{
BLI_assert(size_ > 0);
return data_[size_ - 1];
BLI_assert(n >= 0);
BLI_assert(n < size_);
return data_[size_ - 1 - n];
}
/**
@ -673,13 +674,14 @@ template<typename T> class MutableSpan {
}
/**
* Returns a reference to the last element. This invokes undefined behavior when the array is
* empty.
* Returns a reference to the nth last element. This invokes undefined behavior when the span is
* too short.
*/
constexpr T &last() const
constexpr T &last(const int64_t n = 0) const
{
BLI_assert(size_ > 0);
return data_[size_ - 1];
BLI_assert(n >= 0);
BLI_assert(n < size_);
return data_[size_ - 1 - n];
}
/**

View File

@ -639,18 +639,20 @@ class Vector {
}
/**
* Return a reference to the last element in the vector.
* This invokes undefined behavior when the vector is empty.
* Return a reference to the nth last element.
* This invokes undefined behavior when the vector is too short.
*/
const T &last() const
const T &last(const int64_t n = 0) const
{
BLI_assert(this->size() > 0);
return *(end_ - 1);
BLI_assert(n >= 0);
BLI_assert(n < this->size());
return *(end_ - 1 - n);
}
T &last()
T &last(const int64_t n = 0)
{
BLI_assert(this->size() > 0);
return *(end_ - 1);
BLI_assert(n >= 0);
BLI_assert(n < this->size());
return *(end_ - 1 - n);
}
/**

View File

@ -667,7 +667,7 @@ template<typename T> class VArrayCommon {
}
/**
* Returns the internally used span of the virtual array. This invokes undefined behavior is the
* Returns the internally used span of the virtual array. This invokes undefined behavior if the
* virtual array is not stored as a span internally.
*/
Span<T> get_internal_span() const

View File

@ -203,6 +203,7 @@ set(SRC
BLI_heap.h
BLI_heap_simple.h
BLI_index_mask.hh
BLI_index_mask_ops.hh
BLI_index_range.hh
BLI_inplace_priority_queue.hh
BLI_iterator.h

View File

@ -1,9 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_index_mask.hh"
#include "BLI_index_mask_ops.hh"
namespace blender {
IndexMask IndexMask::slice(int64_t start, int64_t size) const
{
return this->slice(IndexRange(start, size));
}
IndexMask IndexMask::slice(IndexRange slice) const
{
return IndexMask(indices_.slice(slice));
@ -30,4 +36,161 @@ IndexMask IndexMask::slice_and_offset(const IndexRange slice, Vector<int64_t> &r
return IndexMask(r_new_indices.as_span());
}
IndexMask IndexMask::invert(const IndexRange full_range, Vector<int64_t> &r_new_indices) const
{
BLI_assert(this->contained_in(full_range));
if (full_range.size() == indices_.size()) {
return {};
}
if (indices_.is_empty()) {
return full_range;
}
r_new_indices.clear();
const Vector<IndexRange> ranges = this->extract_ranges_invert(full_range, nullptr);
for (const IndexRange &range : ranges) {
for (const int64_t index : range) {
r_new_indices.append(index);
}
}
return r_new_indices.as_span();
}
Vector<IndexRange> IndexMask::extract_ranges() const
{
Vector<IndexRange> ranges;
int64_t range_start = 0;
while (range_start < indices_.size()) {
int64_t current_range_end = range_start + 1;
int64_t step_size = 1;
while (true) {
const int64_t possible_range_end = current_range_end + step_size;
if (possible_range_end > indices_.size()) {
break;
}
if (!this->slice(range_start, possible_range_end - range_start).is_range()) {
break;
}
current_range_end = possible_range_end;
step_size *= 2;
}
/* This step size was tried already, no need to try it again. */
step_size /= 2;
while (step_size > 0) {
const int64_t possible_range_end = current_range_end + step_size;
step_size /= 2;
if (possible_range_end > indices_.size()) {
continue;
}
if (!this->slice(range_start, possible_range_end - range_start).is_range()) {
continue;
}
current_range_end = possible_range_end;
}
ranges.append(IndexRange{indices_[range_start], current_range_end - range_start});
range_start = current_range_end;
}
return ranges;
}
Vector<IndexRange> IndexMask::extract_ranges_invert(const IndexRange full_range,
Vector<int64_t> *r_skip_amounts) const
{
BLI_assert(this->contained_in(full_range));
const Vector<IndexRange> ranges = this->extract_ranges();
Vector<IndexRange> inverted_ranges;
int64_t skip_amount = 0;
int64_t next_start = full_range.start();
for (const int64_t i : ranges.index_range()) {
const IndexRange range = ranges[i];
if (range.start() > next_start) {
inverted_ranges.append({next_start, range.start() - next_start});
if (r_skip_amounts != nullptr) {
r_skip_amounts->append(skip_amount);
}
}
next_start = range.one_after_last();
skip_amount += range.size();
}
if (next_start < full_range.one_after_last()) {
inverted_ranges.append({next_start, full_range.one_after_last() - next_start});
if (r_skip_amounts != nullptr) {
r_skip_amounts->append(skip_amount);
}
}
return inverted_ranges;
}
} // namespace blender
namespace blender::index_mask_ops::detail {
IndexMask find_indices_based_on_predicate__merge(
IndexMask indices_to_check,
threading::EnumerableThreadSpecific<Vector<Vector<int64_t>>> &sub_masks,
Vector<int64_t> &r_indices)
{
/* Gather vectors that have been generated by possibly multiple threads. */
Vector<Vector<int64_t> *> all_vectors;
int64_t result_mask_size = 0;
for (Vector<Vector<int64_t>> &local_sub_masks : sub_masks) {
for (Vector<int64_t> &sub_mask : local_sub_masks) {
all_vectors.append(&sub_mask);
result_mask_size += sub_mask.size();
}
}
if (all_vectors.is_empty()) {
/* Special case when the predicate was false for all elements. */
return {};
}
if (result_mask_size == indices_to_check.size()) {
/* Special case when the predicate was true for all elements. */
return indices_to_check;
}
if (all_vectors.size() == 1) {
/* Special case when all indices for which the predicate is true happen to be in a single
* vector. */
r_indices = std::move(*all_vectors[0]);
return r_indices.as_span();
}
/* Indices in separate vectors don't overlap. So it is ok to sort the vectors just by looking at
* the first element. */
std::sort(all_vectors.begin(),
all_vectors.end(),
[](const Vector<int64_t> *a, const Vector<int64_t> *b) { return (*a)[0] < (*b)[0]; });
/* Precompute the offsets for the individual vectors, so that the indices can be copied into the
* final vector in parallel. */
Vector<int64_t> offsets;
offsets.reserve(all_vectors.size() + 1);
offsets.append(0);
for (Vector<int64_t> *vector : all_vectors) {
offsets.append(offsets.last() + vector->size());
}
r_indices.resize(result_mask_size);
/* Fill the final index mask in parallel again. */
threading::parallel_for(all_vectors.index_range(), 100, [&](const IndexRange all_vectors_range) {
for (const int64_t vector_index : all_vectors_range) {
Vector<int64_t> &vector = *all_vectors[vector_index];
const int64_t offset = offsets[vector_index];
threading::parallel_for(vector.index_range(), 1024, [&](const IndexRange range) {
initialized_copy_n(vector.data() + range.start(),
range.size(),
r_indices.data() + offset + range.start());
});
}
});
return r_indices.as_span();
}
} // namespace blender::index_mask_ops::detail

View File

@ -903,6 +903,18 @@ float dist_squared_to_projected_aabb_simple(const float projmat[4][4],
/** \} */
float dist_seg_seg_v2(const float a1[3], const float a2[3], const float b1[3], const float b2[3])
{
if (isect_seg_seg_v2_simple(a1, a2, b1, b2)) {
return 0.0f;
}
const float d1 = dist_squared_to_line_segment_v2(a1, b1, b2);
const float d2 = dist_squared_to_line_segment_v2(a2, b1, b2);
const float d3 = dist_squared_to_line_segment_v2(b1, a1, a2);
const float d4 = dist_squared_to_line_segment_v2(b2, a1, a2);
return sqrtf(min_ffff(d1, d2, d3, d4));
}
void closest_on_tri_to_point_v3(
float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
{

View File

@ -231,9 +231,11 @@ TEST(array, Last)
{
Array<int> array = {5, 7, 8, 9};
EXPECT_EQ(array.last(), 9);
EXPECT_EQ(array.last(1), 8);
array.last() = 1;
EXPECT_EQ(array[3], 1);
EXPECT_EQ(const_cast<const Array<int> &>(array).last(), 1);
EXPECT_EQ(const_cast<const Array<int> &>(array).last(2), 7);
}
TEST(array, Reinitialize)

View File

@ -64,4 +64,153 @@ TEST(index_mask, SliceAndOffset)
}
}
TEST(index_mask, ExtractRanges)
{
{
Vector<int64_t> indices = {1, 2, 3, 5, 7, 8};
Vector<IndexRange> ranges = IndexMask(indices).extract_ranges();
EXPECT_EQ(ranges.size(), 3);
EXPECT_EQ(ranges[0], IndexRange(1, 3));
EXPECT_EQ(ranges[1], IndexRange(5, 1));
EXPECT_EQ(ranges[2], IndexRange(7, 2));
}
{
Vector<int64_t> indices;
Vector<IndexRange> ranges = IndexMask(indices).extract_ranges();
EXPECT_EQ(ranges.size(), 0);
}
{
Vector<int64_t> indices = {5, 6, 7, 8, 9, 10};
Vector<IndexRange> ranges = IndexMask(indices).extract_ranges();
EXPECT_EQ(ranges.size(), 1);
EXPECT_EQ(ranges[0], IndexRange(5, 6));
}
{
Vector<int64_t> indices = {1, 3, 6, 8};
Vector<IndexRange> ranges = IndexMask(indices).extract_ranges();
EXPECT_EQ(ranges.size(), 4);
EXPECT_EQ(ranges[0], IndexRange(1, 1));
EXPECT_EQ(ranges[1], IndexRange(3, 1));
EXPECT_EQ(ranges[2], IndexRange(6, 1));
EXPECT_EQ(ranges[3], IndexRange(8, 1));
}
{
Vector<int64_t> indices;
IndexRange range1{4, 10};
IndexRange range2{20, 30};
IndexRange range3{100, 1};
IndexRange range4{150, 100};
for (const IndexRange &range : {range1, range2, range3, range4}) {
for (const int64_t i : range) {
indices.append(i);
}
}
Vector<IndexRange> ranges = IndexMask(indices).extract_ranges();
EXPECT_EQ(ranges.size(), 4);
EXPECT_EQ(ranges[0], range1);
EXPECT_EQ(ranges[1], range2);
EXPECT_EQ(ranges[2], range3);
EXPECT_EQ(ranges[3], range4);
}
{
const int64_t max_test_range_size = 50;
Vector<int64_t> indices;
int64_t offset = 0;
for (const int64_t range_size : IndexRange(1, max_test_range_size)) {
for (const int i : IndexRange(range_size)) {
indices.append(offset + i);
}
offset += range_size + 1;
}
Vector<IndexRange> ranges = IndexMask(indices).extract_ranges();
EXPECT_EQ(ranges.size(), max_test_range_size);
for (const int64_t range_size : IndexRange(1, max_test_range_size)) {
const IndexRange range = ranges[range_size - 1];
EXPECT_EQ(range.size(), range_size);
}
}
}
TEST(index_mask, Invert)
{
{
Vector<int64_t> indices;
Vector<int64_t> new_indices;
IndexMask inverted_mask = IndexMask(indices).invert(IndexRange(10), new_indices);
EXPECT_EQ(inverted_mask.size(), 10);
EXPECT_TRUE(new_indices.is_empty());
}
{
Vector<int64_t> indices = {3, 4, 5, 6};
Vector<int64_t> new_indices;
IndexMask inverted_mask = IndexMask(indices).invert(IndexRange(3, 4), new_indices);
EXPECT_TRUE(inverted_mask.is_empty());
}
{
Vector<int64_t> indices = {5};
Vector<int64_t> new_indices;
IndexMask inverted_mask = IndexMask(indices).invert(IndexRange(10), new_indices);
EXPECT_EQ(inverted_mask.size(), 9);
EXPECT_EQ(inverted_mask.indices(), Span<int64_t>({0, 1, 2, 3, 4, 6, 7, 8, 9}));
}
{
Vector<int64_t> indices = {0, 1, 2, 6, 7, 9};
Vector<int64_t> new_indices;
IndexMask inverted_mask = IndexMask(indices).invert(IndexRange(10), new_indices);
EXPECT_EQ(inverted_mask.size(), 4);
EXPECT_EQ(inverted_mask.indices(), Span<int64_t>({3, 4, 5, 8}));
}
}
TEST(index_mask, ExtractRangesInvert)
{
{
Vector<int64_t> indices;
Vector<IndexRange> ranges = IndexMask(indices).extract_ranges_invert(IndexRange(10), nullptr);
EXPECT_EQ(ranges.size(), 1);
EXPECT_EQ(ranges[0], IndexRange(10));
}
{
Vector<int64_t> indices = {1, 2, 3, 6, 7};
Vector<int64_t> skip_amounts;
Vector<IndexRange> ranges = IndexMask(indices).extract_ranges_invert(IndexRange(10),
&skip_amounts);
EXPECT_EQ(ranges.size(), 3);
EXPECT_EQ(ranges[0], IndexRange(0, 1));
EXPECT_EQ(ranges[1], IndexRange(4, 2));
EXPECT_EQ(ranges[2], IndexRange(8, 2));
EXPECT_EQ(skip_amounts[0], 0);
EXPECT_EQ(skip_amounts[1], 3);
EXPECT_EQ(skip_amounts[2], 5);
}
{
Vector<int64_t> indices = {0, 1, 2, 3, 4};
Vector<int64_t> skip_amounts;
Vector<IndexRange> ranges = IndexMask(indices).extract_ranges_invert(IndexRange(5),
&skip_amounts);
EXPECT_TRUE(ranges.is_empty());
EXPECT_TRUE(skip_amounts.is_empty());
}
{
Vector<int64_t> indices = {5, 6, 7, 10, 11};
Vector<int64_t> skip_amounts;
Vector<IndexRange> ranges = IndexMask(indices).extract_ranges_invert(IndexRange(5, 20),
&skip_amounts);
EXPECT_EQ(ranges.size(), 2);
EXPECT_EQ(ranges[0], IndexRange(8, 2));
EXPECT_EQ(ranges[1], IndexRange(12, 13));
EXPECT_EQ(skip_amounts[0], 3);
EXPECT_EQ(skip_amounts[1], 5);
}
}
TEST(index_mask, ContainedIn)
{
EXPECT_TRUE(IndexMask({3, 4, 5}).contained_in(IndexRange(10)));
EXPECT_TRUE(IndexMask().contained_in(IndexRange(5, 0)));
EXPECT_FALSE(IndexMask({3}).contained_in(IndexRange(3)));
EXPECT_FALSE(IndexMask({4, 5, 6}).contained_in(IndexRange(5, 10)));
EXPECT_FALSE(IndexMask({5, 6}).contained_in(IndexRange()));
}
} // namespace blender::tests

View File

@ -247,6 +247,8 @@ TEST(span, FirstLast)
Span<int> a_span(a);
EXPECT_EQ(a_span.first(), 6);
EXPECT_EQ(a_span.last(), 9);
EXPECT_EQ(a_span.last(1), 8);
EXPECT_EQ(a_span.last(2), 7);
}
TEST(span, FirstLast_OneElement)
@ -255,6 +257,7 @@ TEST(span, FirstLast_OneElement)
Span<int> a_span(&a, 1);
EXPECT_EQ(a_span.first(), 3);
EXPECT_EQ(a_span.last(), 3);
EXPECT_EQ(a_span.last(0), 3);
}
TEST(span, Get)

View File

@ -447,6 +447,9 @@ TEST(vector, Last)
{
Vector<int> a{3, 5, 7};
EXPECT_EQ(a.last(), 7);
EXPECT_EQ(a.last(0), 7);
EXPECT_EQ(a.last(1), 5);
EXPECT_EQ(a.last(2), 3);
}
TEST(vector, AppendNTimes)

View File

@ -948,6 +948,10 @@ void blo_do_versions_userdef(UserDef *userdef)
}
}
if (!USER_VERSION_ATLEAST(300, 43)) {
userdef->ndof_flag |= NDOF_CAMERA_PAN_ZOOM;
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -212,10 +212,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
if (!me || !me->totvert) {
if (me && is_new) { /* No verts? still copy custom-data layout. */
CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_ASSIGN, 0);
CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_ASSIGN, 0);
CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_ASSIGN, 0);
CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_ASSIGN, 0);
CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_DEFAULT, 0);
CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_DEFAULT, 0);
CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_DEFAULT, 0);
CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_DEFAULT, 0);
CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
@ -934,9 +934,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
/* There is no way to tell if BMesh normals are dirty or not. Instead of calculating the normals
* on the BMesh possibly unnecessarily, just tag them dirty on the resulting mesh. */
BKE_mesh_normals_tag_dirty(me);
/* Clear normals on the mesh completely, since the original vertex and polygon count might be
* different than the BMesh's. */
BKE_mesh_clear_derived_normals(me);
me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);

View File

@ -626,11 +626,6 @@ static void dof_reduce_pass_init(EEVEE_FramebufferList *fbl,
"dof_reduced_color", UNPACK2(res), mip_count, GPU_RGBA16F, NULL);
txl->dof_reduced_coc = GPU_texture_create_2d(
"dof_reduced_coc", UNPACK2(res), mip_count, GPU_R16F, NULL);
/* TODO(@fclem): Remove once we have immutable storage or when mips are generated on creation.
*/
GPU_texture_generate_mipmap(txl->dof_reduced_color);
GPU_texture_generate_mipmap(txl->dof_reduced_coc);
}
GPU_framebuffer_ensure_config(&fbl->dof_reduce_fb,

View File

@ -273,11 +273,9 @@ void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Resize shcasters buffers if too big. */
if (frontbuffer->alloc_count - frontbuffer->count > SH_CASTER_ALLOC_CHUNK) {
frontbuffer->alloc_count = (frontbuffer->count / SH_CASTER_ALLOC_CHUNK) *
frontbuffer->alloc_count = divide_ceil_u(max_ii(1, frontbuffer->count),
SH_CASTER_ALLOC_CHUNK) *
SH_CASTER_ALLOC_CHUNK;
frontbuffer->alloc_count += (frontbuffer->count % SH_CASTER_ALLOC_CHUNK != 0) ?
SH_CASTER_ALLOC_CHUNK :
0;
frontbuffer->bbox = MEM_reallocN(frontbuffer->bbox,
sizeof(EEVEE_BoundBox) * frontbuffer->alloc_count);
BLI_BITMAP_RESIZE(frontbuffer->update, frontbuffer->alloc_count);

View File

@ -641,11 +641,6 @@ class Texture : NonCopyable {
}
if (tx_ == nullptr) {
tx_ = create(w, h, d, mips, format, data, layered, cubemap);
if (mips > 1) {
/* TODO(@fclem): Remove once we have immutable storage or when mips are
* generated on creation. */
GPU_texture_generate_mipmap(tx_);
}
return true;
}
return false;

View File

@ -339,11 +339,7 @@ static void drw_mesh_attributes_merge(DRW_MeshAttributes *dst,
/* Return true if all requests in b are in a. */
static bool drw_mesh_attributes_overlap(DRW_MeshAttributes *a, DRW_MeshAttributes *b)
{
if (a->num_requests != b->num_requests) {
return false;
}
for (int i = 0; i < a->num_requests; i++) {
for (int i = 0; i < b->num_requests; i++) {
if (!has_request(a, b->requests[i])) {
return false;
}
@ -1712,7 +1708,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
const int required_mode = BKE_subsurf_modifier_eval_required_mode(DRW_state_is_scene_render(),
is_editmode);
const bool do_subdivision = BKE_subsurf_modifier_can_do_gpu_subdiv(scene, ob, required_mode);
const bool do_subdivision = BKE_subsurf_modifier_can_do_gpu_subdiv(scene, ob, me, required_mode);
MeshBufferList *mbuflist = &cache->final.buff;

View File

@ -67,7 +67,6 @@ enum {
SHADER_BUFFER_NORMALS_ACCUMULATE,
SHADER_BUFFER_NORMALS_FINALIZE,
SHADER_PATCH_EVALUATION,
SHADER_PATCH_EVALUATION_LIMIT_NORMALS,
SHADER_PATCH_EVALUATION_FVAR,
SHADER_PATCH_EVALUATION_FACE_DOTS,
SHADER_COMP_CUSTOM_DATA_INTERP_1D,
@ -107,7 +106,6 @@ static const char *get_shader_code(int shader_type)
return datatoc_common_subdiv_normals_finalize_comp_glsl;
}
case SHADER_PATCH_EVALUATION:
case SHADER_PATCH_EVALUATION_LIMIT_NORMALS:
case SHADER_PATCH_EVALUATION_FVAR:
case SHADER_PATCH_EVALUATION_FACE_DOTS: {
return datatoc_common_subdiv_patch_evaluation_comp_glsl;
@ -159,9 +157,6 @@ static const char *get_shader_name(int shader_type)
case SHADER_PATCH_EVALUATION: {
return "subdiv patch evaluation";
}
case SHADER_PATCH_EVALUATION_LIMIT_NORMALS: {
return "subdiv patch evaluation limit normals";
}
case SHADER_PATCH_EVALUATION_FVAR: {
return "subdiv patch evaluation face-varying";
}
@ -199,13 +194,7 @@ static GPUShader *get_patch_evaluation_shader(int shader_type)
const char *compute_code = get_shader_code(shader_type);
const char *defines = nullptr;
if (shader_type == SHADER_PATCH_EVALUATION_LIMIT_NORMALS) {
defines =
"#define OSD_PATCH_BASIS_GLSL\n"
"#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
"#define LIMIT_NORMALS\n";
}
else if (shader_type == SHADER_PATCH_EVALUATION_FVAR) {
if (shader_type == SHADER_PATCH_EVALUATION_FVAR) {
defines =
"#define OSD_PATCH_BASIS_GLSL\n"
"#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
@ -246,7 +235,6 @@ static GPUShader *get_subdiv_shader(int shader_type, const char *defines)
{
if (ELEM(shader_type,
SHADER_PATCH_EVALUATION,
SHADER_PATCH_EVALUATION_LIMIT_NORMALS,
SHADER_PATCH_EVALUATION_FVAR,
SHADER_PATCH_EVALUATION_FACE_DOTS)) {
return get_patch_evaluation_shader(shader_type);
@ -1194,9 +1182,7 @@ static void drw_subdiv_compute_dispatch(const DRWSubdivCache *cache,
GPU_compute_dispatch(shader, dispatch_rx, dispatch_ry, 1);
}
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
GPUVertBuf *pos_nor,
const bool do_limit_normals)
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, GPUVertBuf *pos_nor)
{
Subdiv *subdiv = cache->subdiv;
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
@ -1221,8 +1207,7 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
get_patch_param_format());
evaluator->wrapPatchParamBuffer(evaluator, &patch_param_buffer_interface);
GPUShader *shader = get_patch_evaluation_shader(
do_limit_normals ? SHADER_PATCH_EVALUATION_LIMIT_NORMALS : SHADER_PATCH_EVALUATION);
GPUShader *shader = get_patch_evaluation_shader(SHADER_PATCH_EVALUATION);
GPU_shader_bind(shader);
GPU_vertbuf_bind_as_ssbo(src_buffer, 0);
@ -1394,6 +1379,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
GPUVertBuf *pos_nor,
GPUVertBuf *face_adjacency_offsets,
GPUVertBuf *face_adjacency_lists,
GPUVertBuf *vertex_loop_map,
GPUVertBuf *vertex_normals)
{
GPUShader *shader = get_subdiv_shader(SHADER_BUFFER_NORMALS_ACCUMULATE, nullptr);
@ -1404,6 +1390,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
GPU_vertbuf_bind_as_ssbo(face_adjacency_offsets, binding_point++);
GPU_vertbuf_bind_as_ssbo(face_adjacency_lists, binding_point++);
GPU_vertbuf_bind_as_ssbo(vertex_loop_map, binding_point++);
GPU_vertbuf_bind_as_ssbo(vertex_normals, binding_point++);
drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache->num_subdiv_verts);
@ -1851,8 +1838,6 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
draw_cache->subdiv = subdiv;
draw_cache->optimal_display = optimal_display;
draw_cache->num_subdiv_triangles = tris_count_from_number_of_loops(draw_cache->num_subdiv_loops);
/* We can only evaluate limit normals if the patches are adaptive. */
draw_cache->do_limit_normals = settings.is_adaptive;
draw_cache->use_custom_loop_normals = (smd->flags & eSubsurfModifierFlag_UseCustomNormals) &&
(mesh_eval->flag & ME_AUTOSMOOTH) &&

View File

@ -51,7 +51,6 @@ typedef struct DRWSubdivCache {
struct BMesh *bm;
struct Subdiv *subdiv;
bool optimal_display;
bool do_limit_normals;
bool use_custom_loop_normals;
/* Coordinates used to evaluate patches for UVs, positions, and normals. */
@ -165,6 +164,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
struct GPUVertBuf *pos_nor,
struct GPUVertBuf *face_adjacency_offsets,
struct GPUVertBuf *face_adjacency_lists,
struct GPUVertBuf *vertex_loop_map,
struct GPUVertBuf *vertex_normals);
void draw_subdiv_finalize_normals(const DRWSubdivCache *cache,
@ -176,9 +176,7 @@ void draw_subdiv_finalize_custom_normals(const DRWSubdivCache *cache,
GPUVertBuf *src_custom_normals,
GPUVertBuf *pos_nor);
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
struct GPUVertBuf *pos_nor,
bool do_limit_normals);
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, struct GPUVertBuf *pos_nor);
void draw_subdiv_interp_custom_data(const DRWSubdivCache *cache,
struct GPUVertBuf *src_data,

View File

@ -217,14 +217,12 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
void *UNUSED(data))
{
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
const bool do_limit_normals = subdiv_cache->do_limit_normals &&
!subdiv_cache->use_custom_loop_normals;
/* Initialize the vertex buffer, it was already allocated. */
GPU_vertbuf_init_build_on_device(
vbo, get_pos_nor_format(), subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
draw_subdiv_extract_pos_nor(subdiv_cache, vbo, do_limit_normals);
draw_subdiv_extract_pos_nor(subdiv_cache, vbo);
if (subdiv_cache->use_custom_loop_normals) {
Mesh *coarse_mesh = subdiv_cache->mesh;
@ -250,7 +248,7 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
GPU_vertbuf_discard(src_custom_normals);
GPU_vertbuf_discard(dst_custom_normals);
}
else if (!do_limit_normals) {
else {
/* We cannot evaluate vertex normals using the limit surface, so compute them manually. */
GPUVertBuf *subdiv_loop_subdiv_vert_index = draw_subdiv_build_origindex_buffer(
subdiv_cache->subdiv_loop_subdiv_vert_index, subdiv_cache->num_subdiv_loops);
@ -263,6 +261,7 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
vbo,
subdiv_cache->subdiv_vertex_face_adjacency_offsets,
subdiv_cache->subdiv_vertex_face_adjacency,
subdiv_loop_subdiv_vert_index,
vertex_normals);
draw_subdiv_finalize_normals(subdiv_cache, vertex_normals, subdiv_loop_subdiv_vert_index, vbo);

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
layout(std430, binding = 1) readonly restrict buffer sourceBuffer
{

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
layout(std430, binding = 0) readonly buffer inputEdgeOrigIndex
{

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
/* Generate triangles from subdivision quads indices. */

View File

@ -140,6 +140,13 @@ void set_vertex_nor(inout PosNorLoop vertex_data, vec3 nor)
set_vertex_nor(vertex_data, nor, 0);
}
void add_newell_cross_v3_v3v3(inout vec3 n, vec3 v_prev, vec3 v_curr)
{
n[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]);
n[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]);
n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]);
}
#define ORIGINDEX_NONE -1
#ifdef SUBDIV_POLYGON_OFFSET

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
layout(std430, binding = 0) readonly buffer inputVertexData
{
@ -16,11 +16,33 @@ layout(std430, binding = 2) readonly buffer faceAdjacencyLists
uint face_adjacency_lists[];
};
layout(std430, binding = 3) writeonly buffer vertexNormals
layout(std430, binding = 3) readonly buffer vertexLoopMap
{
uint vert_loop_map[];
};
layout(std430, binding = 4) writeonly buffer vertexNormals
{
vec3 normals[];
};
void find_prev_and_next_vertex_on_face(
uint face_index, uint vertex_index, out uint curr, out uint next, out uint prev)
{
uint start_loop_index = face_index * 4;
for (uint i = 0; i < 4; i++) {
uint subdiv_vert_index = vert_loop_map[start_loop_index + i];
if (subdiv_vert_index == vertex_index) {
curr = i;
next = (i + 1) % 4;
prev = (i + 4 - 1) % 4;
break;
}
}
}
void main()
{
uint vertex_index = get_global_invocation_index();
@ -39,18 +61,37 @@ void main()
uint adjacent_face = face_adjacency_lists[first_adjacent_face_offset + i];
uint start_loop_index = adjacent_face * 4;
/* Compute face normal. */
vec3 adjacent_verts[3];
for (uint j = 0; j < 3; j++) {
adjacent_verts[j] = get_vertex_pos(pos_nor[start_loop_index + j]);
/* Compute the face normal using Newell's method. */
vec3 verts[4];
for (uint j = 0; j < 4; j++) {
verts[j] = get_vertex_pos(pos_nor[start_loop_index + j]);
}
vec3 face_normal = normalize(
cross(adjacent_verts[1] - adjacent_verts[0], adjacent_verts[2] - adjacent_verts[0]));
accumulated_normal += face_normal;
vec3 face_normal = vec3(0.0);
add_newell_cross_v3_v3v3(face_normal, verts[0], verts[1]);
add_newell_cross_v3_v3v3(face_normal, verts[1], verts[2]);
add_newell_cross_v3_v3v3(face_normal, verts[2], verts[3]);
add_newell_cross_v3_v3v3(face_normal, verts[3], verts[0]);
/* Accumulate angle weighted normal. */
uint curr_vert = 0;
uint next_vert = 0;
uint prev_vert = 0;
find_prev_and_next_vertex_on_face(
adjacent_face, vertex_index, curr_vert, next_vert, prev_vert);
vec3 curr_co = verts[curr_vert];
vec3 prev_co = verts[next_vert];
vec3 next_co = verts[prev_vert];
vec3 edvec_prev = normalize(prev_co - curr_co);
vec3 edvec_next = normalize(curr_co - next_co);
float fac = acos(-dot(edvec_prev, edvec_next));
accumulated_normal += face_normal * fac;
}
float weight = 1.0 / float(number_of_adjacent_faces);
vec3 normal = normalize(accumulated_normal);
normals[vertex_index] = normal;
}

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
#ifdef CUSTOM_NORMALS
struct CustomNormal {

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
/* Source buffer. */
layout(std430, binding = 0) buffer src_buffer
@ -394,12 +394,8 @@ void main()
evaluate_patches_limits(patch_co.patch_index, uv.x, uv.y, pos, du, dv);
# if defined(LIMIT_NORMALS)
vec3 nor = normalize(cross(du, dv));
# else
/* This will be computed later. */
vec3 nor = vec3(0.0);
# endif
int origindex = input_vert_origindex[loop_index];
uint flag = 0;

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
layout(std430, binding = 0) readonly buffer inputVertexData
{

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
layout(std430, binding = 0) readonly buffer inputVerts
{

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
layout(std430, binding = 1) readonly buffer inputCoarseData
{

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
layout(std430, binding = 1) readonly buffer inputVertexData
{
@ -38,13 +38,18 @@ void main()
}
}
else {
/* Face is flat shaded, compute flat face normal from an inscribed triangle. */
vec3 verts[3];
for (int i = 0; i < 3; i++) {
verts[i] = get_vertex_pos(pos_nor[start_loop_index + i]);
}
vec3 v0 = get_vertex_pos(pos_nor[start_loop_index + 0]);
vec3 v1 = get_vertex_pos(pos_nor[start_loop_index + 1]);
vec3 v2 = get_vertex_pos(pos_nor[start_loop_index + 2]);
vec3 v3 = get_vertex_pos(pos_nor[start_loop_index + 3]);
vec3 face_normal = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
vec3 face_normal = vec3(0.0);
add_newell_cross_v3_v3v3(face_normal, v0, v1);
add_newell_cross_v3_v3v3(face_normal, v1, v2);
add_newell_cross_v3_v3v3(face_normal, v2, v3);
add_newell_cross_v3_v3v3(face_normal, v3, v0);
face_normal = normalize(face_normal);
for (int i = 0; i < 4; i++) {
output_lnor[start_loop_index + i] = face_normal;
}

View File

@ -1,5 +1,5 @@
/* To be compile with common_subdiv_lib.glsl */
/* To be compiled with common_subdiv_lib.glsl */
struct SculptData {
uint face_set_color;

View File

@ -960,7 +960,13 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *even
mm->evtx = event->xy[0];
fac = ((float)(event->xy[0] - mm->firstx) * dx);
apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, FPS, 0.1 * FPS, 0);
apply_keyb_grid((event->modifier & KM_SHIFT) != 0,
(event->modifier & KM_CTRL) != 0,
&fac,
0.0,
FPS,
0.1 * FPS,
0);
RNA_int_set(op->ptr, "frames", (int)fac);
ed_marker_move_apply(C, op);

View File

@ -427,7 +427,7 @@ static int pose_clear_paths_exec(bContext *C, wmOperator *op)
/* operator callback/wrapper */
static int pose_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if ((event->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
if ((event->modifier & KM_SHIFT) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
RNA_boolean_set(op->ptr, "only_selected", true);
}
return pose_clear_paths_exec(C, op);

View File

@ -17,9 +17,9 @@ AssetLibraryReferenceWrapper::AssetLibraryReferenceWrapper(const AssetLibraryRef
bool operator==(const AssetLibraryReferenceWrapper &a, const AssetLibraryReferenceWrapper &b)
{
return (a.type == b.type) && (a.type == ASSET_LIBRARY_CUSTOM) ?
(a.custom_library_index == b.custom_library_index) :
true;
return (a.type == b.type) &&
((a.type == ASSET_LIBRARY_CUSTOM) ? (a.custom_library_index == b.custom_library_index) :
true);
}
uint64_t AssetLibraryReferenceWrapper::hash() const

View File

@ -1640,7 +1640,9 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
EditFont *ef = cu->editfont;
static int accentcode = 0;
uintptr_t ascii = event->ascii;
int alt = event->alt, shift = event->shift, ctrl = event->ctrl;
const bool alt = event->modifier & KM_ALT;
const bool shift = event->modifier & KM_SHIFT;
const bool ctrl = event->modifier & KM_CTRL;
int event_type = event->type, event_val = event->val;
char32_t inserted_text[2] = {0};

View File

@ -2060,7 +2060,7 @@ static void annotation_draw_apply_event(
p->mval[1] = (float)event->mval[1] - y;
/* Key to toggle stabilization. */
if (event->shift && p->paintmode == GP_PAINTMODE_DRAW) {
if ((event->modifier & KM_SHIFT) && (p->paintmode == GP_PAINTMODE_DRAW)) {
/* Using permanent stabilization, shift will deactivate the flag. */
if (p->flags & GP_PAINTFLAG_USE_STABILIZER) {
if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) {
@ -2075,7 +2075,7 @@ static void annotation_draw_apply_event(
}
}
/* verify key status for straight lines */
else if (event->ctrl || event->alt) {
else if (event->modifier & (KM_CTRL | KM_ALT)) {
if (p->straight[0] == 0) {
int dx = abs((int)(p->mval[0] - p->mvalo[0]));
int dy = abs((int)(p->mval[1] - p->mvalo[1]));
@ -2299,7 +2299,7 @@ static int annotation_draw_invoke(bContext *C, wmOperator *op, const wmEvent *ev
p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP;
annotation_draw_toggle_stabilizer_cursor(p, true);
}
else if (event->shift) {
else if (event->modifier & KM_SHIFT) {
p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
annotation_draw_toggle_stabilizer_cursor(p, true);
}

View File

@ -1239,7 +1239,7 @@ static bool contract_shape(ImBuf *ibuf)
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
const int max_size = (ibuf->x * ibuf->y) - 1;
/* Detect if pixel is near of no green pixels and mark green to be cleared. */
/* Detect if pixel is near of no green pixels and mark green pixel to be cleared. */
for (int row = 0; row < ibuf->y; row++) {
if (!is_row_filled(ibuf, row)) {
continue;
@ -2172,7 +2172,8 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
tgpf->on_back = RNA_boolean_get(op->ptr, "on_back");
const bool is_brush_inv = brush_settings->fill_direction == BRUSH_DIR_IN;
const bool is_inverted = (is_brush_inv && !event->ctrl) || (!is_brush_inv && event->ctrl);
const bool is_inverted = (is_brush_inv && (event->modifier & KM_CTRL) == 0) ||
(!is_brush_inv && (event->modifier & KM_CTRL) != 0);
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(tgpf->gpd);
const bool do_extend = (tgpf->fill_extend_fac > 0.0f);
const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) ||
@ -2313,7 +2314,7 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
case EVT_PAGEUPKEY:
case WHEELUPMOUSE:
if (tgpf->oldkey == 1) {
tgpf->fill_extend_fac -= (event->shift) ? 0.01f : 0.1f;
tgpf->fill_extend_fac -= (event->modifier & KM_SHIFT) ? 0.01f : 0.1f;
CLAMP_MIN(tgpf->fill_extend_fac, 0.0f);
gpencil_update_extend(tgpf);
}
@ -2321,7 +2322,7 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
case EVT_PAGEDOWNKEY:
case WHEELDOWNMOUSE:
if (tgpf->oldkey == 1) {
tgpf->fill_extend_fac += (event->shift) ? 0.01f : 0.1f;
tgpf->fill_extend_fac += (event->modifier & KM_SHIFT) ? 0.01f : 0.1f;
CLAMP_MAX(tgpf->fill_extend_fac, 100.0f);
gpencil_update_extend(tgpf);
}

View File

@ -235,7 +235,7 @@ typedef struct tGPsdata {
/** key used for invoking the operator */
short keymodifier;
/** shift modifier flag */
short shift;
bool shift;
/** size in pixels for uv calculation */
float totpixlen;
/** Special mode for fill brush. */
@ -2841,11 +2841,11 @@ static void gpencil_draw_apply_event(bContext *C,
* add any x,y override position
*/
copy_v2fl_v2i(p->mval, event->mval);
p->shift = event->shift;
p->shift = (event->modifier & KM_SHIFT) != 0;
/* verify direction for straight lines and guides */
if ((is_speed_guide) ||
(event->alt && (RNA_boolean_get(op->ptr, "disable_straight") == false))) {
((event->modifier & KM_ALT) && (RNA_boolean_get(op->ptr, "disable_straight") == false))) {
if (p->straight == 0) {
int dx = (int)fabsf(p->mval[0] - p->mvali[0]);
int dy = (int)fabsf(p->mval[1] - p->mvali[1]);
@ -2886,13 +2886,13 @@ static void gpencil_draw_apply_event(bContext *C,
/* special eraser modes */
if (p->paintmode == GP_PAINTMODE_ERASER) {
if (event->shift) {
if (event->modifier & KM_SHIFT) {
p->flags |= GP_PAINTFLAG_HARD_ERASER;
}
else {
p->flags &= ~GP_PAINTFLAG_HARD_ERASER;
}
if (event->alt) {
if (event->modifier & KM_ALT) {
p->flags |= GP_PAINTFLAG_STROKE_ERASER;
}
else {
@ -3116,11 +3116,11 @@ static void gpencil_guide_event_handling(bContext *C,
else if ((event->type == EVT_LKEY) && (event->val == KM_RELEASE)) {
add_notifier = true;
guide->use_guide = true;
if (event->ctrl) {
if (event->modifier & KM_CTRL) {
guide->angle = 0.0f;
guide->type = GP_GUIDE_PARALLEL;
}
else if (event->alt) {
else if (event->modifier & KM_ALT) {
guide->type = GP_GUIDE_PARALLEL;
guide->angle = RNA_float_get(op->ptr, "guide_last_angle");
}
@ -3150,10 +3150,10 @@ static void gpencil_guide_event_handling(bContext *C,
add_notifier = true;
float angle = guide->angle;
float adjust = (float)M_PI / 180.0f;
if (event->alt) {
if (event->modifier & KM_ALT) {
adjust *= 45.0f;
}
else if (!event->shift) {
else if ((event->modifier & KM_SHIFT) == 0) {
adjust *= 15.0f;
}
angle += (event->type == EVT_JKEY) ? adjust : -adjust;
@ -3633,7 +3633,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
*/
}
else if (event->type == EVT_ZKEY) {
if (event->ctrl) {
if (event->modifier & KM_CTRL) {
p->status = GP_STATUS_DONE;
estate = OPERATOR_FINISHED;
}

View File

@ -1494,7 +1494,7 @@ static void gpencil_primitive_edit_event_handling(
float dy = (tgpi->mval[1] - tgpi->mvalo[1]);
tgpi->cp1[0] += dx;
tgpi->cp1[1] += dy;
if (event->shift) {
if (event->modifier & KM_SHIFT) {
copy_v2_v2(tgpi->cp2, tgpi->cp1);
}
}
@ -1503,7 +1503,7 @@ static void gpencil_primitive_edit_event_handling(
float dy = (tgpi->mval[1] - tgpi->mvalo[1]);
tgpi->cp2[0] += dx;
tgpi->cp2[1] += dy;
if (event->shift) {
if (event->modifier & KM_SHIFT) {
copy_v2_v2(tgpi->cp1, tgpi->cp2);
}
}
@ -1692,7 +1692,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
WM_cursor_modal_set(win, WM_CURSOR_NSEW_SCROLL);
copy_v2_v2(tgpi->end, tgpi->mval);
if (event->shift) {
if (event->modifier & KM_SHIFT) {
gpencil_primitive_constrain(tgpi, true);
}
@ -1722,7 +1722,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
case EVT_FKEY: /* brush thickness/ brush strength */
{
if ((event->val == KM_PRESS)) {
if (event->shift) {
if (event->modifier & KM_SHIFT) {
tgpi->prev_flag = tgpi->flag;
tgpi->flag = IN_BRUSH_STRENGTH;
}
@ -1900,7 +1900,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
case EVT_FKEY: /* brush thickness/ brush strength */
{
if ((event->val == KM_PRESS)) {
if (event->shift) {
if (event->modifier & KM_SHIFT) {
tgpi->prev_flag = tgpi->flag;
tgpi->flag = IN_BRUSH_STRENGTH;
}
@ -1954,12 +1954,12 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
copy_v2_v2(tgpi->origin, tgpi->mval);
}
/* Keep square if shift key */
if (event->shift) {
if (event->modifier & KM_SHIFT) {
gpencil_primitive_constrain(
tgpi, (ELEM(tgpi->type, GP_STROKE_LINE, GP_STROKE_POLYLINE) || tgpi->curve));
}
/* Center primitive if alt key */
if (event->alt && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
if ((event->modifier & KM_ALT) && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
tgpi->start[0] = tgpi->origin[0] - (tgpi->end[0] - tgpi->origin[0]);
tgpi->start[1] = tgpi->origin[1] - (tgpi->end[1] - tgpi->origin[1]);
}

View File

@ -1883,7 +1883,7 @@ static void gpencil_sculpt_brush_apply_event(bContext *C, wmOperator *op, const
RNA_collection_add(op->ptr, "stroke", &itemptr);
RNA_float_set_array(&itemptr, "mouse", mouse);
RNA_boolean_set(&itemptr, "pen_flip", event->ctrl != false);
RNA_boolean_set(&itemptr, "pen_flip", (event->modifier & KM_CTRL) != 0);
RNA_boolean_set(&itemptr, "is_start", gso->first);
/* handle pressure sensitivity (which is supplied by tablets and otherwise 1.0) */
@ -1895,7 +1895,7 @@ static void gpencil_sculpt_brush_apply_event(bContext *C, wmOperator *op, const
}
RNA_float_set(&itemptr, "pressure", pressure);
if (event->shift) {
if (event->modifier & KM_SHIFT) {
gso->brush_prev = gso->brush;
gso->brush = gpencil_sculpt_get_smooth_brush(gso);

View File

@ -2659,7 +2659,7 @@ static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *eve
RNA_int_set_array(op->ptr, "location", event->mval);
if (!RNA_struct_property_is_set(op->ptr, "use_shift_extend")) {
RNA_boolean_set(op->ptr, "use_shift_extend", event->shift);
RNA_boolean_set(op->ptr, "use_shift_extend", event->modifier & KM_SHIFT);
}
return gpencil_select_exec(C, op);

View File

@ -1241,7 +1241,7 @@ static void gpencil_vertexpaint_brush_apply_event(bContext *C,
RNA_collection_add(op->ptr, "stroke", &itemptr);
RNA_float_set_array(&itemptr, "mouse", mouse);
RNA_boolean_set(&itemptr, "pen_flip", event->ctrl != false);
RNA_boolean_set(&itemptr, "pen_flip", event->modifier & KM_CTRL);
RNA_boolean_set(&itemptr, "is_start", gso->first);
/* Handle pressure sensitivity (which is supplied by tablets). */

View File

@ -698,7 +698,7 @@ static void gpencil_weightpaint_brush_apply_event(bContext *C,
RNA_collection_add(op->ptr, "stroke", &itemptr);
RNA_float_set_array(&itemptr, "mouse", mouse);
RNA_boolean_set(&itemptr, "pen_flip", event->ctrl != false);
RNA_boolean_set(&itemptr, "pen_flip", event->modifier & KM_CTRL);
RNA_boolean_set(&itemptr, "is_start", gso->first);
/* Handle pressure sensitivity (which is supplied by tablets). */

View File

@ -106,7 +106,7 @@ void ED_slider_allow_overshoot_set(struct tSlider *slider, bool value);
* \note Shift/Control are not configurable key-bindings.
*/
void apply_keyb_grid(
int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert);
bool shift, bool ctrl, float *val, float fac1, float fac2, float fac3, int invert);
/* where else to go ? */
void unpack_menu(struct bContext *C,

View File

@ -222,9 +222,9 @@ static void eyedropper_add_palette_color(bContext *C, const float col_conv[4])
static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, EyedropperGPencil *eye)
{
const bool only_stroke = ((!event->ctrl) && (!event->shift));
const bool only_fill = ((!event->ctrl) && (event->shift));
const bool both = ((event->ctrl) && (event->shift));
const bool only_stroke = (event->modifier & (KM_CTRL | KM_SHIFT)) == 0;
const bool only_fill = ((event->modifier & KM_CTRL) == 0 && (event->modifier & KM_SHIFT));
const bool both = ((event->modifier & KM_CTRL) && (event->modifier & KM_SHIFT));
float col_conv[4];

View File

@ -275,7 +275,7 @@ static void ui_selectcontext_apply(bContext *C,
const double value,
const double value_orig);
# define IS_ALLSELECT_EVENT(event) ((event)->alt != 0)
# define IS_ALLSELECT_EVENT(event) (((event)->modifier & KM_ALT) != 0)
/** just show a tinted color so users know its activated */
# define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE
@ -708,7 +708,8 @@ enum eSnapType {
static enum eSnapType ui_event_to_snap(const wmEvent *event)
{
return (event->ctrl) ? (event->shift) ? SNAP_ON_SMALL : SNAP_ON : SNAP_OFF;
return (event->modifier & KM_CTRL) ? (event->modifier & KM_SHIFT) ? SNAP_ON_SMALL : SNAP_ON :
SNAP_OFF;
}
static bool ui_event_is_snap(const wmEvent *event)
@ -1937,7 +1938,7 @@ static void ui_selectcontext_apply(bContext *C,
/* could check for 'handle_layer_buttons' */
but->func) {
wmWindow *win = CTX_wm_window(C);
if (!win->eventstate->shift) {
if ((win->eventstate->modifier & KM_SHIFT) == 0) {
const int len = RNA_property_array_length(&but->rnapoin, prop);
bool *tmparray = MEM_callocN(sizeof(bool) * len, __func__);
@ -3747,11 +3748,11 @@ static void ui_do_but_textedit(
case EVT_XKEY:
case EVT_CKEY:
#if defined(__APPLE__)
if ((event->oskey && !IS_EVENT_MOD(event, shift, alt, ctrl)) ||
(event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey))) {
if (ELEM(event->modifier, KM_OSKEY, KM_CTRL))
#else
if (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey)) {
if (event->modifier == KM_CTRL)
#endif
{
if (event->type == EVT_VKEY) {
changed = ui_textedit_copypaste(but, data, UI_TEXTEDIT_PASTE);
}
@ -3769,16 +3770,16 @@ static void ui_do_but_textedit(
ui_textedit_move(but,
data,
STRCUR_DIR_NEXT,
event->shift != 0,
event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
event->modifier & KM_SHIFT,
(event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
retval = WM_UI_HANDLER_BREAK;
break;
case EVT_LEFTARROWKEY:
ui_textedit_move(but,
data,
STRCUR_DIR_PREV,
event->shift != 0,
event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
event->modifier & KM_SHIFT,
(event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
retval = WM_UI_HANDLER_BREAK;
break;
case WHEELDOWNMOUSE:
@ -3795,7 +3796,7 @@ static void ui_do_but_textedit(
}
ATTR_FALLTHROUGH;
case EVT_ENDKEY:
ui_textedit_move(but, data, STRCUR_DIR_NEXT, event->shift != 0, STRCUR_JUMP_ALL);
ui_textedit_move(but, data, STRCUR_DIR_NEXT, event->modifier & KM_SHIFT, STRCUR_JUMP_ALL);
retval = WM_UI_HANDLER_BREAK;
break;
case WHEELUPMOUSE:
@ -3812,7 +3813,7 @@ static void ui_do_but_textedit(
}
ATTR_FALLTHROUGH;
case EVT_HOMEKEY:
ui_textedit_move(but, data, STRCUR_DIR_PREV, event->shift != 0, STRCUR_JUMP_ALL);
ui_textedit_move(but, data, STRCUR_DIR_PREV, event->modifier & KM_SHIFT, STRCUR_JUMP_ALL);
retval = WM_UI_HANDLER_BREAK;
break;
case EVT_PADENTER:
@ -3822,13 +3823,13 @@ static void ui_do_but_textedit(
break;
case EVT_DELKEY:
changed = ui_textedit_delete(
but, data, 1, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
but, data, 1, (event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
retval = WM_UI_HANDLER_BREAK;
break;
case EVT_BACKSPACEKEY:
changed = ui_textedit_delete(
but, data, 0, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
but, data, 0, (event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
retval = WM_UI_HANDLER_BREAK;
break;
@ -3837,10 +3838,9 @@ static void ui_do_but_textedit(
/* Ctrl-A: Select all. */
#if defined(__APPLE__)
/* OSX uses Command-A system-wide, so add it. */
if ((event->oskey && !IS_EVENT_MOD(event, shift, alt, ctrl)) ||
(event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey)))
if (ELEM(event->modifier, KM_OSKEY, KM_CTRL))
#else
if (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey))
if (event->modifier == KM_CTRL)
#endif
{
ui_textedit_move(but, data, STRCUR_DIR_PREV, false, STRCUR_JUMP_ALL);
@ -3859,9 +3859,9 @@ static void ui_do_but_textedit(
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
else if (!IS_EVENT_MOD(event, ctrl, alt, oskey)) {
else if ((event->modifier & (KM_CTRL | KM_ALT | KM_OSKEY)) == 0) {
/* Use standard keys for cycling through buttons Tab, Shift-Tab to reverse. */
if (event->shift) {
if (event->modifier & KM_SHIFT) {
ui_textedit_prev_but(block, but, data);
}
else {
@ -3874,12 +3874,12 @@ static void ui_do_but_textedit(
case EVT_ZKEY: {
/* Ctrl-Z or Ctrl-Shift-Z: Undo/Redo (allowing for OS-Key on Apple). */
const bool is_redo = (event->shift != 0);
const bool is_redo = (event->modifier & KM_SHIFT);
if (
#if defined(__APPLE__)
(event->oskey && !IS_EVENT_MOD(event, alt, ctrl)) ||
((event->modifier & KM_OSKEY) && ((event->modifier & (KM_ALT | KM_CTRL)) == 0)) ||
#endif
(event->ctrl && !IS_EVENT_MOD(event, alt, oskey))) {
((event->modifier & KM_CTRL) && ((event->modifier & (KM_ALT | KM_OSKEY)) == 0))) {
int undo_pos;
const char *undo_str = ui_textedit_undo(
data->undo_stack_text, is_redo ? 1 : -1, &undo_pos);
@ -4542,19 +4542,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C,
}
/* always set */
but->modifier_key = 0;
if (event->shift) {
but->modifier_key |= KM_SHIFT;
}
if (event->alt) {
but->modifier_key |= KM_ALT;
}
if (event->ctrl) {
but->modifier_key |= KM_CTRL;
}
if (event->oskey) {
but->modifier_key |= KM_OSKEY;
}
but->modifier_key = event->modifier;
ui_but_update(but);
ED_region_tag_redraw(data->region);
@ -4633,7 +4621,8 @@ static int ui_do_but_TAB(
const int rna_type = but->rnaprop ? RNA_property_type(but->rnaprop) : 0;
if (is_property && ELEM(rna_type, PROP_POINTER, PROP_STRING) && (but->custom_data != NULL) &&
(event->type == LEFTMOUSE) && ((event->val == KM_DBL_CLICK) || event->ctrl)) {
(event->type == LEFTMOUSE) &&
((event->val == KM_DBL_CLICK) || (event->modifier & KM_CTRL))) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
return WM_UI_HANDLER_BREAK;
}
@ -4666,7 +4655,8 @@ static int ui_do_but_TEX(
if (ELEM(event->type, EVT_PADENTER, EVT_RETKEY) && (!UI_but_is_utf8(but))) {
/* pass - allow filesel, enter to execute */
}
else if (ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS) && !event->ctrl) {
else if (ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS) &&
((event->modifier & KM_CTRL) == 0)) {
/* pass */
}
else {
@ -4735,7 +4725,7 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && (event->modifier & KM_CTRL)) {
/* Support Ctrl-Wheel to cycle values on expanded enum rows. */
if (but->type == UI_BTYPE_ROW) {
int type = event->type;
@ -5325,24 +5315,24 @@ static int ui_do_but_NUM(
}
/* XXX hardcoded keymap check.... */
if (type == MOUSEPAN && event->ctrl) {
if (type == MOUSEPAN && (event->modifier & KM_CTRL)) {
/* allow accumulating values, otherwise scrolling gets preference */
retval = WM_UI_HANDLER_BREAK;
}
else if (type == WHEELDOWNMOUSE && event->ctrl) {
else if (type == WHEELDOWNMOUSE && (event->modifier & KM_CTRL)) {
mx = but->rect.xmin;
but->drawflag &= ~UI_BUT_ACTIVE_RIGHT;
but->drawflag |= UI_BUT_ACTIVE_LEFT;
click = 1;
}
else if (type == WHEELUPMOUSE && event->ctrl) {
else if ((type == WHEELUPMOUSE) && (event->modifier & KM_CTRL)) {
mx = but->rect.xmax;
but->drawflag &= ~UI_BUT_ACTIVE_LEFT;
but->drawflag |= UI_BUT_ACTIVE_RIGHT;
click = 1;
}
else if (event->val == KM_PRESS) {
if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->ctrl) {
if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && (event->modifier & KM_CTRL)) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
@ -5402,7 +5392,7 @@ static int ui_do_but_NUM(
#endif
fac = 1.0f;
if (event->shift) {
if (event->modifier & KM_SHIFT) {
fac /= 10.0f;
}
@ -5668,27 +5658,27 @@ static int ui_do_but_SLI(
}
/* XXX hardcoded keymap check.... */
if (type == MOUSEPAN && event->ctrl) {
if ((type == MOUSEPAN) && (event->modifier & KM_CTRL)) {
/* allow accumulating values, otherwise scrolling gets preference */
retval = WM_UI_HANDLER_BREAK;
}
else if (type == WHEELDOWNMOUSE && event->ctrl) {
else if ((type == WHEELDOWNMOUSE) && (event->modifier & KM_CTRL)) {
mx = but->rect.xmin;
click = 2;
}
else if (type == WHEELUPMOUSE && event->ctrl) {
else if ((type == WHEELUPMOUSE) && (event->modifier & KM_CTRL)) {
mx = but->rect.xmax;
click = 2;
}
else if (event->val == KM_PRESS) {
if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->ctrl) {
if (ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && (event->modifier & KM_CTRL)) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
#ifndef USE_ALLSELECT
/* alt-click on sides to get "arrows" like in UI_BTYPE_NUM buttons,
* and match wheel usage above */
else if (event->type == LEFTMOUSE && event->alt) {
else if ((event->type == LEFTMOUSE) && (event->modifier & KM_ALT)) {
int halfpos = BLI_rctf_cent_x(&but->rect);
click = 2;
if (mx < halfpos) {
@ -5754,8 +5744,13 @@ static int ui_do_but_SLI(
data->multi_data.drag_dir[0] += abs(data->draglastx - mx);
data->multi_data.drag_dir[1] += abs(data->draglasty - my);
#endif
if (ui_numedit_but_SLI(
but, data, mx, true, is_motion, event->ctrl != 0, event->shift != 0)) {
if (ui_numedit_but_SLI(but,
data,
mx,
true,
is_motion,
event->modifier & KM_CTRL,
event->modifier & KM_SHIFT)) {
ui_numedit_apply(C, block, but, data);
}
@ -5981,8 +5976,8 @@ static int ui_do_but_LISTROW(bContext *C,
/* hack to pass on ctrl+click and double click to overlapping text
* editing field for editing list item names
*/
if ((ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && event->val == KM_PRESS &&
event->ctrl) ||
if ((ELEM(event->type, LEFTMOUSE, EVT_PADENTER, EVT_RETKEY) && (event->val == KM_PRESS) &&
(event->modifier & KM_CTRL)) ||
(event->type == LEFTMOUSE && event->val == KM_DBL_CLICK)) {
uiBut *labelbut = ui_but_list_row_text_activate(
C, but, data, event, BUTTON_ACTIVATE_TEXT_EDITING);
@ -6023,7 +6018,8 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
return WM_UI_HANDLER_BREAK;
}
if (ui_but_supports_cycling(but)) {
if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) &&
(event->modifier & KM_CTRL)) {
int type = event->type;
int val = event->val;
@ -6210,7 +6206,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
return WM_UI_HANDLER_BREAK;
}
if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && (event->modifier & KM_CTRL)) {
ColorPicker *cpicker = but->custom_data;
float hsv_static[3] = {0.0f};
float *hsv = cpicker ? cpicker->hsv_perceptual : hsv_static;
@ -6269,7 +6265,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
if (color_but->is_pallete_color) {
if (!event->ctrl) {
if ((event->modifier & KM_CTRL) == 0) {
float color[3];
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
@ -6639,7 +6635,7 @@ static int ui_do_but_HSVCUBE(
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
/* also do drag the first time */
if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->shift != 0)) {
if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->modifier & KM_SHIFT)) {
ui_numedit_apply(C, block, but, data);
}
@ -6650,7 +6646,7 @@ static int ui_do_but_HSVCUBE(
const wmNDOFMotionData *ndof = event->customdata;
const enum eSnapType snap = ui_event_to_snap(event);
ui_ndofedit_but_HSVCUBE(hsv_but, data, ndof, snap, event->shift != 0);
ui_ndofedit_but_HSVCUBE(hsv_but, data, ndof, snap, event->modifier & KM_SHIFT);
button_activate_state(C, but, BUTTON_STATE_EXIT);
ui_apply_but(C, but->block, but, data, true);
@ -6702,7 +6698,7 @@ static int ui_do_but_HSVCUBE(
if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
const enum eSnapType snap = ui_event_to_snap(event);
if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->shift != 0)) {
if (ui_numedit_but_HSVCUBE(but, data, mx, my, snap, event->modifier & KM_SHIFT)) {
ui_numedit_apply(C, block, but, data);
}
}
@ -6914,7 +6910,7 @@ static int ui_do_but_HSVCIRCLE(
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
/* also do drag the first time */
if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->shift != 0)) {
if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->modifier & KM_SHIFT)) {
ui_numedit_apply(C, block, but, data);
}
@ -6925,7 +6921,7 @@ static int ui_do_but_HSVCIRCLE(
const enum eSnapType snap = ui_event_to_snap(event);
const wmNDOFMotionData *ndof = event->customdata;
ui_ndofedit_but_HSVCIRCLE(but, data, ndof, snap, event->shift != 0);
ui_ndofedit_but_HSVCIRCLE(but, data, ndof, snap, event->modifier & KM_SHIFT);
button_activate_state(C, but, BUTTON_STATE_EXIT);
ui_apply_but(C, but->block, but, data, true);
@ -6987,7 +6983,7 @@ static int ui_do_but_HSVCIRCLE(
if (mx != data->draglastx || my != data->draglasty || event->type != MOUSEMOVE) {
const enum eSnapType snap = ui_event_to_snap(event);
if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->shift != 0)) {
if (ui_numedit_but_HSVCIRCLE(but, data, mx, my, snap, event->modifier & KM_SHIFT)) {
ui_numedit_apply(C, block, but, data);
}
}
@ -7037,7 +7033,7 @@ static int ui_do_but_COLORBAND(
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
ColorBand *coba = (ColorBand *)but->poin;
if (event->ctrl) {
if (event->modifier & KM_CTRL) {
/* insert new key on mouse location */
const float pos = ((float)(mx - but->rect.xmin)) / BLI_rctf_size_x(&but->rect);
BKE_colorband_element_add(coba, pos);
@ -7237,7 +7233,7 @@ static int ui_do_but_CURVE(
float dist_min_sq = square_f(U.dpi_fac * 14.0f); /* 14 pixels radius */
int sel = -1;
if (event->ctrl) {
if (event->modifier & KM_CTRL) {
float f_xy[2];
BLI_rctf_transform_pt_v(&cumap->curr, &but->rect, f_xy, m_xy);
@ -7301,7 +7297,7 @@ static int ui_do_but_CURVE(
if (sel != -1) {
/* ok, we move a point */
/* deselect all if this one is deselect. except if we hold shift */
if (!event->shift) {
if ((event->modifier & KM_SHIFT) == 0) {
for (int a = 0; a < cuma->totpoint; a++) {
cmp[a].flag &= ~CUMA_SELECT;
}
@ -7336,8 +7332,8 @@ static int ui_do_but_CURVE(
data,
event->xy[0],
event->xy[1],
event->ctrl != 0,
event->shift != 0)) {
event->modifier & KM_CTRL,
event->modifier & KM_SHIFT)) {
ui_numedit_apply(C, block, but, data);
}
}
@ -7350,7 +7346,7 @@ static int ui_do_but_CURVE(
if (data->dragchange == false) {
/* deselect all, select one */
if (!event->shift) {
if ((event->modifier & KM_SHIFT) == 0) {
for (int a = 0; a < cuma->totpoint; a++) {
cmp[a].flag &= ~CUMA_SELECT;
}
@ -7539,7 +7535,7 @@ static int ui_do_but_CURVEPROFILE(
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
const float m_xy[2] = {mx, my};
if (event->ctrl) {
if (event->modifier & KM_CTRL) {
float f_xy[2];
BLI_rctf_transform_pt_v(&profile->view_rect, &but->rect, f_xy, m_xy);
@ -7616,7 +7612,7 @@ static int ui_do_but_CURVEPROFILE(
/* Change the flag for the point(s) if one was selected or added. */
if (i_selected != -1) {
/* Deselect all if this one is deselected, except if we hold shift. */
if (event->shift) {
if (event->modifier & KM_SHIFT) {
pts[i_selected].flag ^= selection_type;
}
else {
@ -7647,7 +7643,7 @@ static int ui_do_but_CURVEPROFILE(
if (event->type == MOUSEMOVE) {
if (mx != data->draglastx || my != data->draglasty) {
if (ui_numedit_but_CURVEPROFILE(
block, but, data, mx, my, event->ctrl != 0, event->shift != 0)) {
block, but, data, mx, my, event->modifier & KM_CTRL, event->modifier & KM_SHIFT)) {
ui_numedit_apply(C, block, but, data);
}
}
@ -7871,7 +7867,7 @@ static int ui_do_but_TRACKPREVIEW(
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
/* also do drag the first time */
if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->shift != 0)) {
if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->modifier & KM_SHIFT)) {
ui_numedit_apply(C, block, but, data);
}
@ -7888,7 +7884,7 @@ static int ui_do_but_TRACKPREVIEW(
}
else if (event->type == MOUSEMOVE) {
if (mx != data->draglastx || my != data->draglasty) {
if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->shift != 0)) {
if (ui_numedit_but_TRACKPREVIEW(C, but, data, mx, my, event->modifier & KM_SHIFT)) {
ui_numedit_apply(C, block, but, data);
}
}
@ -7918,8 +7914,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if (data->state == BUTTON_STATE_HIGHLIGHT) {
/* handle copy and paste */
bool is_press_ctrl_but_no_shift = event->val == KM_PRESS && IS_EVENT_MOD(event, ctrl, oskey) &&
!event->shift;
bool is_press_ctrl_but_no_shift = (event->val == KM_PRESS) &&
(event->modifier & (KM_CTRL | KM_OSKEY)) &&
(event->modifier & KM_SHIFT) == 0;
const bool do_copy = event->type == EVT_CKEY && is_press_ctrl_but_no_shift;
const bool do_paste = event->type == EVT_VKEY && is_press_ctrl_but_no_shift;
@ -7934,12 +7931,14 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
/* do copy first, because it is the only allowed operator when disabled */
if (do_copy) {
ui_but_copy(C, but, event->alt);
ui_but_copy(C, but, event->modifier & KM_ALT);
return WM_UI_HANDLER_BREAK;
}
/* handle menu */
if ((event->type == RIGHTMOUSE) && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) &&
if ((event->type == RIGHTMOUSE) &&
(event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) == 0 &&
(event->val == KM_PRESS)) {
/* For some button types that are typically representing entire sets of data, right-clicking
* to spawn the context menu should also activate the item. This makes it clear which item
@ -7960,7 +7959,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
if (do_paste) {
ui_but_paste(C, but, data, event->alt);
ui_but_paste(C, but, data, event->modifier & KM_ALT);
return WM_UI_HANDLER_BREAK;
}
@ -8947,7 +8946,7 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *reg
if (but) {
button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER);
if (event->alt && but->active) {
if ((event->modifier & KM_ALT) && but->active) {
/* Display tool-tips if holding Alt on mouse-over when tool-tips are disabled in the
* preferences. */
but->active->tooltip_force = true;
@ -9555,9 +9554,9 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi
}
else if (val == KM_PRESS) {
if ((ELEM(type, EVT_UPARROWKEY, EVT_DOWNARROWKEY, EVT_LEFTARROWKEY, EVT_RIGHTARROWKEY) &&
!IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) ||
((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->ctrl &&
!IS_EVENT_MOD(event, shift, alt, oskey)))) {
(event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) == 0) ||
((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && (event->modifier & KM_CTRL) &&
(event->modifier & (KM_SHIFT | KM_ALT | KM_OSKEY)) == 0))) {
const int value_orig = RNA_property_int_get(&listbox->rnapoin, listbox->rnaprop);
int value, min, max;
@ -9614,7 +9613,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *regi
}
retval = WM_UI_HANDLER_BREAK;
}
else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && (event->modifier & KM_SHIFT)) {
/* We now have proper grip, but keep this anyway! */
if (ui_list->list_grip < (dyn_data->visual_height_min - UI_LIST_AUTO_SIZE_THRESHOLD)) {
ui_list->list_grip = dyn_data->visual_height;
@ -10268,7 +10267,7 @@ static int ui_handle_menu_event(bContext *C,
/* Smooth scrolling for popovers. */
case MOUSEPAN: {
if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
if (event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) {
/* pass */
}
else if (!ui_block_is_menu(block)) {
@ -10290,7 +10289,7 @@ static int ui_handle_menu_event(bContext *C,
}
case WHEELUPMOUSE:
case WHEELDOWNMOUSE: {
if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
if (event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) {
/* pass */
}
else if (!ui_block_is_menu(block)) {
@ -10313,7 +10312,7 @@ static int ui_handle_menu_event(bContext *C,
case EVT_HOMEKEY:
case EVT_ENDKEY:
/* Arrow-keys: only handle for block_loop blocks. */
if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
if (event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) {
/* pass */
}
else if (inside || (block->flag & UI_BLOCK_LOOP)) {
@ -10464,7 +10463,7 @@ static int ui_handle_menu_event(bContext *C,
break;
}
if (event->alt) {
if (event->modifier & KM_ALT) {
act += 10;
}
@ -10544,7 +10543,7 @@ static int ui_handle_menu_event(bContext *C,
case EVT_YKEY:
case EVT_ZKEY: {
if (ELEM(event->val, KM_PRESS, KM_DBL_CLICK) &&
!IS_EVENT_MOD(event, shift, ctrl, oskey) &&
((event->modifier & (KM_SHIFT | KM_CTRL | KM_OSKEY)) == 0) &&
/* Only respond to explicit press to avoid the event that opened the menu
* activating an item when the key is held. */
!event->is_repeat) {
@ -11071,7 +11070,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
case EVT_YKEY:
case EVT_ZKEY: {
if ((ELEM(event->val, KM_PRESS, KM_DBL_CLICK)) &&
!IS_EVENT_MOD(event, shift, ctrl, oskey)) {
((event->modifier & (KM_SHIFT | KM_CTRL | KM_OSKEY)) == 0)) {
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (but->menu_key == event->type) {
ui_but_pie_button_activate(C, but, menu);

View File

@ -492,7 +492,7 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index)
PointerRNA *ptr = &but->rnapoin;
PropertyRNA *prop = but->rnaprop;
const int index = POINTER_AS_INT(arg_index);
const int shift = win->eventstate->shift;
const bool shift = win->eventstate->modifier & KM_SHIFT;
const int len = RNA_property_array_length(ptr, prop);
if (!shift) {
@ -752,7 +752,7 @@ static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2)
{
wmWindow *win = CTX_wm_window(C);
if (!win->eventstate->shift) {
if ((win->eventstate->modifier & KM_SHIFT) == 0) {
uiBut *but = (uiBut *)arg1;
const int enum_value = POINTER_AS_INT(arg2);

View File

@ -2061,8 +2061,8 @@ static void ui_handle_panel_header(const bContext *C,
const uiBlock *block,
const int mx,
const int event_type,
const short ctrl,
const short shift)
const bool ctrl,
const bool shift)
{
Panel *panel = block->panel;
ARegion *region = CTX_wm_region(C);
@ -2274,7 +2274,7 @@ static int ui_handle_panel_category_cycling(const wmEvent *event,
(event->mval[0] > ((PanelCategoryDyn *)region->panels_category.first)->rect.xmin));
/* If mouse is inside non-tab region, ctrl key is required. */
if (is_mousewheel && !event->ctrl && !inside_tabregion) {
if (is_mousewheel && (event->modifier & KM_CTRL) == 0 && !inside_tabregion) {
return WM_UI_HANDLER_CONTINUE;
}
@ -2291,7 +2291,7 @@ static int ui_handle_panel_category_cycling(const wmEvent *event,
pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev;
}
else {
const bool backwards = event->shift;
const bool backwards = event->modifier & KM_SHIFT;
pc_dyn = backwards ? pc_dyn->prev : pc_dyn->next;
if (!pc_dyn) {
/* Proper cyclic behavior, back to first/last category (only used for ctrl+tab). */
@ -2349,7 +2349,7 @@ int ui_handler_panel_region(bContext *C,
retval = WM_UI_HANDLER_BREAK;
}
}
else if ((event->type == EVT_TABKEY && event->ctrl) ||
else if (((event->type == EVT_TABKEY) && (event->modifier & KM_CTRL)) ||
ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
/* Cycle tabs. */
retval = ui_handle_panel_category_cycling(event, region, active_but);
@ -2386,9 +2386,11 @@ int ui_handler_panel_region(bContext *C,
/* The panel collapse / expand key "A" is special as it takes priority over
* active button handling. */
if (event->type == EVT_AKEY && !IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) {
if (event->type == EVT_AKEY &&
((event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) == 0)) {
retval = WM_UI_HANDLER_BREAK;
ui_handle_panel_header(C, block, mx, event->type, event->ctrl, event->shift);
ui_handle_panel_header(
C, block, mx, event->type, event->modifier & KM_CTRL, event->modifier & KM_SHIFT);
break;
}
}
@ -2402,7 +2404,8 @@ int ui_handler_panel_region(bContext *C,
/* All mouse clicks inside panel headers should return in break. */
if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER, LEFTMOUSE)) {
retval = WM_UI_HANDLER_BREAK;
ui_handle_panel_header(C, block, mx, event->type, event->ctrl, event->shift);
ui_handle_panel_header(
C, block, mx, event->type, event->modifier & KM_CTRL, event->modifier & KM_SHIFT);
}
else if (event->type == RIGHTMOUSE) {
retval = WM_UI_HANDLER_BREAK;

View File

@ -310,7 +310,7 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
uiBut *ui_but_find_mouse_over(const ARegion *region, const wmEvent *event)
{
return ui_but_find_mouse_over_ex(region, event->xy, event->ctrl != 0, NULL, NULL);
return ui_but_find_mouse_over_ex(region, event->xy, event->modifier & KM_CTRL, NULL, NULL);
}
uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px)

View File

@ -701,7 +701,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
/* Keymap */
/* This is too handy not to expose somehow, let's be sneaky for now. */
if ((is_label == false) && CTX_wm_window(C)->eventstate->shift) {
if ((is_label == false) && CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) {
const char *expr_imports[] = {"bpy", "bl_ui", NULL};
char expr[256];
SNPRINTF(expr,

View File

@ -609,7 +609,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
if (id && CTX_wm_window(C)->eventstate->shift) {
if (id && CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) {
/* only way to force-remove data (on save) */
id_us_clear_real(id);
id_fake_user_clear(id);
@ -635,7 +635,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
case UI_ID_LOCAL:
if (id) {
Main *bmain = CTX_data_main(C);
if (CTX_wm_window(C)->eventstate->shift) {
if (CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) {
if (ID_IS_OVERRIDABLE_LIBRARY(id)) {
/* Only remap that specific ID usage to overriding local data-block. */
ID *override_id = BKE_lib_override_library_create_from_id(bmain, id, false);
@ -5539,7 +5539,7 @@ static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
uiBut *but = arg1;
const int cur = POINTER_AS_INT(arg2);
wmWindow *win = CTX_wm_window(C);
const int shift = win->eventstate->shift;
const bool shift = win->eventstate->modifier & KM_SHIFT;
if (!shift) {
const int tot = RNA_property_array_length(&but->rnapoin, but->rnaprop);

View File

@ -1449,7 +1449,7 @@ static int view2d_ndof_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* tune these until it feels right */
const float zoom_sensitivity = 0.5f;
const float speed = 10.0f; /* match view3d ortho */
const bool has_translate = (ndof->tvec[0] && ndof->tvec[1]) && view_pan_poll(C);
const bool has_translate = !is_zero_v2(ndof->tvec) && view_pan_poll(C);
const bool has_zoom = (ndof->tvec[2] != 0.0f) && view_zoom_poll(C);
if (has_translate) {

View File

@ -546,7 +546,7 @@ static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event)
value = value_start[vmode] + value * opdata->scale[vmode];
/* Fake shift-transform... */
if (event->shift) {
if (event->modifier & KM_SHIFT) {
if (opdata->shift_value[vmode] < 0.0f) {
opdata->shift_value[vmode] = (vmode == SEGMENTS_VALUE) ?
opdata->segments :

View File

@ -581,7 +581,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
handled = true;
break;
case MOUSEPAN:
if (event->alt == 0) {
if ((event->modifier & KM_ALT) == 0) {
cuts += 0.02f * (event->xy[1] - event->prev_xy[1]);
if (cuts < 1 && lcd->cuts >= 1) {
cuts = 1;
@ -598,7 +598,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event->val == KM_RELEASE) {
break;
}
if (event->alt == 0) {
if ((event->modifier & KM_ALT) == 0) {
cuts += 1;
}
else {
@ -612,7 +612,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event->val == KM_RELEASE) {
break;
}
if (event->alt == 0) {
if ((event->modifier & KM_ALT) == 0) {
cuts = max_ff(cuts - 1, 1);
}
else {

View File

@ -1367,10 +1367,10 @@ static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* detecting these options based on shift/ctrl here is weak, but it's done
* to make this work when clicking buttons or menus */
if (!RNA_struct_property_is_set(op->ptr, "use_extend")) {
RNA_boolean_set(op->ptr, "use_extend", event->shift);
RNA_boolean_set(op->ptr, "use_extend", event->modifier & KM_SHIFT);
}
if (!RNA_struct_property_is_set(op->ptr, "use_expand")) {
RNA_boolean_set(op->ptr, "use_expand", event->ctrl);
RNA_boolean_set(op->ptr, "use_expand", event->modifier & KM_CTRL);
}
return edbm_select_mode_exec(C, op);

Some files were not shown because too many files have changed in this diff Show More