Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Vazquez <blendergit@gmail.com>2020-06-26 13:57:10 +0300
committerAntonio Vazquez <blendergit@gmail.com>2020-06-26 13:57:10 +0300
commitb5640df6c017ee15571e217a782a87dc85f4de3c (patch)
tree03acba02adc1013f7f49b5a466a9e479a16adcb6
parent302499b4a69a7d16eca7d0f1d7e621e8b9591e3c (diff)
parente3a420c4773a1d1a79c21f15137066d4411d3574 (diff)
Merge branch 'master' into greasepencil-edit-curve
-rw-r--r--build_files/build_environment/cmake/usd.cmake3
-rw-r--r--intern/cycles/render/session.cpp21
-rw-r--r--intern/mantaflow/intern/MANTA_main.cpp4
-rw-r--r--intern/mantaflow/intern/strings/fluid_script.h2
-rw-r--r--intern/mantaflow/intern/strings/liquid_script.h16
-rw-r--r--intern/mantaflow/intern/strings/smoke_script.h8
-rwxr-xr-xrelease/datafiles/blender_icons_geom_update.py4
-rw-r--r--release/scripts/modules/addon_utils.py21
-rw-r--r--release/scripts/modules/bl_previews_utils/bl_previews_render.py4
-rw-r--r--release/scripts/modules/bl_ui_utils/bug_report_url.py6
-rw-r--r--release/scripts/modules/bpy/ops.py2
-rw-r--r--release/scripts/modules/bpy/utils/previews.py7
-rw-r--r--release/scripts/startup/bl_operators/sequencer.py4
-rw-r--r--release/scripts/startup/bl_operators/wm.py10
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py4
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py2
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py6
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py40
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py4
-rw-r--r--source/blender/blenkernel/intern/brush.c20
-rw-r--r--source/blender/blenloader/intern/versioning_cycles.c3
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c417
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc17
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc41
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc4
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h2
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c5
-rw-r--r--source/blender/draw/engines/overlay/overlay_grid.c4
-rw-r--r--source/blender/draw/engines/overlay/shaders/grid_frag.glsl7
-rw-r--r--source/blender/editors/animation/time_scrub_ui.c11
-rw-r--r--source/blender/editors/interface/interface_draw.c5
-rw-r--r--source/blender/editors/interface/interface_panel.c17
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl2
-rw-r--r--source/blender/makesrna/intern/rna_main.c2
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c1
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c4
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c4
42 files changed, 566 insertions, 190 deletions
diff --git a/build_files/build_environment/cmake/usd.cmake b/build_files/build_environment/cmake/usd.cmake
index c98a9cae959..5fa1872cabc 100644
--- a/build_files/build_environment/cmake/usd.cmake
+++ b/build_files/build_environment/cmake/usd.cmake
@@ -27,6 +27,9 @@ set(USD_EXTRA_ARGS
-DTBB_INCLUDE_DIRS=${LIBDIR}/tbb/include
-DTBB_LIBRARIES=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${LIBEXT}
-DTbb_TBB_LIBRARY=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${LIBEXT}
+ # USD wants the tbb debug lib set even when you are doing a release build
+ # Otherwise it will error out during the cmake configure phase.
+ -DTBB_LIBRARIES_DEBUG=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${LIBEXT}
# This is a preventative measure that avoids possible conflicts when add-ons
# try to load another USD library into the same process space.
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 8c36d34aeea..1a94d3e9db7 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -61,8 +61,10 @@ Session::Session(const SessionParams &params_)
TaskScheduler::init(params.threads);
+ /* Create CPU/GPU devices. */
device = Device::create(params.device, stats, profiler, params.background);
+ /* Create buffers for interactive rendering. */
if (params.background && !params.write_render_cb) {
buffers = NULL;
display = NULL;
@@ -72,6 +74,9 @@ Session::Session(const SessionParams &params_)
display = new DisplayBuffer(device, params.display_buffer_linear);
}
+ /* Validate denoising parameters. */
+ set_denoising(params.denoising);
+
session_thread = NULL;
scene = NULL;
@@ -944,17 +949,21 @@ void Session::set_pause(bool pause_)
void Session::set_denoising(const DenoiseParams &denoising)
{
- const bool need_denoise = denoising.need_denoising_task();
-
- if (need_denoise && !(params.device.denoisers & denoising.type)) {
- progress.set_error("Denoiser type not supported by compute device");
- return;
- }
+ bool need_denoise = denoising.need_denoising_task();
/* Lock buffers so no denoising operation is triggered while the settings are changed here. */
thread_scoped_lock buffers_lock(buffers_mutex);
params.denoising = denoising;
+ if (!(params.device.denoisers & denoising.type)) {
+ if (need_denoise) {
+ progress.set_error("Denoiser type not supported by compute device");
+ }
+
+ params.denoising.use = false;
+ need_denoise = false;
+ }
+
// TODO(pmours): Query the required overlap value for denoising from the device?
tile_manager.slice_overlap = need_denoise && !params.background ? 64 : 0;
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index e81b2b2e268..a008100a3e2 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -755,7 +755,7 @@ void MANTA::initializeRNAMap(FluidModifierData *mmd)
mRNAMap["USING_OUTFLOW"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW);
mRNAMap["USING_LOG_DISSOLVE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DISSOLVE_LOG);
mRNAMap["USING_DISSOLVE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DISSOLVE);
- mRNAMap["DO_OPEN"] = getBooleanString(mds->border_collisions == 0);
+ mRNAMap["DOMAIN_CLOSED"] = getBooleanString(borderCollisions.compare("") == 0);
mRNAMap["CACHE_RESUMABLE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE);
mRNAMap["USING_ADAPTIVETIME"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_TIME);
mRNAMap["USING_SPEEDVECTORS"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS);
@@ -1280,7 +1280,7 @@ bool MANTA::readNoise(FluidModifierData *mmd, int framenr, bool resumable)
FluidDomainSettings *mds = mmd->domain;
string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE);
- string resumable_cache = (resumable) ? "False" : "True";
+ string resumable_cache = (!resumable) ? "False" : "True";
/* Support older caches which had more granular file format control. */
char format = (!strcmp(mds->cache_id, FLUID_CACHE_VERSION)) ? mds->cache_data_format :
diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h
index 0fb577cc109..62274101859 100644
--- a/intern/mantaflow/intern/strings/fluid_script.h
+++ b/intern/mantaflow/intern/strings/fluid_script.h
@@ -96,7 +96,7 @@ gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$) # in SI unit (e.g. m
gs_s$ID$ = vec3($RESX$, $RESY$, $RESZ$)\n\
maxVel_s$ID$ = 0\n\
\n\
-doOpen_s$ID$ = $DO_OPEN$\n\
+domainClosed_s$ID$ = $DOMAIN_CLOSED$\n\
boundConditions_s$ID$ = '$BOUND_CONDITIONS$'\n\
boundaryWidth_s$ID$ = $BOUNDARY_WIDTH$\n\
deleteInObstacle_s$ID$ = $DELETE_IN_OBSTACLE$\n\
diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h
index 1dec61c02da..04505206601 100644
--- a/intern/mantaflow/intern/strings/liquid_script.h
+++ b/intern/mantaflow/intern/strings/liquid_script.h
@@ -211,10 +211,10 @@ def liquid_adaptive_step_$ID$(framenr):\n\
if using_invel_s$ID$:\n\
extrapolateVec3Simple(vel=invelC_s$ID$, phi=phiIn_s$ID$, distance=6, inside=True)\n\
resampleVec3ToMac(source=invelC_s$ID$, target=invel_s$ID$)\n\
- pVel_pp$ID$.setSource(invel_s$ID$, isMAC=True)\n\
- # ensure that pvel has vel as source (important when resuming bake jobs)\n\
+ pVel_pp$ID$.setSource(grid=invel_s$ID$, isMAC=True)\n\
+ # reset pvel grid source before sampling new particles - ensures that new particles are initialized with 0 velocity\n\
else:\n\
- pVel_pp$ID$.setSource(vel_s$ID$, isMAC=True)\n\
+ pVel_pp$ID$.setSource(grid=None, isMAC=False)\n\
\n\
sampleLevelsetWithParticles(phi=phiIn_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, discretization=particleNumber_s$ID$, randomness=randomness_s$ID$)\n\
flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
@@ -257,7 +257,7 @@ def liquid_step_$ID$():\n\
extrapolateLsSimple(phi=phi_s$ID$, distance=3)\n\
phi_s$ID$.setBoundNeumann(0) # make sure no particles are placed at outer boundary\n\
\n\
- if doOpen_s$ID$ or using_outflow_s$ID$:\n\
+ if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
resetOutflow(flags=flags_s$ID$, phi=phi_s$ID$, parts=pp_s$ID$, index=gpi_s$ID$, indexSys=pindex_s$ID$)\n\
flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
\n\
@@ -298,10 +298,10 @@ def liquid_step_$ID$():\n\
\n\
if using_guiding_s$ID$:\n\
mantaMsg('Guiding and pressure')\n\
- PD_fluid_guiding(vel=vel_s$ID$, velT=velT_s$ID$, flags=flags_s$ID$, phi=phi_s$ID$, curv=curvature_s$ID$, surfTens=surfaceTension_s$ID$, fractions=fractions_s$ID$, weight=weightGuide_s$ID$, blurRadius=beta_sg$ID$, pressure=pressure_s$ID$, tau=tau_sg$ID$, sigma=sigma_sg$ID$, theta=theta_sg$ID$, zeroPressureFixing=not doOpen_s$ID$)\n\
+ PD_fluid_guiding(vel=vel_s$ID$, velT=velT_s$ID$, flags=flags_s$ID$, phi=phi_s$ID$, curv=curvature_s$ID$, surfTens=surfaceTension_s$ID$, fractions=fractions_s$ID$, weight=weightGuide_s$ID$, blurRadius=beta_sg$ID$, pressure=pressure_s$ID$, tau=tau_sg$ID$, sigma=sigma_sg$ID$, theta=theta_sg$ID$, zeroPressureFixing=domainClosed_s$ID$)\n\
else:\n\
mantaMsg('Pressure')\n\
- solvePressure(flags=flags_s$ID$, vel=vel_s$ID$, pressure=pressure_s$ID$, phi=phi_s$ID$, curv=curvature_s$ID$, surfTens=surfaceTension_s$ID$, fractions=fractions_s$ID$, obvel=obvel_s$ID$ if using_fractions_s$ID$ else None)\n\
+ solvePressure(flags=flags_s$ID$, vel=vel_s$ID$, pressure=pressure_s$ID$, phi=phi_s$ID$, curv=curvature_s$ID$, surfTens=surfaceTension_s$ID$, fractions=fractions_s$ID$, obvel=obvel_s$ID$ if using_fractions_s$ID$ else None, zeroPressureFixing=domainClosed_s$ID$)\n\
\n\
extrapolateMACSimple(flags=flags_s$ID$, vel=vel_s$ID$, distance=4, intoObs=True if using_fractions_s$ID$ else False)\n\
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=None if using_fractions_s$ID$ else obvel_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$)\n\
@@ -310,7 +310,7 @@ def liquid_step_$ID$():\n\
extrapolateMACSimple(flags=flags_s$ID$, vel=vel_s$ID$)\n\
\n\
# set source grids for resampling, used in adjustNumber!\n\
- pVel_pp$ID$.setSource(vel_s$ID$, isMAC=True)\n\
+ pVel_pp$ID$.setSource(grid=vel_s$ID$, isMAC=True)\n\
adjustNumber(parts=pp_s$ID$, vel=vel_s$ID$, flags=flags_s$ID$, minParticles=minParticles_s$ID$, maxParticles=maxParticles_s$ID$, phi=phi_s$ID$, exclude=phiObs_s$ID$, radiusFactor=radiusFactor_s$ID$, narrowBand=adjustedNarrowBandWidth_s$ID$)\n\
flipVelocityUpdate(vel=vel_s$ID$, velOld=velOld_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, flipRatio=flipRatio_s$ID$)\n";
@@ -347,7 +347,7 @@ def liquid_step_mesh_$ID$():\n\
# Vert vel vector needs to pull data from vel grid with correct dim\n\
if using_speedvectors_s$ID$:\n\
interpolateMACGrid(target=vel_sm$ID$, source=vel_s$ID$)\n\
- mVel_mesh$ID$.setSource(vel_sm$ID$, isMAC=True)\n\
+ mVel_mesh$ID$.setSource(grid=vel_sm$ID$, isMAC=True)\n\
\n\
# Set 0.5 boundary at walls + account for extra wall thickness in fractions mode + account for grid scaling:\n\
# E.g. at upres=1 we expect 1 cell border (or 2 with fractions), at upres=2 we expect 2 cell border (or 4 with fractions), etc.\n\
diff --git a/intern/mantaflow/intern/strings/smoke_script.h b/intern/mantaflow/intern/strings/smoke_script.h
index 5e80e4443a3..612d01b85ef 100644
--- a/intern/mantaflow/intern/strings/smoke_script.h
+++ b/intern/mantaflow/intern/strings/smoke_script.h
@@ -365,7 +365,7 @@ def smoke_step_$ID$():\n\
mantaMsg('Advecting velocity')\n\
advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=vel_s$ID$, order=2)\n\
\n\
- if doOpen_s$ID$ or using_outflow_s$ID$:\n\
+ if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
resetOutflow(flags=flags_s$ID$, real=density_s$ID$)\n\
\n\
mantaMsg('Vorticity')\n\
@@ -406,10 +406,10 @@ def smoke_step_$ID$():\n\
mantaMsg('Using preconditioner: ' + str(preconditioner_s$ID$))\n\
if using_guiding_s$ID$:\n\
mantaMsg('Guiding and pressure')\n\
- PD_fluid_guiding(vel=vel_s$ID$, velT=velT_s$ID$, flags=flags_s$ID$, weight=weightGuide_s$ID$, blurRadius=beta_sg$ID$, pressure=pressure_s$ID$, tau=tau_sg$ID$, sigma=sigma_sg$ID$, theta=theta_sg$ID$, preconditioner=preconditioner_s$ID$, zeroPressureFixing=not doOpen_s$ID$)\n\
+ PD_fluid_guiding(vel=vel_s$ID$, velT=velT_s$ID$, flags=flags_s$ID$, weight=weightGuide_s$ID$, blurRadius=beta_sg$ID$, pressure=pressure_s$ID$, tau=tau_sg$ID$, sigma=sigma_sg$ID$, theta=theta_sg$ID$, preconditioner=preconditioner_s$ID$, zeroPressureFixing=domainClosed_s$ID$)\n\
else:\n\
mantaMsg('Pressure')\n\
- solvePressure(flags=flags_s$ID$, vel=vel_s$ID$, pressure=pressure_s$ID$, preconditioner=preconditioner_s$ID$, zeroPressureFixing=not doOpen_s$ID$) # closed domains require pressure fixing\n\
+ solvePressure(flags=flags_s$ID$, vel=vel_s$ID$, pressure=pressure_s$ID$, preconditioner=preconditioner_s$ID$, zeroPressureFixing=domainClosed_s$ID$) # closed domains require pressure fixing\n\
\n\
def process_burn_$ID$():\n\
mantaMsg('Process burn')\n\
@@ -551,7 +551,7 @@ const std::string smoke_load_noise =
"\n\
def smoke_load_noise_$ID$(path, framenr, file_format, resumable):\n\
mantaMsg('Smoke load noise')\n\
- dict = { **smoke_noise_dict_final_s$ID$, **smoke_data_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\
+ dict = { **smoke_noise_dict_final_s$ID$, **smoke_noise_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\
fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_noise_s$ID$)\n\
\n\
if resumable:\n\
diff --git a/release/datafiles/blender_icons_geom_update.py b/release/datafiles/blender_icons_geom_update.py
index 3b7724756db..5b95961ae6b 100755
--- a/release/datafiles/blender_icons_geom_update.py
+++ b/release/datafiles/blender_icons_geom_update.py
@@ -21,10 +21,10 @@ def edit_text_file(filename, marker_begin, marker_end, content):
while data[marker_end_index - 1] in {'\t', ' '}:
marker_end_index -= 1
if marker_begin_index == -1:
- print('Error: {!r} not found'.format(marker_begin))
+ print('Error: %r not found' % marker_begin)
return
if marker_end_index == -1:
- print('Error: {!r} not found'.format(marker_end))
+ print('Error: %r not found' % marker_end)
return
marker_begin_index += len(marker_begin) + 1
data_update = data[:marker_begin_index] + content + data[marker_end_index:]
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index a65ff15393a..8a074d23db9 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -172,8 +172,8 @@ def modules_refresh(module_cache=addons_fake_modules):
if mod.__file__ != mod_path:
print(
"multiple addons with the same name:\n"
- " " f"{mod.__file__!r}" "\n"
- " " f"{mod_path!r}"
+ " %r\n"
+ " %r" % (mod.__file__, mod_path)
)
error_duplicates.append((mod.bl_info["name"], mod.__file__, mod_path))
@@ -241,7 +241,7 @@ def check(module_name):
if loaded_state is Ellipsis:
print(
- "Warning: addon-module " f"{module_name:s}" " found module "
+ "Warning: addon-module", module_name, "found module "
"but without '__addon_enabled__' field, "
"possible name collision from file:",
repr(getattr(mod, "__file__", "<unknown>")),
@@ -439,8 +439,9 @@ def disable(module_name, *, default_set=False, handle_error=None):
handle_error(ex)
else:
print(
- "addon_utils.disable: " f"{module_name:s}" " not",
- ("disabled" if mod is None else "loaded")
+ "addon_utils.disable: %s not %s" % (
+ module_name,
+ "disabled" if mod is None else "loaded")
)
# could be in more than once, unlikely but better do this just in case.
@@ -502,7 +503,7 @@ def _blender_manual_url_prefix():
else:
manual_version = "dev"
- return f"https://docs.blender.org/manual/en/{manual_version}"
+ return "https://docs.blender.org/manual/en/" + manual_version
def module_bl_info(mod, info_basis=None):
@@ -544,11 +545,11 @@ def module_bl_info(mod, info_basis=None):
addon_info["doc_url"] = doc_url
if _bpy.app.debug:
print(
- "Warning: add-on \"{addon_name}\": 'wiki_url' in 'bl_info' "
+ "Warning: add-on \"%s\": 'wiki_url' in 'bl_info' "
"is deprecated please use 'doc_url' instead!\n"
- " {addon_path}".format(
- addon_name=addon_info['name'],
- addon_path=getattr(mod, "__file__", None),
+ " %s" % (
+ addon_info['name'],
+ getattr(mod, "__file__", None),
)
)
diff --git a/release/scripts/modules/bl_previews_utils/bl_previews_render.py b/release/scripts/modules/bl_previews_utils/bl_previews_render.py
index b79c0b744d0..73004cee731 100644
--- a/release/scripts/modules/bl_previews_utils/bl_previews_render.py
+++ b/release/scripts/modules/bl_previews_utils/bl_previews_render.py
@@ -505,7 +505,7 @@ def main():
if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- print(" *** Blend file {} *** \n".format(bpy.data.filepath))
+ print("\n\n *** Running %s *** \n" % __file__)
+ print(" *** Blend file %s *** \n" % bpy.data.filepath)
main()
bpy.ops.wm.quit_blender()
diff --git a/release/scripts/modules/bl_ui_utils/bug_report_url.py b/release/scripts/modules/bl_ui_utils/bug_report_url.py
index 2adee70bc86..5676e0d6815 100644
--- a/release/scripts/modules/bl_ui_utils/bug_report_url.py
+++ b/release/scripts/modules/bl_ui_utils/bug_report_url.py
@@ -31,13 +31,13 @@ def url_prefill_from_blender(addon_info=None):
fh.write("**System Information**\n")
fh.write(
- "Operating system: {!s} {!s} Bits\n".format(
+ "Operating system: %s %d Bits\n" % (
platform.platform(),
struct.calcsize("P") * 8,
)
)
fh.write(
- "Graphics card: {!s} {!s} {!s}\n".format(
+ "Graphics card: %s %s %s\n" % (
bgl.glGetString(bgl.GL_RENDERER),
bgl.glGetString(bgl.GL_VENDOR),
bgl.glGetString(bgl.GL_VERSION),
@@ -48,7 +48,7 @@ def url_prefill_from_blender(addon_info=None):
"**Blender Version**\n"
)
fh.write(
- "Broken: version: {!s}, branch: {!s}, commit date: {!s} {!s}, hash: `rB{!s}`\n".format(
+ "Broken: version: %s, branch: %s, commit date: %s %s, hash: `rB%s`\n" % (
bpy.app.version_string,
bpy.app.build_branch.decode('utf-8', 'replace'),
bpy.app.build_commit_date.decode('utf-8', 'replace'),
diff --git a/release/scripts/modules/bpy/ops.py b/release/scripts/modules/bpy/ops.py
index 8f8f42bcd46..4e226f80f79 100644
--- a/release/scripts/modules/bpy/ops.py
+++ b/release/scripts/modules/bpy/ops.py
@@ -123,7 +123,7 @@ class BPyOpsSubModOp:
# op_class = getattr(bpy.types, idname)
op_class = op_get_rna_type(idname)
descr = op_class.description
- return f"{sig}\n{descr}"
+ return "%s\n%s" % (sig, descr)
@staticmethod
def _parse_args(args):
diff --git a/release/scripts/modules/bpy/utils/previews.py b/release/scripts/modules/bpy/utils/previews.py
index bfdf28e0db4..7f337677635 100644
--- a/release/scripts/modules/bpy/utils/previews.py
+++ b/release/scripts/modules/bpy/utils/previews.py
@@ -76,8 +76,7 @@ class ImagePreviewCollection(dict):
return
raise ResourceWarning(
- f"{self!r}: left open, remove with "
- "'bpy.utils.previews.remove()'"
+ "%r: left open, remove with 'bpy.utils.previews.remove()'" % self
)
self.close()
@@ -116,7 +115,9 @@ class ImagePreviewCollection(dict):
super().__delitem__(key)
def __repr__(self):
- return f"<{self.__class__.__name__:s} id={self._uuid:s}[{len(self):d}], {super()!r}>"
+ return "<%s id=%s[%d], %r>" % (
+ self.__class__.__name__, self._uuid, len(self), super()
+ )
def new():
diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py
index e0aaea3c085..f8f37953f1c 100644
--- a/release/scripts/startup/bl_operators/sequencer.py
+++ b/release/scripts/startup/bl_operators/sequencer.py
@@ -234,7 +234,7 @@ class SequencerFadesAdd(Operator):
sequence.invalidate('COMPOSITE')
sequence_string = "sequence" if len(faded_sequences) == 1 else "sequences"
- self.report({'INFO'}, "Added fade animation to {} {}.".format(len(faded_sequences), sequence_string))
+ self.report({'INFO'}, "Added fade animation to %d %s." % (len(faded_sequences), sequence_string))
return {'FINISHED'}
def calculate_fade_duration(self, context, sequence):
@@ -362,7 +362,7 @@ class Fade:
return max_value if max_value > 0.0 else 1.0
def __repr__(self):
- return "Fade {}: {} to {}".format(self.type, self.start, self.end)
+ return "Fade %r: %r to %r" % (self.type, self.start, self.end)
def calculate_duration_frames(context, duration_seconds):
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 4c4736cd669..04bd5687364 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -1697,7 +1697,7 @@ class WM_OT_tool_set_by_id(Operator):
tool_settings.workspace_tool_type = 'FALLBACK'
return {'FINISHED'}
else:
- self.report({'WARNING'}, f"Tool {self.name!r:s} not found for space {space_type!r:s}.")
+ self.report({'WARNING'}, "Tool %r not found for space %r." % (self.name, space_type))
return {'CANCELLED'}
@@ -2216,8 +2216,8 @@ class WM_OT_batch_rename(Operator):
elif ty == 'STRIP':
chars = action.strip_chars
chars_strip = (
- "{:s}{:s}{:s}"
- ).format(
+ "%s%s%s"
+ ) % (
string.punctuation if 'PUNCT' in chars else "",
string.digits if 'DIGIT' in chars else "",
" " if 'SPACE' in chars else "",
@@ -2282,7 +2282,7 @@ class WM_OT_batch_rename(Operator):
split.prop(self, "data_type", text="")
split = layout.split(factor=0.5)
- split.label(text="Rename {:d} {:s}:".format(len(self._data[0]), self._data[2]))
+ split.label(text="Rename %d %s:" % (len(self._data[0]), self._data[2]))
split.row().prop(self, "data_source", expand=True)
for action in self.actions:
@@ -2397,7 +2397,7 @@ class WM_OT_batch_rename(Operator):
change_len += 1
total_len += 1
- self.report({'INFO'}, "Renamed {:d} of {:d} {:s}".format(change_len, total_len, descr))
+ self.report({'INFO'}, "Renamed %d of %d %s" % (change_len, total_len, descr))
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 696883d965c..5b8d97488f9 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -1528,7 +1528,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel):
split.alignment = 'RIGHT'
split.label(text="End")
split = split.split(factor=0.8 + max_factor, align=True)
- split.label(text="{:>14}".format(smpte_from_frame(frame_final_end)))
+ split.label(text="%14s" % smpte_from_frame(frame_final_end))
split.alignment = 'RIGHT'
split.label(text=str(frame_final_end) + " ")
@@ -1572,7 +1572,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel):
split.label(text="Playhead")
split = split.split(factor=0.8 + max_factor, align=True)
frame_display = frame_current - frame_final_start
- split.label(text="{:>14}".format(smpte_from_frame(frame_display)))
+ split.label(text="%14s" % smpte_from_frame(frame_display))
split.alignment = 'RIGHT'
split.label(text=str(frame_display) + " ")
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py
index e0651dcac2b..f052e42766c 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_common.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py
@@ -450,7 +450,7 @@ class ToolSelectPanelHelper:
@classmethod
def _km_action_simple(cls, kc_default, kc, context_descr, label, keymap_fn):
- km_idname = f"{cls.keymap_prefix:s} {context_descr:s}, {label:s}"
+ km_idname = "%s %s, %s" % (cls.keymap_prefix, context_descr, label)
km = kc.keymaps.get(km_idname)
km_kwargs = dict(space_type=cls.bl_space_type, region_type='WINDOW', tool=True)
if km is None:
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 2605cf1e1b9..d52cc6a6dad 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -124,12 +124,12 @@ class _defs_view3d_generic:
kmi_remove = None
return tip_(
"Measure distance and angles.\n"
- "\u2022 {} anywhere for new measurement.\n"
+ "\u2022 %s anywhere for new measurement.\n"
"\u2022 Drag ruler segment to measure an angle.\n"
- "\u2022 {} to remove the active ruler.\n"
+ "\u2022 %s to remove the active ruler.\n"
"\u2022 Ctrl while dragging to snap.\n"
"\u2022 Shift while dragging to measure surface thickness"
- ).format(
+ ) % (
kmi_to_string_or_none(kmi_add),
kmi_to_string_or_none(kmi_remove),
)
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 42ae00203f3..c1502165e44 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -45,7 +45,7 @@ class USERPREF_HT_header(Header):
# Show '*' to let users know the preferences have been modified.
layout.operator(
"wm.save_userpref",
- text="Save Preferences{:s}".format(" *" if prefs.is_dirty else ""),
+ text="Save Preferences" + (" *" if prefs.is_dirty else ""),
)
def draw(self, context):
@@ -1903,8 +1903,10 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
"wm.url_open", text="Report a Bug", icon='URL',
).url = info["tracker_url"]
elif not user_addon:
- addon_info = ("Name: {} {}\nAuthor: {}\n").format(
- info["name"], info["version"], info["author"])
+ addon_info = (
+ "Name: %s %s\n"
+ "Author: %s\n"
+ ) % (info["name"], str(info["version"]), info["author"])
props = sub.operator(
"wm.url_open_preset", text="Report a Bug", icon='URL',
)
@@ -1987,7 +1989,7 @@ class StudioLightPanelMixin:
for studio_light in lights:
self.draw_studio_light(flow, studio_light)
else:
- layout.label(text="No custom {} configured".format(self.bl_label))
+ layout.label(text="No custom %s configured" % self.bl_label)
def draw_studio_light(self, layout, studio_light):
box = layout.box()
@@ -2132,19 +2134,39 @@ class USERPREF_PT_experimental_virtual_reality(ExperimentalPanel, Panel):
"""
-class USERPREF_PT_experimental_system(ExperimentalPanel, Panel):
- bl_label = "System"
+class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
+ bl_label = "New Features"
def draw(self, context):
self._draw_items(
context, (
- ({"property": "use_undo_legacy"}, "T60695"),
({"property": "use_new_particle_system"}, "T73324"),
+ ),
+ )
+
+
+class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
+ bl_label = "Prototypes"
+
+ def draw(self, context):
+ self._draw_items(
+ context, (
({"property": "use_new_hair_type"}, "T68981"),
),
)
+class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
+ bl_label = "Debugging"
+
+ def draw(self, context):
+ self._draw_items(
+ context, (
+ ({"property": "use_undo_legacy"}, "T60695"),
+ ),
+ )
+
+
# -----------------------------------------------------------------------------
# Class Registration
@@ -2235,7 +2257,9 @@ classes = (
# Popovers.
USERPREF_PT_ndof_settings,
- USERPREF_PT_experimental_system,
+ USERPREF_PT_experimental_new_features,
+ USERPREF_PT_experimental_prototypes,
+ USERPREF_PT_experimental_debugging,
# Add dynamically generated editor theme panels last,
# so they show up last in the theme section.
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index c8c8ab2ebb7..25e87a39bc1 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -5642,8 +5642,8 @@ class VIEW3D_PT_object_type_visibility(Panel):
elif attr == "pointcloud" and not hasattr(bpy.data, "pointclouds"):
continue
- attr_v = "show_object_viewport_" f"{attr:s}"
- attr_s = "show_object_select_" f"{attr:s}"
+ attr_v = "show_object_viewport_" + attr
+ attr_s = "show_object_select_" + attr
icon_v = 'HIDE_OFF' if getattr(view, attr_v) else 'HIDE_ON'
icon_s = 'RESTRICT_SELECT_OFF' if getattr(view, attr_s) else 'RESTRICT_SELECT_ON'
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 0a991d3ef4a..417fd182e73 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -1185,6 +1185,11 @@ void BKE_brush_gpencil_paint_presets(Main *bmain, ToolSettings *ts, const bool r
if (reset || brush_prev == NULL) {
BKE_paint_brush_set(paint, deft_draw);
}
+ else {
+ if (brush_prev != NULL) {
+ BKE_paint_brush_set(paint, brush_prev);
+ }
+ }
}
/* Create a set of grease pencil Vertex Paint presets. */
@@ -1227,6 +1232,11 @@ void BKE_brush_gpencil_vertex_presets(Main *bmain, ToolSettings *ts, const bool
if (reset || brush_prev == NULL) {
BKE_paint_brush_set(vertexpaint, deft_vertex);
}
+ else {
+ if (brush_prev != NULL) {
+ BKE_paint_brush_set(vertexpaint, brush_prev);
+ }
+ }
}
/* Create a set of grease pencil Sculpt Paint presets. */
@@ -1297,6 +1307,11 @@ void BKE_brush_gpencil_sculpt_presets(Main *bmain, ToolSettings *ts, const bool
if (reset || brush_prev == NULL) {
BKE_paint_brush_set(sculptpaint, deft_sculpt);
}
+ else {
+ if (brush_prev != NULL) {
+ BKE_paint_brush_set(sculptpaint, brush_prev);
+ }
+ }
}
/* Create a set of grease pencil Weight Paint presets. */
@@ -1318,6 +1333,11 @@ void BKE_brush_gpencil_weight_presets(Main *bmain, ToolSettings *ts, const bool
if (reset || brush_prev == NULL) {
BKE_paint_brush_set(weightpaint, deft_weight);
}
+ else {
+ if (brush_prev != NULL) {
+ BKE_paint_brush_set(weightpaint, brush_prev);
+ }
+ }
}
struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode)
diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c
index 72ee4c5ec4d..46faddf6e5a 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -1568,6 +1568,7 @@ void do_versions_after_linking_cycles(Main *bmain)
}
if (cscene) {
+ const int DENOISER_AUTO = 0;
const int DENOISER_NLM = 1;
const int DENOISER_OPTIX = 2;
@@ -1578,7 +1579,7 @@ void do_versions_after_linking_cycles(Main *bmain)
/* Migrate Optix denoiser to new settings. */
if (cycles_property_int(cscene, "preview_denoising", 0)) {
cycles_property_boolean_set(cscene, "use_preview_denoising", true);
- cycles_property_boolean_set(cscene, "preview_denoiser", DENOISER_OPTIX);
+ cycles_property_int_set(cscene, "preview_denoiser", DENOISER_AUTO);
}
}
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 10f93a8f095..e971e465eca 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -175,6 +175,26 @@ typedef struct ProfileSpacing {
} ProfileSpacing;
/**
+ * If the mesh has custom data Loop layers that 'have math' we use this
+ * data to help decide which face to use as representative when there
+ * is an ambiguous choice as to which face to use, which happens
+ * when there is an odd number of segments.
+ *
+ * The face_compent field of the following will only be set if there are an odd
+ * number of segments. The it uses BMFace indices to index into it, so will
+ * only be valid as long BMFaces are not added or deleted in the BMesh.
+ * "Connected Component" here means connected in UV space:
+ * i.e., one face is directly connected to another if they share an edge and
+ * all of Loop UV custom layers are contiguous across that edge.
+ */
+typedef struct MathLayerInfo {
+ /** A connected-component id for each BMFace in the mesh. */
+ int *face_component;
+ /** Does the mesh have any custom loop uv layers? */
+ bool has_math_layers;
+} MathLayerInfo;
+
+/**
* An element in a cyclic boundary of a Vertex Mesh (VMesh), placed on each side of beveled edges
* where each profile starts, or on each side of a miter.
*/
@@ -297,6 +317,8 @@ typedef struct BevelParams {
ProfileSpacing pro_spacing;
/** Parameter values for evenly spaced profile points for the miter profiles. */
ProfileSpacing pro_spacing_miter;
+ /** Information about 'math' loop layers, like UV layers. */
+ MathLayerInfo math_layer_info;
/** Blender units to offset each side of a beveled edge. */
float offset;
/** How offset is measured; enum defined in bmesh_operators.h. */
@@ -733,12 +755,13 @@ static BMFace *bev_create_quad_ex(BMesh *bm,
BMEdge *e2,
BMEdge *e3,
BMEdge *e4,
+ BMFace *frep,
int mat_nr)
{
BMVert *varr[4] = {v1, v2, v3, v4};
BMFace *farr[4] = {f1, f2, f3, f4};
BMEdge *earr[4] = {e1, e2, e3, e4};
- return bev_create_ngon(bm, varr, 4, farr, f1, earr, mat_nr, true);
+ return bev_create_ngon(bm, varr, 4, farr, frep, earr, mat_nr, true);
}
/* Is Loop layer layer_index contiguous across shared vertex of l1 and l2? */
@@ -752,7 +775,8 @@ static bool contig_ldata_across_loops(BMesh *bm, BMLoop *l1, BMLoop *l2, int lay
}
/* Are all loop layers with have math (e.g., UVs)
- * contiguous from face f1 to face f2 across edge e? */
+ * contiguous from face f1 to face f2 across edge e?
+ */
static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f2)
{
BMLoop *lef1, *lef2;
@@ -764,41 +788,202 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f
return true;
}
- v1 = e->v1;
- v2 = e->v2;
if (!BM_edge_loop_pair(e, &lef1, &lef2)) {
return false;
}
+ /* If faces are oriented consistently around e,
+ * should now have lef1 and lef2 being f1 and f2 in either order.
+ */
if (lef1->f == f2) {
SWAP(BMLoop *, lef1, lef2);
}
-
- if (lef1->v == v1) {
- lv1f1 = lef1;
- lv2f1 = BM_face_other_edge_loop(f1, e, v2);
+ if (lef1->f != f1 || lef2 != lef2) {
+ return false;
}
- else {
- lv2f1 = lef1;
- lv1f1 = BM_face_other_edge_loop(f1, e, v1);
+ v1 = lef1->v;
+ v2 = lef2->v;
+ BLI_assert((v1 == e->v1 && v2 == e->v2) || (v1 == e->v2 && v2 == e->v1));
+ lv1f1 = lef1;
+ lv2f1 = lef1->next;
+ lv1f2 = lef2->next;
+ lv2f2 = lef2;
+ BLI_assert(lv1f1->v == v1 && lv1f1->f == f1 && lv2f1->v == v2 && lv2f1->f == f1 &&
+ lv1f2->v == v1 && lv1f2->f == f2 && lv2f2->v == v2 && lv2f2->f == f2);
+ for (i = 0; i < bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i)) {
+ if (!contig_ldata_across_loops(bm, lv1f1, lv1f2, i) ||
+ !contig_ldata_across_loops(bm, lv2f1, lv2f2, i)) {
+ return false;
+ }
+ }
}
+ return true;
+}
+
+/*
+ * Set up the fields of bp->math_layer_info.
+ * We always set has_math_layers to the correct value.
+ * Only if there are UV layers and the number of segments is odd,
+ * we need to calculate connected face components in UV space.
+ */
+static void math_layer_info_init(BevelParams *bp, BMesh *bm)
+{
+ int i, f, stack_top, totface, current_component;
+ int bmf_index, bmf_other_index;
+ int *face_component;
+ BMFace *bmf, *bmf_other;
+ BMEdge *bme;
+ BMFace **stack;
+ BMIter eiter, fiter;
- if (lef2->v == v1) {
- lv1f2 = lef2;
- lv2f2 = BM_face_other_edge_loop(f2, e, v2);
+ bp->math_layer_info.has_math_layers = false;
+ bp->math_layer_info.face_component = NULL;
+ for (i = 0; i < bm->ldata.totlayer; i++) {
+ if (CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
+ bp->math_layer_info.has_math_layers = true;
+ break;
+ }
}
- else {
- lv2f2 = lef2;
- lv1f2 = BM_face_other_edge_loop(f2, e, v1);
+ if (!bp->math_layer_info.has_math_layers || (bp->seg % 2) == 0) {
+ return;
}
- for (i = 0; i < bm->ldata.totlayer; i++) {
- if (CustomData_layer_has_math(&bm->ldata, i) &&
- (!contig_ldata_across_loops(bm, lv1f1, lv1f2, i) ||
- !contig_ldata_across_loops(bm, lv2f1, lv2f2, i))) {
- return false;
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
+ totface = bm->totface;
+ face_component = BLI_memarena_alloc(bp->mem_arena, totface * sizeof(int));
+ bp->math_layer_info.face_component = face_component;
+
+ /* Set all component ids by DFS from faces with unassigned components. */
+ for (f = 0; f < totface; f++) {
+ face_component[f] = -1;
+ }
+ current_component = -1;
+
+ /* Use an array as a stack. Stack size can't exceed double total faces. */
+ stack = MEM_malloc_arrayN(2 * totface, sizeof(BMFace *), __func__);
+ for (f = 0; f < totface; f++) {
+ if (face_component[f] == -1) {
+ stack_top = 0;
+ current_component++;
+ BLI_assert(stack_top < 2 * totface);
+ stack[stack_top] = BM_face_at_index(bm, f);
+ while (stack_top >= 0) {
+ bmf = stack[stack_top];
+ stack_top--;
+ bmf_index = BM_elem_index_get(bmf);
+ if (face_component[bmf_index] != -1) {
+ continue;
+ }
+ face_component[bmf_index] = current_component;
+ /* Neighbors are faces that share an edge with bmf and
+ * are where contig_ldata_across_edge(...) is true for the
+ * shared edge and two faces.
+ */
+ BM_ITER_ELEM (bme, &eiter, bmf, BM_EDGES_OF_FACE) {
+ BM_ITER_ELEM (bmf_other, &fiter, bme, BM_FACES_OF_EDGE) {
+ if (bmf_other != bmf) {
+ bmf_other_index = BM_elem_index_get(bmf_other);
+ if (face_component[bmf_other_index] != -1) {
+ continue;
+ }
+ if (contig_ldata_across_edge(bm, bme, bmf, bmf_other)) {
+ stack_top++;
+ BLI_assert(stack_top < 2 * totface);
+ stack[stack_top] = bmf_other;
+ }
+ }
+ }
+ }
+ }
}
}
- return true;
+ MEM_freeN(stack);
+}
+
+/* Use a tie-breaking rule to choose a representative face when
+ * there are number of choices, face[0], face[1], ..., face[nfaces].
+ * This is needed when there are an odd number of segments, and the center
+ * segmment (and its continuation into vmesh) can usually arbitrarily be
+ * the previous face or the next face.
+ * Or, for the center polygon of a corner, all of the faces around
+ * the vertex are possible choices.
+ * If we just choose randomly, the resulting UV maps or material
+ * assignment can look ugly/inconsistent.
+ * Allow for the case when args are null.
+ */
+static BMFace *choose_rep_face(BevelParams *bp, BMFace **face, int nfaces)
+{
+ int f, bmf_index, value_index, best_f, i;
+ BMFace *bmf;
+ float cent[3];
+#define VEC_VALUE_LEN 6
+ float(*value_vecs)[VEC_VALUE_LEN] = NULL;
+ bool *still_viable = NULL;
+ int num_viable = 0;
+
+ value_vecs = BLI_array_alloca(value_vecs, nfaces);
+ still_viable = BLI_array_alloca(still_viable, nfaces);
+ for (int f = 0; f < nfaces; f++) {
+ bmf = face[f];
+ if (bmf == NULL) {
+ still_viable[f] = false;
+ continue;
+ }
+ still_viable[f] = true;
+ num_viable++;
+ bmf_index = BM_elem_index_get(bmf);
+ value_index = 0;
+ /* First tie-breaker: lower math-layer connected component id. */
+ value_vecs[f][value_index++] = bp->math_layer_info.face_component ?
+ (float)bp->math_layer_info.face_component[bmf_index] :
+ 0.0f;
+ /* Next tie-breaker: selected face beats unselected one. */
+ value_vecs[f][value_index++] = BM_elem_flag_test(bmf, BM_ELEM_SELECT) ? 0.0f : 1.0f;
+ /* Next tie-breaker: lower material index. */
+ value_vecs[f][value_index++] = bmf->mat_nr >= 0 ? (float)bmf->mat_nr : 0.0f;
+ /* Next three tie-breakers: z, x, y components of face center. */
+ BM_face_calc_center_bounds(bmf, cent);
+ value_vecs[f][value_index++] = cent[2];
+ value_vecs[f][value_index++] = cent[0];
+ value_vecs[f][value_index++] = cent[1];
+ BLI_assert(value_index == VEC_VALUE_LEN);
+ }
+
+ /* Look for a face that has a unique minimum value for in a value_index,
+ * trying each value_index in turn until find a unique minimum.
+ */
+ best_f = -1;
+ for (value_index = 0; num_viable > 1 && value_index < VEC_VALUE_LEN; value_index++) {
+ for (f = 0; f < nfaces; f++) {
+ if (!still_viable[f] || f == best_f) {
+ continue;
+ }
+ if (best_f == -1) {
+ best_f = f;
+ continue;
+ }
+ if (value_vecs[f][value_index] < value_vecs[best_f][value_index]) {
+ best_f = f;
+ /* Previous f's are now not viable any more. */
+ for (i = f - 1; i >= 0; i--) {
+ if (still_viable[i]) {
+ still_viable[i] = false;
+ num_viable--;
+ }
+ }
+ }
+ else if (value_vecs[f][value_index] > value_vecs[best_f][value_index]) {
+ still_viable[f] = false;
+ num_viable--;
+ }
+ }
+ }
+ if (best_f == -1) {
+ best_f = 0;
+ }
+ return face[best_f];
+#undef VEC_VALUE_LEN
}
/* Merge (using average) all the UV values for loops of v's faces.
@@ -4472,6 +4657,105 @@ static float snap_face_dist_squared(float *co, BMFace *f, BMEdge **r_snap_e, flo
return beste_d2;
}
+/* What would be the area of the polygon around bv if interpolated in face frep?
+ */
+static float interp_poly_area(BevVert *bv, BMFace *frep)
+{
+ BoundVert *v;
+ VMesh *vm = bv->vmesh;
+ BMEdge *snape;
+ int n;
+ float(*uv_co)[3] = NULL;
+ float area;
+
+ BLI_assert(vm != NULL);
+ uv_co = BLI_array_alloca(uv_co, vm->count);
+ v = vm->boundstart;
+ n = 0;
+ do {
+ BLI_assert(n < vm->count);
+ snap_face_dist_squared(v->nv.v->co, frep, &snape, uv_co[n]);
+ n++;
+ } while ((v = v->next) != vm->boundstart);
+ area = fabsf(area_poly_v3(uv_co, n));
+ return area;
+}
+
+/**
+ * If we make a poly out of verts around bv, snapping to rep frep, will uv poly have zero area?
+ * The uv poly is made by snapping all outside-of-frep vertices to the closest edge in frep.
+ * Sometimes this results in a zero or very small area polygon, which translates to a zero
+ * or very small area polygong in UV space -- not good for interpolating textures.
+ */
+static bool is_bad_uv_poly(BevVert *bv, BMFace *frep)
+{
+ float area = interp_poly_area(bv, frep);
+ return area < BEVEL_EPSILON_BIG;
+}
+
+/*
+ * Pick a good face from all the faces around bv to use for
+ * a representative face, using choose_rep_face.
+ * We want to choose from among the faces that would be
+ * chosen for a single-segment edge polygon between two successive
+ * Boundverts.
+ * But the single beveled edge is a special case,
+ * where we also want to consider the third face (else can get
+ * zero-area UV interpolated face).
+ *
+ * If there are math-having custom loop layers, like UV, then
+ * don't include faces that would result in zero-area UV polygons
+ * if chosen as the rep.
+ */
+static BMFace *frep_for_center_poly(BevelParams *bp, BevVert *bv)
+{
+ int i, j, fcount;
+ BMFace **fchoices, *bmf, *bmf1, *bmf2, *any_bmf;
+ BMFace *ftwo[2];
+ bool already_there;
+ bool consider_all_faces;
+
+ fcount = 0;
+ any_bmf = NULL;
+ consider_all_faces = bv->selcount == 1;
+ /* Make an array that can hold maximum possible number of choices. */
+ fchoices = BLI_array_alloca(fchoices, bv->edgecount);
+ for (i = 0; i < bv->edgecount; i++) {
+ if (!bv->edges[i].is_bev && !consider_all_faces) {
+ continue;
+ }
+ bmf1 = bv->edges[i].fprev;
+ bmf2 = bv->edges[i].fnext;
+ ftwo[0] = bmf1;
+ ftwo[1] = bmf2;
+ bmf = choose_rep_face(bp, ftwo, 2);
+ if (bmf != NULL) {
+ if (any_bmf == NULL) {
+ any_bmf = bmf;
+ }
+ already_there = false;
+ for (j = fcount - 1; j >= 0; j--) {
+ if (fchoices[j] == bmf) {
+ already_there = true;
+ break;
+ }
+ }
+ if (!already_there) {
+ if (bp->math_layer_info.has_math_layers) {
+ if (is_bad_uv_poly(bv, bmf)) {
+ continue;
+ }
+ }
+ fchoices[fcount++] = bmf;
+ }
+ }
+ }
+ if (fcount == 0) {
+ return any_bmf;
+ }
+ return choose_rep_face(bp, fchoices, fcount);
+}
+
static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_nr)
{
VMesh *vm = bv->vmesh;
@@ -4488,7 +4772,7 @@ static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_n
ns2 = vm->seg / 2;
if (bv->any_seam) {
- frep = boundvert_rep_face(vm->boundstart, NULL);
+ frep = frep_for_center_poly(bp, bv);
get_incident_edges(frep, bv->v, &frep_e1, &frep_e2);
}
else {
@@ -4813,7 +5097,8 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
VMesh *vm1, *vm;
BoundVert *bndv;
BMVert *bmv1, *bmv2, *bmv3, *bmv4;
- BMFace *f, *f2, *r_f;
+ BMFace *f, *f2, *r_f, *fc;
+ BMFace *fchoices[2];
BMEdge *bme, *bme1, *bme2, *bme3;
EdgeHalf *e;
int mat_nr = bp->mat_nr;
@@ -4867,6 +5152,14 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
i = bndv->index;
f = boundvert_rep_face(bndv, NULL);
f2 = boundvert_rep_face(bndv->next, NULL);
+ fchoices[0] = f;
+ fchoices[1] = f2;
+ if (odd) {
+ fc = choose_rep_face(bp, fchoices, 2);
+ }
+ else {
+ fc = NULL;
+ }
if (bp->vertex_only) {
e = bndv->efirst;
}
@@ -4877,7 +5170,10 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
/* For odd ns, make polys with lower left corner at (i,j,k) for
* j in [0, ns2-1], k in [0, ns2]. And then the center ngon.
* For even ns,
- * j in [0, ns2-1], k in [0, ns2-1]. */
+ * j in [0, ns2-1], k in [0, ns2-1].
+ *
+ * Recall: j is ring index, k is segment index.
+ */
for (j = 0; j < ns2; j++) {
for (k = 0; k < ns2 + odd; k++) {
bmv1 = mesh_vert(vm, i, j, k)->v;
@@ -4901,6 +5197,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
NULL,
bndv->next->efirst->e,
bme,
+ f2,
mat_nr);
}
else {
@@ -4914,11 +5211,11 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
/* Only one edge attached to v, since vertex_only. */
if (e->is_seam) {
r_f = bev_create_quad_ex(
- bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, bme, NULL, bme, NULL, mat_nr);
+ bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, bme, NULL, bme, NULL, f2, mat_nr);
}
else {
r_f = bev_create_quad_ex(
- bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f, bme, NULL, bme, NULL, mat_nr);
+ bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f, bme, NULL, bme, NULL, f2, mat_nr);
}
}
}
@@ -4927,10 +5224,11 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
if (k == ns2) {
if (e && e->is_seam) {
r_f = bev_create_quad_ex(
- bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, NULL, bme, bme, NULL, mat_nr);
+ bm, bmv1, bmv2, bmv3, bmv4, fc, fc, fc, fc, NULL, bme, bme, NULL, fc, mat_nr);
}
else {
- r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f2, f2, f, mat_nr);
+ r_f = bev_create_quad_ex(
+ bm, bmv1, bmv2, bmv3, bmv4, f, f2, f2, f, NULL, bme, bme, NULL, fc, mat_nr);
}
}
else {
@@ -4945,7 +5243,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
}
bme2 = bme1 != NULL ? bme1 : bme3;
r_f = bev_create_quad_ex(
- bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, NULL, bme1, bme2, bme3, mat_nr);
+ bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, NULL, bme1, bme2, bme3, f, mat_nr);
}
}
record_face_kind(bp, r_f, F_VERT);
@@ -5143,43 +5441,9 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
}
}
-/**
- * If we make a poly out of verts around bv, snapping to rep frep, will uv poly have zero area?
- * The uv poly is made by snapping all outside-of-frep vertices to the closest edge in frep.
- * Assume that this function is called when the only inside-of-frep vertex is vm->boundstart.
- * The poly will have zero area if the distance of that first vertex to some edge e is zero,
- * and all the other vertices snap to e or snap to an edge
- * at a point that is essentially on e too.
- */
-static bool is_bad_uv_poly(BevVert *bv, BMFace *frep)
-{
- BoundVert *v;
- BMEdge *snape, *firste;
- float co[3];
- VMesh *vm = bv->vmesh;
- float d2;
-
- v = vm->boundstart;
- d2 = snap_face_dist_squared(v->nv.v->co, frep, &firste, co);
- if (d2 > BEVEL_EPSILON_BIG_SQ || firste == NULL) {
- return false;
- }
-
- for (v = v->next; v != vm->boundstart; v = v->next) {
- snap_face_dist_squared(v->nv.v->co, frep, &snape, co);
- if (snape != firste) {
- d2 = dist_to_line_v3(co, firste->v1->co, firste->v2->co);
- if (d2 > BEVEL_EPSILON_BIG_SQ) {
- return false;
- }
- }
- }
- return true;
-}
-
static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
{
- BMFace *f, *repface, *frep2;
+ BMFace *f, *repface;
int n, k;
VMesh *vm = bv->vmesh;
BoundVert *bndv;
@@ -5192,10 +5456,7 @@ static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
BLI_array_staticdeclare(bmfaces, BM_DEFAULT_NGON_STACK_SIZE);
if (bv->any_seam) {
- repface = boundvert_rep_face(vm->boundstart, &frep2);
- if (frep2 && repface && is_bad_uv_poly(bv, repface)) {
- repface = frep2;
- }
+ repface = frep_for_center_poly(bp, bv);
get_incident_edges(repface, bv->v, &repface_e1, &repface_e2);
}
else {
@@ -6413,7 +6674,7 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
VMesh *vm1, *vm2;
EdgeHalf *e1, *e2;
BMEdge *bme1, *bme2, *center_bme;
- BMFace *f1, *f2, *f, *r_f;
+ BMFace *f1, *f2, *f, *r_f, *f_choice;
BMVert *verts[4];
BMFace *faces[4];
BMEdge *edges[4];
@@ -6474,15 +6735,17 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
verts[3] = mesh_vert(vm1, i1, 0, k)->v;
verts[2] = mesh_vert(vm2, i2, 0, nseg - k)->v;
if (odd && k == mid + 1) {
+ BMFace *fchoices[2] = {f1, f2};
+ edges[0] = edges[1] = NULL;
+ edges[2] = edges[3] = bme;
+ f_choice = choose_rep_face(bp, fchoices, 2);
if (e1->is_seam) {
- /* Straddles a seam: choose to interpolate in f1 and snap right edge to bme. */
- edges[0] = edges[1] = NULL;
- edges[2] = edges[3] = bme;
- r_f = bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
+ /* Straddles a seam: choose to interpolate in f_choice and snap right edge to bme. */
+ r_f = bev_create_ngon(bm, verts, 4, NULL, f_choice, edges, mat_nr, true);
}
else {
/* Straddles but not a seam: interpolate left half in f1, right half in f2. */
- r_f = bev_create_ngon(bm, verts, 4, faces, NULL, NULL, mat_nr, true);
+ r_f = bev_create_ngon(bm, verts, 4, faces, f_choice, NULL, mat_nr, true);
}
}
else if (!odd && k == mid) {
@@ -7264,6 +7527,8 @@ void BM_mesh_bevel(BMesh *bm,
bp.face_hash = BLI_ghash_ptr_new(__func__);
BLI_ghash_flag_set(bp.face_hash, GHASH_FLAG_ALLOW_DUPES);
+ math_layer_info_init(&bp, bm);
+
/* Analyze input vertices, sorting edges and assigning initial new vertex positions. */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index d84ec9b1363..dab5c3ea911 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -594,7 +594,7 @@ void DepsgraphNodeBuilder::build_object(int base_index,
}
id_node->has_base |= (base_index != -1);
/* Various flags, flushing from bases/collections. */
- build_object_flags(base_index, object, linked_state);
+ build_object_from_layer(base_index, object, linked_state);
/* Transform. */
build_object_transform(object);
/* Parent. */
@@ -662,6 +662,21 @@ void DepsgraphNodeBuilder::build_object(int base_index,
function_bind(BKE_object_sync_to_original, _1, object_cow));
}
+void DepsgraphNodeBuilder::build_object_from_layer(int base_index,
+ Object *object,
+ eDepsNode_LinkedState_Type linked_state)
+{
+
+ OperationNode *entry_node = add_operation_node(
+ &object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_FROM_LAYER_ENTRY);
+ entry_node->set_as_entry();
+ OperationNode *exit_node = add_operation_node(
+ &object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_FROM_LAYER_EXIT);
+ exit_node->set_as_exit();
+
+ build_object_flags(base_index, object, linked_state);
+}
+
void DepsgraphNodeBuilder::build_object_flags(int base_index,
Object *object,
eDepsNode_LinkedState_Type linked_state)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index e0553182918..dbe3e310d72 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -168,6 +168,9 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
virtual void build_object_proxy_from(Object *object, bool is_object_visible);
virtual void build_object_proxy_group(Object *object, bool is_object_visible);
virtual void build_object_instance_collection(Object *object, bool is_object_visible);
+ virtual void build_object_from_layer(int base_index,
+ Object *object,
+ eDepsNode_LinkedState_Type linked_state);
virtual void build_object_flags(int base_index,
Object *object,
eDepsNode_LinkedState_Type linked_state);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index e21a83485ad..5b49e13e17a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -621,12 +621,9 @@ void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_coll
}
}
-void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
+void DepsgraphRelationBuilder::build_object(Base * /*base*/, Object *object)
{
if (built_map_.checkIsBuiltAndTag(object)) {
- if (base != nullptr) {
- build_object_flags(base, object);
- }
return;
}
/* Object Transforms */
@@ -644,7 +641,7 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
OperationKey ob_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
add_relation(init_transform_key, local_transform_key, "Transform Init");
/* Various flags, flushing from bases/collections. */
- build_object_flags(base, object);
+ build_object_from_layer_relations(object);
/* Parenting. */
if (object->parent != nullptr) {
/* Make sure parent object's relations are built. */
@@ -755,20 +752,34 @@ void DepsgraphRelationBuilder::build_object_proxy_group(Object *object)
add_relation(proxy_group_eval_key, transform_eval_key, "Proxy Group Transform");
}
-void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object)
+void DepsgraphRelationBuilder::build_object_from_layer_relations(Object *object)
{
- if (base == nullptr) {
- return;
+ OperationKey object_from_layer_entry_key(
+ &object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_FROM_LAYER_ENTRY);
+ OperationKey object_from_layer_exit_key(
+ &object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_FROM_LAYER_EXIT);
+ OperationKey object_flags_key(
+ &object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_BASE_FLAGS);
+
+ /* Only connect Entry -> Exit if there is no OBJECT_BASE_FLAGS node. */
+ if (has_node(object_flags_key)) {
+ /* Entry -> OBJECT_BASE_FLAGS -> Exit */
+ add_relation(object_from_layer_entry_key, object_flags_key, "Base flags flush Entry");
+ add_relation(object_flags_key, object_from_layer_exit_key, "Base flags flush Exit");
+
+ /* Synchronization back to original object. */
+ OperationKey synchronize_key(
+ &object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
+ add_relation(object_from_layer_exit_key, synchronize_key, "Synchronize to Original");
+ }
+ else {
+ /* Directly connect Entry -> Exit. */
+ add_relation(object_from_layer_entry_key, object_from_layer_exit_key, "Object from Layer");
}
+
OperationKey view_layer_done_key(
&scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
- OperationKey object_flags_key(
- &object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_BASE_FLAGS);
- add_relation(view_layer_done_key, object_flags_key, "Base flags flush");
- /* Synchronization back to original object. */
- OperationKey synchronize_key(
- &object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
- add_relation(object_flags_key, synchronize_key, "Synchronize to Original");
+ add_relation(view_layer_done_key, object_from_layer_entry_key, "View Layer flags to Object");
}
void DepsgraphRelationBuilder::build_object_data(Object *object)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index aa6d8ababd3..1be68babbc5 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -213,7 +213,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
virtual void build_object(Base *base, Object *object);
virtual void build_object_proxy_from(Object *object);
virtual void build_object_proxy_group(Object *object);
- virtual void build_object_flags(Base *base, Object *object);
+ virtual void build_object_from_layer_relations(Object *object);
virtual void build_object_data(Object *object);
virtual void build_object_data_camera(Object *object);
virtual void build_object_data_geometry(Object *object);
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index b757a4fc477..73aa58d2072 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -109,7 +109,7 @@ void depsgraph_select_tag_to_component_opcode(const ID *id,
}
else if (id_type == ID_OB) {
*component_type = NodeType::OBJECT_FROM_LAYER;
- *operation_code = OperationCode::OBJECT_BASE_FLAGS;
+ *operation_code = OperationCode::OBJECT_FROM_LAYER_ENTRY;
}
else if (id_type == ID_MC) {
*component_type = NodeType::BATCH_CACHE;
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc
index 91bd0117f6c..33d2bf79a5e 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc
@@ -63,8 +63,12 @@ const char *operationCodeAsString(OperationCode opcode)
case OperationCode::AUDIO_VOLUME:
return "AUDIO_VOLUME";
/* Object related. */
+ case OperationCode::OBJECT_FROM_LAYER_ENTRY:
+ return "OBJECT_FROM_LAYER_ENTRY";
case OperationCode::OBJECT_BASE_FLAGS:
return "OBJECT_BASE_FLAGS";
+ case OperationCode::OBJECT_FROM_LAYER_EXIT:
+ return "OBJECT_FROM_LAYER_EXIT";
case OperationCode::DIMENSIONS:
return "DIMENSIONS";
/* Transform. */
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h
index 6b14e6af02f..4ed266d355f 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.h
@@ -63,7 +63,9 @@ enum class OperationCode {
AUDIO_VOLUME,
/* Object related. ------------------------------------------------------ */
+ OBJECT_FROM_LAYER_ENTRY,
OBJECT_BASE_FLAGS,
+ OBJECT_FROM_LAYER_EXIT,
DIMENSIONS,
/* Transform. ----------------------------------------------------------- */
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index 04878c7268a..714481c39f1 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -365,8 +365,9 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
effects->taa_current_sample += 1;
}
else {
- if ((effects->taa_total_sample == 0) ||
- (effects->taa_current_sample < effects->taa_total_sample)) {
+ if (!DRW_state_is_playback() &&
+ ((effects->taa_total_sample == 0) ||
+ (effects->taa_current_sample < effects->taa_total_sample))) {
DRW_viewport_request_redraw();
}
}
diff --git a/source/blender/draw/engines/overlay/overlay_grid.c b/source/blender/draw/engines/overlay/overlay_grid.c
index 5ed32de6d93..e3079870d8f 100644
--- a/source/blender/draw/engines/overlay/overlay_grid.c
+++ b/source/blender/draw/engines/overlay/overlay_grid.c
@@ -41,6 +41,7 @@ enum {
CLIP_ZPOS = (1 << 7),
CLIP_ZNEG = (1 << 8),
GRID_BACK = (1 << 9),
+ GRID_CAMERA = (1 << 10),
};
void OVERLAY_grid_init(OVERLAY_Data *vedata)
@@ -145,6 +146,9 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
if (rv3d->persp == RV3D_CAMOB && v3d->camera && v3d->camera->type == OB_CAMERA) {
Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera);
dist = ((Camera *)(camera_object->data))->clip_end;
+ shd->grid_flag |= GRID_CAMERA;
+ shd->zneg_flag |= GRID_CAMERA;
+ shd->zpos_flag |= GRID_CAMERA;
}
else {
dist = v3d->clip_end;
diff --git a/source/blender/draw/engines/overlay/shaders/grid_frag.glsl b/source/blender/draw/engines/overlay/shaders/grid_frag.glsl
index 9743f918ce3..317e9fe0447 100644
--- a/source/blender/draw/engines/overlay/shaders/grid_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/grid_frag.glsl
@@ -28,7 +28,8 @@ uniform float gridSteps[STEPS_LEN] = float[](0.001, 0.01, 0.1, 1.0, 10.0, 100.0,
#define PLANE_XY (1 << 4)
#define PLANE_XZ (1 << 5)
#define PLANE_YZ (1 << 6)
-#define GRID_BACK (1 << 9) /* grid is behind objects */
+#define GRID_BACK (1 << 9) /* grid is behind objects */
+#define GRID_CAMERA (1 << 10) /* In camera view */
#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */
@@ -104,7 +105,9 @@ void main()
fade *= 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance);
}
else {
- dist = abs(gl_FragCoord.z * 2.0 - 1.0);
+ dist = gl_FragCoord.z * 2.0 - 1.0;
+ /* Avoid fading in +Z direction in camera view (see T70193). */
+ dist = ((gridFlag & GRID_CAMERA) != 0) ? clamp(dist, 0.0, 1.0) : abs(dist);
fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5);
dist = 1.0; /* avoid branch after */
diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c
index f4ed2add624..edc36326c57 100644
--- a/source/blender/editors/animation/time_scrub_ui.c
+++ b/source/blender/editors/animation/time_scrub_ui.c
@@ -112,16 +112,15 @@ static void draw_current_frame(const Scene *scene,
/* Draw vertical line to from the bottom of the current frame box to the bottom of the screen.
*/
const float subframe_x = UI_view2d_view_to_region_x(v2d, current_frame + sub_frame);
- GPU_line_width(2.0f);
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_CFRAME);
- immBegin(GPU_PRIM_LINES, 2);
-
- immVertex2f(pos, subframe_x, scrub_region_rect->ymax - box_padding);
- immVertex2f(pos, subframe_x, 0.0f);
- immEnd();
+ immRectf(pos,
+ subframe_x - U.pixelsize,
+ scrub_region_rect->ymax - box_padding,
+ subframe_x + U.pixelsize,
+ 0.0f);
immUnbindProgram();
}
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 98cb85061f2..d9402261175 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -475,13 +475,18 @@ void UI_draw_roundbox_shade_x(bool filled,
.color_outline[1] = clamp_f(col[1] + shadetop + shadedown, 0.0f, 1.0f),
.color_outline[2] = clamp_f(col[2] + shadetop + shadedown, 0.0f, 1.0f),
.color_outline[3] = clamp_f(col[3] + shadetop + shadedown, 0.0f, 1.0f),
+ .shade_dir = 1.0f,
.alpha_discard = 1.0f,
};
+ GPU_blend(true);
+
GPUBatch *batch = ui_batch_roundbox_widget_get();
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
GPU_batch_draw(batch);
+
+ GPU_blend(false);
}
#if 0 /* unused */
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 173aa51f406..9ff678df0db 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -1491,11 +1491,6 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co
ps->panel->ofsx = 0;
ps->panel->ofsy = -get_panel_size_y(ps->panel);
ps->panel->ofsx += ps->panel->runtime.region_ofsx;
- /* Extra margin if the panel is a box style panel. */
- if (ps->panel->type && ps->panel->type->flag & PNL_DRAW_BOX) {
- ps->panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN;
- ps->panel->ofsy -= UI_PANEL_BOX_STYLE_MARGIN;
- }
for (a = 0; a < tot - 1; a++, ps++) {
psnext = ps + 1;
@@ -1505,16 +1500,12 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co
bool use_box_next = psnext->panel->type && psnext->panel->type->flag & PNL_DRAW_BOX;
psnext->panel->ofsx = ps->panel->ofsx;
psnext->panel->ofsy = get_panel_real_ofsy(ps->panel) - get_panel_size_y(psnext->panel);
+
/* Extra margin for box style panels. */
+ ps->panel->ofsx += (use_box) ? UI_PANEL_BOX_STYLE_MARGIN : 0.0f;
if (use_box || use_box_next) {
psnext->panel->ofsy -= UI_PANEL_BOX_STYLE_MARGIN;
}
- if (use_box && !use_box_next) {
- psnext->panel->ofsx -= UI_PANEL_BOX_STYLE_MARGIN;
- }
- else if (!use_box && use_box_next) {
- psnext->panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN;
- }
}
else {
psnext->panel->ofsx = get_panel_real_ofsx(ps->panel);
@@ -1522,6 +1513,10 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co
get_panel_size_y(psnext->panel);
}
}
+ /* Extra margin for the last panel if it's a box-style panel. */
+ if (panelsort[tot - 1].panel->type && panelsort[tot - 1].panel->type->flag & PNL_DRAW_BOX) {
+ panelsort[tot - 1].panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN;
+ }
/* we interpolate */
done = false;
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index f07bb800eca..bc272431e3a 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -2356,8 +2356,10 @@ void outliner_build_tree(
for (lib = mainvar->libraries.first; lib; lib = lib->id.next) {
ten = outliner_add_library_contents(mainvar, soops, &soops->tree, lib);
- BLI_assert(ten != NULL);
- lib->id.newid = (ID *)ten;
+ /* NULL-check matters, due to filtering there may not be a new element. */
+ if (ten) {
+ lib->id.newid = (ID *)ten;
+ }
}
/* make hierarchy */
ten = soops->tree.first;
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
index 05fbae53e18..21c7f79a57c 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
@@ -19,9 +19,14 @@ vec3 compute_masks(vec2 uv)
bool right_half = uv.x > outRectSize.x * 0.5;
float corner_rad;
+ /* Correct aspect ratio for 2D views not using uniform scalling.
+ * uv is already in pixel space so a uniform scale should give us a ratio of 1. */
+ float ratio = (butCo != -2.0) ? (dFdy(uv.y) / dFdx(uv.x)) : 1.0;
vec2 uv_sdf = uv;
+ uv_sdf.x *= ratio;
+
if (right_half) {
- uv_sdf.x = outRectSize.x - uv_sdf.x;
+ uv_sdf.x = outRectSize.x * ratio - uv_sdf.x;
}
if (upper_half) {
uv_sdf.y = outRectSize.y - uv_sdf.y;
@@ -43,7 +48,7 @@ vec3 compute_masks(vec2 uv)
/* Clamp line width to be at least 1px wide. This can happen if the projection matrix
* has been scaled (i.e: Node editor)... */
- float line_width = (lineWidth > 0.0) ? max(fwidth(uv.x), lineWidth) : 0.0;
+ float line_width = (lineWidth > 0.0) ? max(fwidth(uv.y), lineWidth) : 0.0;
const float aa_radius = 0.5;
vec3 masks;
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
index 30d0cd05926..2fd5effccce 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
@@ -163,7 +163,7 @@ vec2 do_tria()
borderColor = vec4(0.0);
embossColor = vec4(0.0);
- butCo = -1.0;
+ butCo = -2.0;
return pos;
}
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index 9e0194f8a1b..1670e08325f 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -445,7 +445,7 @@ void RNA_def_main(BlenderRNA *brna)
0,
INT_MAX,
"Version",
- "Version of Blender the .blend was saved with",
+ "File format version the .blend file was saved with",
0,
INT_MAX);
RNA_def_property_int_funcs(prop, "rna_Main_version_get", NULL, NULL);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index c35b768fd01..57e46314777 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -5454,6 +5454,7 @@ static void rna_def_modifier_remesh(BlenderRNA *brna)
prop = RNA_def_property(srna, "voxel_size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "voxel_size");
+ RNA_def_property_range(prop, 0.0001f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0001, 2, 0.1, 3);
RNA_def_property_ui_text(prop,
"Voxel Size",
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 9c07280e70f..6a6d9f3054f 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -6074,11 +6074,11 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_new_particle_system", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_new_particle_system", 1);
RNA_def_property_ui_text(
- prop, "Use New Particle System", "Enable the new particle system in the ui");
+ prop, "New Particle System", "Enable the new particle system in the ui");
prop = RNA_def_property(srna, "use_new_hair_type", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_new_hair_type", 1);
- RNA_def_property_ui_text(prop, "Use New Hair Type", "Enable the new hair type in the ui");
+ RNA_def_property_ui_text(prop, "New Hair Type", "Enable the new hair type in the ui");
}
static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop)
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 32e36fbd09e..894a48d9f62 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -440,6 +440,8 @@ static void panel_draw(const bContext *C, Panel *panel)
PointerRNA ob_ptr;
modifier_panel_get_property_pointers(C, panel, &ob_ptr, &ptr);
+ PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
+
PointerRNA texture_ptr = RNA_pointer_get(&ptr, "texture");
bool has_texture = !RNA_pointer_is_null(&texture_ptr);
int texture_coords = RNA_enum_get(&ptr, "texture_coords");
@@ -467,7 +469,7 @@ static void panel_draw(const bContext *C, Panel *panel)
}
}
else if (texture_coords == MOD_DISP_MAP_UV && RNA_enum_get(&ob_ptr, "type") == OB_MESH) {
- uiItemR(col, &ptr, "uv_layer", 0, NULL, ICON_NONE);
+ uiItemPointerR(col, &ptr, "uv_layer", &obj_data_ptr, "uv_layers", NULL, ICON_NONE);
}
uiItemS(layout);