Compare commits

...

38 Commits

Author SHA1 Message Date
ef9ca44dee Update submodule hashes before tagging Blender 3.4.1 release. 2022-12-20 09:50:50 +01:00
55485cb379 Version char bump for Blender 3.4.1, release. 2022-12-19 18:00:38 +01:00
b9ced50094 Fix T103037: Regression: Grease Pencil Line Texture last point gets distorted
This was due to a missing endpoint case that wasn't handled in the port.

The last point still have to be discarded manually because of the
dot/stroke setting of the material.

The first test `ma1.x == -1` is not necessary anymore since the index
buffer do not contain this point (which was rendered using instance
rendering before.

Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D16812
2022-12-19 14:16:38 +01:00
48f0d5de54 Fix T103261: Undo after mask extract doesn't restore active object 2022-12-19 11:47:21 +01:00
c79d853e4d Fix T103321: NodeSocket.node is None in Node.copy callback
Tag the topology cache dirty before Python can do arbitrary things
in the RNA copy callback.
2022-12-19 10:26:19 +01:00
b64a80edd5 Fix T103293: GPencil Multiframe Scale affects stroke thickness inversely
The problem was the falloff factor was applied directly
and in the thickness must be inversed. Now the thickess
is calculated using an interpolation.
2022-12-19 10:26:07 +01:00
Iliya Katueshenock
75849c7796 Fix: ignore unavailable sockets linked to multi-input socket
Differential Revision: https://developer.blender.org/D16784
2022-12-19 10:25:56 +01:00
e01b98cdb6 Fix T103187: Opening node search menu is slow because of assets.
Avoid utility function call that would query the file system, this was a
bottleneck. The path joining was also problematic. See patch for more
details.

Differential Revision: https://developer.blender.org/D16768

Reviewed by: Jacques Lucke
2022-12-19 10:25:41 +01:00
b87bcd3f8f Fix T102346: Mouse escapes window during walk navigation
This is an alternative fix to [0] which kept the cursor centrally
located as part of GHOST cursor grabbing which caused T102792.

Now this is done as part of walk mode as it's the operator that most
often ran into this problem although ideally this would be handled by
GHOST - but that's a much bigger project.

[0]: 9fd6dae793
2022-12-16 15:49:28 +01:00
nutti
a1e7d96801 Fix T102213: Invalid font size in the image editor with some scripts
The size could be left at an unexpected value by scripts, causing
the wrong size to be shown.

Ref D16493
2022-12-16 15:47:57 +01:00
d4a6108ef2 Fix T103234: GPencil applying armature does not work
The problem was the bake function was using the evaluated
data and must use the original data.

The problem was caused by commit: rBcff6eb65804d: Cleanup: Remove duplicate Bake modifier code.

Fix by Philipp Oeser
2022-12-16 15:47:43 +01:00
c1537d4134 Cleanup: declare GHOST_Window::getCursorGrabBounds as const
Needed so it the method can be called on a cosnt GHOST_Window.
2022-12-16 15:47:29 +01:00
08fa18fb6e Fix cursor warping display under Wayland
Under Wayland the transform cursor wasn't displaying the warped cursor.

This worked on other platforms because cursor motion is warped where as
Wayland simulates cursor warping, so it's necessary to apply warping
when requesting the cursor location too.
2022-12-16 15:47:16 +01:00
72260deac1 WM: support checking windowing capabilities
Historically checks for windowing capabilities used platform
pre-processor checks however that doesn't work when Blender is built
with both X11 & Wayland.

Add a capabilities flag which can be used to check which functionality
is supported. This has the advantage of being more descriptive/readable.
2022-12-16 15:47:04 +01:00
5d73850dd4 Revert "Fix T102346: Mouse escapes window during walk navigation"
This reverts commits
9fd6dae793,
4cac8025f0 (minor cleanup).

Re-introducing T102346, which will be fixed in isolation.

Unfortunately even when the cursor is hidden & grabbed,
the underlying cursor coordinates are still shown in some cases.

This caused bug where dragging a button in the sculpt-context popup
would draw the brush at unexpected locations because internally
the cursor was warping in the middle of the window, reported as T102792.

Resolving this issue with the paint cursor is possible but tend towards
over-complicated solutions.

Revert this change in favor of a more localized workaround for walk-mode
(as was done prior [0] to fix T99021).

[0]: 4c4e8cc926
2022-12-16 15:46:52 +01:00
3dcd999267 Fix T103237: Prevent UV Unwrap from packing hidden UV islands
When migrating to the new packing API, pin_unselected was not
implemented correctly.

Regression from rB143e74c0b8eb, rBe3075f3cf7ce, rB0ce18561bc82.

Differential Revision: https://developer.blender.org/D16788

Reviewed By: Campbell Barton
2022-12-16 16:22:27 +13:00
fd3943dbd5 Fix T103049: Cycles specular light leak regression
The logic here is not ideal but was unintentionally changed in refactoring
for path guiding, now restore it back to 3.3 behavior again.
2022-12-15 22:03:57 +01:00
c2e7bf3953 GPencil: Fix unreported interpolate crash in empty layers
If there is a layer that hasn't frames but is not the active layer
the pointer to frames can be NULL and crash.

Now, the empty layers are skipped.

Reported to me by Samuel Bernou.
2022-12-15 11:38:49 +01:00
6325174a75 Fix T103101: random Cycles animation rendering freezing up the application 2022-12-14 22:34:12 +01:00
0b706237b0 Fix T103066: Cycles missing full constant foler for mix float and mix vector 2022-12-14 22:34:02 +01:00
28e6a8414a Revert "Fix T102571: Can't stop audio playback when using multiple windows"
This reverts commit 42b51bf6a9.

Commit caused crash when playback is stopped, see T103008.
2022-12-14 22:33:51 +01:00
Iliya Katueshenock
9992096c49 Fix T103208: unavailable socket linked to multi-input socket crashes
Differential Revision: https://developer.blender.org/D16772
2022-12-14 22:33:39 +01:00
d6e75e2c23 Fix T103143: Cycles can lose default color attribute
The `render_color_index` skips attributes with different types
and domains in order to give the proper order for the UI list.
That is a different than an index in the group of all attributes.

The most solid solution I could think of is exposing the name of
the default color attribute. It's "solid" because we always address
attributes by name internally. Doing something different is bound
to create problems. It's also aligned with the design in T98366 and
D15169.

Another option would be to change the way the "attribute index"
is incremented in Cycles. That would be a valid solution, but would
be more complex and annoying.

For consistency, I also exposed the name of the active color attribute
the same way, though it isn't necessary to fix this particular bug.

The properties aren't editable, that can come in 3.5 as part of D15169.

Differential Revision: https://developer.blender.org/D16769
2022-12-14 22:33:28 +01:00
7e5cb94748 Fix T103119: Allow Win32 Diacritical Composition
Allow keyboard layouts which include "dead keys" to enter diacritics
by calling MapVirtualKeyW even when not key_down.

See D16770 for more details.

Differential Revision: https://developer.blender.org/D16770

Reviewed by Campbell Barton
2022-12-14 22:33:11 +01:00
e22f49c801 Fix T103052: Box trim does not create face sets attribute
Previously the sculpt box trim operator always created face sets,
but after face sets became optional it only modified them if they
already existed. Absent a better way to turn the behavior on and off,
the fix is to just always create face sets.
2022-12-14 22:20:41 +01:00
ef40604b87 Fix T103051: Changed behavior when removing a material slot
Before f1c0249f34 the material was assigned to the previous
slot rather than the next. Though the behavior is arbitrary, there
is no reason to change it.
2022-12-14 22:20:24 +01:00
d666c64f5d Fix T103195: Initialize face sets from bevel weights broken
The conversion from char to float (divide by 255) wasn't removed in
291c313f80. Also fix a crash when the edge crease layer
didn't exist.
2022-12-14 22:20:10 +01:00
94e7e83cd9 Fix T103061: GPencil export to SVG wrong line thickness
When the line was very thin the precision of the thickness
calculation was not precise enough.

The algorithm has been improved. This affects SVG and PDF.
2022-12-14 22:19:52 +01:00
389b086929 Fix T103067: Regression: Workbench render crash in 3.4
The workbench engine assumes that the Z pass exists, but didn't register it before.
Since rB3411a96e7493, this is mandatory.
2022-12-14 22:19:33 +01:00
c4251110a9 Fix T102992: GPencil Array doesn't respect restriction in Offset
The problem was the bounding box was calculated using
all strokes, but if a filter is added, the bounding box must
include only selected strokes.

Fix by @frogstomp
2022-12-14 22:19:18 +01:00
a47d1ad9d5 Fix T103031: ViewLayer: Crash in indirect_only_get due to missing null check
Previous fix (rBe00f76c6a8cca) accidentally lost a null check.
Fixes T103031.
2022-12-14 22:19:00 +01:00
Edward
fa5164a8b2 Sculpt: Fix T101914: Wpaint gradient tool doesn't work with vertex mask
Reviewed by: Julian Kaspar & Joseph Eagar
Differential Revision: https://developer.blender.org/D16293
Ref D16293
2022-12-14 21:30:57 +01:00
08d687e8cd Fix: UI: broken texpaintslot/color attributes/attributes name filtering
rB8b7cd1ed2a17 broke this for the paint slots
rB4669178fc378 broke this for regular attributes

Name filtering in UI Lists works when:
- [one] the items to be filtered have a name property
-- see how `uilist_filter_items_default` gets the `namebuf`
- [two] custom python filter functions (`filter_items`) implement it
themselves
-- if you use `filter_items` and dont do name filtering there, the default
name filtering wont be used

So, two problems with rB8b7cd1ed2a17:
- [1] items to be listed changed from `texture_paint_images` to
`texture_paint_slots`
-- the former has name_property defined, the later lacks this
- [2] the new `ColorAttributesListBase` defined a `filter_items` function,
but did not implement name filtering

And the problem with rB4669178fc378:
- it added `filter_items` functions, but did not implement name filtering.

These are all corrected now.

Fixes T102878

Maniphest Tasks: T102878

Differential Revision: https://developer.blender.org/D16676
2022-12-14 21:30:40 +01:00
18ecaaf9cb GPU: Fix using FLOAT_2D_ARRAY and FLOAT_3D textures via Python.
Translation from python enum values were incorrect and textures created
in python using those types would result in faulty textures. In
renderdoc those textures would not bind.
2022-12-14 21:29:42 +01:00
fd70f9dfda Fix T102276: Hotkey conflict Alt D in Node Editor with Duplicate Linked and Detach
This unassign the Alt+D shortcut from the detach operator. Right now the
operator has to be accessed via the menu.

Alt+D is left for duplicate link, following the other editors.
2022-12-14 21:29:20 +01:00
28235df709 Version bump for Blender 3.4.1, rc. 2022-12-14 21:27:52 +01:00
175bd38201 Update subrepository references before tagging. 2022-12-07 12:39:39 +01:00
a95bf1ac01 Blender 3.4.0: Splash and cycle bump.
Splash: Blender Studio, Project Heist.
2022-12-06 19:46:15 +01:00
51 changed files with 485 additions and 209 deletions

View File

@@ -367,13 +367,11 @@ static void attr_create_generic(Scene *scene,
{
AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
static const ustring u_velocity("velocity");
int attribute_index = 0;
int render_color_index = b_mesh.attributes.render_color_index();
const ustring default_color_name{b_mesh.attributes.default_color_name().c_str()};
for (BL::Attribute &b_attribute : b_mesh.attributes) {
const ustring name{b_attribute.name().c_str()};
const bool is_render_color = (attribute_index++ == render_color_index);
const bool is_render_color = name == default_color_name;
if (need_motion && name == u_velocity) {
attr_create_motion(mesh, b_attribute, motion_scale);

View File

@@ -578,11 +578,11 @@ ccl_device_inline
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
eval = bsdf_microfacet_ggx_eval(sc, sd->I, omega_in, pdf);
eval = bsdf_microfacet_ggx_eval(sc, sd->N, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
eval = bsdf_microfacet_multi_ggx_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state);
eval = bsdf_microfacet_multi_ggx_eval(sc, sd->N, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
@@ -590,10 +590,10 @@ ccl_device_inline
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval(sc, sd->I, omega_in, pdf);
eval = bsdf_microfacet_beckmann_eval(sc, sd->N, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
eval = bsdf_ashikhmin_shirley_eval(sc, sd->I, omega_in, pdf);
eval = bsdf_ashikhmin_shirley_eval(sc, sd->N, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
eval = bsdf_ashikhmin_velvet_eval(sc, sd->I, omega_in, pdf);

View File

@@ -40,11 +40,13 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float rough
}
ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval(ccl_private const ShaderClosure *sc,
const float3 Ng,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
const float cosNgI = dot(Ng, omega_in);
float3 N = bsdf->N;
float NdotI = dot(N, I); /* in Cycles/OSL convention I is omega_out */
@@ -52,7 +54,8 @@ ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval(ccl_private const Sh
float out = 0.0f;
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f || !(NdotI > 0.0f && NdotO > 0.0f)) {
if ((cosNgI < 0.0f) || fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f ||
!(NdotI > 0.0f && NdotO > 0.0f)) {
*pdf = 0.0f;
return zero_spectrum();
}
@@ -210,7 +213,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc
}
else {
/* leave the rest to eval */
*eval = bsdf_ashikhmin_shirley_eval(sc, I, *omega_in, pdf);
*eval = bsdf_ashikhmin_shirley_eval(sc, N, I, *omega_in, pdf);
}
return label;

View File

@@ -517,27 +517,30 @@ ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const Microfac
}
ccl_device Spectrum bsdf_microfacet_ggx_eval(ccl_private const ShaderClosure *sc,
const float3 Ng,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
const float alpha_x = bsdf->alpha_x;
const float alpha_y = bsdf->alpha_y;
const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
const float3 N = bsdf->N;
const float cosNO = dot(N, I);
const float cosNI = dot(N, omega_in);
const float cosNgI = dot(Ng, omega_in);
if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) {
if (((cosNgI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) {
*pdf = 0.0f;
return zero_spectrum();
}
return (cosNI < 0.0f) ? bsdf_microfacet_ggx_eval_transmit(
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) :
bsdf_microfacet_ggx_eval_reflect(
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI);
const float3 N = bsdf->N;
const float cosNO = dot(N, I);
const float cosNI = dot(N, omega_in);
return (cosNgI < 0.0f) ? bsdf_microfacet_ggx_eval_transmit(
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) :
bsdf_microfacet_ggx_eval_reflect(
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI);
}
ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
@@ -942,23 +945,26 @@ ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const Mic
}
ccl_device Spectrum bsdf_microfacet_beckmann_eval(ccl_private const ShaderClosure *sc,
const float3 Ng,
const float3 I,
const float3 omega_in,
ccl_private float *pdf)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
const float alpha_x = bsdf->alpha_x;
const float alpha_y = bsdf->alpha_y;
const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
const float3 N = bsdf->N;
const float cosNO = dot(N, I);
const float cosNI = dot(N, omega_in);
const float cosNgI = dot(Ng, omega_in);
if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) {
if (((cosNgI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) {
*pdf = 0.0f;
return zero_spectrum();
}
const float3 N = bsdf->N;
const float cosNO = dot(N, I);
const float cosNI = dot(N, omega_in);
return (cosNI < 0.0f) ? bsdf_microfacet_beckmann_eval_transmit(
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) :
bsdf_microfacet_beckmann_eval_reflect(

View File

@@ -416,14 +416,16 @@ ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(ccl_private Microfacet
}
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval(ccl_private const ShaderClosure *sc,
const float3 Ng,
const float3 I,
const float3 omega_in,
ccl_private float *pdf,
ccl_private uint *lcg_state)
{
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
const float cosNgI = dot(Ng, omega_in);
if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
if ((cosNgI < 0.0f) || bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
*pdf = 0.0f;
return zero_spectrum();
}

View File

@@ -386,6 +386,46 @@ void ConstantFolder::fold_mix_color(NodeMix type, bool clamp_factor, bool clamp)
}
}
void ConstantFolder::fold_mix_float(bool clamp_factor, bool clamp) const
{
ShaderInput *fac_in = node->input("Factor");
ShaderInput *float1_in = node->input("A");
ShaderInput *float2_in = node->input("B");
float fac = clamp_factor ? saturatef(node->get_float(fac_in->socket_type)) :
node->get_float(fac_in->socket_type);
bool fac_is_zero = !fac_in->link && fac == 0.0f;
bool fac_is_one = !fac_in->link && fac == 1.0f;
/* remove no-op node when factor is 0.0 */
if (fac_is_zero) {
if (try_bypass_or_make_constant(float1_in, clamp)) {
return;
}
}
/* remove useless mix floats nodes */
if (float1_in->link && float2_in->link) {
if (float1_in->link == float2_in->link) {
try_bypass_or_make_constant(float1_in, clamp);
return;
}
}
else if (!float1_in->link && !float2_in->link) {
float value1 = node->get_float(float1_in->socket_type);
float value2 = node->get_float(float2_in->socket_type);
if (value1 == value2) {
try_bypass_or_make_constant(float1_in, clamp);
return;
}
}
/* remove no-op mix float node when factor is 1.0 */
if (fac_is_one) {
try_bypass_or_make_constant(float2_in, clamp);
return;
}
}
void ConstantFolder::fold_math(NodeMathType type) const
{
ShaderInput *value1_in = node->input("Value1");

View File

@@ -52,6 +52,7 @@ class ConstantFolder {
/* Specific nodes. */
void fold_mix(NodeMix type, bool clamp) const;
void fold_mix_color(NodeMix type, bool clamp_factor, bool clamp) const;
void fold_mix_float(bool clamp_factor, bool clamp) const;
void fold_math(NodeMathType type) const;
void fold_vector_math(NodeVectorMathType type) const;
void fold_mapping(NodeMappingType type) const;

View File

@@ -5132,6 +5132,9 @@ void MixFloatNode::constant_fold(const ConstantFolder &folder)
}
folder.make_constant(a * (1 - fac) + b * fac);
}
else {
folder.fold_mix_float(use_clamp, false);
}
}
/* Mix Vector */
@@ -5185,6 +5188,9 @@ void MixVectorNode::constant_fold(const ConstantFolder &folder)
}
folder.make_constant(a * (one_float3() - fac) + b * fac);
}
else {
folder.fold_mix_color(NODE_MIX_BLEND, use_clamp, false);
}
}
/* Mix Vector Non Uniform */

View File

@@ -254,7 +254,7 @@ class GHOST_IWindow {
*/
virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0;
virtual GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) = 0;
virtual GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) const = 0;
virtual void getCursorGrabState(GHOST_TGrabCursorMode &mode,
GHOST_TAxisFlag &axis_flag,

View File

@@ -5826,8 +5826,36 @@ static GHOST_TSuccess getCursorPositionClientRelative_impl(
int32_t &y)
{
const wl_fixed_t scale = win->scale();
x = wl_fixed_to_int(scale * seat_state_pointer->xy[0]);
y = wl_fixed_to_int(scale * seat_state_pointer->xy[1]);
if (win->getCursorGrabModeIsWarp()) {
/* As the cursor is restored at the warped location,
* apply warping when requesting the cursor location. */
GHOST_Rect wrap_bounds{};
if (win->getCursorGrabModeIsWarp()) {
if (win->getCursorGrabBounds(wrap_bounds) == GHOST_kFailure) {
win->getClientBounds(wrap_bounds);
}
}
int xy_wrap[2] = {
seat_state_pointer->xy[0],
seat_state_pointer->xy[1],
};
GHOST_Rect wrap_bounds_scale;
wrap_bounds_scale.m_l = wl_fixed_from_int(wrap_bounds.m_l) / scale;
wrap_bounds_scale.m_t = wl_fixed_from_int(wrap_bounds.m_t) / scale;
wrap_bounds_scale.m_r = wl_fixed_from_int(wrap_bounds.m_r) / scale;
wrap_bounds_scale.m_b = wl_fixed_from_int(wrap_bounds.m_b) / scale;
wrap_bounds_scale.wrapPoint(UNPACK2(xy_wrap), 0, win->getCursorGrabAxis());
x = wl_fixed_to_int(scale * xy_wrap[0]);
y = wl_fixed_to_int(scale * xy_wrap[1]);
}
else {
x = wl_fixed_to_int(scale * seat_state_pointer->xy[0]);
y = wl_fixed_to_int(scale * seat_state_pointer->xy[1]);
}
return GHOST_kSuccess;
}

View File

@@ -1055,46 +1055,17 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
int32_t x_new = x_screen;
int32_t y_new = y_screen;
int32_t x_accum, y_accum;
GHOST_Rect bounds;
/* Warp within bounds. */
{
GHOST_Rect bounds;
int32_t bounds_margin = 0;
GHOST_TAxisFlag bounds_axis = GHOST_kAxisNone;
if (window->getCursorGrabMode() == GHOST_kGrabHide) {
window->getClientBounds(bounds);
/* WARNING(@campbellbarton): The current warping logic fails to warp on every event,
* so the box needs to small enough not to let the cursor escape the window but large
* enough that the cursor isn't being warped every time.
* If this was not the case it would be less trouble to simply warp the cursor to the
* center of the screen on every motion, see: D16558 (alternative fix for T102346). */
const int32_t subregion_div = 4; /* One quarter of the region. */
const int32_t size[2] = {bounds.getWidth(), bounds.getHeight()};
const int32_t center[2] = {(bounds.m_l + bounds.m_r) / 2, (bounds.m_t + bounds.m_b) / 2};
/* Shrink the box to prevent the cursor escaping. */
bounds.m_l = center[0] - (size[0] / (subregion_div * 2));
bounds.m_r = center[0] + (size[0] / (subregion_div * 2));
bounds.m_t = center[1] - (size[1] / (subregion_div * 2));
bounds.m_b = center[1] + (size[1] / (subregion_div * 2));
bounds_margin = 0;
bounds_axis = GHOST_TAxisFlag(GHOST_kAxisX | GHOST_kAxisY);
}
else {
/* Fallback to window bounds. */
if (window->getCursorGrabBounds(bounds) == GHOST_kFailure) {
window->getClientBounds(bounds);
}
bounds_margin = 2;
bounds_axis = window->getCursorGrabAxis();
}
/* Could also clamp to screen bounds wrap with a window outside the view will
* fail at the moment. Use inset in case the window is at screen bounds. */
bounds.wrapPoint(x_new, y_new, bounds_margin, bounds_axis);
/* Fallback to window bounds. */
if (window->getCursorGrabBounds(bounds) == GHOST_kFailure) {
window->getClientBounds(bounds);
}
/* Could also clamp to screen bounds wrap with a window outside the view will
* fail at the moment. Use inset in case the window is at screen bounds. */
bounds.wrapPoint(x_new, y_new, 2, window->getCursorGrabAxis());
window->getCursorGrabAccum(x_accum, y_accum);
if (x_new != x_screen || y_new != y_screen) {
system->setCursorPosition(x_new, y_new); /* wrap */
@@ -1195,16 +1166,16 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
const bool ctrl_pressed = has_state && state[VK_CONTROL] & 0x80;
const bool alt_pressed = has_state && state[VK_MENU] & 0x80;
if (!key_down) {
/* Pass. */
}
/* We can be here with !key_down if processing dead keys (diacritics). See T103119. */
/* No text with control key pressed (Alt can be used to insert special characters though!). */
else if (ctrl_pressed && !alt_pressed) {
if (ctrl_pressed && !alt_pressed) {
/* Pass. */
}
/* Don't call #ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical
* composition. */
else if (MapVirtualKeyW(vk, 2) != 0) {
* composition. XXX: we are not checking return of MapVirtualKeyW for high bit set, which is
* what is supposed to indicate dead keys. But this is working now so approach cautiously. */
else if (MapVirtualKeyW(vk, MAPVK_VK_TO_CHAR) != 0) {
wchar_t utf16[3] = {0};
int r;
/* TODO: #ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here).
@@ -1219,6 +1190,10 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
utf8_char[0] = '\0';
}
}
if (!key_down) {
/* Clear or wm_event_add_ghostevent will warn of unexpected data on key up. */
utf8_char[0] = '\0';
}
}
#ifdef WITH_INPUT_IME

View File

@@ -934,48 +934,17 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
int32_t x_new = xme.x_root;
int32_t y_new = xme.y_root;
int32_t x_accum, y_accum;
GHOST_Rect bounds;
/* Warp within bounds. */
{
GHOST_Rect bounds;
int32_t bounds_margin = 0;
GHOST_TAxisFlag bounds_axis = GHOST_kAxisNone;
if (window->getCursorGrabMode() == GHOST_kGrabHide) {
window->getClientBounds(bounds);
/* TODO(@campbellbarton): warp the cursor to `window->getCursorGrabInitPos`,
* on every motion event, see: D16557 (alternative fix for T102346). */
const int32_t subregion_div = 4; /* One quarter of the region. */
const int32_t size[2] = {bounds.getWidth(), bounds.getHeight()};
const int32_t center[2] = {
(bounds.m_l + bounds.m_r) / 2,
(bounds.m_t + bounds.m_b) / 2,
};
/* Shrink the box to prevent the cursor escaping. */
bounds.m_l = center[0] - (size[0] / (subregion_div * 2));
bounds.m_r = center[0] + (size[0] / (subregion_div * 2));
bounds.m_t = center[1] - (size[1] / (subregion_div * 2));
bounds.m_b = center[1] + (size[1] / (subregion_div * 2));
bounds_margin = 0;
bounds_axis = GHOST_TAxisFlag(GHOST_kAxisX | GHOST_kAxisY);
}
else {
/* Fallback to window bounds. */
if (window->getCursorGrabBounds(bounds) == GHOST_kFailure) {
window->getClientBounds(bounds);
}
/* Could also clamp to screen bounds wrap with a window outside the view will
* fail at the moment. Use offset of 8 in case the window is at screen bounds. */
bounds_margin = 8;
bounds_axis = window->getCursorGrabAxis();
}
/* Could also clamp to screen bounds wrap with a window outside the view will
* fail at the moment. Use inset in case the window is at screen bounds. */
bounds.wrapPoint(x_new, y_new, bounds_margin, bounds_axis);
/* fallback to window bounds */
if (window->getCursorGrabBounds(bounds) == GHOST_kFailure) {
window->getClientBounds(bounds);
}
/* Could also clamp to screen bounds wrap with a window outside the view will
* fail at the moment. Use offset of 8 in case the window is at screen bounds. */
bounds.wrapPoint(x_new, y_new, 8, window->getCursorGrabAxis());
window->getCursorGrabAccum(x_accum, y_accum);
if (x_new != xme.x_root || y_new != xme.y_root) {

View File

@@ -159,7 +159,7 @@ GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode,
return GHOST_kFailure;
}
GHOST_TSuccess GHOST_Window::getCursorGrabBounds(GHOST_Rect &bounds)
GHOST_TSuccess GHOST_Window::getCursorGrabBounds(GHOST_Rect &bounds) const
{
if (m_cursorGrab != GHOST_kGrabWrap) {
return GHOST_kFailure;

View File

@@ -152,7 +152,7 @@ class GHOST_Window : public GHOST_IWindow {
* Gets the cursor grab region, if unset the window is used.
* reset when grab is disabled.
*/
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) override;
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) const override;
void getCursorGrabState(GHOST_TGrabCursorMode &mode,
GHOST_TAxisFlag &axis_flag,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 823 KiB

After

Width:  |  Height:  |  Size: 890 KiB

View File

@@ -2137,9 +2137,6 @@ def km_node_editor(params):
)),
("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
("node.move_detach_links",
{"type": 'D', "value": 'PRESS', "alt": True},
{"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
("node.move_detach_links_release",
{"type": params.action_mouse, "value": 'CLICK_DRAG', "alt": True},
{"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),

View File

@@ -88,8 +88,16 @@ class CURVES_UL_attributes(UIList):
flags = []
indices = [i for i in range(len(attributes))]
for item in attributes:
flags.append(0 if item.is_internal else self.bitflag_filter_item)
# Filtering by name
if self.filter_name:
flags = bpy.types.UI_UL_list.filter_items_by_name(
self.filter_name, self.bitflag_filter_item, attributes, "name", reverse=self.use_filter_invert)
if not flags:
flags = [self.bitflag_filter_item] * len(attributes)
# Filtering internal attributes
for idx, item in enumerate(attributes):
flags[idx] = 0 if item.is_internal else flags[idx]
return flags, indices

View File

@@ -535,8 +535,16 @@ class MESH_UL_attributes(UIList):
flags = []
indices = [i for i in range(len(attributes))]
for item in attributes:
flags.append(0 if item.is_internal else self.bitflag_filter_item)
# Filtering by name
if self.filter_name:
flags = bpy.types.UI_UL_list.filter_items_by_name(
self.filter_name, self.bitflag_filter_item, attributes, "name", reverse=self.use_filter_invert)
if not flags:
flags = [self.bitflag_filter_item] * len(attributes)
# Filtering internal attributes
for idx, item in enumerate(attributes):
flags[idx] = 0 if item.is_internal else flags[idx]
return flags, indices
@@ -624,20 +632,26 @@ class ColorAttributesListBase():
}
def filter_items(self, _context, data, property):
attrs = getattr(data, property)
ret = []
idxs = []
attributes = getattr(data, property)
flags = []
indices = [i for i in range(len(attributes))]
for idx, item in enumerate(attrs):
# Filtering by name
if self.filter_name:
flags = bpy.types.UI_UL_list.filter_items_by_name(
self.filter_name, self.bitflag_filter_item, attributes, "name", reverse=self.use_filter_invert)
if not flags:
flags = [self.bitflag_filter_item] * len(attributes)
for idx, item in enumerate(attributes):
skip = (
(item.domain not in {"POINT", "CORNER"}) or
(item.data_type not in {"FLOAT_COLOR", "BYTE_COLOR"}) or
item.is_internal
)
ret.append(0 if skip else self.bitflag_filter_item)
idxs.append(idx)
flags[idx] = 0 if skip else flags[idx]
return ret, idxs
return flags, indices
class MESH_UL_color_attributes(UIList, ColorAttributesListBase):

View File

@@ -70,8 +70,16 @@ class POINTCLOUD_UL_attributes(UIList):
flags = []
indices = [i for i in range(len(attributes))]
for item in attributes:
flags.append(0 if item.is_internal else self.bitflag_filter_item)
# Filtering by name
if self.filter_name:
flags = bpy.types.UI_UL_list.filter_items_by_name(
self.filter_name, self.bitflag_filter_item, attributes, "name", reverse=self.use_filter_invert)
if not flags:
flags = [self.bitflag_filter_item] * len(attributes)
# Filtering internal attributes
for idx, item in enumerate(attributes):
flags[idx] = 0 if item.is_internal else flags[idx]
return flags, indices

View File

@@ -19,9 +19,9 @@ extern "C" {
/* Blender major and minor version. */
#define BLENDER_VERSION 304
/* Blender patch version for bugfix releases. */
#define BLENDER_VERSION_PATCH 0
#define BLENDER_VERSION_PATCH 1
/** Blender release cycle stage: alpha/beta/rc/release. */
#define BLENDER_VERSION_CYCLE rc
#define BLENDER_VERSION_CYCLE release
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION

View File

@@ -1364,7 +1364,7 @@ void BKE_mesh_material_index_remove(Mesh *me, short index)
}
MutableVArraySpan<int> indices_span(material_indices.varray);
for (const int i : indices_span.index_range()) {
if (indices_span[i] > 0 && indices_span[i] > index) {
if (indices_span[i] > 0 && indices_span[i] >= index) {
indices_span[i]--;
}
}

View File

@@ -2323,6 +2323,10 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree,
node_src.typeinfo->copyfunc(dst_tree, node_dst, &node_src);
}
if (dst_tree) {
BKE_ntree_update_tag_node_new(dst_tree, node_dst);
}
/* Only call copy function when a copy is made for the main database, not
* for cases like the dependency graph and localization. */
if (node_dst->typeinfo->copyfunc_api && !(flag & LIB_ID_CREATE_NO_MAIN)) {
@@ -2332,10 +2336,6 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree,
node_dst->typeinfo->copyfunc_api(&ptr, &node_src);
}
if (dst_tree) {
BKE_ntree_update_tag_node_new(dst_tree, node_dst);
}
/* Reset the declaration of the new node. */
nodeDeclarationEnsure(dst_tree, node_dst);

View File

@@ -214,4 +214,7 @@ void workbench_render(void *ved, RenderEngine *engine, RenderLayer *render_layer
void workbench_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
{
RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
if ((view_layer->passflag & SCE_PASS_Z) != 0) {
RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_Z, 1, "Z", SOCK_FLOAT);
}
}

View File

@@ -187,6 +187,13 @@ vec4 gpencil_vertex(vec4 viewport_size,
is_squares = false;
}
/* Endpoints, we discard the vertices. */
if (!is_dot && ma2.x == -1) {
/* We set the vertex at the camera origin to generate 0 fragments. */
out_ndc = vec4(0.0, 0.0, -3e36, 0.0);
return out_ndc;
}
/* Avoid using a vertex attribute for quad positioning. */
float x = float(gl_VertexID & 1) * 2.0 - 1.0; /* [-1..1] */
float y = float(gl_VertexID & 2) - 1.0; /* [-1..1] */

View File

@@ -479,15 +479,20 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
continue;
}
/* create temp data for each layer */
bGPDframe *gpf_prv = gpencil_get_previous_keyframe(gpl, scene->r.cfra);
if (gpf_prv == NULL) {
continue;
}
bGPDframe *gpf_next = gpencil_get_next_keyframe(gpl, scene->r.cfra);
if (gpf_next == NULL) {
continue;
}
/* Create temp data for each layer. */
tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
tgpil->gpl = gpl;
bGPDframe *gpf = gpencil_get_previous_keyframe(gpl, scene->r.cfra);
tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpf, true);
gpf = gpencil_get_next_keyframe(gpl, scene->r.cfra);
tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpf, true);
tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpf_prv, true);
tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpf_next, true);
BLI_addtail(&tgpi->ilayers, tgpil);

View File

@@ -37,6 +37,7 @@
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_undo.h"
#include "ED_view3d.h"
#include "bmesh_tools.h"
@@ -287,6 +288,16 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
params.add_boundary_loop = RNA_boolean_get(op->ptr, "add_boundary_loop");
params.apply_shrinkwrap = RNA_boolean_get(op->ptr, "apply_shrinkwrap");
params.add_solidify = RNA_boolean_get(op->ptr, "add_solidify");
/* Push an undo step prior to extraction.
* Note: A second push happens after the operator due to
* the OPTYPE_UNDO flag; having an initial undo step here
* is just needed to preserve the active object pointer.
*
* Fixes T103261.
*/
ED_undo_push_op(C, op);
return geometry_extract_apply(C, op, geometry_extract_tag_masked_faces, &params);
}

View File

@@ -3531,6 +3531,9 @@ void ED_region_info_draw_multiline(ARegion *region,
/* background box */
rcti rect = *ED_region_visible_rect(region);
/* Needed in case scripts leave the font size at an unexpected value, see: T102213. */
BLF_size(fontid, style->widget.points * U.dpi_fac);
/* Box fill entire width or just around text. */
if (!full_redraw) {
const char **text = &text_array[0];

View File

@@ -4812,28 +4812,19 @@ bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm)
int ED_screen_animation_play(bContext *C, int sync, int mode)
{
bScreen *screen = CTX_wm_screen(C);
Scene *scene = CTX_data_scene(C);
Scene *scene_eval = DEG_get_evaluated_scene(CTX_data_ensure_evaluated_depsgraph(C));
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
/* stop playback now */
ED_screen_animation_timer(C, 0, 0, 0);
Main *bmain = CTX_data_main(C);
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
Depsgraph *graph = BKE_scene_get_depsgraph(scene, view_layer);
if (graph) {
Scene *scene_eval = DEG_get_evaluated_scene(graph);
/* The audio handles are preserved throughout the dependency graph evaluation.
* Checking for scene->playback_handle even for non-evaluated scene should be okay. */
BKE_sound_stop_scene(scene_eval);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
}
}
BKE_sound_stop_scene(scene_eval);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
else {
/* these settings are currently only available from a menu in the TimeLine */
if (mode == 1) { /* XXX only play audio forwards!? */
Scene *scene_eval = DEG_get_evaluated_scene(CTX_data_ensure_evaluated_depsgraph(C));
BKE_sound_play_scene(scene_eval);
}

View File

@@ -1345,6 +1345,11 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext)
static void sculpt_gesture_trim_begin(bContext *C, SculptGestureContext *sgcontext)
{
Object *object = sgcontext->vc.obact;
SculptSession *ss = object->sculpt;
Mesh *mesh = (Mesh *)object->data;
ss->face_sets = BKE_sculpt_face_sets_ensure(mesh);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
sculpt_gesture_trim_calculate_depth(sgcontext);
sculpt_gesture_trim_geometry_generate(sgcontext);
@@ -1369,9 +1374,9 @@ static void sculpt_gesture_trim_end(bContext *UNUSED(C), SculptGestureContext *s
{
Object *object = sgcontext->vc.obact;
SculptSession *ss = object->sculpt;
Mesh *mesh = (Mesh *)object->data;
ss->face_sets = CustomData_get_layer_named(
&((Mesh *)object->data)->pdata, CD_PROP_INT32, ".sculpt_face_set");
ss->face_sets = CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, ".sculpt_face_set");
if (ss->face_sets) {
/* Assign a new Face Set ID to the new faces created by the trim operation. */
const int next_face_set_id = ED_sculpt_face_sets_find_next_available_id(object->data);

View File

@@ -587,6 +587,7 @@ typedef struct WPGradient_userData {
Scene *scene;
Mesh *me;
MDeformVert *dvert;
const bool *select_vert;
Brush *brush;
const float *sco_start; /* [2] */
const float *sco_end; /* [2] */
@@ -683,7 +684,7 @@ static void gradientVertInit__mapFunc(void *userData,
WPGradient_userData *grad_data = userData;
WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
if (grad_data->use_select && !(grad_data->dvert[index].flag & SELECT)) {
if (grad_data->use_select && (grad_data->select_vert && !grad_data->select_vert[index])) {
copy_v2_fl(vs->sco, FLT_MAX);
return;
}
@@ -811,6 +812,8 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
data.scene = scene;
data.me = ob->data;
data.dvert = dverts;
data.select_vert = (const bool *)CustomData_get_layer_named(
&me->vdata, CD_PROP_BOOL, ".select_vert");
data.sco_start = sco_start;
data.sco_end = sco_end;
data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end);

View File

@@ -692,7 +692,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
CustomData_get_layer(&mesh->edata, CD_CREASE));
sculpt_face_sets_init_flood_fill(
ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool {
return creases[edge] < threshold;
return creases ? creases[edge] < threshold : true;
});
break;
}
@@ -709,7 +709,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
CustomData_get_layer(&mesh->edata, CD_BWEIGHT));
sculpt_face_sets_init_flood_fill(
ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool {
return bevel_weights ? bevel_weights[edge] / 255.0f < threshold : true;
return bevel_weights ? bevel_weights[edge] < threshold : true;
});
break;
}

View File

@@ -317,7 +317,6 @@ static void filelist_readjob_main_assets(FileListReadJob *job_params,
/* helper, could probably go in BKE actually? */
static int groupname_to_code(const char *group);
static uint64_t groupname_to_filter_id(const char *group);
static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size);
static bool filelist_intern_entry_is_main_file(const FileListInternEntry *intern_entry);
@@ -745,7 +744,7 @@ static bool is_filtered_file(FileListInternEntry *file,
}
static bool is_filtered_id_file_type(const FileListInternEntry *file,
const char *id_group,
const short id_code,
const char *name,
const FileListFilter *filter)
{
@@ -755,12 +754,12 @@ static bool is_filtered_id_file_type(const FileListInternEntry *file,
/* We only check for types if some type are enabled in filtering. */
if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) {
if (id_group) {
if (id_code) {
if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) {
return false;
}
uint64_t filter_id = groupname_to_filter_id(id_group);
const uint64_t filter_id = BKE_idtype_idcode_to_idfilter(id_code);
if (!(filter_id & filter->filter_id)) {
return false;
}
@@ -843,15 +842,11 @@ static bool is_filtered_asset(FileListInternEntry *file, FileListFilter *filter)
}
static bool is_filtered_lib_type(FileListInternEntry *file,
const char *root,
const char * /*root*/,
FileListFilter *filter)
{
char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name;
BLI_path_join(path, sizeof(path), root, file->relpath);
if (BLO_library_path_explode(path, dir, &group, &name)) {
return is_filtered_id_file_type(file, group, name, filter);
if (file->typeflag & FILE_TYPE_BLENDERLIB) {
return is_filtered_id_file_type(file, file->blentype, file->name, filter);
}
return is_filtered_file_type(file, filter);
}
@@ -873,7 +868,7 @@ static bool is_filtered_main_assets(FileListInternEntry *file,
FileListFilter *filter)
{
/* "Filtered" means *not* being filtered out... So return true if the file should be visible. */
return is_filtered_id_file_type(file, file->relpath, file->name, filter) &&
return is_filtered_id_file_type(file, file->blentype, file->name, filter) &&
is_filtered_asset(file, filter);
}
@@ -2859,13 +2854,6 @@ static int groupname_to_code(const char *group)
return buf[0] ? BKE_idtype_idcode_from_name(buf) : 0;
}
static uint64_t groupname_to_filter_id(const char *group)
{
int id_code = groupname_to_code(group);
return BKE_idtype_idcode_to_idfilter(id_code);
}
/**
* From here, we are in 'Job Context',
* i.e. have to be careful about sharing stuff between background working thread.

View File

@@ -55,6 +55,14 @@
#define USE_TABLET_SUPPORT
/**
* Use alternative behavior when cursor warp is supported
* to prevent the cursor escaping the window bounds, see: T102346.
*
* \note this is not needed if cursor positioning is not supported.
*/
#define USE_CURSOR_WARP_HACK
/* -------------------------------------------------------------------- */
/** \name Modal Key-map
* \{ */
@@ -221,6 +229,10 @@ typedef struct WalkInfo {
bool need_rotation_keyframe;
bool need_translation_keyframe;
#ifdef USE_CURSOR_WARP_HACK
bool need_modal_cursor_warp_hack;
#endif
/** Previous 2D mouse values. */
int prev_mval[2];
/** Initial mouse location. */
@@ -579,6 +591,10 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op, const int
walk->need_rotation_keyframe = false;
walk->need_translation_keyframe = false;
#ifdef USE_CURSOR_WARP_HACK
walk->need_modal_cursor_warp_hack = false;
#endif
walk->time_lastdraw = PIL_check_seconds_timer();
walk->draw_handle_pixel = ED_region_draw_cb_activate(
@@ -594,7 +610,31 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op, const int
copy_v2_v2_int(walk->init_mval, mval);
copy_v2_v2_int(walk->prev_mval, mval);
WM_cursor_grab_enable(win, 0, true, NULL);
#ifdef USE_CURSOR_WARP_HACK
if (WM_capabilities_flag() & WM_CAPABILITY_CURSOR_WARP) {
int bounds[4];
const rcti *rect = &walk->region->winrct;
const int center[2] = {BLI_rcti_cent_x(rect), BLI_rcti_cent_y(rect)};
const int size[2] = {BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)};
const int div = 4; /* Where 2 is the region size. */
bounds[0] = center[0] - (size[0] / div); /* X-min. */
bounds[1] = center[1] + (size[1] / div); /* Y-max. */
bounds[2] = center[0] + (size[0] / div); /* X-max. */
bounds[3] = center[1] - (size[1] / div); /* Y-min. */
WM_cursor_grab_enable(win, WM_CURSOR_WRAP_XY, false, bounds);
/* Important to hide afterwards (not part of grabbing),
* since enabling cursor and hiding at the same time ignores bounds. */
WM_cursor_modal_set(win, WM_CURSOR_NONE);
walk->need_modal_cursor_warp_hack = true;
}
else
#endif /* USE_CURSOR_WARP_HACK */
{
WM_cursor_grab_enable(win, 0, true, NULL);
}
return 1;
}
@@ -643,7 +683,16 @@ static int walkEnd(bContext *C, WalkInfo *walk)
}
#endif
WM_cursor_grab_enable(win, 0, true, NULL);
WM_cursor_grab_disable(win, NULL);
#ifdef USE_CURSOR_WARP_HACK
if (walk->need_modal_cursor_warp_hack) {
WM_cursor_warp(win,
walk->region->winrct.xmin + walk->init_mval[0],
walk->region->winrct.ymin + walk->init_mval[1]);
WM_cursor_modal_restore(win);
}
#endif
if (walk->state == WALK_CONFIRM) {
MEM_freeN(walk);

View File

@@ -1029,8 +1029,9 @@ void ElementResize(const TransInfo *t,
applyNumInput(&num_evil, values_final_evil);
float ratio = values_final_evil[0];
*td->val = td->ival * fabs(ratio) * gps->runtime.multi_frame_falloff;
CLAMP_MIN(*td->val, 0.001f);
float transformed_value = td->ival * fabs(ratio);
*td->val = max_ff(interpf(transformed_value, td->ival, gps->runtime.multi_frame_falloff),
0.001f);
}
}
else {

View File

@@ -600,13 +600,21 @@ static BoxPack *pack_islands_params(const blender::Vector<FaceIsland *> &island_
return box_array;
}
static bool island_has_pins(const Scene *scene, FaceIsland *island, const bool pin_unselected)
static bool island_has_pins(const Scene *scene,
FaceIsland *island,
const UVPackIsland_Params *params)
{
const bool pin_unselected = params->pin_unselected;
const bool only_selected_faces = params->only_selected_faces;
BMLoop *l;
BMIter iter;
const int cd_loop_uv_offset = island->cd_loop_uv_offset;
for (int i = 0; i < island->faces_len; i++) {
BM_ITER_ELEM (l, &iter, island->faces[i], BM_LOOPS_OF_FACE) {
BMFace *efa = island->faces[i];
if (pin_unselected && only_selected_faces && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
return true;
}
BM_ITER_ELEM (l, &iter, efa, BM_LOOPS_OF_FACE) {
MLoopUV *luv = static_cast<MLoopUV *>(BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset));
if (luv->flag & MLOOPUV_PINNED) {
return true;
@@ -679,7 +687,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
/* Remove from linked list and append to blender::Vector. */
LISTBASE_FOREACH_MUTABLE (struct FaceIsland *, island, &island_list) {
BLI_remlink(&island_list, island);
if (params->ignore_pinned && island_has_pins(scene, island, params->pin_unselected)) {
if (params->ignore_pinned && island_has_pins(scene, island, params)) {
MEM_freeN(island->faces);
MEM_freeN(island);
continue;

View File

@@ -118,14 +118,12 @@ static void bakeModifier(Main *UNUSED(bmain),
GpencilModifierData *md,
Object *ob)
{
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)md;
GpencilModifierData *md_eval = BKE_gpencil_modifiers_findby_name(object_eval, md->name);
if (mmd->object == NULL) {
return;
}
generic_bake_deform_stroke(depsgraph, md_eval, object_eval, true, deformStroke);
generic_bake_deform_stroke(depsgraph, md, ob, true, deformStroke);
}
static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))

View File

@@ -113,7 +113,45 @@ static void BKE_gpencil_instance_modifier_instance_tfm(Object *ob,
zero_v3(r_mat[3]);
}
}
static bool gpencil_data_selected_minmax(ArrayGpencilModifierData *mmd,
Object *ob,
float r_min[3],
float r_max[3])
{
bGPdata *gpd = (bGPdata *)ob->data;
bool changed = false;
INIT_MINMAX(r_min, r_max);
if (gpd == NULL) {
return changed;
}
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *gpf = gpl->actframe;
if (gpf != NULL) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (is_stroke_affected_by_modifier(ob,
mmd->layername,
mmd->material,
mmd->pass_index,
mmd->layer_pass,
1,
gpl,
gps,
mmd->flag & GP_ARRAY_INVERT_LAYER,
mmd->flag & GP_ARRAY_INVERT_PASS,
mmd->flag & GP_ARRAY_INVERT_LAYERPASS,
mmd->flag & GP_ARRAY_INVERT_MATERIAL)) {
changed |= BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
}
}
}
}
return changed;
}
/* array modifier - generate geometry callback (for viewport/rendering) */
static void generate_geometry(GpencilModifierData *md,
Depsgraph *depsgraph,
@@ -131,7 +169,7 @@ static void generate_geometry(GpencilModifierData *md,
if (mmd->flag & GP_ARRAY_USE_RELATIVE) {
float min[3];
float max[3];
if (BKE_gpencil_data_minmax(gpd, min, max)) {
if (gpencil_data_selected_minmax(mmd, ob, min, max)) {
sub_v3_v3v3(size, max, min);
/* Need a minimum size (for flat drawings). */
CLAMP3_MIN(size, 0.01f);

View File

@@ -177,7 +177,8 @@ void GpencilExporterPDF::export_gpencil_layers()
/* Apply layer thickness change. */
gps_duplicate->thickness += gpl->line_change;
/* Apply object scale to thickness. */
gps_duplicate->thickness *= mat4_to_scale(ob->object_to_world);
const float scalef = mat4_to_scale(ob->object_to_world);
gps_duplicate->thickness = ceilf((float)gps_duplicate->thickness * scalef);
CLAMP_MIN(gps_duplicate->thickness, 1.0f);
/* Fill. */
if ((is_fill) && (params_.flag & GP_EXPORT_FILL)) {
@@ -236,7 +237,9 @@ void GpencilExporterPDF::export_stroke_to_polyline(bGPDlayer *gpl,
if (is_stroke && !do_fill) {
HPDF_Page_SetLineJoin(page_, HPDF_ROUND_JOIN);
HPDF_Page_SetLineWidth(page_, MAX2((radius * 2.0f) - gpl->line_change, 1.0f));
const float width = MAX2(
MAX2(gps->thickness + gpl->line_change, (radius * 2.0f) + gpl->line_change), 1.0f);
HPDF_Page_SetLineWidth(page_, width);
}
/* Loop all points. */

View File

@@ -198,7 +198,8 @@ void GpencilExporterSVG::export_gpencil_layers()
/* Apply layer thickness change. */
gps_duplicate->thickness += gpl->line_change;
/* Apply object scale to thickness. */
gps_duplicate->thickness *= mat4_to_scale(ob->object_to_world);
const float scalef = mat4_to_scale(ob->object_to_world);
gps_duplicate->thickness = ceilf((float)gps_duplicate->thickness * scalef);
CLAMP_MIN(gps_duplicate->thickness, 1.0f);
const bool is_normalized = ((params_.flag & GP_EXPORT_NORM_THICKNESS) != 0) ||
@@ -308,7 +309,9 @@ void GpencilExporterSVG::export_stroke_to_polyline(bGPDlayer *gpl,
color_string_set(gpl, gps, node_gps, do_fill);
if (is_stroke && !do_fill) {
node_gps.append_attribute("stroke-width").set_value((radius * 2.0f) - gpl->line_change);
const float width = MAX2(
MAX2(gps->thickness + gpl->line_change, (radius * 2.0f) + gpl->line_change), 1.0f);
node_gps.append_attribute("stroke-width").set_value(width);
}
std::string txt;

View File

@@ -651,6 +651,49 @@ static void rna_AttributeGroup_render_color_index_range(
*softmin = *min;
*softmax = *max;
}
static void rna_AttributeGroup_default_color_name_get(PointerRNA *ptr, char *value)
{
const ID *id = ptr->owner_id;
const CustomDataLayer *layer = BKE_id_attributes_render_color_get(id);
if (!layer) {
value[0] = '\0';
return;
}
BLI_strncpy(value, layer->name, MAX_CUSTOMDATA_LAYER_NAME);
}
static int rna_AttributeGroup_default_color_name_length(PointerRNA *ptr)
{
const ID *id = ptr->owner_id;
const CustomDataLayer *layer = BKE_id_attributes_render_color_get(id);
if (!layer) {
return 0;
}
return strlen(layer->name);
}
static void rna_AttributeGroup_active_color_name_get(PointerRNA *ptr, char *value)
{
const ID *id = ptr->owner_id;
const CustomDataLayer *layer = BKE_id_attributes_active_color_get(id);
if (!layer) {
value[0] = '\0';
return;
}
BLI_strncpy(value, layer->name, MAX_CUSTOMDATA_LAYER_NAME);
}
static int rna_AttributeGroup_active_color_name_length(PointerRNA *ptr)
{
const ID *id = ptr->owner_id;
const CustomDataLayer *layer = BKE_id_attributes_active_color_get(id);
if (!layer) {
return 0;
}
return strlen(layer->name);
}
#else
static void rna_def_attribute_float(BlenderRNA *brna)
@@ -1110,6 +1153,29 @@ static void rna_def_attribute_group(BlenderRNA *brna)
"rna_AttributeGroup_render_color_index_set",
"rna_AttributeGroup_render_color_index_range");
RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active_color");
prop = RNA_def_property(srna, "default_color_name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_string_maxlength(prop, MAX_CUSTOMDATA_LAYER_NAME);
RNA_def_property_string_funcs(prop,
"rna_AttributeGroup_default_color_name_get",
"rna_AttributeGroup_default_color_name_length",
NULL);
RNA_def_property_ui_text(
prop,
"Default Color Attribute",
"The name of the default color attribute used as a fallback for rendering");
prop = RNA_def_property(srna, "active_color_name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_string_maxlength(prop, MAX_CUSTOMDATA_LAYER_NAME);
RNA_def_property_string_funcs(prop,
"rna_AttributeGroup_active_color_name_get",
"rna_AttributeGroup_active_color_name_length",
NULL);
RNA_def_property_ui_text(prop,
"Active Color Attribute",
"The name of the active color attribute for display and editing");
}
void rna_def_attributes_common(StructRNA *srna)

View File

@@ -1052,6 +1052,7 @@ static void rna_def_tex_slot(BlenderRNA *brna)
RNA_def_property_string_funcs(
prop, "rna_TexPaintSlot_name_get", "rna_TexPaintSlot_name_length", NULL);
RNA_def_property_ui_text(prop, "Name", "Name of the slot");
RNA_def_struct_name_property(srna, prop);
prop = RNA_def_property(srna, "icon_value", PROP_INT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);

View File

@@ -205,6 +205,10 @@ static bool rna_Object_holdout_get(Object *ob, bContext *C, PointerRNA *view_lay
static bool rna_Object_indirect_only_get(Object *ob, bContext *C, PointerRNA *view_layer_ptr)
{
Base *base = find_view_layer_base_with_synced_ensure(ob, C, view_layer_ptr, NULL, NULL);
if (!base) {
return false;
}
return ((base->flag & BASE_INDIRECT_ONLY) != 0);
}

View File

@@ -160,9 +160,11 @@ class LazyFunctionForMultiInput : public LazyFunction {
BLI_assert(socket.is_multi_input());
const bNodeTree &btree = socket.owner_tree();
for (const bNodeLink *link : socket.directly_linked_links()) {
if (!(link->is_muted() || nodeIsDanglingReroute(&btree, link->fromnode))) {
inputs_.append({"Input", *base_type_});
if (link->is_muted() || !link->fromsock->is_available() ||
nodeIsDanglingReroute(&btree, link->fromnode)) {
continue;
}
inputs_.append({"Input", *base_type_});
}
const CPPType *vector_type = get_vector_type(*base_type_);
BLI_assert(vector_type != nullptr);
@@ -1154,10 +1156,11 @@ struct GeometryNodesLazyFunctionGraphBuilder {
if (multi_input_link == link) {
break;
}
if (!(multi_input_link->is_muted() ||
nodeIsDanglingReroute(&btree_, multi_input_link->fromnode))) {
link_index++;
if (multi_input_link->is_muted() || !multi_input_link->fromsock->is_available() ||
nodeIsDanglingReroute(&btree_, multi_input_link->fromnode)) {
continue;
}
link_index++;
}
if (to_bsocket.owner_node().is_muted()) {
if (link_index == 0) {

View File

@@ -115,8 +115,8 @@ static const struct PyC_StringEnumItems pygpu_imagetype_items[] = {
{int(ImageType::FLOAT_1D), "FLOAT_1D"},
{int(ImageType::FLOAT_1D_ARRAY), "FLOAT_1D_ARRAY"},
{int(ImageType::FLOAT_2D), "FLOAT_2D"},
{int(ImageType::FLOAT_2D_ARRAY), "FLOAT"},
{int(ImageType::FLOAT_3D), "FLOAT_2D_ARRAY"},
{int(ImageType::FLOAT_2D_ARRAY), "FLOAT_2D_ARRAY"},
{int(ImageType::FLOAT_3D), "FLOAT_3D"},
{int(ImageType::FLOAT_CUBE), "FLOAT_CUBE"},
{int(ImageType::FLOAT_CUBE_ARRAY), "FLOAT_CUBE_ARRAY"},
{int(ImageType::INT_BUFFER), "INT_BUFFER"},

View File

@@ -1044,14 +1044,19 @@ bool RE_engine_render(Render *re, bool do_all)
re->engine = engine;
}
/* create render result */
/* Create render result. Do this before acquiring lock, to avoid lock
* inversion as this calls python to get the render passes, while python UI
* code can also hold a lock on the render result. */
const bool create_new_result = (re->result == nullptr || !(re->r.scemode & R_BUTS_PREVIEW));
RenderResult *new_result = engine_render_create_result(re);
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
if (re->result == nullptr || !(re->r.scemode & R_BUTS_PREVIEW)) {
if (create_new_result) {
if (re->result) {
render_result_free(re->result);
}
re->result = engine_render_create_result(re);
re->result = new_result;
}
BLI_rw_mutex_unlock(&re->resultmutex);

View File

@@ -126,6 +126,15 @@ void WM_init_opengl(void);
*/
const char *WM_ghost_backend(void);
typedef enum eWM_CapabilitiesFlag {
/** Ability to warp the cursor (set it's location). */
WM_CAPABILITY_CURSOR_WARP = (1 << 0),
/** Ability to access window positions & move them. */
WM_CAPABILITY_WINDOW_POSITION = (1 << 1),
} eWM_CapabilitiesFlag;
eWM_CapabilitiesFlag WM_capabilities_flag(void);
void WM_check(struct bContext *C);
void WM_reinit_gizmomap_all(struct Main *bmain);

View File

@@ -1643,6 +1643,23 @@ GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gp
return GHOST_kDrawingContextTypeNone;
}
eWM_CapabilitiesFlag WM_capabilities_flag(void)
{
static eWM_CapabilitiesFlag flag = -1;
if (flag != -1) {
return flag;
}
flag = 0;
if (GHOST_SupportsCursorWarp()) {
flag |= WM_CAPABILITY_CURSOR_WARP;
}
if (GHOST_SupportsWindowPosition()) {
flag |= WM_CAPABILITY_WINDOW_POSITION;
}
return flag;
}
/** \} */
/* -------------------------------------------------------------------- */