Vulkan: Push constants #104880

Merged
Jeroen Bakker merged 73 commits from Jeroen-Bakker/blender:vulkan-push-constants into main 2023-03-06 12:29:06 +01:00
117 changed files with 1751 additions and 854 deletions
Showing only changes of commit bbece58e98 - Show all commits

View File

@ -524,7 +524,7 @@ endif()
if(NOT APPLE) if(NOT APPLE)
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" ON) option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" ON)
option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF) option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF)
set(CYCLES_HIP_BINARIES_ARCH gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 gfx1035 gfx1100 gfx1101 gfx1102 CACHE STRING "AMD HIP architectures to build binaries for") set(CYCLES_HIP_BINARIES_ARCH gfx900 gfx906 gfx90c gfx902 gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 gfx1035 gfx1100 gfx1101 gfx1102 CACHE STRING "AMD HIP architectures to build binaries for")
mark_as_advanced(WITH_CYCLES_DEVICE_HIP) mark_as_advanced(WITH_CYCLES_DEVICE_HIP)
mark_as_advanced(CYCLES_HIP_BINARIES_ARCH) mark_as_advanced(CYCLES_HIP_BINARIES_ARCH)
endif() endif()

View File

@ -299,7 +299,11 @@ else
ifneq ("$(wildcard $(DEPS_BUILD_DIR)/build.ninja)","") ifneq ("$(wildcard $(DEPS_BUILD_DIR)/build.ninja)","")
DEPS_BUILD_COMMAND:=ninja DEPS_BUILD_COMMAND:=ninja
else else
DEPS_BUILD_COMMAND:=make -s ifeq ($(OS), Darwin)
DEPS_BUILD_COMMAND:=make -s
else
DEPS_BUILD_COMMAND:="$(BLENDER_DIR)/build_files/build_environment/linux/make_deps_wrapper.sh" -s
endif
endif endif
endif endif
@ -398,7 +402,7 @@ endif
deps: .FORCE deps: .FORCE
@echo @echo
@echo Configuring dependencies in \"$(DEPS_BUILD_DIR)\" @echo Configuring dependencies in \"$(DEPS_BUILD_DIR)\", install to \"$(DEPS_INSTALL_DIR)\"
@cmake -H"$(DEPS_SOURCE_DIR)" \ @cmake -H"$(DEPS_SOURCE_DIR)" \
-B"$(DEPS_BUILD_DIR)" \ -B"$(DEPS_BUILD_DIR)" \

View File

@ -0,0 +1,73 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# This script ensures:
# - One dependency is built at a time.
# - That dependency uses all available cores.
#
# Without this, simply calling `make -j$(nproc)` from the `${CMAKE_BUILD_DIR}/deps/`
# directory will build all projects at once.
#
# This is undesirable for the following reasons:
#
# - The output from many projects is mixed together,
# making it difficult to track down the cause of a build failure.
#
# - Larger dependencies such as LLVM can bottleneck the build process,
# making it necessary to cancel the build and manually run build commands in each directory.
#
# - Building many projects at once means canceling (Control-C) can lead to the build being in an undefined state.
# It's possible canceling happens as a patch is being applied or files are being copied.
# (steps that aren't part of the compilation process where it's typically safe to cancel).
if [[ -z "${MY_MAKE_CALL_LEVEL}" ]]; then
export MY_MAKE_CALL_LEVEL=0
export MY_MAKEFLAGS=$MAKEFLAGS
# Extract the jobs argument (`-jN`, `-j N`, `--jobs=N`).
add_next=0
for i in "$@"; do
case $i in
-j*)
export MY_JOBS_ARG=$i
if [ "$MY_JOBS_ARG" = "-j" ]; then
add_next=1
fi
;;
--jobs=*)
shift # past argument=value
export MY_JOBS_ARG=$i
;;
*)
if (( $add_next == 1 )); then
export MY_JOBS_ARG="$MY_JOBS_ARG $i"
add_next=0
fi
;;
esac
done
unset i add_next
if [[ -z "${MY_JOBS_ARG}" ]]; then
export MY_JOBS_ARG="-j$(nproc)"
fi
# Support user defined `MAKEFLAGS`.
export MAKEFLAGS="$MY_MAKEFLAGS -j1"
else
export MY_MAKE_CALL_LEVEL=$(( $MY_MAKE_CALL_LEVEL + 1 ))
if (( $MY_MAKE_CALL_LEVEL == 1 )); then
# Important to set jobs to 1, otherwise user defined jobs argument is used.
export MAKEFLAGS="$MY_MAKEFLAGS -j1"
elif (( $MY_MAKE_CALL_LEVEL == 2 )); then
# This is the level used by each sub-project.
export MAKEFLAGS="$MY_MAKEFLAGS $MY_JOBS_ARG"
fi
# Else leave `MY_MAKEFLAGS` flags as-is, avoids setting a high number of jobs on recursive
# calls (which may easily run out of memory). Let the job-server handle the rest.
fi
# Useful for troubleshooting the wrapper.
# echo "Call level: $MY_MAKE_CALL_LEVEL, args=$@".
# Call actual make but ensure recursive calls run via this script.
exec make MAKE="$0" "$@"

View File

@ -487,7 +487,7 @@ BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
if BLENDER_REVISION != "Unknown": if BLENDER_REVISION != "Unknown":
# SHA1 Git hash # SHA1 Git hash
BLENDER_VERSION_HASH = BLENDER_REVISION BLENDER_VERSION_HASH = BLENDER_REVISION
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://developer.blender.org/rB%s>%s</a>" % ( BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://projects.blender.org/blender/blender/commit/%s>%s</a>" % (
BLENDER_VERSION_HASH, BLENDER_VERSION_HASH, BLENDER_VERSION_HASH, BLENDER_VERSION_HASH,
) )
BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP)) BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP))
@ -647,7 +647,7 @@ def undocumented_message(module_name, type_name, identifier):
module_name, type_name, identifier, module_name, type_name, identifier,
) )
return "Undocumented, consider `contributing <https://developer.blender.org/T51061>`__." return "Undocumented, consider `contributing <https://developer.blender.org/>`__."
def range_str(val): def range_str(val):

View File

@ -1679,12 +1679,12 @@ class CyclesPreferences(bpy.types.AddonPreferences):
import sys import sys
if sys.platform[:3] == "win": if sys.platform[:3] == "win":
driver_version = "21.Q4" driver_version = "21.Q4"
col.label(text="Requires AMD GPU with RDNA architecture", icon='BLANK1') col.label(text="Requires AMD GPU with Vega or RDNA architecture", icon='BLANK1')
col.label(text=iface_("and AMD Radeon Pro %s driver or newer") % driver_version, col.label(text=iface_("and AMD Radeon Pro %s driver or newer") % driver_version,
icon='BLANK1', translate=False) icon='BLANK1', translate=False)
elif sys.platform.startswith("linux"): elif sys.platform.startswith("linux"):
driver_version = "22.10" driver_version = "22.10"
col.label(text="Requires AMD GPU with RDNA architecture", icon='BLANK1') col.label(text="Requires AMD GPU with Vega or RDNA architecture", icon='BLANK1')
col.label(text=iface_("and AMD driver version %s or newer") % driver_version, icon='BLANK1', col.label(text=iface_("and AMD driver version %s or newer") % driver_version, icon='BLANK1',
translate=False) translate=False)
elif device_type == 'ONEAPI': elif device_type == 'ONEAPI':

View File

@ -51,7 +51,7 @@ static inline bool hipSupportsDevice(const int hipDevId)
hipDeviceGetAttribute(&major, hipDeviceAttributeComputeCapabilityMajor, hipDevId); hipDeviceGetAttribute(&major, hipDeviceAttributeComputeCapabilityMajor, hipDevId);
hipDeviceGetAttribute(&minor, hipDeviceAttributeComputeCapabilityMinor, hipDevId); hipDeviceGetAttribute(&minor, hipDeviceAttributeComputeCapabilityMinor, hipDevId);
return (major >= 10); return (major >= 9);
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@ -899,8 +899,8 @@ int RenderScheduler::get_num_samples_during_navigation(int resolution_divider) c
/* Schedule samples equal to the resolution divider up to a maximum of 4. /* Schedule samples equal to the resolution divider up to a maximum of 4.
* The idea is to have enough information on the screen by increasing the sample count as the * The idea is to have enough information on the screen by increasing the sample count as the
* resolution is decreased. */ * resolution is decreased. */
/* NOTE: Changeing this formula will change the formula in /* NOTE: Changing this formula will change the formula in
* "RenderScheduler::calculate_resolution_divider_for_time()"*/ * `RenderScheduler::calculate_resolution_divider_for_time()`. */
return min(max(1, resolution_divider / pixel_size_), 4); return min(max(1, resolution_divider / pixel_size_), 4);
} }
@ -1177,18 +1177,18 @@ int RenderScheduler::calculate_resolution_divider_for_time(double desired_time,
{ {
const double ratio_between_times = actual_time / desired_time; const double ratio_between_times = actual_time / desired_time;
/* We can pass "ratio_between_times" to "get_num_samples_during_navigation()" to get our /* We can pass `ratio_between_times` to `get_num_samples_during_navigation()` to get our
* navigation samples because the equation for calculating the resolution divider is as follows: * navigation samples because the equation for calculating the resolution divider is as follows:
* "actual_time / desired_time = sqr(resolution_divider) / sample_count". * `actual_time / desired_time = sqr(resolution_divider) / sample_count`.
* While "resolution_divider" is less than or equal to 4, "resolution_divider = sample_count" * While `resolution_divider` is less than or equal to 4, `resolution_divider = sample_count`
* (This relationship is determined in "get_num_samples_during_navigation()"). With some * (This relationship is determined in `get_num_samples_during_navigation()`). With some
* substitution we end up with "actual_time / desired_time = resolution_divider" while the * substitution we end up with `actual_time / desired_time = resolution_divider` while the
* resolution divider is less than or equal to 4. Once the resolution divider increases above 4, * resolution divider is less than or equal to 4. Once the resolution divider increases above 4,
* the relationsip of "actual_time / desired_time = resolution_divider" is no longer true, * the relationship of `actual_time / desired_time = resolution_divider` is no longer true,
* however the sample count retrieved from "get_num_samples_during_navigation()" is still * however the sample count retrieved from `get_num_samples_during_navigation()` is still
* accurate if we continue using this assumption. It should be noted that the interaction between * accurate if we continue using this assumption. It should be noted that the interaction between
* pixel_size, sample count, and resolution divider are automatically accounted for and that's * `pixel_size`, sample count, and resolution divider are automatically accounted for and that's
* why pixel_size isn't included in any of the equations. */ * why `pixel_size` isn't included in any of the equations. */
const int navigation_samples = get_num_samples_during_navigation( const int navigation_samples = get_num_samples_during_navigation(
ceil_to_int(ratio_between_times)); ceil_to_int(ratio_between_times));

View File

@ -412,11 +412,12 @@ if(WITH_CYCLES_CUDA_BINARIES)
# warn for other versions # warn for other versions
if((CUDA_VERSION STREQUAL "101") OR if((CUDA_VERSION STREQUAL "101") OR
(CUDA_VERSION STREQUAL "102") OR (CUDA_VERSION STREQUAL "102") OR
(CUDA_VERSION_MAJOR STREQUAL "11")) (CUDA_VERSION_MAJOR STREQUAL "11") OR
(CUDA_VERSION_MAJOR STREQUAL "12"))
else() else()
message(WARNING message(WARNING
"CUDA version ${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR} detected, " "CUDA version ${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR} detected, "
"build may succeed but only CUDA 11, 10.2 and 10.1 have been tested") "build may succeed but only CUDA 12, 11, 10.2 and 10.1 have been tested")
endif() endif()
# build for each arch # build for each arch
@ -514,6 +515,16 @@ if(WITH_CYCLES_CUDA_BINARIES)
else() else()
message(STATUS "CUDA binaries for ${arch} require CUDA 10 or earlier, skipped.") message(STATUS "CUDA binaries for ${arch} require CUDA 10 or earlier, skipped.")
endif() endif()
elseif(${arch} MATCHES ".*_3.")
if(DEFINED CUDA11_NVCC_EXECUTABLE)
set(cuda_nvcc_executable ${CUDA11_NVCC_EXECUTABLE})
set(cuda_toolkit_root_dir ${CUDA11_TOOLKIT_ROOT_DIR})
elseif("${CUDA_VERSION}" LESS 120) # Support for sm_35, sm_37 was removed in CUDA 12
set(cuda_nvcc_executable ${CUDA_NVCC_EXECUTABLE})
set(cuda_toolkit_root_dir ${CUDA_TOOLKIT_ROOT_DIR})
else()
message(STATUS "CUDA binaries for ${arch} require CUDA 11 or earlier, skipped.")
endif()
elseif(${arch} MATCHES ".*_7." AND "${CUDA_VERSION}" LESS 100) elseif(${arch} MATCHES ".*_7." AND "${CUDA_VERSION}" LESS 100)
message(STATUS "CUDA binaries for ${arch} require CUDA 10.0+, skipped.") message(STATUS "CUDA binaries for ${arch} require CUDA 10.0+, skipped.")
elseif(${arch} MATCHES ".*_8.") elseif(${arch} MATCHES ".*_8.")

View File

@ -686,7 +686,7 @@ ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd,
albedo *= ((ccl_private const PrincipledSheenBsdf *)sc)->avg_value; albedo *= ((ccl_private const PrincipledSheenBsdf *)sc)->avg_value;
break; break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
albedo *= bsdf_principled_hair_albedo(sc); albedo *= bsdf_principled_hair_albedo(sd, sc);
break; break;
default: default:
break; break;

View File

@ -478,10 +478,18 @@ ccl_device_inline float bsdf_principled_hair_albedo_roughness_scale(
return (((((0.245f * x) + 5.574f) * x - 10.73f) * x + 2.532f) * x - 0.215f) * x + 5.969f; return (((((0.245f * x) + 5.574f) * x - 10.73f) * x + 2.532f) * x - 0.215f) * x + 5.969f;
} }
ccl_device Spectrum bsdf_principled_hair_albedo(ccl_private const ShaderClosure *sc) ccl_device Spectrum bsdf_principled_hair_albedo(ccl_private const ShaderData *sd,
ccl_private const ShaderClosure *sc)
{ {
ccl_private PrincipledHairBSDF *bsdf = (ccl_private PrincipledHairBSDF *)sc; ccl_private PrincipledHairBSDF *bsdf = (ccl_private PrincipledHairBSDF *)sc;
return exp(-sqrt(bsdf->sigma) * bsdf_principled_hair_albedo_roughness_scale(bsdf->v));
const float cos_theta_o = cos_from_sin(dot(sd->wi, safe_normalize(sd->dPdu)));
const float cos_gamma_o = cos_from_sin(bsdf->extra->geom.w);
const float f = fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta);
const float roughness_scale = bsdf_principled_hair_albedo_roughness_scale(bsdf->v);
/* TODO(lukas): Adding the Fresnel term here as a workaround until the proper refactor. */
return exp(-sqrt(bsdf->sigma) * roughness_scale) + make_spectrum(f);
} }
ccl_device_inline Spectrum ccl_device_inline Spectrum

View File

@ -281,6 +281,8 @@ inline T *MEM_new(const char *allocation_name, Args &&...args)
*/ */
template<typename T> inline void MEM_delete(const T *ptr) template<typename T> inline void MEM_delete(const T *ptr)
{ {
static_assert(!std::is_void_v<T>,
"MEM_delete on a void pointer not possible. Cast it to a non-void type?");
if (ptr == nullptr) { if (ptr == nullptr) {
/* Support #ptr being null, because C++ `delete` supports that as well. */ /* Support #ptr being null, because C++ `delete` supports that as well. */
return; return;

View File

@ -30,7 +30,7 @@ def url_prefill_from_blender(*, addon_info=None):
"**Blender Version**\n" "**Blender Version**\n"
) )
fh.write( fh.write(
"Broken: version: %s, branch: %s, commit date: %s %s, hash: `rB%s`\n" % ( "Broken: version: %s, branch: %s, commit date: %s %s, hash: `%s`\n" % (
bpy.app.version_string, bpy.app.version_string,
bpy.app.build_branch.decode('utf-8', 'replace'), bpy.app.build_branch.decode('utf-8', 'replace'),
bpy.app.build_commit_date.decode('utf-8', 'replace'), bpy.app.build_commit_date.decode('utf-8', 'replace'),

View File

@ -991,6 +991,7 @@ url_manual_mapping = (
("bpy.types.geometrynodeinputmeshfacearea*", "modeling/geometry_nodes/mesh/read/face_area.html#bpy-types-geometrynodeinputmeshfacearea"), ("bpy.types.geometrynodeinputmeshfacearea*", "modeling/geometry_nodes/mesh/read/face_area.html#bpy-types-geometrynodeinputmeshfacearea"),
("bpy.types.geometrynodeinputsplinecyclic*", "modeling/geometry_nodes/curve/read/is_spline_cyclic.html#bpy-types-geometrynodeinputsplinecyclic"), ("bpy.types.geometrynodeinputsplinecyclic*", "modeling/geometry_nodes/curve/read/is_spline_cyclic.html#bpy-types-geometrynodeinputsplinecyclic"),
("bpy.types.geometrynodeinstancestopoints*", "modeling/geometry_nodes/instances/instances_to_points.html#bpy-types-geometrynodeinstancestopoints"), ("bpy.types.geometrynodeinstancestopoints*", "modeling/geometry_nodes/instances/instances_to_points.html#bpy-types-geometrynodeinstancestopoints"),
("bpy.types.geometrynodematerialselection*", "modeling/geometry_nodes/material/material_selection.html#bpy-types-geometrynodematerialselection"),
("bpy.types.gpencillayer.viewlayer_render*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-viewlayer-render"), ("bpy.types.gpencillayer.viewlayer_render*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-viewlayer-render"),
("bpy.types.imagepaint.use_normal_falloff*", "sculpt_paint/brush/falloff.html#bpy-types-imagepaint-use-normal-falloff"), ("bpy.types.imagepaint.use_normal_falloff*", "sculpt_paint/brush/falloff.html#bpy-types-imagepaint-use-normal-falloff"),
("bpy.types.layercollection.hide_viewport*", "editors/outliner/interface.html#bpy-types-layercollection-hide-viewport"), ("bpy.types.layercollection.hide_viewport*", "editors/outliner/interface.html#bpy-types-layercollection-hide-viewport"),
@ -2027,6 +2028,7 @@ url_manual_mapping = (
("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"), ("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"),
("bpy.ops.mball.delete_metaelems*", "modeling/metas/editing.html#bpy-ops-mball-delete-metaelems"), ("bpy.ops.mball.delete_metaelems*", "modeling/metas/editing.html#bpy-ops-mball-delete-metaelems"),
("bpy.ops.mball.reveal_metaelems*", "modeling/metas/properties.html#bpy-ops-mball-reveal-metaelems"), ("bpy.ops.mball.reveal_metaelems*", "modeling/metas/properties.html#bpy-ops-mball-reveal-metaelems"),
("bpy.ops.mesh.bridge_edge_loops*", "modeling/meshes/editing/edge/bridge_edge_loops.html#bpy-ops-mesh-bridge-edge-loops"),
("bpy.ops.mesh.intersect_boolean*", "modeling/meshes/editing/face/intersect_boolean.html#bpy-ops-mesh-intersect-boolean"), ("bpy.ops.mesh.intersect_boolean*", "modeling/meshes/editing/face/intersect_boolean.html#bpy-ops-mesh-intersect-boolean"),
("bpy.ops.mesh.loop_multi_select*", "modeling/meshes/selecting/loops.html#bpy-ops-mesh-loop-multi-select"), ("bpy.ops.mesh.loop_multi_select*", "modeling/meshes/selecting/loops.html#bpy-ops-mesh-loop-multi-select"),
("bpy.ops.mesh.vert_connect_path*", "modeling/meshes/editing/vertex/connect_vertex_path.html#bpy-ops-mesh-vert-connect-path"), ("bpy.ops.mesh.vert_connect_path*", "modeling/meshes/editing/vertex/connect_vertex_path.html#bpy-ops-mesh-vert-connect-path"),
@ -3021,6 +3023,7 @@ url_manual_mapping = (
("bpy.types.bakesettings*", "render/cycles/baking.html#bpy-types-bakesettings"), ("bpy.types.bakesettings*", "render/cycles/baking.html#bpy-types-bakesettings"),
("bpy.types.blendtexture*", "render/materials/legacy_textures/types/blend.html#bpy-types-blendtexture"), ("bpy.types.blendtexture*", "render/materials/legacy_textures/types/blend.html#bpy-types-blendtexture"),
("bpy.types.brush.height*", "sculpt_paint/sculpting/tools/layer.html#bpy-types-brush-height"), ("bpy.types.brush.height*", "sculpt_paint/sculpting/tools/layer.html#bpy-types-brush-height"),
("bpy.types.brush.jitter*", "sculpt_paint/brush/stroke.html#bpy-types-brush-jitter"),
("bpy.types.castmodifier*", "modeling/modifiers/deform/cast.html#bpy-types-castmodifier"), ("bpy.types.castmodifier*", "modeling/modifiers/deform/cast.html#bpy-types-castmodifier"),
("bpy.types.curve.offset*", "modeling/curves/properties/geometry.html#bpy-types-curve-offset"), ("bpy.types.curve.offset*", "modeling/curves/properties/geometry.html#bpy-types-curve-offset"),
("bpy.types.geometrynode*", "modeling/geometry_nodes/index.html#bpy-types-geometrynode"), ("bpy.types.geometrynode*", "modeling/geometry_nodes/index.html#bpy-types-geometrynode"),

View File

@ -6345,9 +6345,8 @@ def km_node_link_modal_map(_params):
return keymap return keymap
# Fallback for gizmos that don't have custom a custom key-map. # Fallback for gizmos that don't have custom a custom key-map.
def km_generic_gizmo(_params): def km_generic_gizmo(_params):
keymap = ( keymap = (
"Generic Gizmo", "Generic Gizmo",

View File

@ -1249,7 +1249,31 @@ class WM_OT_doc_view_manual(Operator):
# XXX, for some reason all RNA ID's are stored lowercase # XXX, for some reason all RNA ID's are stored lowercase
# Adding case into all ID's isn't worth the hassle so force lowercase. # Adding case into all ID's isn't worth the hassle so force lowercase.
rna_id = rna_id.lower() rna_id = rna_id.lower()
# NOTE: `fnmatch` in Python is slow as it translate the string to a regular-expression
# which needs to be compiled (as of Python 3.11), this is slow enough to cause a noticeable
# delay when opening manual links (approaching half a second).
#
# Resolve by matching characters that have a special meaning to `fnmatch`.
# The characters that can occur as the first special character are `*?[`.
# If any of these are used we must let `fnmatch` run its own matching logic.
# However, in most cases a literal prefix is used making it considerably faster
# to do a simple `startswith` check before performing a full match.
# An alternative solution could be to use `fnmatch` from C which is significantly
# faster than Python's, see !104581 for details.
import re
re_match_non_special = re.compile(r"^[^?\*\[]+").match
for pattern, url_suffix in url_mapping: for pattern, url_suffix in url_mapping:
# Simple optimization, makes a big difference (over 50x speedup).
# Even when `non_special.end()` is zero (resulting in an empty-string),
# the `startswith` check succeeds so there is no need to check for an empty match.
non_special = re_match_non_special(pattern)
if non_special is None or not rna_id.startswith(pattern[:non_special.end()]):
continue
# End simple optimization.
if fnmatchcase(rna_id, pattern): if fnmatchcase(rna_id, pattern):
if verbose: if verbose:
print(" match found: '%s' --> '%s'" % (pattern, url_suffix)) print(" match found: '%s' --> '%s'" % (pattern, url_suffix))

File diff suppressed because it is too large Load Diff

View File

@ -2319,21 +2319,15 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
bl_label = "New Features" bl_label = "New Features"
def draw(self, context): def draw(self, context):
self._draw_items(context, self._draw_items(
(({"property": "use_sculpt_tools_tilt"}, context, (
("blender/blender/issues/82877", ({"property": "use_sculpt_tools_tilt"}, ("blender/blender/issues/82877", "#82877")),
"#82877")), ({"property": "use_extended_asset_browser"},
({"property": "use_extended_asset_browser"}, ("blender/blender/projects/10", "Pipeline, Assets & IO Project Page")),
("blender/blender/projects/10", ({"property": "use_override_templates"}, ("blender/blender/issues/73318", "Milestone 4")),
"Pipeline, Assets & IO Project Page")), ({"property": "use_new_volume_nodes"}, ("blender/blender/issues/103248", "#103248")),
({"property": "use_override_templates"}, ),
("blender/blender/issues/73318", )
"Milestone 4")),
({"property": "use_new_volume_nodes"},
("blender/blender/issues/103248",
"#103248")),
),
)
class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel): class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):

View File

@ -137,6 +137,7 @@ bool CustomData_has_referenced(const struct CustomData *data);
* implemented for mloopuv/mloopcol, for now. * implemented for mloopuv/mloopcol, for now.
*/ */
void CustomData_data_copy_value(int type, const void *source, void *dest); void CustomData_data_copy_value(int type, const void *source, void *dest);
void CustomData_data_set_default_value(int type, void *elem);
/** /**
* Mixes the "value" (e.g. mloopuv uv or mloopcol colors) from one block into * Mixes the "value" (e.g. mloopuv uv or mloopcol colors) from one block into
@ -304,8 +305,8 @@ void CustomData_copy_data(const struct CustomData *source,
int source_index, int source_index,
int dest_index, int dest_index,
int count); int count);
void CustomData_copy_data_layer(const CustomData *source, void CustomData_copy_data_layer(const struct CustomData *source,
CustomData *dest, struct CustomData *dest,
int src_layer_index, int src_layer_index,
int dst_layer_index, int dst_layer_index,
int src_index, int src_index,
@ -444,7 +445,7 @@ void *CustomData_get_layer_named_for_write(CustomData *data,
int totelem); int totelem);
int CustomData_get_offset(const struct CustomData *data, int type); int CustomData_get_offset(const struct CustomData *data, int type);
int CustomData_get_offset_named(const CustomData *data, int type, const char *name); int CustomData_get_offset_named(const struct CustomData *data, int type, const char *name);
int CustomData_get_n_offset(const struct CustomData *data, int type, int n); int CustomData_get_n_offset(const struct CustomData *data, int type, int n);
int CustomData_get_layer_index(const struct CustomData *data, int type); int CustomData_get_layer_index(const struct CustomData *data, int type);
@ -506,6 +507,8 @@ void CustomData_clear_layer_flag(struct CustomData *data, int type, int flag);
void CustomData_bmesh_set_default(struct CustomData *data, void **block); void CustomData_bmesh_set_default(struct CustomData *data, void **block);
void CustomData_bmesh_free_block(struct CustomData *data, void **block); void CustomData_bmesh_free_block(struct CustomData *data, void **block);
void CustomData_bmesh_alloc_block(struct CustomData *data, void **block);
/** /**
* Same as #CustomData_bmesh_free_block but zero the memory rather than freeing. * Same as #CustomData_bmesh_free_block but zero the memory rather than freeing.
*/ */
@ -517,24 +520,6 @@ void CustomData_bmesh_free_block_data_exclude_by_type(struct CustomData *data,
void *block, void *block,
eCustomDataMask mask_exclude); eCustomDataMask mask_exclude);
/**
* Copy custom data to/from layers as in mesh/derived-mesh, to edit-mesh
* blocks of data. the CustomData's must not be compatible.
*
* \param use_default_init: initializes data which can't be copied,
* typically you'll want to use this if the BM_xxx create function
* is called with BM_CREATE_SKIP_CD flag
*/
void CustomData_to_bmesh_block(const struct CustomData *source,
struct CustomData *dest,
int src_index,
void **dest_block,
bool use_default_init);
void CustomData_from_bmesh_block(const struct CustomData *source,
struct CustomData *dest,
void *src_block,
int dest_index);
/** /**
* Query info over types. * Query info over types.
*/ */
@ -743,7 +728,7 @@ void CustomData_blend_write(BlendWriter *writer,
void CustomData_blend_read(struct BlendDataReader *reader, struct CustomData *data, int count); void CustomData_blend_read(struct BlendDataReader *reader, struct CustomData *data, int count);
size_t CustomData_get_elem_size(struct CustomDataLayer *layer); size_t CustomData_get_elem_size(const struct CustomDataLayer *layer);
#ifndef NDEBUG #ifndef NDEBUG
struct DynStr; struct DynStr;

View File

@ -36,10 +36,10 @@ struct PropertyRNA;
/* Data Management */ /* Data Management */
/** /**
* Remove the given NLA strip from the NLA track it occupies, free the strip's data, * Frees the given NLA strip, and calls #BKE_nlastrip_remove_and_free to
* and the strip itself. * remove and free all children strips.
*/ */
void BKE_nlastrip_free(ListBase *strips, struct NlaStrip *strip, bool do_id_user); void BKE_nlastrip_free(struct NlaStrip *strip, bool do_id_user);
/** /**
* Remove the given NLA track from the set of NLA tracks, free the track's data, * Remove the given NLA track from the set of NLA tracks, free the track's data,
* and the track itself. * and the track itself.
@ -94,10 +94,22 @@ void BKE_nla_tracks_copy_from_adt(struct Main *bmain,
struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt, struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt,
struct NlaTrack *prev, struct NlaTrack *prev,
bool is_liboverride); bool is_liboverride);
/** /**
* Create a NLA Strip referencing the given Action. * Create a NLA Strip referencing the given Action.
*/ */
struct NlaStrip *BKE_nlastrip_new(struct bAction *act); struct NlaStrip *BKE_nlastrip_new(struct bAction *act);
/*
* Removes the given NLA strip from the list of strips provided.
*/
void BKE_nlastrip_remove(ListBase *strips, struct NlaStrip *strip);
/*
* Removes the given NLA strip from the list of strips provided, and frees it's memory.
*/
void BKE_nlastrip_remove_and_free(ListBase *strips, struct NlaStrip *strip, const bool do_id_user);
/** /**
* Add new NLA-strip to the top of the NLA stack - i.e. * Add new NLA-strip to the top of the NLA stack - i.e.
* into the last track if space, or a new one otherwise. * into the last track if space, or a new one otherwise.
@ -139,13 +151,9 @@ void BKE_nlastrips_sort_strips(ListBase *strips);
void BKE_nlastrips_add_strip_unsafe(ListBase *strips, struct NlaStrip *strip); void BKE_nlastrips_add_strip_unsafe(ListBase *strips, struct NlaStrip *strip);
/** /**
* \brief NULL checks incoming strip and verifies no overlap / invalid * NULL checks incoming strip and verifies no overlap / invalid
* configuration against other strips in NLA Track. * configuration against other strips in NLA Track before calling
* * #BKE_nlastrips_add_strip_unsafe.
* \param strips:
* \param strip:
* \return true
* \return false
*/ */
bool BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip); bool BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip);
@ -215,11 +223,16 @@ bool BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end);
void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
/** /**
* Add the given NLA-Strip to the given NLA-Track, assuming that it * Add the given NLA-Strip to the given NLA-Track.
* isn't currently attached to another one. * Calls #BKE_nlastrips_add_strip to check if strip can be added.
*/ */
bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip, bool is_liboverride); bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip, bool is_liboverride);
/**
* Remove the NLA-Strip from the given NLA-Track.
*/
void BKE_nlatrack_remove_strip(struct NlaTrack *track, struct NlaStrip *strip);
/** /**
* Get the extents of the given NLA-Track including gaps between strips, * Get the extents of the given NLA-Track including gaps between strips,
* returning whether this succeeded or not * returning whether this succeeded or not

View File

@ -249,8 +249,8 @@ set(SRC
intern/particle_distribute.c intern/particle_distribute.c
intern/particle_system.c intern/particle_system.c
intern/pbvh.cc intern/pbvh.cc
intern/pbvh_colors.cc
intern/pbvh_bmesh.cc intern/pbvh_bmesh.cc
intern/pbvh_colors.cc
intern/pbvh_pixels.cc intern/pbvh_pixels.cc
intern/pbvh_uv_islands.cc intern/pbvh_uv_islands.cc
intern/pointcache.c intern/pointcache.c

View File

@ -3654,7 +3654,7 @@ void CustomData_bmesh_free_block_data(CustomData *data, void *block)
} }
} }
static void CustomData_bmesh_alloc_block(CustomData *data, void **block) void CustomData_bmesh_alloc_block(CustomData *data, void **block)
{ {
if (*block) { if (*block) {
CustomData_bmesh_free_block(data, block); CustomData_bmesh_free_block(data, block);
@ -3689,19 +3689,23 @@ void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data,
} }
} }
static void CustomData_bmesh_set_default_n(CustomData *data, void **block, const int n) void CustomData_data_set_default_value(const int type, void *elem)
{ {
int offset = data->layers[n].offset; const LayerTypeInfo *typeInfo = layerType_getInfo(type);
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
if (typeInfo->set_default_value) { if (typeInfo->set_default_value) {
typeInfo->set_default_value(POINTER_OFFSET(*block, offset), 1); typeInfo->set_default_value(elem, 1);
} }
else { else {
memset(POINTER_OFFSET(*block, offset), 0, typeInfo->size); memset(elem, 0, typeInfo->size);
} }
} }
static void CustomData_bmesh_set_default_n(CustomData *data, void **block, const int n)
{
const int offset = data->layers[n].offset;
CustomData_data_set_default_value(data->layers[n].type, POINTER_OFFSET(*block, offset));
}
void CustomData_bmesh_set_default(CustomData *data, void **block) void CustomData_bmesh_set_default(CustomData *data, void **block)
{ {
if (*block == nullptr) { if (*block == nullptr) {
@ -3891,8 +3895,8 @@ void CustomData_data_copy_value(int type, const void *source, void *dest)
return; return;
} }
if (typeInfo->copyvalue) { if (typeInfo->copy) {
typeInfo->copyvalue(source, dest, CDT_MIX_NOMIX, 0.0f); typeInfo->copy(source, dest, 1);
} }
else { else {
memcpy(dest, source, typeInfo->size); memcpy(dest, source, typeInfo->size);
@ -4067,115 +4071,6 @@ void CustomData_bmesh_interp(CustomData *data,
} }
} }
void CustomData_to_bmesh_block(const CustomData *source,
CustomData *dest,
int src_index,
void **dest_block,
bool use_default_init)
{
if (*dest_block == nullptr) {
CustomData_bmesh_alloc_block(dest, dest_block);
}
/* copies a layer at a time */
int dest_i = 0;
for (int src_i = 0; src_i < source->totlayer; src_i++) {
/* find the first dest layer with type >= the source type
* (this should work because layers are ordered by type)
*/
while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
if (use_default_init) {
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
}
dest_i++;
}
/* if there are no more dest layers, we're done */
if (dest_i >= dest->totlayer) {
break;
}
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type) {
int offset = dest->layers[dest_i].offset;
const void *src_data = source->layers[src_i].data;
void *dest_data = POINTER_OFFSET(*dest_block, offset);
const LayerTypeInfo *typeInfo = layerType_getInfo(dest->layers[dest_i].type);
const size_t src_offset = size_t(src_index) * typeInfo->size;
if (typeInfo->copy) {
typeInfo->copy(POINTER_OFFSET(src_data, src_offset), dest_data, 1);
}
else {
memcpy(dest_data, POINTER_OFFSET(src_data, src_offset), typeInfo->size);
}
/* if there are multiple source & dest layers of the same type,
* we don't want to copy all source layers to the same dest, so
* increment dest_i
*/
dest_i++;
}
}
if (use_default_init) {
while (dest_i < dest->totlayer) {
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
dest_i++;
}
}
}
void CustomData_from_bmesh_block(const CustomData *source,
CustomData *dest,
void *src_block,
int dest_index)
{
/* copies a layer at a time */
int dest_i = 0;
for (int src_i = 0; src_i < source->totlayer; src_i++) {
if (source->layers[src_i].flag & CD_FLAG_NOCOPY) {
continue;
}
/* find the first dest layer with type >= the source type
* (this should work because layers are ordered by type)
*/
while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
dest_i++;
}
/* if there are no more dest layers, we're done */
if (dest_i >= dest->totlayer) {
return;
}
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type) {
const LayerTypeInfo *typeInfo = layerType_getInfo(dest->layers[dest_i].type);
int offset = source->layers[src_i].offset;
const void *src_data = POINTER_OFFSET(src_block, offset);
void *dst_data = POINTER_OFFSET(dest->layers[dest_i].data,
size_t(dest_index) * typeInfo->size);
if (typeInfo->copy) {
typeInfo->copy(src_data, dst_data, 1);
}
else {
memcpy(dst_data, src_data, typeInfo->size);
}
/* if there are multiple source & dest layers of the same type,
* we don't want to copy all source layers to the same dest, so
* increment dest_i
*/
dest_i++;
}
}
}
void CustomData_file_write_info(int type, const char **r_struct_name, int *r_struct_num) void CustomData_file_write_info(int type, const char **r_struct_name, int *r_struct_num)
{ {
const LayerTypeInfo *typeInfo = layerType_getInfo(type); const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@ -5308,7 +5203,7 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
} // namespace blender::bke } // namespace blender::bke
size_t CustomData_get_elem_size(CustomDataLayer *layer) size_t CustomData_get_elem_size(const CustomDataLayer *layer)
{ {
return LAYERTYPEINFO[layer->type].size; return LAYERTYPEINFO[layer->type].size;
} }

View File

@ -61,7 +61,7 @@ static void nla_tweakmode_find_active(const ListBase /* NlaTrack */ *nla_tracks,
/* Freeing ------------------------------------------- */ /* Freeing ------------------------------------------- */
void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user) void BKE_nlastrip_free(NlaStrip *strip, const bool do_id_user)
{ {
NlaStrip *cs, *csn; NlaStrip *cs, *csn;
@ -73,7 +73,7 @@ void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user)
/* free child-strips */ /* free child-strips */
for (cs = strip->strips.first; cs; cs = csn) { for (cs = strip->strips.first; cs; cs = csn) {
csn = cs->next; csn = cs->next;
BKE_nlastrip_free(&strip->strips, cs, do_id_user); BKE_nlastrip_remove_and_free(&strip->strips, cs, do_id_user);
} }
/* remove reference to action */ /* remove reference to action */
@ -81,10 +81,6 @@ void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user)
id_us_min(&strip->act->id); id_us_min(&strip->act->id);
} }
/* free remapping info */
// if (strip->remap)
// BKE_animremap_free();
/* free own F-Curves */ /* free own F-Curves */
BKE_fcurves_free(&strip->fcurves); BKE_fcurves_free(&strip->fcurves);
@ -92,12 +88,7 @@ void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user)
free_fmodifiers(&strip->modifiers); free_fmodifiers(&strip->modifiers);
/* free the strip itself */ /* free the strip itself */
if (strips) { MEM_freeN(strip);
BLI_freelinkN(strips, strip);
}
else {
MEM_freeN(strip);
}
} }
void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt, bool do_id_user) void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt, bool do_id_user)
@ -112,7 +103,7 @@ void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt, bool do_id_user)
/* free strips */ /* free strips */
for (strip = nlt->strips.first; strip; strip = stripn) { for (strip = nlt->strips.first; strip; strip = stripn) {
stripn = strip->next; stripn = strip->next;
BKE_nlastrip_free(&nlt->strips, strip, do_id_user); BKE_nlastrip_remove_and_free(&nlt->strips, strip, do_id_user);
} }
/* free NLA track itself now */ /* free NLA track itself now */
@ -875,7 +866,7 @@ void BKE_nlastrips_clear_metastrip(ListBase *strips, NlaStrip *strip)
} }
/* free the meta-strip now */ /* free the meta-strip now */
BKE_nlastrip_free(strips, strip, true); BKE_nlastrip_remove_and_free(strips, strip, true);
} }
void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp) void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp)
@ -1190,6 +1181,12 @@ bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip, const bool is_libove
return BKE_nlastrips_add_strip(&nlt->strips, strip); return BKE_nlastrips_add_strip(&nlt->strips, strip);
} }
void BKE_nlatrack_remove_strip(NlaTrack *track, NlaStrip *strip)
{
BLI_assert(track);
BKE_nlastrip_remove(&track->strips, strip);
}
bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2]) bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2])
{ {
NlaStrip *strip; NlaStrip *strip;
@ -1318,6 +1315,18 @@ NlaStrip *BKE_nlastrip_find_active(NlaTrack *nlt)
return nlastrip_find_active(&nlt->strips); return nlastrip_find_active(&nlt->strips);
} }
void BKE_nlastrip_remove(ListBase *strips, NlaStrip *strip)
{
BLI_assert(strips);
BLI_remlink(strips, strip);
}
void BKE_nlastrip_remove_and_free(ListBase *strips, NlaStrip *strip, const bool do_id_user)
{
BKE_nlastrip_remove(strips, strip);
BKE_nlastrip_free(strip, do_id_user);
}
void BKE_nlastrip_set_active(AnimData *adt, NlaStrip *strip) void BKE_nlastrip_set_active(AnimData *adt, NlaStrip *strip)
{ {
NlaTrack *nlt; NlaTrack *nlt;

View File

@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-or-later /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. All rights reserved. */ * Copyright 2023 Blender Foundation. All rights reserved. */
#include "BLI_listbase.h"
#include "BKE_nla.h" #include "BKE_nla.h"
#include "DNA_anim_types.h" #include "DNA_anim_types.h"
@ -20,19 +22,19 @@ TEST(nla_strip, BKE_nlastrip_recalculate_blend)
strip.start = 1; strip.start = 1;
strip.end = 10; strip.end = 10;
/* Scaling a strip up doesn't affect the blend in/out value */ /* Scaling a strip up doesn't affect the blend in/out value. */
strip.end = 20; strip.end = 20;
BKE_nlastrip_recalculate_blend(&strip); BKE_nlastrip_recalculate_blend(&strip);
EXPECT_FLOAT_EQ(strip.blendin, 4.0); EXPECT_FLOAT_EQ(strip.blendin, 4.0);
EXPECT_FLOAT_EQ(strip.blendout, 5.0); EXPECT_FLOAT_EQ(strip.blendout, 5.0);
/* Scaling a strip down affects the blend-in value before the blend-out value */ /* Scaling a strip down affects the blend-in value before the blend-out value. */
strip.end = 7; strip.end = 7;
BKE_nlastrip_recalculate_blend(&strip); BKE_nlastrip_recalculate_blend(&strip);
EXPECT_FLOAT_EQ(strip.blendin, 1.0); EXPECT_FLOAT_EQ(strip.blendin, 1.0);
EXPECT_FLOAT_EQ(strip.blendout, 5.0); EXPECT_FLOAT_EQ(strip.blendout, 5.0);
/* Scaling a strip down to nothing updates the blend in/out values accordingly */ /* Scaling a strip down to nothing updates the blend in/out values accordingly. */
strip.end = 1.1; strip.end = 1.1;
BKE_nlastrip_recalculate_blend(&strip); BKE_nlastrip_recalculate_blend(&strip);
EXPECT_FLOAT_EQ(strip.blendin, 0.0); EXPECT_FLOAT_EQ(strip.blendin, 0.0);
@ -63,4 +65,30 @@ TEST(nla_strip, BKE_nlastrips_add_strip)
EXPECT_TRUE(BKE_nlastrips_add_strip(&strips, &strip2)); EXPECT_TRUE(BKE_nlastrips_add_strip(&strips, &strip2));
} }
TEST(nla_track, BKE_nlatrack_remove_strip)
{
NlaTrack track{};
ListBase strips{};
NlaStrip strip1{};
strip1.start = 0;
strip1.end = 10;
NlaStrip strip2{};
strip2.start = 11;
strip2.end = 20;
// Add NLA strips to the NLATrack.
BKE_nlastrips_add_strip(&strips, &strip1);
BKE_nlastrips_add_strip(&strips, &strip2);
track.strips = strips;
// ensure we have 2 strips in the track.
EXPECT_EQ(2, BLI_listbase_count(&track.strips));
BKE_nlatrack_remove_strip(&track, &strip2);
EXPECT_EQ(1, BLI_listbase_count(&track.strips));
// ensure the correct strip was removed.
EXPECT_EQ(-1, BLI_findindex(&track.strips, &strip2));
}
} // namespace blender::bke::tests } // namespace blender::bke::tests

View File

@ -265,7 +265,7 @@ static DupliObject *make_dupli(const DupliContext *ctx,
/* Store geometry set data for attribute lookup in innermost to outermost /* Store geometry set data for attribute lookup in innermost to outermost
* order, copying only non-null entries to save space. */ * order, copying only non-null entries to save space. */
const int max_instance = sizeof(dob->instance_data) / sizeof(void *); const int max_instance = ARRAY_SIZE(dob->instance_data);
int next_instance = 0; int next_instance = 0;
if (geometry != nullptr) { if (geometry != nullptr) {
dob->instance_idx[next_instance] = int(instance_index); dob->instance_idx[next_instance] = int(instance_index);
@ -1821,7 +1821,7 @@ static bool find_geonode_attribute_rgba(const DupliObject *dupli,
using namespace blender; using namespace blender;
/* Loop over layers from innermost to outermost. */ /* Loop over layers from innermost to outermost. */
for (const int i : IndexRange(sizeof(dupli->instance_data) / sizeof(void *))) { for (const int i : IndexRange(ARRAY_SIZE(dupli->instance_data))) {
/* Skip non-geonode layers. */ /* Skip non-geonode layers. */
if (dupli->instance_data[i] == nullptr) { if (dupli->instance_data[i] == nullptr) {
continue; continue;

View File

@ -1704,7 +1704,7 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Object *ob, RigidBodyO
} }
} }
/* Make transformed objects temporarily kinmatic /* Make transformed objects temporarily kinematic
* so that they can be moved by the user during simulation. */ * so that they can be moved by the user during simulation. */
if (is_selected && (G.moving & G_TRANSFORM_OBJ)) { if (is_selected && (G.moving & G_TRANSFORM_OBJ)) {
RB_body_set_kinematic_state(rbo->shared->physics_object, true); RB_body_set_kinematic_state(rbo->shared->physics_object, true);

View File

@ -352,7 +352,7 @@ struct StaticOrHeapIntStorage {
static void static_or_heap_storage_init(StaticOrHeapIntStorage *storage) static void static_or_heap_storage_init(StaticOrHeapIntStorage *storage)
{ {
storage->static_storage_len = sizeof(storage->static_storage) / sizeof(*storage->static_storage); storage->static_storage_len = ARRAY_SIZE(storage->static_storage);
storage->heap_storage = nullptr; storage->heap_storage = nullptr;
storage->heap_storage_len = 0; storage->heap_storage_len = 0;
} }

View File

@ -538,13 +538,14 @@ void tracking_cameraIntrinscisOptionsFromTracking(
void tracking_trackingCameraFromIntrinscisOptions( void tracking_trackingCameraFromIntrinscisOptions(
MovieTracking *tracking, const libmv_CameraIntrinsicsOptions *camera_intrinsics_options) MovieTracking *tracking, const libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
{ {
float aspy = 1.0f / tracking->camera.pixel_aspect;
MovieTrackingCamera *camera = &tracking->camera; MovieTrackingCamera *camera = &tracking->camera;
camera->focal = camera_intrinsics_options->focal_length; camera->focal = camera_intrinsics_options->focal_length;
/* NOTE: The image size stored in the `camera_intrinsics_options` is aspect-ratio corrected,
* so there is no need to "un-apply" it from the principal point. */
const float principal_px[2] = {camera_intrinsics_options->principal_point_x, const float principal_px[2] = {camera_intrinsics_options->principal_point_x,
camera_intrinsics_options->principal_point_y / (double)aspy}; camera_intrinsics_options->principal_point_y};
tracking_principal_point_pixel_to_normalized(principal_px, tracking_principal_point_pixel_to_normalized(principal_px,
camera_intrinsics_options->image_width, camera_intrinsics_options->image_width,

View File

@ -97,8 +97,9 @@ MINLINE float saacos(float fac);
MINLINE float saasin(float fac); MINLINE float saasin(float fac);
MINLINE float sasqrt(float fac); MINLINE float sasqrt(float fac);
MINLINE float interpf(float a, float b, float t); /* Compute linear interpolation (lerp) between origin and target. */
MINLINE double interpd(double a, double b, double t); MINLINE float interpf(float target, float origin, float t);
MINLINE double interpd(double target, double origin, double t);
MINLINE float ratiof(float min, float max, float pos); MINLINE float ratiof(float min, float max, float pos);
MINLINE double ratiod(double min, double max, double pos); MINLINE double ratiod(double min, double max, double pos);

View File

@ -806,6 +806,10 @@ extern bool BLI_memory_is_zero(const void *arr, size_t arr_size);
{ \ { \
return a = (_enum_type)(uint64_t(a) & uint64_t(b)); \ return a = (_enum_type)(uint64_t(a) & uint64_t(b)); \
} \ } \
inline _enum_type &operator^=(_enum_type &a, _enum_type b) \
{ \
return a = (_enum_type)(uint64_t(a) ^ uint64_t(b)); \
} \
} /* extern "C++" */ } /* extern "C++" */
#else #else

View File

@ -281,10 +281,10 @@ set(SRC
BLI_math_solvers.h BLI_math_solvers.h
BLI_math_statistics.h BLI_math_statistics.h
BLI_math_time.h BLI_math_time.h
BLI_math_vector_mpq_types.hh
BLI_math_vector_types.hh
BLI_math_vector.h BLI_math_vector.h
BLI_math_vector.hh BLI_math_vector.hh
BLI_math_vector_mpq_types.hh
BLI_math_vector_types.hh
BLI_memarena.h BLI_memarena.h
BLI_memblock.h BLI_memblock.h
BLI_memiter.h BLI_memiter.h
@ -490,13 +490,13 @@ if(WITH_GTESTS)
tests/BLI_math_bits_test.cc tests/BLI_math_bits_test.cc
tests/BLI_math_color_test.cc tests/BLI_math_color_test.cc
tests/BLI_math_geom_test.cc tests/BLI_math_geom_test.cc
tests/BLI_math_matrix_types_test.cc
tests/BLI_math_matrix_test.cc tests/BLI_math_matrix_test.cc
tests/BLI_math_matrix_types_test.cc
tests/BLI_math_rotation_test.cc tests/BLI_math_rotation_test.cc
tests/BLI_math_solvers_test.cc tests/BLI_math_solvers_test.cc
tests/BLI_math_time_test.cc tests/BLI_math_time_test.cc
tests/BLI_math_vector_types_test.cc
tests/BLI_math_vector_test.cc tests/BLI_math_vector_test.cc
tests/BLI_math_vector_types_test.cc
tests/BLI_memiter_test.cc tests/BLI_memiter_test.cc
tests/BLI_memory_utils_test.cc tests/BLI_memory_utils_test.cc
tests/BLI_mesh_boolean_test.cc tests/BLI_mesh_boolean_test.cc

View File

@ -85,6 +85,7 @@
#include "BLI_span.hh" #include "BLI_span.hh"
#include "BLI_string_ref.hh" #include "BLI_string_ref.hh"
#include "BLI_task.hh" #include "BLI_task.hh"
#include "BLI_vector.hh"
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_customdata.h" #include "BKE_customdata.h"
@ -110,6 +111,7 @@ using blender::IndexRange;
using blender::MutableSpan; using blender::MutableSpan;
using blender::Span; using blender::Span;
using blender::StringRef; using blender::StringRef;
using blender::Vector;
static char bm_edge_flag_from_mflag(const short mflag) static char bm_edge_flag_from_mflag(const short mflag)
{ {
@ -164,6 +166,63 @@ static BMFace *bm_face_create_from_mpoly(BMesh &bm,
return BM_face_create(&bm, verts.data(), edges.data(), loops.size(), nullptr, BM_CREATE_SKIP_CD); return BM_face_create(&bm, verts.data(), edges.data(), loops.size(), nullptr, BM_CREATE_SKIP_CD);
} }
struct MeshToBMeshLayerInfo {
eCustomDataType type;
/** The layer's position in the BMesh element's data block. */
int bmesh_offset;
/** The mesh's #CustomDataLayer::data. When null, the BMesh block is set to its default value. */
const void *mesh_data;
/** The size of every custom data element. */
size_t elem_size;
};
/**
* Calculate the necessary information to copy every data layer from the Mesh to the BMesh.
*/
static Vector<MeshToBMeshLayerInfo> mesh_to_bm_copy_info_calc(const CustomData &mesh_data,
CustomData &bm_data)
{
Vector<MeshToBMeshLayerInfo> infos;
std::array<int, CD_NUMTYPES> per_type_index;
per_type_index.fill(0);
for (const int i : IndexRange(bm_data.totlayer)) {
const CustomDataLayer &bm_layer = bm_data.layers[i];
const eCustomDataType type = eCustomDataType(bm_layer.type);
const int mesh_layer_index =
bm_layer.name[0] == '\0' ?
CustomData_get_layer_index_n(&mesh_data, type, per_type_index[type]) :
CustomData_get_named_layer_index(&mesh_data, type, bm_layer.name);
MeshToBMeshLayerInfo info{};
info.type = type;
info.bmesh_offset = bm_layer.offset;
info.mesh_data = (mesh_layer_index == -1) ? nullptr : mesh_data.layers[mesh_layer_index].data;
info.elem_size = CustomData_get_elem_size(&bm_layer);
infos.append(info);
per_type_index[type]++;
}
return infos;
}
static void mesh_attributes_copy_to_bmesh_block(CustomData &data,
const Span<MeshToBMeshLayerInfo> copy_info,
const int mesh_index,
BMHeader &header)
{
CustomData_bmesh_alloc_block(&data, &header.data);
for (const MeshToBMeshLayerInfo &info : copy_info) {
if (info.mesh_data) {
CustomData_data_copy_value(info.type,
POINTER_OFFSET(info.mesh_data, info.elem_size * mesh_index),
POINTER_OFFSET(header.data, info.bmesh_offset));
}
else {
CustomData_data_set_default_value(info.type, POINTER_OFFSET(header.data, info.bmesh_offset));
}
}
}
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params) void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
{ {
if (!me) { if (!me) {
@ -259,6 +318,11 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
CustomData_bmesh_merge(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, bm, BM_LOOP); CustomData_bmesh_merge(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, bm, BM_LOOP);
} }
const Vector<MeshToBMeshLayerInfo> vert_info = mesh_to_bm_copy_info_calc(mesh_vdata, bm->vdata);
const Vector<MeshToBMeshLayerInfo> edge_info = mesh_to_bm_copy_info_calc(mesh_edata, bm->edata);
const Vector<MeshToBMeshLayerInfo> poly_info = mesh_to_bm_copy_info_calc(mesh_pdata, bm->pdata);
const Vector<MeshToBMeshLayerInfo> loop_info = mesh_to_bm_copy_info_calc(mesh_ldata, bm->ldata);
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Shape Key */ /* Shape Key */
int tot_shape_keys = 0; int tot_shape_keys = 0;
@ -393,8 +457,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
copy_v3_v3(v->no, vert_normals[i]); copy_v3_v3(v->no, vert_normals[i]);
} }
/* Copy Custom Data */ mesh_attributes_copy_to_bmesh_block(bm->vdata, vert_info, i, v->head);
CustomData_to_bmesh_block(&mesh_vdata, &bm->vdata, i, &v->head.data, true);
/* Set shape key original index. */ /* Set shape key original index. */
if (cd_shape_keyindex_offset != -1) { if (cd_shape_keyindex_offset != -1) {
@ -432,8 +495,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
BM_elem_flag_enable(e, BM_ELEM_SMOOTH); BM_elem_flag_enable(e, BM_ELEM_SMOOTH);
} }
/* Copy Custom Data */ mesh_attributes_copy_to_bmesh_block(bm->edata, edge_info, i, e->head);
CustomData_to_bmesh_block(&mesh_edata, &bm->edata, i, &e->head.data, true);
} }
if (is_new) { if (is_new) {
bm->elem_index_dirty &= ~BM_EDGE; /* Added in order, clear dirty flag. */ bm->elem_index_dirty &= ~BM_EDGE; /* Added in order, clear dirty flag. */
@ -491,12 +553,11 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
/* Don't use 'j' since we may have skipped some faces, hence some loops. */ /* Don't use 'j' since we may have skipped some faces, hence some loops. */
BM_elem_index_set(l_iter, totloops++); /* set_ok */ BM_elem_index_set(l_iter, totloops++); /* set_ok */
/* Save index of corresponding #MLoop. */ mesh_attributes_copy_to_bmesh_block(bm->ldata, loop_info, j, l_iter->head);
CustomData_to_bmesh_block(&mesh_ldata, &bm->ldata, j++, &l_iter->head.data, true); j++;
} while ((l_iter = l_iter->next) != l_first); } while ((l_iter = l_iter->next) != l_first);
/* Copy Custom Data */ mesh_attributes_copy_to_bmesh_block(bm->pdata, poly_info, i, f->head);
CustomData_to_bmesh_block(&mesh_pdata, &bm->pdata, i, &f->head.data, true);
if (params->calc_face_normal) { if (params->calc_face_normal) {
BM_face_normal_update(f); BM_face_normal_update(f);
@ -998,6 +1059,66 @@ static void convert_bmesh_selection_flags_to_mesh_attributes(BMesh &bm,
} }
} }
struct BMeshToMeshLayerInfo {
eCustomDataType type;
/** The layer's position in the BMesh element's data block. */
int bmesh_offset;
/** The mesh's #CustomDataLayer::data. When null, the BMesh block is set to its default value. */
void *mesh_data;
/** The size of every custom data element. */
size_t elem_size;
};
/**
* Calculate the necessary information to copy every data layer from the BMesh to the Mesh.
*/
static Vector<BMeshToMeshLayerInfo> bm_to_mesh_copy_info_calc(const CustomData &bm_data,
CustomData &mesh_data)
{
Vector<BMeshToMeshLayerInfo> infos;
std::array<int, CD_NUMTYPES> per_type_index;
per_type_index.fill(0);
for (const int i : IndexRange(mesh_data.totlayer)) {
const CustomDataLayer &mesh_layer = mesh_data.layers[i];
const eCustomDataType type = eCustomDataType(mesh_layer.type);
const int bm_layer_index =
mesh_layer.name[0] == '\0' ?
CustomData_get_layer_index_n(&bm_data, type, per_type_index[type]) :
CustomData_get_named_layer_index(&bm_data, type, mesh_layer.name);
/* Skip layers that don't exist in `bm_data` or are explicitly set to not be
* copied. The layers are either set separately or shouldn't exist on the mesh. */
if (bm_layer_index == -1) {
continue;
}
const CustomDataLayer &bm_layer = bm_data.layers[bm_layer_index];
if (bm_layer.flag & CD_FLAG_NOCOPY) {
continue;
}
BMeshToMeshLayerInfo info{};
info.type = type;
info.bmesh_offset = bm_layer.offset;
info.mesh_data = mesh_layer.data;
info.elem_size = CustomData_get_elem_size(&mesh_layer);
infos.append(info);
per_type_index[type]++;
}
return infos;
}
static void bmesh_block_copy_to_mesh_attributes(const Span<BMeshToMeshLayerInfo> copy_info,
const int mesh_index,
const void *block)
{
for (const BMeshToMeshLayerInfo &info : copy_info) {
CustomData_data_copy_value(info.type,
POINTER_OFFSET(block, info.bmesh_offset),
POINTER_OFFSET(info.mesh_data, info.elem_size * mesh_index));
}
}
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params) void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
{ {
using namespace blender; using namespace blender;
@ -1011,6 +1132,8 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
const int ototvert = me->totvert; const int ototvert = me->totvert;
blender::Vector<int> ldata_layers_marked_nocopy;
/* Free custom data. */ /* Free custom data. */
CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge); CustomData_free(&me->edata, me->totedge);
@ -1041,9 +1164,17 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_edge_select_name_get(layer_name, sub_layer_name)); &bm->ldata, CD_PROP_BOOL, BKE_uv_map_edge_select_name_get(layer_name, sub_layer_name));
int pin_layer_index = CustomData_get_named_layer_index( int pin_layer_index = CustomData_get_named_layer_index(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(layer_name, sub_layer_name)); &bm->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(layer_name, sub_layer_name));
int vertsel_offset = bm->ldata.layers[vertsel_layer_index].offset;
int edgesel_offset = bm->ldata.layers[edgesel_layer_index].offset; /* If ever the uv map associated bool layers become optional in BMesh as well (like in Mesh)
int pin_offset = bm->ldata.layers[pin_layer_index].offset; * this assert needs to be removed. For now it is a bug if they don't exist. */
BLI_assert(vertsel_layer_index >= 0 && edgesel_layer_index >= 0 && pin_layer_index >= 0);
int vertsel_offset = vertsel_layer_index >= 0 ? bm->ldata.layers[vertsel_layer_index].offset :
-1;
int edgesel_offset = edgesel_layer_index >= 0 ? bm->ldata.layers[edgesel_layer_index].offset :
-1;
int pin_offset = pin_layer_index >= 0 ? bm->ldata.layers[pin_layer_index].offset : -1;
bool need_vertsel = false; bool need_vertsel = false;
bool need_edgesel = false; bool need_edgesel = false;
bool need_pin = false; bool need_pin = false;
@ -1051,10 +1182,20 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BMIter liter; BMIter liter;
BMLoop *l; BMLoop *l;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { if (vertsel_layer_index >= 0) {
need_vertsel |= BM_ELEM_CD_GET_BOOL(l, vertsel_offset); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
need_edgesel |= BM_ELEM_CD_GET_BOOL(l, edgesel_offset); need_vertsel |= BM_ELEM_CD_GET_BOOL(l, vertsel_offset);
need_pin |= BM_ELEM_CD_GET_BOOL(l, pin_offset); }
}
if (edgesel_layer_index >= 0) {
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
need_edgesel |= BM_ELEM_CD_GET_BOOL(l, edgesel_offset);
}
}
if (pin_layer_index) {
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
need_pin |= BM_ELEM_CD_GET_BOOL(l, pin_offset);
}
} }
} }
@ -1063,18 +1204,21 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
} }
else { else {
bm->ldata.layers[vertsel_layer_index].flag |= CD_FLAG_NOCOPY; bm->ldata.layers[vertsel_layer_index].flag |= CD_FLAG_NOCOPY;
ldata_layers_marked_nocopy.append(vertsel_layer_index);
} }
if (need_edgesel) { if (need_edgesel) {
bm->ldata.layers[edgesel_layer_index].flag &= ~CD_FLAG_NOCOPY; bm->ldata.layers[edgesel_layer_index].flag &= ~CD_FLAG_NOCOPY;
} }
else { else {
bm->ldata.layers[edgesel_layer_index].flag |= CD_FLAG_NOCOPY; bm->ldata.layers[edgesel_layer_index].flag |= CD_FLAG_NOCOPY;
ldata_layers_marked_nocopy.append(edgesel_layer_index);
} }
if (need_pin) { if (need_pin) {
bm->ldata.layers[pin_layer_index].flag &= ~CD_FLAG_NOCOPY; bm->ldata.layers[pin_layer_index].flag &= ~CD_FLAG_NOCOPY;
} }
else { else {
bm->ldata.layers[pin_layer_index].flag |= CD_FLAG_NOCOPY; bm->ldata.layers[pin_layer_index].flag |= CD_FLAG_NOCOPY;
ldata_layers_marked_nocopy.append(pin_layer_index);
} }
} }
@ -1087,6 +1231,16 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_SET_DEFAULT, me->totpoly); CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_SET_DEFAULT, me->totpoly);
} }
const Vector<BMeshToMeshLayerInfo> vert_info = bm_to_mesh_copy_info_calc(bm->vdata, me->vdata);
const Vector<BMeshToMeshLayerInfo> edge_info = bm_to_mesh_copy_info_calc(bm->edata, me->edata);
const Vector<BMeshToMeshLayerInfo> poly_info = bm_to_mesh_copy_info_calc(bm->pdata, me->pdata);
const Vector<BMeshToMeshLayerInfo> loop_info = bm_to_mesh_copy_info_calc(bm->ldata, me->ldata);
/* Clear the CD_FLAG_NOCOPY flags for the layers they were temporarily set on */
for (const int i : ldata_layers_marked_nocopy) {
bm->ldata.layers[i].flag &= ~CD_FLAG_NOCOPY;
}
CustomData_add_layer_named( CustomData_add_layer_named(
&me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, me->totvert, "position"); &me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, me->totvert, "position");
CustomData_add_layer(&me->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, me->totedge); CustomData_add_layer(&me->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, me->totedge);
@ -1119,8 +1273,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
BM_elem_index_set(v, i); /* set_inline */ BM_elem_index_set(v, i); /* set_inline */
/* Copy over custom-data. */ bmesh_block_copy_to_mesh_attributes(vert_info, i, v->head.data);
CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i);
i++; i++;
@ -1146,8 +1299,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
BM_elem_index_set(e, i); /* set_inline */ BM_elem_index_set(e, i); /* set_inline */
/* Copy over custom-data. */ bmesh_block_copy_to_mesh_attributes(edge_info, i, e->head.data);
CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i);
i++; i++;
BM_CHECK_ELEMENT(e); BM_CHECK_ELEMENT(e);
@ -1176,8 +1328,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
mloop[j].e = BM_elem_index_get(l_iter->e); mloop[j].e = BM_elem_index_get(l_iter->e);
mloop[j].v = BM_elem_index_get(l_iter->v); mloop[j].v = BM_elem_index_get(l_iter->v);
/* Copy over custom-data. */ bmesh_block_copy_to_mesh_attributes(loop_info, j, l_iter->head.data);
CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j);
j++; j++;
BM_CHECK_ELEMENT(l_iter); BM_CHECK_ELEMENT(l_iter);
@ -1189,8 +1340,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
me->act_face = i; me->act_face = i;
} }
/* Copy over custom-data. */ bmesh_block_copy_to_mesh_attributes(poly_info, i, f->head.data);
CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i);
i++; i++;
BM_CHECK_ELEMENT(f); BM_CHECK_ELEMENT(f);
@ -1399,12 +1549,13 @@ static void bm_to_mesh_verts(const BMesh &bm,
MutableSpan<bool> select_vert, MutableSpan<bool> select_vert,
MutableSpan<bool> hide_vert) MutableSpan<bool> hide_vert)
{ {
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.vdata, mesh.vdata);
MutableSpan<float3> dst_vert_positions = mesh.vert_positions_for_write(); MutableSpan<float3> dst_vert_positions = mesh.vert_positions_for_write();
threading::parallel_for(dst_vert_positions.index_range(), 1024, [&](const IndexRange range) { threading::parallel_for(dst_vert_positions.index_range(), 1024, [&](const IndexRange range) {
for (const int vert_i : range) { for (const int vert_i : range) {
const BMVert &src_vert = *bm_verts[vert_i]; const BMVert &src_vert = *bm_verts[vert_i];
copy_v3_v3(dst_vert_positions[vert_i], src_vert.co); copy_v3_v3(dst_vert_positions[vert_i], src_vert.co);
CustomData_from_bmesh_block(&bm.vdata, &mesh.vdata, src_vert.head.data, vert_i); bmesh_block_copy_to_mesh_attributes(info, vert_i, src_vert.head.data);
} }
if (!select_vert.is_empty()) { if (!select_vert.is_empty()) {
for (const int vert_i : range) { for (const int vert_i : range) {
@ -1426,6 +1577,7 @@ static void bm_to_mesh_edges(const BMesh &bm,
MutableSpan<bool> hide_edge, MutableSpan<bool> hide_edge,
MutableSpan<bool> sharp_edge) MutableSpan<bool> sharp_edge)
{ {
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.edata, mesh.edata);
MutableSpan<MEdge> dst_edges = mesh.edges_for_write(); MutableSpan<MEdge> dst_edges = mesh.edges_for_write();
threading::parallel_for(dst_edges.index_range(), 512, [&](const IndexRange range) { threading::parallel_for(dst_edges.index_range(), 512, [&](const IndexRange range) {
for (const int edge_i : range) { for (const int edge_i : range) {
@ -1434,7 +1586,7 @@ static void bm_to_mesh_edges(const BMesh &bm,
dst_edge.v1 = BM_elem_index_get(src_edge.v1); dst_edge.v1 = BM_elem_index_get(src_edge.v1);
dst_edge.v2 = BM_elem_index_get(src_edge.v2); dst_edge.v2 = BM_elem_index_get(src_edge.v2);
dst_edge.flag = bm_edge_flag_to_mflag(&src_edge); dst_edge.flag = bm_edge_flag_to_mflag(&src_edge);
CustomData_from_bmesh_block(&bm.edata, &mesh.edata, src_edge.head.data, edge_i); bmesh_block_copy_to_mesh_attributes(info, edge_i, src_edge.head.data);
} }
if (!select_edge.is_empty()) { if (!select_edge.is_empty()) {
for (const int edge_i : range) { for (const int edge_i : range) {
@ -1461,6 +1613,7 @@ static void bm_to_mesh_faces(const BMesh &bm,
MutableSpan<bool> hide_poly, MutableSpan<bool> hide_poly,
MutableSpan<int> material_indices) MutableSpan<int> material_indices)
{ {
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.pdata, mesh.pdata);
MutableSpan<MPoly> dst_polys = mesh.polys_for_write(); MutableSpan<MPoly> dst_polys = mesh.polys_for_write();
threading::parallel_for(dst_polys.index_range(), 1024, [&](const IndexRange range) { threading::parallel_for(dst_polys.index_range(), 1024, [&](const IndexRange range) {
for (const int face_i : range) { for (const int face_i : range) {
@ -1469,7 +1622,7 @@ static void bm_to_mesh_faces(const BMesh &bm,
dst_poly.totloop = src_face.len; dst_poly.totloop = src_face.len;
dst_poly.loopstart = BM_elem_index_get(BM_FACE_FIRST_LOOP(&src_face)); dst_poly.loopstart = BM_elem_index_get(BM_FACE_FIRST_LOOP(&src_face));
dst_poly.flag = bm_face_flag_to_mflag(&src_face); dst_poly.flag = bm_face_flag_to_mflag(&src_face);
CustomData_from_bmesh_block(&bm.pdata, &mesh.pdata, src_face.head.data, face_i); bmesh_block_copy_to_mesh_attributes(info, face_i, src_face.head.data);
} }
if (!select_poly.is_empty()) { if (!select_poly.is_empty()) {
for (const int face_i : range) { for (const int face_i : range) {
@ -1491,6 +1644,7 @@ static void bm_to_mesh_faces(const BMesh &bm,
static void bm_to_mesh_loops(const BMesh &bm, const Span<const BMLoop *> bm_loops, Mesh &mesh) static void bm_to_mesh_loops(const BMesh &bm, const Span<const BMLoop *> bm_loops, Mesh &mesh)
{ {
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.ldata, mesh.ldata);
MutableSpan<MLoop> dst_loops = mesh.loops_for_write(); MutableSpan<MLoop> dst_loops = mesh.loops_for_write();
threading::parallel_for(dst_loops.index_range(), 1024, [&](const IndexRange range) { threading::parallel_for(dst_loops.index_range(), 1024, [&](const IndexRange range) {
for (const int loop_i : range) { for (const int loop_i : range) {
@ -1498,7 +1652,7 @@ static void bm_to_mesh_loops(const BMesh &bm, const Span<const BMLoop *> bm_loop
MLoop &dst_loop = dst_loops[loop_i]; MLoop &dst_loop = dst_loops[loop_i];
dst_loop.v = BM_elem_index_get(src_loop.v); dst_loop.v = BM_elem_index_get(src_loop.v);
dst_loop.e = BM_elem_index_get(src_loop.e); dst_loop.e = BM_elem_index_get(src_loop.e);
CustomData_from_bmesh_block(&bm.ldata, &mesh.ldata, src_loop.head.data, loop_i); bmesh_block_copy_to_mesh_attributes(info, loop_i, src_loop.head.data);
} }
}); });
} }

View File

@ -1197,8 +1197,8 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data)
{ {
BMwFaceLoopWalker *lwalk, owalk, *owalk_pt; BMwFaceLoopWalker *lwalk, owalk, *owalk_pt;
BMEdge *e = data; BMEdge *e = data;
/* BMesh *bm = walker->bm; */ /* UNUSED */ // BMesh *bm = walker->bm; /* UNUSED */
/* int fcount = BM_edge_face_count(e); */ /* UNUSED */ // int fcount = BM_edge_face_count(e); /* UNUSED */
if (!bmw_FaceLoopWalker_edge_begins_loop(walker, e)) { if (!bmw_FaceLoopWalker_edge_begins_loop(walker, e)) {
return; return;

View File

@ -1183,7 +1183,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
f = BM_face_create_verts(bm, varr, j, es->l->f, BM_CREATE_NOP, true); f = BM_face_create_verts(bm, varr, j, es->l->f, BM_CREATE_NOP, true);
BMO_face_flag_enable(bm, f, ELE_NEW); BMO_face_flag_enable(bm, f, ELE_NEW);
/* Copy for loop data, otherwise UVs and vcols are no good. /* Copy for loop data, otherwise UVs and vertex-colors are no good.
* tiny speedup here we could be more clever and copy from known adjacent data * tiny speedup here we could be more clever and copy from known adjacent data
* also - we could attempt to interpolate the loop data, * also - we could attempt to interpolate the loop data,
* this would be much slower but more useful too. */ * this would be much slower but more useful too. */

View File

@ -225,7 +225,7 @@ set(SRC
DRW_select_buffer.h DRW_select_buffer.h
intern/DRW_gpu_wrapper.hh intern/DRW_gpu_wrapper.hh
intern/DRW_render.h intern/DRW_render.h
intern/draw_attributes.h intern/draw_attributes.hh
intern/draw_cache.h intern/draw_cache.h
intern/draw_cache_extract.hh intern/draw_cache_extract.hh
intern/draw_cache_impl.h intern/draw_cache_impl.h
@ -234,7 +234,7 @@ set(SRC
intern/draw_command.hh intern/draw_command.hh
intern/draw_common.h intern/draw_common.h
intern/draw_common_shader_shared.h intern/draw_common_shader_shared.h
intern/draw_curves_private.h intern/draw_curves_private.hh
intern/draw_debug.h intern/draw_debug.h
intern/draw_debug.hh intern/draw_debug.hh
intern/draw_hair_private.h intern/draw_hair_private.h

View File

@ -21,8 +21,7 @@ void main()
float light_count = 0.0; float light_count = 0.0;
uint light_cull = 0u; uint light_cull = 0u;
vec2 px = gl_FragCoord.xy; vec2 px = gl_FragCoord.xy;
LIGHT_FOREACH_BEGIN_LOCAL(light_cull_buf, light_zbin_buf, light_tile_buf, px, vP_z, l_idx) LIGHT_FOREACH_BEGIN_LOCAL (light_cull_buf, light_zbin_buf, light_tile_buf, px, vP_z, l_idx) {
{
LightData light = light_buf[l_idx]; LightData light = light_buf[l_idx];
light_cull |= 1u << l_idx; light_cull |= 1u << l_idx;
light_count += 1.0; light_count += 1.0;

View File

@ -192,4 +192,4 @@ void main()
break; break;
} }
} }
} }

View File

@ -38,4 +38,4 @@ void main()
} }
tile_start += lod_len; tile_start += lod_len;
} }
} }

View File

@ -126,4 +126,4 @@ void main()
clear_dispatch_buf.num_groups_x = pages_infos_buf.page_size / SHADOW_PAGE_CLEAR_GROUP_SIZE; clear_dispatch_buf.num_groups_x = pages_infos_buf.page_size / SHADOW_PAGE_CLEAR_GROUP_SIZE;
clear_dispatch_buf.num_groups_y = pages_infos_buf.page_size / SHADOW_PAGE_CLEAR_GROUP_SIZE; clear_dispatch_buf.num_groups_y = pages_infos_buf.page_size / SHADOW_PAGE_CLEAR_GROUP_SIZE;
clear_dispatch_buf.num_groups_z = 0; clear_dispatch_buf.num_groups_z = 0;
} }

View File

@ -51,4 +51,4 @@ void main()
} }
tile_start += lod_len; tile_start += lod_len;
} }
} }

View File

@ -52,4 +52,4 @@ void main()
} }
} }
} }
} }

View File

@ -91,4 +91,4 @@ void main()
} }
} }
} }
} }

View File

@ -29,4 +29,4 @@ void main()
vec2 pixel = vec2(gl_GlobalInvocationID.xy); vec2 pixel = vec2(gl_GlobalInvocationID.xy);
shadow_tag_usage(vP, P, pixel); shadow_tag_usage(vP, P, pixel);
} }

View File

@ -12,4 +12,4 @@
void main() void main()
{ {
shadow_tag_usage(interp.vP, interp.P, gl_FragCoord.xy); shadow_tag_usage(interp.vP, interp.P, gl_FragCoord.xy);
} }

View File

@ -101,4 +101,4 @@ void shadow_tag_usage(vec3 vP, vec3 P, vec2 pixel)
shadow_tag_usage_tilemap(l_idx, P, dist_to_cam, false); shadow_tag_usage_tilemap(l_idx, P, dist_to_cam, false);
} }
LIGHT_FOREACH_END LIGHT_FOREACH_END
} }

View File

@ -19,4 +19,4 @@ void main()
interp.vP = point_world_to_view(interp.P); interp.vP = point_world_to_view(interp.P);
gl_Position = point_world_to_ndc(interp.P); gl_Position = point_world_to_ndc(interp.P);
} }

View File

@ -395,4 +395,4 @@ void main()
EXPECT_NEAR(shadow_slope_bias_get(atlas_size, light, lNg, lP0, vec2(0.0), 2), 0.0, 1e-4); EXPECT_NEAR(shadow_slope_bias_get(atlas_size, light, lNg, lP0, vec2(0.0), 2), 0.0, 1e-4);
} }
} }
} }

View File

@ -74,4 +74,4 @@ void main()
* thread 0. */ * thread 0. */
} }
LIGHT_FOREACH_END LIGHT_FOREACH_END
} }

View File

@ -178,4 +178,4 @@ void main()
/* Clamp it as it can underflow if there is too much tile present on screen. */ /* Clamp it as it can underflow if there is too much tile present on screen. */
pages_infos_buf.page_free_count = max(pages_infos_buf.page_free_count, 0); pages_infos_buf.page_free_count = max(pages_infos_buf.page_free_count, 0);
} }
} }

View File

@ -90,4 +90,4 @@ void main()
tiles_buf[tile_store] = tile; tiles_buf[tile_store] = tile;
} }
} }
} }

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "eevee_defines.hh" #include "eevee_defines.hh"

View File

@ -5,10 +5,14 @@
* \ingroup draw_engine * \ingroup draw_engine
*/ */
#include "BKE_curves.h"
#include "DRW_render.h" #include "DRW_render.h"
#include "ED_view3d.h" #include "ED_view3d.h"
#include "DEG_depsgraph_query.h"
#include "draw_cache_impl.h" #include "draw_cache_impl.h"
#include "overlay_private.hh" #include "overlay_private.hh"
@ -17,7 +21,10 @@ void OVERLAY_edit_curves_init(OVERLAY_Data *vedata)
{ {
OVERLAY_PrivateData *pd = vedata->stl->pd; OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get(); const DRWContextState *draw_ctx = DRW_context_state_get();
const Object *obact_orig = DEG_get_original_object(draw_ctx->obact);
const Curves &curves_id = *static_cast<const Curves *>(obact_orig->data);
pd->edit_curves.do_points = curves_id.selection_domain == ATTR_DOMAIN_POINT;
pd->edit_curves.do_zbufclip = XRAY_FLAG_ENABLED(draw_ctx->v3d); pd->edit_curves.do_zbufclip = XRAY_FLAG_ENABLED(draw_ctx->v3d);
/* Create view with depth offset. */ /* Create view with depth offset. */
@ -39,10 +46,12 @@ void OVERLAY_edit_curves_cache_init(OVERLAY_Data *vedata)
/* Run Twice for in-front passes. */ /* Run Twice for in-front passes. */
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
DRW_PASS_CREATE(psl->edit_curves_points_ps[i], (state | pd->clipping_state)); if (pd->edit_curves.do_points) {
sh = OVERLAY_shader_edit_particle_point(); DRW_PASS_CREATE(psl->edit_curves_points_ps[i], (state | pd->clipping_state));
grp = pd->edit_curves_points_grp[i] = DRW_shgroup_create(sh, psl->edit_curves_points_ps[i]); sh = OVERLAY_shader_edit_particle_point();
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); grp = pd->edit_curves_points_grp[i] = DRW_shgroup_create(sh, psl->edit_curves_points_ps[i]);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
DRW_PASS_CREATE(psl->edit_curves_lines_ps[i], (state | pd->clipping_state)); DRW_PASS_CREATE(psl->edit_curves_lines_ps[i], (state | pd->clipping_state));
sh = OVERLAY_shader_edit_particle_strand(); sh = OVERLAY_shader_edit_particle_strand();
@ -56,9 +65,11 @@ static void overlay_edit_curves_add_ob_to_pass(OVERLAY_PrivateData *pd, Object *
{ {
Curves *curves = static_cast<Curves *>(ob->data); Curves *curves = static_cast<Curves *>(ob->data);
DRWShadingGroup *point_shgrp = pd->edit_curves_points_grp[in_front]; if (pd->edit_curves.do_points) {
struct GPUBatch *geom_points = DRW_curves_batch_cache_get_edit_points(curves); DRWShadingGroup *point_shgrp = pd->edit_curves_points_grp[in_front];
DRW_shgroup_call_no_cull(point_shgrp, geom_points, ob); struct GPUBatch *geom_points = DRW_curves_batch_cache_get_edit_points(curves);
DRW_shgroup_call_no_cull(point_shgrp, geom_points, ob);
}
DRWShadingGroup *lines_shgrp = pd->edit_curves_lines_grp[in_front]; DRWShadingGroup *lines_shgrp = pd->edit_curves_lines_grp[in_front];
struct GPUBatch *geom_lines = DRW_curves_batch_cache_get_edit_lines(curves); struct GPUBatch *geom_lines = DRW_curves_batch_cache_get_edit_lines(curves);
@ -89,12 +100,16 @@ void OVERLAY_edit_curves_draw(OVERLAY_Data *vedata)
if (pd->edit_curves.do_zbufclip) { if (pd->edit_curves.do_zbufclip) {
DRW_view_set_active(pd->view_edit_curves); DRW_view_set_active(pd->view_edit_curves);
DRW_draw_pass(psl->edit_curves_points_ps[NOT_IN_FRONT]); if (pd->edit_curves.do_points) {
DRW_draw_pass(psl->edit_curves_points_ps[NOT_IN_FRONT]);
}
DRW_draw_pass(psl->edit_curves_lines_ps[NOT_IN_FRONT]); DRW_draw_pass(psl->edit_curves_lines_ps[NOT_IN_FRONT]);
} }
else { else {
DRW_view_set_active(pd->view_edit_curves); DRW_view_set_active(pd->view_edit_curves);
DRW_draw_pass(psl->edit_curves_points_ps[IN_FRONT]); if (pd->edit_curves.do_points) {
DRW_draw_pass(psl->edit_curves_points_ps[IN_FRONT]);
}
DRW_draw_pass(psl->edit_curves_lines_ps[IN_FRONT]); DRW_draw_pass(psl->edit_curves_lines_ps[IN_FRONT]);
} }
} }

View File

@ -362,6 +362,7 @@ typedef struct OVERLAY_PrivateData {
int flag; /** Copy of #v3d->overlay.edit_flag. */ int flag; /** Copy of #v3d->overlay.edit_flag. */
} edit_mesh; } edit_mesh;
struct { struct {
bool do_points;
bool do_zbufclip; bool do_zbufclip;
} edit_curves; } edit_curves;
struct { struct {

View File

@ -59,6 +59,6 @@ struct ExtrudedFrustum {
struct ShadowPassData { struct ShadowPassData {
float4 far_plane; float4 far_plane;
float3 light_direction_ws; packed_float3 light_direction_ws;
int _padding; int _padding;
}; };

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later /* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2022 Blender Foundation. All rights reserved. */ * Copyright 2022 Blender Foundation. All rights reserved. */
#include "draw_attributes.h" #include "draw_attributes.hh"
/* Return true if the given DRW_AttributeRequest is already in the requests. */ /* Return true if the given DRW_AttributeRequest is already in the requests. */
static bool drw_attributes_has_request(const DRW_Attributes *requests, DRW_AttributeRequest req) static bool drw_attributes_has_request(const DRW_Attributes *requests, DRW_AttributeRequest req)

View File

@ -9,9 +9,7 @@
#pragma once #pragma once
#ifdef __cplusplus #include <mutex>
# include <mutex>
#endif
#include "DNA_customdata_types.h" #include "DNA_customdata_types.h"
@ -24,23 +22,19 @@
#include "GPU_shader.h" #include "GPU_shader.h"
#include "GPU_vertex_format.h" #include "GPU_vertex_format.h"
#ifdef __cplusplus struct DRW_AttributeRequest {
extern "C" {
#endif
typedef struct DRW_AttributeRequest {
eCustomDataType cd_type; eCustomDataType cd_type;
int layer_index; int layer_index;
eAttrDomain domain; eAttrDomain domain;
char attribute_name[64]; char attribute_name[64];
} DRW_AttributeRequest; };
typedef struct DRW_Attributes { struct DRW_Attributes {
DRW_AttributeRequest requests[GPU_MAX_ATTR]; DRW_AttributeRequest requests[GPU_MAX_ATTR];
int num_requests; int num_requests;
} DRW_Attributes; };
typedef struct DRW_MeshCDMask { struct DRW_MeshCDMask {
uint32_t uv : 8; uint32_t uv : 8;
uint32_t tan : 8; uint32_t tan : 8;
uint32_t orco : 1; uint32_t orco : 1;
@ -50,7 +44,7 @@ typedef struct DRW_MeshCDMask {
* Edit uv layer is from the base edit mesh as modifiers could remove it. (see #68857) * Edit uv layer is from the base edit mesh as modifiers could remove it. (see #68857)
*/ */
uint32_t edit_uv : 1; uint32_t edit_uv : 1;
} DRW_MeshCDMask; };
/* Keep `DRW_MeshCDMask` struct within a `uint32_t`. /* Keep `DRW_MeshCDMask` struct within a `uint32_t`.
* bit-wise and atomic operations are used to compare and update the struct. * bit-wise and atomic operations are used to compare and update the struct.
@ -59,11 +53,9 @@ BLI_STATIC_ASSERT(sizeof(DRW_MeshCDMask) <= sizeof(uint32_t), "DRW_MeshCDMask ex
void drw_attributes_clear(DRW_Attributes *attributes); void drw_attributes_clear(DRW_Attributes *attributes);
#ifdef __cplusplus
void drw_attributes_merge(DRW_Attributes *dst, void drw_attributes_merge(DRW_Attributes *dst,
const DRW_Attributes *src, const DRW_Attributes *src,
std::mutex &render_mutex); std::mutex &render_mutex);
#endif
/* Return true if all requests in b are in a. */ /* Return true if all requests in b are in a. */
bool drw_attributes_overlap(const DRW_Attributes *a, const DRW_Attributes *b); bool drw_attributes_overlap(const DRW_Attributes *a, const DRW_Attributes *b);
@ -78,7 +70,3 @@ bool drw_custom_data_match_attribute(const CustomData *custom_data,
const char *name, const char *name,
int *r_layer_index, int *r_layer_index,
eCustomDataType *r_type); eCustomDataType *r_type);
#ifdef __cplusplus
}
#endif

View File

@ -22,7 +22,7 @@
#include "GPU_index_buffer.h" #include "GPU_index_buffer.h"
#include "GPU_vertex_buffer.h" #include "GPU_vertex_buffer.h"
#include "draw_attributes.h" #include "draw_attributes.hh"
struct DRWSubdivCache; struct DRWSubdivCache;
struct MeshRenderData; struct MeshRenderData;

View File

@ -34,10 +34,10 @@
#include "DRW_render.h" #include "DRW_render.h"
#include "draw_attributes.h" #include "draw_attributes.hh"
#include "draw_cache_impl.h" /* own include */ #include "draw_cache_impl.h" /* own include */
#include "draw_cache_inline.h" #include "draw_cache_inline.h"
#include "draw_curves_private.h" /* own include */ #include "draw_curves_private.hh" /* own include */
#include "draw_shader.h" #include "draw_shader.h"
using blender::ColorGeometry4f; using blender::ColorGeometry4f;

View File

@ -25,7 +25,7 @@
#include "GPU_batch.h" #include "GPU_batch.h"
#include "GPU_material.h" #include "GPU_material.h"
#include "draw_attributes.h" #include "draw_attributes.hh"
#include "draw_cache_impl.h" #include "draw_cache_impl.h"
#include "draw_cache_inline.h" #include "draw_cache_inline.h"
#include "draw_pointcloud_private.hh" /* own include */ #include "draw_pointcloud_private.hh" /* own include */

View File

@ -26,7 +26,7 @@
#include "DRW_render.h" #include "DRW_render.h"
#include "draw_cache_impl.h" #include "draw_cache_impl.h"
#include "draw_curves_private.h" #include "draw_curves_private.hh"
#include "draw_hair_private.h" #include "draw_hair_private.h"
#include "draw_manager.h" #include "draw_manager.h"
#include "draw_shader.h" #include "draw_shader.h"

View File

@ -10,26 +10,23 @@
#include "BKE_attribute.h" #include "BKE_attribute.h"
#include "GPU_shader.h" #include "GPU_shader.h"
#include "draw_attributes.h" #include "draw_attributes.hh"
#ifdef __cplusplus
extern "C" {
#endif
struct Curves; struct Curves;
struct GPUVertBuf; struct GPUVertBuf;
struct GPUBatch; struct GPUBatch;
struct GPUMaterial;
#define MAX_THICKRES 2 /* see eHairType */ #define MAX_THICKRES 2 /* see eHairType */
#define MAX_HAIR_SUBDIV 4 /* see hair_subdiv rna */ #define MAX_HAIR_SUBDIV 4 /* see hair_subdiv rna */
typedef enum CurvesEvalShader { enum CurvesEvalShader {
CURVES_EVAL_CATMULL_ROM = 0, CURVES_EVAL_CATMULL_ROM = 0,
CURVES_EVAL_BEZIER = 1, CURVES_EVAL_BEZIER = 1,
} CurvesEvalShader; };
#define CURVES_EVAL_SHADER_NUM 3 #define CURVES_EVAL_SHADER_NUM 3
typedef struct CurvesEvalFinalCache { struct CurvesEvalFinalCache {
/* Output of the subdivision stage: vertex buffer sized to subdiv level. */ /* Output of the subdivision stage: vertex buffer sized to subdiv level. */
GPUVertBuf *proc_buf; GPUVertBuf *proc_buf;
@ -58,10 +55,10 @@ typedef struct CurvesEvalFinalCache {
/* Output of the subdivision stage: vertex buffers sized to subdiv level. This is only attributes /* Output of the subdivision stage: vertex buffers sized to subdiv level. This is only attributes
* on point domain. */ * on point domain. */
GPUVertBuf *attributes_buf[GPU_MAX_ATTR]; GPUVertBuf *attributes_buf[GPU_MAX_ATTR];
} CurvesEvalFinalCache; };
/* Curves procedural display: Evaluation is done on the GPU. */ /* Curves procedural display: Evaluation is done on the GPU. */
typedef struct CurvesEvalCache { struct CurvesEvalCache {
/* Control point positions on evaluated data-block combined with parameter data. */ /* Control point positions on evaluated data-block combined with parameter data. */
GPUVertBuf *proc_point_buf; GPUVertBuf *proc_point_buf;
@ -82,19 +79,15 @@ typedef struct CurvesEvalCache {
int strands_len; int strands_len;
int elems_len; int elems_len;
int point_len; int point_len;
} CurvesEvalCache; };
/** /**
* Ensure all necessary textures and buffers exist for GPU accelerated drawing. * Ensure all necessary textures and buffers exist for GPU accelerated drawing.
*/ */
bool curves_ensure_procedural_data(struct Curves *curves, bool curves_ensure_procedural_data(Curves *curves,
struct CurvesEvalCache **r_hair_cache, CurvesEvalCache **r_hair_cache,
struct GPUMaterial *gpu_material, GPUMaterial *gpu_material,
int subdiv, int subdiv,
int thickness_res); int thickness_res);
void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32]); void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32]);
#ifdef __cplusplus
}
#endif

View File

@ -7,7 +7,7 @@
#include "DRW_pbvh.hh" #include "DRW_pbvh.hh"
#include "draw_attributes.h" #include "draw_attributes.hh"
#include "draw_manager.h" #include "draw_manager.h"
#include "draw_pbvh.h" #include "draw_pbvh.h"
@ -698,7 +698,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob)
drw_call_calc_orco(ob, ob_infos->orcotexfac); drw_call_calc_orco(ob, ob_infos->orcotexfac);
/* Random float value. */ /* Random float value. */
uint random = (DST.dupli_source) ? uint random = (DST.dupli_source) ?
DST.dupli_source->random_id : DST.dupli_source->random_id :
/* TODO(fclem): this is rather costly to do at runtime. Maybe we can /* TODO(fclem): this is rather costly to do at runtime. Maybe we can
* put it in ob->runtime and make depsgraph ensure it is up to date. */ * put it in ob->runtime and make depsgraph ensure it is up to date. */
BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0); BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0);

View File

@ -21,7 +21,7 @@
#include "DRW_gpu_wrapper.hh" #include "DRW_gpu_wrapper.hh"
#include "DRW_render.h" #include "DRW_render.h"
#include "draw_attributes.h" #include "draw_attributes.hh"
#include "draw_cache_impl.h" #include "draw_cache_impl.h"
#include "draw_common.h" #include "draw_common.h"
#include "draw_manager.h" #include "draw_manager.h"

View File

@ -7,36 +7,38 @@
#pragma once #pragma once
#include "draw_curves_private.h" #ifdef __cplusplus
#include "draw_hair_private.h" # include "draw_curves_private.hh"
# include "draw_hair_private.h"
struct GPUShader;
enum eParticleRefineShaderType {
PART_REFINE_SHADER_TRANSFORM_FEEDBACK,
PART_REFINE_SHADER_TRANSFORM_FEEDBACK_WORKAROUND,
PART_REFINE_SHADER_COMPUTE,
};
/* draw_shader.cc */
GPUShader *DRW_shader_hair_refine_get(ParticleRefineShader refinement,
eParticleRefineShaderType sh_type);
GPUShader *DRW_shader_curves_refine_get(CurvesEvalShader type, eParticleRefineShaderType sh_type);
GPUShader *DRW_shader_debug_print_display_get();
GPUShader *DRW_shader_debug_draw_display_get();
GPUShader *DRW_shader_draw_visibility_compute_get();
GPUShader *DRW_shader_draw_view_finalize_get();
GPUShader *DRW_shader_draw_resource_finalize_get();
GPUShader *DRW_shader_draw_command_generate_get();
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
struct GPUShader;
typedef enum eParticleRefineShaderType {
PART_REFINE_SHADER_TRANSFORM_FEEDBACK,
PART_REFINE_SHADER_TRANSFORM_FEEDBACK_WORKAROUND,
PART_REFINE_SHADER_COMPUTE,
} eParticleRefineShaderType;
/* draw_shader.cc */
struct GPUShader *DRW_shader_hair_refine_get(ParticleRefineShader refinement,
eParticleRefineShaderType sh_type);
struct GPUShader *DRW_shader_curves_refine_get(CurvesEvalShader type,
eParticleRefineShaderType sh_type);
struct GPUShader *DRW_shader_debug_print_display_get(void);
struct GPUShader *DRW_shader_debug_draw_display_get(void);
struct GPUShader *DRW_shader_draw_visibility_compute_get(void);
struct GPUShader *DRW_shader_draw_view_finalize_get(void);
struct GPUShader *DRW_shader_draw_resource_finalize_get(void);
struct GPUShader *DRW_shader_draw_command_generate_get(void);
void DRW_shaders_free(void); void DRW_shaders_free(void);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -17,7 +17,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_mesh.h" #include "BKE_mesh.h"
#include "draw_attributes.h" #include "draw_attributes.hh"
#include "draw_subdivision.h" #include "draw_subdivision.h"
#include "extract_mesh.hh" #include "extract_mesh.hh"

View File

@ -401,9 +401,9 @@ static void add_verts_to_dgroups(ReportList *reports,
vertsfilled = 1; vertsfilled = 1;
} }
else if (BKE_modifiers_findby_type(ob, eModifierType_Subsurf)) { else if (BKE_modifiers_findby_type(ob, eModifierType_Subsurf)) {
/* is subsurf on? Lets use the verts on the limit surface then. /* Is subdivision-surface on? Lets use the verts on the limit surface then.
* = same amount of vertices as mesh, but vertices moved to the * = same amount of vertices as mesh, but vertices moved to the
* subsurfed position, like for 'optimal'. */ * subdivision-surfaced position, like for 'optimal'. */
subsurf_calculate_limit_positions(mesh, verts); subsurf_calculate_limit_positions(mesh, verts);
vertsfilled = 1; vertsfilled = 1;
} }

View File

@ -793,21 +793,19 @@ static int curves_set_selection_domain_exec(bContext *C, wmOperator *op)
if (curves.points_num() == 0) { if (curves.points_num() == 0) {
continue; continue;
} }
const GVArray src = attributes.lookup(".selection", domain);
if (src.is_empty()) {
continue;
}
const CPPType &type = src.type(); if (const GVArray src = attributes.lookup(".selection", domain)) {
void *dst = MEM_malloc_arrayN(attributes.domain_size(domain), type.size(), __func__); const CPPType &type = src.type();
src.materialize(dst); void *dst = MEM_malloc_arrayN(attributes.domain_size(domain), type.size(), __func__);
src.materialize(dst);
attributes.remove(".selection"); attributes.remove(".selection");
if (!attributes.add(".selection", if (!attributes.add(".selection",
domain, domain,
bke::cpp_type_to_custom_data_type(type), bke::cpp_type_to_custom_data_type(type),
bke::AttributeInitMoveArray(dst))) { bke::AttributeInitMoveArray(dst))) {
MEM_freeN(dst); MEM_freeN(dst);
}
} }
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic

View File

@ -357,9 +357,9 @@ static void apply_selection_operation_at_index(GMutableSpan selection,
} }
/** /**
* Helper struct for `find_closest_point_to_screen_co`. * Helper struct for `select_pick`.
*/ */
struct FindClosestPointData { struct FindClosestData {
int index = -1; int index = -1;
float distance = FLT_MAX; float distance = FLT_MAX;
}; };
@ -371,7 +371,7 @@ static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph,
const bke::CurvesGeometry &curves, const bke::CurvesGeometry &curves,
float2 mouse_pos, float2 mouse_pos,
float radius, float radius,
FindClosestPointData &closest_data) FindClosestData &closest_data)
{ {
float4x4 projection; float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d, &object, projection.ptr()); ED_view3d_ob_project_mat_get(rv3d, &object, projection.ptr());
@ -380,12 +380,12 @@ static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph,
bke::crazyspace::get_evaluated_curves_deformation(depsgraph, object); bke::crazyspace::get_evaluated_curves_deformation(depsgraph, object);
const float radius_sq = pow2f(radius); const float radius_sq = pow2f(radius);
auto [min_point_index, min_distance] = threading::parallel_reduce( closest_data = threading::parallel_reduce(
curves.points_range(), curves.points_range(),
1024, 1024,
FindClosestPointData(), FindClosestData(),
[&](const IndexRange point_range, const FindClosestPointData &init) { [&](const IndexRange point_range, const FindClosestData &init) {
FindClosestPointData best_match = init; FindClosestData best_match = init;
for (const int point_i : point_range) { for (const int point_i : point_range) {
const float3 pos = deformation.positions[point_i]; const float3 pos = deformation.positions[point_i];
@ -400,7 +400,7 @@ static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph,
continue; continue;
} }
FindClosestPointData better_candidate; FindClosestData better_candidate;
better_candidate.index = point_i; better_candidate.index = point_i;
better_candidate.distance = std::sqrt(distance_proj_sq); better_candidate.distance = std::sqrt(distance_proj_sq);
@ -408,18 +408,104 @@ static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph,
} }
return best_match; return best_match;
}, },
[](const FindClosestPointData &a, const FindClosestPointData &b) { [](const FindClosestData &a, const FindClosestData &b) {
if (a.distance < b.distance) {
return a;
}
return b;
});
if (closest_data.index > 0) {
return true;
}
return false;
}
static bool find_closest_curve_to_screen_co(const Depsgraph &depsgraph,
const ARegion *region,
const RegionView3D *rv3d,
const Object &object,
const bke::CurvesGeometry &curves,
float2 mouse_pos,
float radius,
FindClosestData &closest_data)
{
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d, &object, projection.ptr());
const bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(depsgraph, object);
const float radius_sq = pow2f(radius);
const OffsetIndices points_by_curve = curves.points_by_curve();
closest_data = threading::parallel_reduce(
curves.curves_range(),
256,
FindClosestData(),
[&](const IndexRange curves_range, const FindClosestData &init) {
FindClosestData best_match = init;
for (const int curve_i : curves_range) {
if (points_by_curve.size(curve_i) == 1) {
const float3 pos = deformation.positions[points_by_curve[curve_i].first()];
/* Find the position of the point in screen space. */
float2 pos_proj;
ED_view3d_project_float_v2_m4(region, pos, pos_proj, projection.ptr());
const float distance_proj_sq = math::distance_squared(pos_proj, mouse_pos);
if (distance_proj_sq > radius_sq ||
distance_proj_sq > best_match.distance * best_match.distance) {
/* Ignore the point because it's too far away or there is already a better point.
*/
continue;
}
FindClosestData better_candidate;
better_candidate.index = curve_i;
better_candidate.distance = std::sqrt(distance_proj_sq);
best_match = better_candidate;
continue;
}
for (const int segment_i : points_by_curve[curve_i].drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
float2 pos1_proj, pos2_proj;
ED_view3d_project_float_v2_m4(region, pos1, pos1_proj, projection.ptr());
ED_view3d_project_float_v2_m4(region, pos2, pos2_proj, projection.ptr());
const float distance_proj_sq = dist_squared_to_line_segment_v2(
mouse_pos, pos1_proj, pos2_proj);
if (distance_proj_sq > radius_sq ||
distance_proj_sq > best_match.distance * best_match.distance) {
/* Ignore the segment because it's too far away or there is already a better point.
*/
continue;
}
FindClosestData better_candidate;
better_candidate.index = curve_i;
better_candidate.distance = std::sqrt(distance_proj_sq);
best_match = better_candidate;
}
}
return best_match;
},
[](const FindClosestData &a, const FindClosestData &b) {
if (a.distance < b.distance) { if (a.distance < b.distance) {
return a; return a;
} }
return b; return b;
}); });
if (min_point_index > 0) { if (closest_data.index > 0) {
closest_data.index = min_point_index;
closest_data.distance = min_distance;
return true; return true;
} }
return false; return false;
} }
@ -429,15 +515,28 @@ bool select_pick(const ViewContext &vc,
const SelectPick_Params &params, const SelectPick_Params &params,
const int2 coord) const int2 coord)
{ {
FindClosestPointData closest_point; FindClosestData closest;
bool found = find_closest_point_to_screen_co(*vc.depsgraph, bool found = false;
vc.region, if (selection_domain == ATTR_DOMAIN_POINT) {
vc.rv3d, found = find_closest_point_to_screen_co(*vc.depsgraph,
*vc.obact, vc.region,
curves, vc.rv3d,
float2(coord), *vc.obact,
ED_view3d_select_dist_px(), curves,
closest_point); float2(coord),
ED_view3d_select_dist_px(),
closest);
}
else if (selection_domain == ATTR_DOMAIN_CURVE) {
found = find_closest_curve_to_screen_co(*vc.depsgraph,
vc.region,
vc.rv3d,
*vc.obact,
curves,
float2(coord),
ED_view3d_select_dist_px(),
closest);
}
bool changed = false; bool changed = false;
if (params.sel_op == SEL_OP_SET) { if (params.sel_op == SEL_OP_SET) {
@ -453,17 +552,7 @@ bool select_pick(const ViewContext &vc,
if (found) { if (found) {
bke::GSpanAttributeWriter selection = ensure_selection_attribute( bke::GSpanAttributeWriter selection = ensure_selection_attribute(
curves, selection_domain, CD_PROP_BOOL); curves, selection_domain, CD_PROP_BOOL);
apply_selection_operation_at_index(selection.span, closest.index, params.sel_op);
int elem_index = closest_point.index;
if (selection_domain == ATTR_DOMAIN_CURVE) {
/* Find the curve index for the found point. */
auto it = std::upper_bound(
curves.offsets().begin(), curves.offsets().end(), closest_point.index);
BLI_assert(it != curves.offsets().end());
elem_index = std::distance(curves.offsets().begin(), it) - 1;
}
apply_selection_operation_at_index(selection.span, elem_index, params.sel_op);
selection.finish(); selection.finish();
} }
@ -507,13 +596,29 @@ bool select_box(const ViewContext &vc,
else if (selection_domain == ATTR_DOMAIN_CURVE) { else if (selection_domain == ATTR_DOMAIN_CURVE) {
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) { threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
for (const int curve_i : curves_range) { for (const int curve_i : curves_range) {
for (const int point_i : points_by_curve[curve_i]) { if (points_by_curve.size(curve_i) == 1) {
float2 pos_proj; float2 pos_proj;
ED_view3d_project_float_v2_m4( ED_view3d_project_float_v2_m4(vc.region,
vc.region, deformation.positions[point_i], pos_proj, projection.ptr()); deformation.positions[points_by_curve[curve_i].first()],
pos_proj,
projection.ptr());
if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) { if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op); apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true; changed = true;
}
continue;
}
for (const int segment_i : points_by_curve[curve_i].drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
float2 pos1_proj, pos2_proj;
ED_view3d_project_float_v2_m4(vc.region, pos1, pos1_proj, projection.ptr());
ED_view3d_project_float_v2_m4(vc.region, pos2, pos2_proj, projection.ptr());
if (BLI_rcti_isect_segment(&rect, int2(pos1_proj), int2(pos2_proj))) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true;
break; break;
} }
} }
@ -569,16 +674,40 @@ bool select_lasso(const ViewContext &vc,
else if (selection_domain == ATTR_DOMAIN_CURVE) { else if (selection_domain == ATTR_DOMAIN_CURVE) {
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) { threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
for (const int curve_i : curves_range) { for (const int curve_i : curves_range) {
for (const int point_i : points_by_curve[curve_i]) { if (points_by_curve.size(curve_i) == 1) {
float2 pos_proj; float2 pos_proj;
ED_view3d_project_float_v2_m4( ED_view3d_project_float_v2_m4(vc.region,
vc.region, deformation.positions[point_i], pos_proj, projection.ptr()); deformation.positions[points_by_curve[curve_i].first()],
pos_proj,
projection.ptr());
/* Check the lasso bounding box first as an optimization. */ /* Check the lasso bounding box first as an optimization. */
if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) && if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
BLI_lasso_is_point_inside( BLI_lasso_is_point_inside(
coord_array, coords.size(), int(pos_proj.x), int(pos_proj.y), IS_CLIPPED)) { coord_array, coords.size(), int(pos_proj.x), int(pos_proj.y), IS_CLIPPED)) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op); apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true; changed = true;
}
continue;
}
for (const int segment_i : points_by_curve[curve_i].drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
float2 pos1_proj, pos2_proj;
ED_view3d_project_float_v2_m4(vc.region, pos1, pos1_proj, projection.ptr());
ED_view3d_project_float_v2_m4(vc.region, pos2, pos2_proj, projection.ptr());
/* Check the lasso bounding box first as an optimization. */
if (BLI_rcti_isect_segment(&bbox, int2(pos1_proj), int2(pos2_proj)) &&
BLI_lasso_is_edge_inside(coord_array,
coords.size(),
int(pos1_proj.x),
int(pos1_proj.y),
int(pos2_proj.x),
int(pos2_proj.y),
IS_CLIPPED)) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true;
break; break;
} }
} }
@ -629,13 +758,31 @@ bool select_circle(const ViewContext &vc,
else if (selection_domain == ATTR_DOMAIN_CURVE) { else if (selection_domain == ATTR_DOMAIN_CURVE) {
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) { threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
for (const int curve_i : curves_range) { for (const int curve_i : curves_range) {
for (const int point_i : points_by_curve[curve_i]) { if (points_by_curve.size(curve_i) == 1) {
float2 pos_proj; float2 pos_proj;
ED_view3d_project_float_v2_m4( ED_view3d_project_float_v2_m4(vc.region,
vc.region, deformation.positions[point_i], pos_proj, projection.ptr()); deformation.positions[points_by_curve[curve_i].first()],
pos_proj,
projection.ptr());
if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) { if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op); apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true; changed = true;
}
continue;
}
for (const int segment_i : points_by_curve[curve_i].drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
float2 pos1_proj, pos2_proj;
ED_view3d_project_float_v2_m4(vc.region, pos1, pos1_proj, projection.ptr());
ED_view3d_project_float_v2_m4(vc.region, pos2, pos2_proj, projection.ptr());
const float distance_proj_sq = dist_squared_to_line_segment_v2(
float2(coord), pos1_proj, pos2_proj);
if (distance_proj_sq <= radius_sq) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true;
break; break;
} }
} }

View File

@ -44,6 +44,8 @@
/* The same as in `draw_cache.c` */ /* The same as in `draw_cache.c` */
#define CIRCLE_RESOL 32 #define CIRCLE_RESOL 32
static int gizmo_cage2d_transform_flag_get(const wmGizmo *gz);
static bool gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[2], float scale[2]) static bool gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[2], float scale[2])
{ {
float matrix_final_no_offset[4][4]; float matrix_final_no_offset[4][4];
@ -616,7 +618,7 @@ static void gizmo_cage2d_draw_intern(wmGizmo *gz,
RNA_float_get_array(gz->ptr, "dimensions", dims); RNA_float_get_array(gz->ptr, "dimensions", dims);
float matrix_final[4][4]; float matrix_final[4][4];
const int transform_flag = RNA_enum_get(gz->ptr, "transform"); const int transform_flag = gizmo_cage2d_transform_flag_get(gz);
const int draw_style = RNA_enum_get(gz->ptr, "draw_style"); const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
const int draw_options = RNA_enum_get(gz->ptr, "draw_options"); const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
@ -831,7 +833,7 @@ static int gizmo_cage2d_test_select(bContext *C, wmGizmo *gz, const int mval[2])
/* Expand for hots-pot. */ /* Expand for hots-pot. */
const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2}; const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
const int transform_flag = RNA_enum_get(gz->ptr, "transform"); const int transform_flag = gizmo_cage2d_transform_flag_get(gz);
const int draw_options = RNA_enum_get(gz->ptr, "draw_options"); const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) { if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
@ -934,8 +936,21 @@ typedef struct RectTransformInteraction {
float orig_matrix_offset[4][4]; float orig_matrix_offset[4][4];
float orig_matrix_final_no_offset[4][4]; float orig_matrix_final_no_offset[4][4];
Dial *dial; Dial *dial;
bool use_temp_uniform;
} RectTransformInteraction; } RectTransformInteraction;
static int gizmo_cage2d_transform_flag_get(const wmGizmo *gz)
{
RectTransformInteraction *data = gz->interaction_data;
int transform_flag = RNA_enum_get(gz->ptr, "transform");
if (data) {
if (data->use_temp_uniform) {
transform_flag |= ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM;
}
}
return transform_flag;
}
static void gizmo_cage2d_setup(wmGizmo *gz) static void gizmo_cage2d_setup(wmGizmo *gz)
{ {
gz->flag |= WM_GIZMO_DRAW_MODAL | WM_GIZMO_DRAW_NO_SCALE; gz->flag |= WM_GIZMO_DRAW_MODAL | WM_GIZMO_DRAW_NO_SCALE;
@ -1020,9 +1035,6 @@ static int gizmo_cage2d_modal(bContext *C,
const wmEvent *event, const wmEvent *event,
eWM_GizmoFlagTweak UNUSED(tweak_flag)) eWM_GizmoFlagTweak UNUSED(tweak_flag))
{ {
if (event->type != MOUSEMOVE) {
return OPERATOR_RUNNING_MODAL;
}
/* For transform logic to be manageable we operate in -0.5..0.5 2D space, /* For transform logic to be manageable we operate in -0.5..0.5 2D space,
* no matter the size of the rectangle, mouse coords are scaled to unit space. * no matter the size of the rectangle, mouse coords are scaled to unit space.
* The mouse coords have been projected into the matrix * The mouse coords have been projected into the matrix
@ -1032,6 +1044,25 @@ static int gizmo_cage2d_modal(bContext *C,
* - Matrix translation is also multiplied by 'dims'. * - Matrix translation is also multiplied by 'dims'.
*/ */
RectTransformInteraction *data = gz->interaction_data; RectTransformInteraction *data = gz->interaction_data;
int transform_flag = RNA_enum_get(gz->ptr, "transform");
if ((transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM) == 0) {
/* WARNING: Checking the events modifier only makes sense as long as `tweak_flag`
* remains unused (this controls #WM_GIZMO_TWEAK_PRECISE by default). */
const bool use_temp_uniform = (event->modifier & KM_SHIFT) != 0;
const bool changed = data->use_temp_uniform != use_temp_uniform;
data->use_temp_uniform = data->use_temp_uniform;
if (use_temp_uniform) {
transform_flag |= ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM;
}
if (changed) {
/* Always refresh. */
}
else if (event->type != MOUSEMOVE) {
return OPERATOR_RUNNING_MODAL;
}
}
float point_local[2]; float point_local[2];
float dims[2]; float dims[2];
@ -1050,7 +1081,6 @@ static int gizmo_cage2d_modal(bContext *C,
} }
} }
const int transform_flag = RNA_enum_get(gz->ptr, "transform");
wmGizmoProperty *gz_prop; wmGizmoProperty *gz_prop;
gz_prop = WM_gizmo_target_property_find(gz, "matrix"); gz_prop = WM_gizmo_target_property_find(gz, "matrix");
@ -1141,12 +1171,9 @@ static int gizmo_cage2d_modal(bContext *C,
} }
} }
if (delta_orig < 0) { /* Original cursor position does not exactly lie on the cage boundary due to margin. */
scale[i] = -delta_curr / (pivot[i] + 0.5f); const float delta_boundary = signf(delta_orig) * 0.5f - pivot[i];
} scale[i] = delta_curr / delta_boundary;
else {
scale[i] = delta_curr / (0.5f - pivot[i]);
}
} }
} }

View File

@ -539,12 +539,9 @@ static int gizmo_cage3d_modal(bContext *C,
} }
} }
if (delta_orig < 0) { /* Original cursor position does not exactly lie on the cage boundary due to margin. */
scale[i] = -delta_curr / (pivot[i] + 0.5f); const float delta_boundary = signf(delta_orig) * 0.5f - pivot[i];
} scale[i] = delta_curr / delta_boundary;
else {
scale[i] = delta_curr / (0.5f - pivot[i]);
}
} }
} }

View File

@ -528,7 +528,7 @@ static short annotation_stroke_addpoint(tGPsdata *p,
/* store settings */ /* store settings */
copy_v2_v2(pt->m_xy, mval); copy_v2_v2(pt->m_xy, mval);
/* #44932 - Pressure vals are unreliable, so ignore for now */ /* Pressure values are unreliable, so ignore for now, see #44932. */
pt->pressure = 1.0f; pt->pressure = 1.0f;
pt->strength = 1.0f; pt->strength = 1.0f;
pt->time = (float)(curtime - p->inittime); pt->time = (float)(curtime - p->inittime);
@ -544,7 +544,7 @@ static short annotation_stroke_addpoint(tGPsdata *p,
/* store settings */ /* store settings */
copy_v2_v2(pt->m_xy, mval); copy_v2_v2(pt->m_xy, mval);
/* #44932 - Pressure vals are unreliable, so ignore for now */ /* Pressure values are unreliable, so ignore for now, see #44932. */
pt->pressure = 1.0f; pt->pressure = 1.0f;
pt->strength = 1.0f; pt->strength = 1.0f;
pt->time = (float)(curtime - p->inittime); pt->time = (float)(curtime - p->inittime);
@ -620,7 +620,7 @@ static short annotation_stroke_addpoint(tGPsdata *p,
/* store settings */ /* store settings */
copy_v2_v2(pt->m_xy, mval); copy_v2_v2(pt->m_xy, mval);
/* #44932 - Pressure vals are unreliable, so ignore for now */ /* Pressure values are unreliable, so ignore for now, see #44932. */
pt->pressure = 1.0f; pt->pressure = 1.0f;
pt->strength = 1.0f; pt->strength = 1.0f;
pt->time = (float)(curtime - p->inittime); pt->time = (float)(curtime - p->inittime);

View File

@ -4059,12 +4059,11 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
ot->prop = RNA_def_enum( ot->prop = RNA_def_enum(
ot->srna, "type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", ""); ot->srna, "type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", "");
prop = RNA_def_boolean( prop = RNA_def_boolean(ot->srna,
ot->srna, "keep_original",
"keep_original", 0,
0, "Keep Original",
"Keep Original", "Keep original strokes and create a copy before reprojecting");
"Keep original strokes and create a copy before reprojecting instead of reproject them");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP);
RNA_def_float(ot->srna, "offset", 0.0f, 0.0f, 10.0f, "Surface Offset", "", 0.0f, 10.0f); RNA_def_float(ot->srna, "offset", 0.0f, 0.0f, 10.0f, "Surface Offset", "", 0.0f, 10.0f);
@ -4771,7 +4770,7 @@ void GPENCIL_OT_stroke_simplify(wmOperatorType *ot)
/* identifiers */ /* identifiers */
ot->name = "Simplify Stroke"; ot->name = "Simplify Stroke";
ot->idname = "GPENCIL_OT_stroke_simplify"; ot->idname = "GPENCIL_OT_stroke_simplify";
ot->description = "Simplify selected stroked reducing number of points"; ot->description = "Simplify selected strokes, reducing number of points";
/* api callbacks */ /* api callbacks */
ot->exec = gpencil_stroke_simplify_exec; ot->exec = gpencil_stroke_simplify_exec;
@ -4832,7 +4831,7 @@ void GPENCIL_OT_stroke_simplify_fixed(wmOperatorType *ot)
/* identifiers */ /* identifiers */
ot->name = "Simplify Fixed Stroke"; ot->name = "Simplify Fixed Stroke";
ot->idname = "GPENCIL_OT_stroke_simplify_fixed"; ot->idname = "GPENCIL_OT_stroke_simplify_fixed";
ot->description = "Simplify selected stroked reducing number of points using fixed algorithm"; ot->description = "Simplify selected strokes, reducing number of points using fixed algorithm";
/* api callbacks */ /* api callbacks */
ot->exec = gpencil_stroke_simplify_fixed_exec; ot->exec = gpencil_stroke_simplify_fixed_exec;

View File

@ -188,7 +188,7 @@ void GPENCIL_OT_stroke_editcurve_set_handle_type(wmOperatorType *ot)
/* identifiers */ /* identifiers */
ot->name = "Set handle type"; ot->name = "Set handle type";
ot->idname = "GPENCIL_OT_stroke_editcurve_set_handle_type"; ot->idname = "GPENCIL_OT_stroke_editcurve_set_handle_type";
ot->description = "Set the type of a edit curve handle"; ot->description = "Set the type of an edit curve handle";
/* api callbacks */ /* api callbacks */
ot->invoke = WM_menu_invoke; ot->invoke = WM_menu_invoke;

View File

@ -764,7 +764,7 @@ static short gpencil_stroke_addpoint(tGPsdata *p,
/* store settings */ /* store settings */
copy_v2_v2(pt->m_xy, mval); copy_v2_v2(pt->m_xy, mval);
/* #44932 - Pressure vals are unreliable, so ignore for now */ /* Pressure values are unreliable, so ignore for now, see #44932. */
pt->pressure = 1.0f; pt->pressure = 1.0f;
pt->strength = 1.0f; pt->strength = 1.0f;
pt->time = (float)(curtime - p->inittime); pt->time = (float)(curtime - p->inittime);
@ -780,7 +780,7 @@ static short gpencil_stroke_addpoint(tGPsdata *p,
/* store settings */ /* store settings */
copy_v2_v2(pt->m_xy, mval); copy_v2_v2(pt->m_xy, mval);
/* #44932 - Pressure vals are unreliable, so ignore for now */ /* Pressure values are unreliable, so ignore for now, see #44932. */
pt->pressure = 1.0f; pt->pressure = 1.0f;
pt->strength = 1.0f; pt->strength = 1.0f;
pt->time = (float)(curtime - p->inittime); pt->time = (float)(curtime - p->inittime);
@ -3685,7 +3685,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
} }
/* We don't pass on key events, GP is used with key-modifiers - /* We don't pass on key events, GP is used with key-modifiers -
* prevents Dkey to insert drivers. */ * prevents D-key to insert drivers. */
if (ISKEYBOARD(event->type)) { if (ISKEYBOARD(event->type)) {
if (ELEM(event->type, EVT_LEFTARROWKEY, EVT_DOWNARROWKEY, EVT_RIGHTARROWKEY, EVT_UPARROWKEY)) { if (ELEM(event->type, EVT_LEFTARROWKEY, EVT_DOWNARROWKEY, EVT_RIGHTARROWKEY, EVT_UPARROWKEY)) {
/* allow some keys: /* allow some keys:

View File

@ -49,12 +49,17 @@
#include "eyedropper_intern.hh" #include "eyedropper_intern.hh"
#include "interface_intern.hh" #include "interface_intern.hh"
typedef enum eGP_EyeMode {
GP_EYE_MATERIAL = 0,
GP_EYE_PALETTE = 1,
} eGP_EyeMode;
struct EyedropperGPencil { struct EyedropperGPencil {
struct ColorManagedDisplay *display; struct ColorManagedDisplay *display;
/** color under cursor RGB */ /** color under cursor RGB */
float color[3]; float color[3];
/** Mode */ /** Mode */
int mode; eGP_EyeMode mode;
}; };
/* Helper: Draw status message while the user is running the operator */ /* Helper: Draw status message while the user is running the operator */
@ -79,7 +84,7 @@ static bool eyedropper_gpencil_init(bContext *C, wmOperator *op)
display_device = scene->display_settings.display_device; display_device = scene->display_settings.display_device;
eye->display = IMB_colormanagement_display_get_named(display_device); eye->display = IMB_colormanagement_display_get_named(display_device);
eye->mode = RNA_enum_get(op->ptr, "mode"); eye->mode = (eGP_EyeMode)RNA_enum_get(op->ptr, "mode");
return true; return true;
} }
@ -228,10 +233,10 @@ static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, Eyed
float col_conv[4]; float col_conv[4];
/* Convert from linear rgb space to display space because grease pencil colors are in display /* Convert from linear rgb space to display space because palette colors are in display
* space, and this conversion is needed to undo the conversion to linear performed by * space, and this conversion is needed to undo the conversion to linear performed by
* eyedropper_color_sample_fl. */ * eyedropper_color_sample_fl. */
if (eye->display) { if ((eye->display) && (eye->mode == GP_EYE_PALETTE)) {
copy_v3_v3(col_conv, eye->color); copy_v3_v3(col_conv, eye->color);
IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display); IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
} }
@ -240,7 +245,7 @@ static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, Eyed
} }
/* Add material or Palette color. */ /* Add material or Palette color. */
if (eye->mode == 0) { if (eye->mode == GP_EYE_MATERIAL) {
eyedropper_add_material(C, col_conv, only_stroke, only_fill, both); eyedropper_add_material(C, col_conv, only_stroke, only_fill, both);
} }
else { else {
@ -348,8 +353,8 @@ static bool eyedropper_gpencil_poll(bContext *C)
void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot) void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot)
{ {
static const EnumPropertyItem items_mode[] = { static const EnumPropertyItem items_mode[] = {
{0, "MATERIAL", 0, "Material", ""}, {GP_EYE_MATERIAL, "MATERIAL", 0, "Material", ""},
{1, "PALETTE", 0, "Palette", ""}, {GP_EYE_PALETTE, "PALETTE", 0, "Palette", ""},
{0, nullptr, 0, nullptr, nullptr}, {0, nullptr, 0, nullptr, nullptr},
}; };
@ -369,5 +374,5 @@ void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
/* properties */ /* properties */
ot->prop = RNA_def_enum(ot->srna, "mode", items_mode, 0, "Mode", ""); ot->prop = RNA_def_enum(ot->srna, "mode", items_mode, GP_EYE_MATERIAL, "Mode", "");
} }

View File

@ -75,7 +75,7 @@ const EnumPropertyItem rna_enum_usd_mtl_name_collision_mode_items[] = {
const EnumPropertyItem rna_enum_usd_tex_import_mode_items[] = { const EnumPropertyItem rna_enum_usd_tex_import_mode_items[] = {
{USD_TEX_IMPORT_NONE, "IMPORT_NONE", 0, "None", "Don't import textures"}, {USD_TEX_IMPORT_NONE, "IMPORT_NONE", 0, "None", "Don't import textures"},
{USD_TEX_IMPORT_PACK, "IMPORT_PACK", 0, "Packed", "Import textures as packed data"}, {USD_TEX_IMPORT_PACK, "IMPORT_PACK", 0, "Packed", "Import textures as packed data"},
{USD_TEX_IMPORT_COPY, "IMPORT_COPY", 0, "Copy", "Copy files to Textures Directory"}, {USD_TEX_IMPORT_COPY, "IMPORT_COPY", 0, "Copy", "Copy files to textures directory"},
{0, NULL, 0, NULL, NULL}, {0, NULL, 0, NULL, NULL},
}; };
@ -382,6 +382,7 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
const bool import_materials = RNA_boolean_get(op->ptr, "import_materials"); const bool import_materials = RNA_boolean_get(op->ptr, "import_materials");
const bool import_meshes = RNA_boolean_get(op->ptr, "import_meshes"); const bool import_meshes = RNA_boolean_get(op->ptr, "import_meshes");
const bool import_volumes = RNA_boolean_get(op->ptr, "import_volumes"); const bool import_volumes = RNA_boolean_get(op->ptr, "import_volumes");
const bool import_shapes = RNA_boolean_get(op->ptr, "import_shapes");
const bool import_subdiv = RNA_boolean_get(op->ptr, "import_subdiv"); const bool import_subdiv = RNA_boolean_get(op->ptr, "import_subdiv");
@ -443,6 +444,7 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
.import_materials = import_materials, .import_materials = import_materials,
.import_meshes = import_meshes, .import_meshes = import_meshes,
.import_volumes = import_volumes, .import_volumes = import_volumes,
.import_shapes = import_shapes,
.import_subdiv = import_subdiv, .import_subdiv = import_subdiv,
.import_instance_proxies = import_instance_proxies, .import_instance_proxies = import_instance_proxies,
.create_collection = create_collection, .create_collection = create_collection,
@ -488,6 +490,7 @@ static void wm_usd_import_draw(bContext *UNUSED(C), wmOperator *op)
uiItemR(col, ptr, "import_materials", 0, NULL, ICON_NONE); uiItemR(col, ptr, "import_materials", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "import_meshes", 0, NULL, ICON_NONE); uiItemR(col, ptr, "import_meshes", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "import_volumes", 0, NULL, ICON_NONE); uiItemR(col, ptr, "import_volumes", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "import_shapes", 0, NULL, ICON_NONE);
uiItemR(box, ptr, "prim_path_mask", 0, NULL, ICON_NONE); uiItemR(box, ptr, "prim_path_mask", 0, NULL, ICON_NONE);
uiItemR(box, ptr, "scale", 0, NULL, ICON_NONE); uiItemR(box, ptr, "scale", 0, NULL, ICON_NONE);
@ -577,6 +580,7 @@ void WM_OT_usd_import(struct wmOperatorType *ot)
RNA_def_boolean(ot->srna, "import_materials", true, "Materials", ""); RNA_def_boolean(ot->srna, "import_materials", true, "Materials", "");
RNA_def_boolean(ot->srna, "import_meshes", true, "Meshes", ""); RNA_def_boolean(ot->srna, "import_meshes", true, "Meshes", "");
RNA_def_boolean(ot->srna, "import_volumes", true, "Volumes", ""); RNA_def_boolean(ot->srna, "import_volumes", true, "Volumes", "");
RNA_def_boolean(ot->srna, "import_shapes", true, "Shapes", "");
RNA_def_boolean(ot->srna, RNA_def_boolean(ot->srna,
"import_subdiv", "import_subdiv",
@ -675,7 +679,7 @@ void WM_OT_usd_import(struct wmOperatorType *ot)
"//textures/", "//textures/",
FILE_MAXDIR, FILE_MAXDIR,
"Textures Directory", "Textures Directory",
"Path to the directory where imported textures will be copied "); "Path to the directory where imported textures will be copied");
RNA_def_enum( RNA_def_enum(
ot->srna, ot->srna,

View File

@ -54,7 +54,7 @@ typedef struct {
BMBackup mesh_backup; BMBackup mesh_backup;
bool is_valid; bool is_valid;
bool is_dirty; bool is_dirty;
} * backup; } *backup;
int backup_len; int backup_len;
} BisectData; } BisectData;
@ -528,15 +528,7 @@ static void gizmo_mesh_bisect_update_from_op(GizmoGroup *ggd)
normalize_v3(ggd->data.rotate_up); normalize_v3(ggd->data.rotate_up);
WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_c, plane_no); WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_c, plane_no);
WM_gizmo_set_matrix_rotation_from_z_axis(ggd->rotate_c, ggd->data.rotate_axis);
float plane_no_cross[3];
cross_v3_v3v3(plane_no_cross, plane_no, ggd->data.rotate_axis);
WM_gizmo_set_matrix_offset_rotation_from_yz_axis(
ggd->rotate_c, plane_no_cross, ggd->data.rotate_axis);
RNA_enum_set(ggd->rotate_c->ptr,
"draw_options",
ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR | ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y);
} }
} }

View File

@ -410,7 +410,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
const bke::AttributeAccessor attributes = mesh->attributes(); const bke::AttributeAccessor attributes = mesh->attributes();
const VArraySpan<bool> select_poly = attributes.lookup_or_default<bool>( const VArraySpan<bool> select_poly = attributes.lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false); ".select_poly", ATTR_DOMAIN_FACE, false);
threading::parallel_for(IndexRange(mesh->totvert), 4096, [&](const IndexRange range) { threading::parallel_for(select_poly.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) { for (const int i : range) {
if (select_poly[i]) { if (select_poly[i]) {
ss->face_sets[i] = next_face_set; ss->face_sets[i] = next_face_set;

View File

@ -50,83 +50,84 @@
#define MARK_BOUNDARY 1 #define MARK_BOUNDARY 1
typedef struct UvAdjacencyElement { typedef struct UvAdjacencyElement {
/* pointer to original uvelement */ /** pointer to original UV-element. */
UvElement *element; UvElement *element;
/* uv pointer for convenience. Caution, this points to the original UVs! */ /** UV pointer for convenience. Caution, this points to the original UVs! */
float *uv; float *uv;
/* Are we on locked in place? */ /** Are we on locked in place? */
bool is_locked; bool is_locked;
/* Are we on the boundary? */ /** Are we on the boundary? */
bool is_boundary; bool is_boundary;
} UvAdjacencyElement; } UvAdjacencyElement;
typedef struct UvEdge { typedef struct UvEdge {
uint uv1; uint uv1;
uint uv2; uint uv2;
/* Are we in the interior? */ /** Are we in the interior? */
bool is_interior; bool is_interior;
} UvEdge; } UvEdge;
typedef struct UVInitialStrokeElement { typedef struct UVInitialStrokeElement {
/* index to unique uv */ /** index to unique UV. */
int uv; int uv;
/* strength of brush on initial position */ /** Strength of brush on initial position. */
float strength; float strength;
/* initial uv position */ /** initial UV position. */
float initial_uv[2]; float initial_uv[2];
} UVInitialStrokeElement; } UVInitialStrokeElement;
typedef struct UVInitialStroke { typedef struct UVInitialStroke {
/* Initial Selection,for grab brushes for instance */ /** Initial Selection,for grab brushes for instance. */
UVInitialStrokeElement *initialSelection; UVInitialStrokeElement *initialSelection;
/* Total initially selected UVs. */ /** Total initially selected UVs. */
int totalInitialSelected; int totalInitialSelected;
/* initial mouse coordinates */ /** Initial mouse coordinates. */
float init_coord[2]; float init_coord[2];
} UVInitialStroke; } UVInitialStroke;
/* custom data for uv smoothing brush */ /** Custom data for UV smoothing brush. */
typedef struct UvSculptData { typedef struct UvSculptData {
/* Contains the first of each set of coincident UVs. /**
* These will be used to perform smoothing on and propagate the changes * Contains the first of each set of coincident UVs.
* to their coincident UVs */ * These will be used to perform smoothing on and propagate the changes to their coincident UVs.
*/
UvAdjacencyElement *uv; UvAdjacencyElement *uv;
/* Total number of unique UVs. */ /** Total number of unique UVs. */
int totalUniqueUvs; int totalUniqueUvs;
/* Edges used for adjacency info, used with laplacian smoothing */ /** Edges used for adjacency info, used with laplacian smoothing */
UvEdge *uvedges; UvEdge *uvedges;
/* Total number of #UvEdge. */ /** Total number of #UvEdge. */
int totalUvEdges; int totalUvEdges;
/* data for initial stroke, used by tools like grab */ /** data for initial stroke, used by tools like grab */
UVInitialStroke *initial_stroke; UVInitialStroke *initial_stroke;
/* timer to be used for airbrush-type brush */ /** Timer to be used for airbrush-type brush. */
wmTimer *timer; wmTimer *timer;
/* to determine quickly adjacent UVs */ /** To determine quickly adjacent UVs. */
UvElementMap *elementMap; UvElementMap *elementMap;
/* uvsmooth Paint for fast reference */ /** UV-smooth Paint for fast reference. */
Paint *uvsculpt; Paint *uvsculpt;
/* tool to use. duplicating here to change if modifier keys are pressed */ /** Tool to use. duplicating here to change if modifier keys are pressed. */
char tool; char tool;
/* store invert flag here */ /** Store invert flag here. */
char invert; char invert;
/* Is constrain to image bounds active? */ /** Is constrain to image bounds active? */
bool constrain_to_bounds; bool constrain_to_bounds;
/* Base for constrain_to_bounds. */ /** Base for constrain_to_bounds. */
float uv_base_offset[2]; float uv_base_offset[2];
} UvSculptData; } UvSculptData;

View File

@ -586,7 +586,7 @@ void ED_animedit_unlink_action(
if (strip->act == act) { if (strip->act == act) {
/* Remove this strip, and the track too if it doesn't have anything else */ /* Remove this strip, and the track too if it doesn't have anything else */
BKE_nlastrip_free(&nlt->strips, strip, true); BKE_nlastrip_remove_and_free(&nlt->strips, strip, true);
if (nlt->strips.first == NULL) { if (nlt->strips.first == NULL) {
BLI_assert(nstrip == NULL); BLI_assert(nstrip == NULL);

View File

@ -986,7 +986,7 @@ void file_draw_list(const bContext *C, ARegion *region)
UI_GetThemeColor4ubv(TH_TEXT, text_col); UI_GetThemeColor4ubv(TH_TEXT, text_col);
for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) { for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
uint file_selflag; eDirEntry_SelectFlag file_selflag;
const int padx = 0.1f * UI_UNIT_X; const int padx = 0.1f * UI_UNIT_X;
int icon_ofs = 0; int icon_ofs = 0;

View File

@ -137,7 +137,7 @@ FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d,
float file_string_width(const char *str); float file_string_width(const char *str);
float file_font_pointsize(void); float file_font_pointsize(void);
void file_select_deselect_all(SpaceFile *sfile, uint flag); void file_select_deselect_all(SpaceFile *sfile, eDirEntry_SelectFlag flag);
int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file); int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file);
int autocomplete_directory(struct bContext *C, char *str, void *arg_v); int autocomplete_directory(struct bContext *C, char *str, void *arg_v);
int autocomplete_file(struct bContext *C, char *str, void *arg_v); int autocomplete_file(struct bContext *C, char *str, void *arg_v);

View File

@ -233,11 +233,15 @@ struct FileList {
FileListEntryCache filelist_cache; FileListEntryCache filelist_cache;
/* We need to keep those info outside of actual filelist items, /**
* We need to keep those info outside of actual file-list items,
* because those are no more persistent * because those are no more persistent
* (only generated on demand, and freed as soon as possible). * (only generated on demand, and freed as soon as possible).
* Persistent part (mere list of paths + stat info) * Persistent part (mere list of paths + stat info)
* is kept as small as possible, and file-browser agnostic. * is kept as small as possible, and file-browser agnostic.
*
* - The key is a #FileDirEntry::uid
* - The value is an #eDirEntry_SelectFlag.
*/ */
GHash *selection_state; GHash *selection_state;
@ -2737,13 +2741,13 @@ int filelist_needs_reading(FileList *filelist)
uint filelist_entry_select_set(const FileList *filelist, uint filelist_entry_select_set(const FileList *filelist,
const FileDirEntry *entry, const FileDirEntry *entry,
FileSelType select, FileSelType select,
uint flag, const eDirEntry_SelectFlag flag,
FileCheckType check) FileCheckType check)
{ {
/* Default nullptr pointer if not found is fine here! */ /* Default nullptr pointer if not found is fine here! */
void **es_p = BLI_ghash_lookup_p(filelist->selection_state, POINTER_FROM_UINT(entry->uid)); void **es_p = BLI_ghash_lookup_p(filelist->selection_state, POINTER_FROM_UINT(entry->uid));
uint entry_flag = es_p ? POINTER_AS_UINT(*es_p) : 0; eDirEntry_SelectFlag entry_flag = eDirEntry_SelectFlag(es_p ? POINTER_AS_UINT(*es_p) : 0);
const uint org_entry_flag = entry_flag; const eDirEntry_SelectFlag org_entry_flag = entry_flag;
BLI_assert(entry); BLI_assert(entry);
BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL)); BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL));
@ -2782,8 +2786,11 @@ uint filelist_entry_select_set(const FileList *filelist,
return entry_flag; return entry_flag;
} }
void filelist_entry_select_index_set( void filelist_entry_select_index_set(FileList *filelist,
FileList *filelist, const int index, FileSelType select, uint flag, FileCheckType check) const int index,
FileSelType select,
const eDirEntry_SelectFlag flag,
FileCheckType check)
{ {
FileDirEntry *entry = filelist_file(filelist, index); FileDirEntry *entry = filelist_file(filelist, index);
@ -2792,8 +2799,11 @@ void filelist_entry_select_index_set(
} }
} }
void filelist_entries_select_index_range_set( void filelist_entries_select_index_range_set(FileList *filelist,
FileList *filelist, FileSelection *sel, FileSelType select, uint flag, FileCheckType check) FileSelection *sel,
FileSelType select,
const eDirEntry_SelectFlag flag,
FileCheckType check)
{ {
/* select all valid files between first and last indicated */ /* select all valid files between first and last indicated */
if ((sel->first >= 0) && (sel->first < filelist->filelist.entries_filtered_num) && if ((sel->first >= 0) && (sel->first < filelist->filelist.entries_filtered_num) &&
@ -2805,7 +2815,9 @@ void filelist_entries_select_index_range_set(
} }
} }
uint filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileCheckType check) eDirEntry_SelectFlag filelist_entry_select_get(FileList *filelist,
FileDirEntry *entry,
FileCheckType check)
{ {
BLI_assert(entry); BLI_assert(entry);
BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL)); BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL));
@ -2813,14 +2825,16 @@ uint filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileChec
if ((check == CHECK_ALL) || ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) || if ((check == CHECK_ALL) || ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) ||
((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR))) { ((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR))) {
/* Default nullptr pointer if not found is fine here! */ /* Default nullptr pointer if not found is fine here! */
return POINTER_AS_UINT( return eDirEntry_SelectFlag(POINTER_AS_UINT(
BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(entry->uid))); BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(entry->uid))));
} }
return 0; return eDirEntry_SelectFlag(0);
} }
uint filelist_entry_select_index_get(FileList *filelist, const int index, FileCheckType check) eDirEntry_SelectFlag filelist_entry_select_index_get(FileList *filelist,
const int index,
FileCheckType check)
{ {
FileDirEntry *entry = filelist_file(filelist, index); FileDirEntry *entry = filelist_file(filelist, index);
@ -2828,7 +2842,7 @@ uint filelist_entry_select_index_get(FileList *filelist, const int index, FileCh
return filelist_entry_select_get(filelist, entry, check); return filelist_entry_select_get(filelist, entry, check);
} }
return 0; return eDirEntry_SelectFlag(0);
} }
bool filelist_entry_is_selected(FileList *filelist, const int index) bool filelist_entry_is_selected(FileList *filelist, const int index)
@ -2838,15 +2852,15 @@ bool filelist_entry_is_selected(FileList *filelist, const int index)
/* BLI_ghash_lookup returns nullptr if not found, which gets mapped to 0, which gets mapped to /* BLI_ghash_lookup returns nullptr if not found, which gets mapped to 0, which gets mapped to
* "not selected". */ * "not selected". */
const uint selection_state = POINTER_AS_UINT( const eDirEntry_SelectFlag selection_state = eDirEntry_SelectFlag(POINTER_AS_UINT(
BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(intern_entry->uid))); BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(intern_entry->uid))));
return selection_state != 0; return selection_state != 0;
} }
void filelist_entry_parent_select_set(FileList *filelist, void filelist_entry_parent_select_set(FileList *filelist,
FileSelType select, FileSelType select,
uint flag, const eDirEntry_SelectFlag flag,
FileCheckType check) FileCheckType check)
{ {
if ((filelist->filter_data.flags & FLF_HIDE_PARENT) == 0) { if ((filelist->filter_data.flags & FLF_HIDE_PARENT) == 0) {

View File

@ -148,31 +148,31 @@ bool filelist_is_ready(struct FileList *filelist);
unsigned int filelist_entry_select_set(const struct FileList *filelist, unsigned int filelist_entry_select_set(const struct FileList *filelist,
const struct FileDirEntry *entry, const struct FileDirEntry *entry,
FileSelType select, FileSelType select,
unsigned int flag, const eDirEntry_SelectFlag flag,
FileCheckType check); FileCheckType check);
void filelist_entry_select_index_set(struct FileList *filelist, void filelist_entry_select_index_set(struct FileList *filelist,
int index, int index,
FileSelType select, FileSelType select,
unsigned int flag, eDirEntry_SelectFlag flag,
FileCheckType check); FileCheckType check);
void filelist_entries_select_index_range_set(struct FileList *filelist, void filelist_entries_select_index_range_set(struct FileList *filelist,
FileSelection *sel, FileSelection *sel,
FileSelType select, FileSelType select,
unsigned int flag, eDirEntry_SelectFlag flag,
FileCheckType check);
unsigned int filelist_entry_select_get(struct FileList *filelist,
struct FileDirEntry *entry,
FileCheckType check);
unsigned int filelist_entry_select_index_get(struct FileList *filelist,
int index,
FileCheckType check); FileCheckType check);
eDirEntry_SelectFlag filelist_entry_select_get(struct FileList *filelist,
struct FileDirEntry *entry,
FileCheckType check);
eDirEntry_SelectFlag filelist_entry_select_index_get(struct FileList *filelist,
int index,
FileCheckType check);
bool filelist_entry_is_selected(struct FileList *filelist, int index); bool filelist_entry_is_selected(struct FileList *filelist, int index);
/** /**
* Set selection of the '..' parent entry, but only if it's actually visible. * Set selection of the '..' parent entry, but only if it's actually visible.
*/ */
void filelist_entry_parent_select_set(struct FileList *filelist, void filelist_entry_parent_select_set(struct FileList *filelist,
FileSelType select, FileSelType select,
unsigned int flag, eDirEntry_SelectFlag flag,
FileCheckType check); FileCheckType check);
void filelist_setrecursion(struct FileList *filelist, int recursion_level); void filelist_setrecursion(struct FileList *filelist, int recursion_level);

View File

@ -1124,7 +1124,7 @@ void ED_file_change_dir(bContext *C)
ED_file_change_dir_ex(C, area); ED_file_change_dir_ex(C, area);
} }
void file_select_deselect_all(SpaceFile *sfile, uint flag) void file_select_deselect_all(SpaceFile *sfile, const eDirEntry_SelectFlag flag)
{ {
FileSelection sel; FileSelection sel;
sel.first = 0; sel.first = 0;

View File

@ -1305,15 +1305,15 @@ static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op))
if (strip->flag & NLASTRIP_FLAG_SELECT) { if (strip->flag & NLASTRIP_FLAG_SELECT) {
/* if a strip either side of this was a transition, delete those too */ /* if a strip either side of this was a transition, delete those too */
if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) { if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) {
BKE_nlastrip_free(&nlt->strips, strip->prev, true); BKE_nlastrip_remove_and_free(&nlt->strips, strip->prev, true);
} }
if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) { if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
nstrip = nstrip->next; nstrip = nstrip->next;
BKE_nlastrip_free(&nlt->strips, strip->next, true); BKE_nlastrip_remove_and_free(&nlt->strips, strip->next, true);
} }
/* finally, delete this strip */ /* finally, delete this strip */
BKE_nlastrip_free(&nlt->strips, strip, true); BKE_nlastrip_remove_and_free(&nlt->strips, strip, true);
} }
} }
} }
@ -1824,7 +1824,7 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op))
if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) { if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) {
/* remove from its current track, and add to the one above /* remove from its current track, and add to the one above
* (it 'should' work, so no need to worry) */ * (it 'should' work, so no need to worry) */
BLI_remlink(&nlt->strips, strip); BKE_nlatrack_remove_strip(nlt, strip);
BKE_nlatrack_add_strip(nltn, strip, is_liboverride); BKE_nlatrack_add_strip(nltn, strip, is_liboverride);
} }
} }
@ -1916,7 +1916,7 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op))
if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) { if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) {
/* remove from its current track, and add to the one above /* remove from its current track, and add to the one above
* (it 'should' work, so no need to worry) */ * (it 'should' work, so no need to worry) */
BLI_remlink(&nlt->strips, strip); BKE_nlatrack_remove_strip(nlt, strip);
BKE_nlatrack_add_strip(nltp, strip, is_liboverride); BKE_nlatrack_add_strip(nltp, strip, is_liboverride);
} }
} }

View File

@ -148,7 +148,7 @@ static bool node_under_mouse_tweak(const bNodeTree &ntree, const float2 &mouse)
switch (node->type) { switch (node->type) {
case NODE_REROUTE: { case NODE_REROUTE: {
const float2 location = node_to_view(*node, {node->locx, node->locy}); const float2 location = node_to_view(*node, {node->locx, node->locy});
if (math::distance(mouse, location) < 24.0f) { if (math::distance_squared(mouse, location) < square_f(24.0f)) {
return true; return true;
} }
break; break;

View File

@ -3077,7 +3077,6 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
* generic attribute for now. */ * generic attribute for now. */
DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &curves_id); WM_event_add_notifier(C, NC_GEOM | ND_DATA, &curves_id);
return true;
} }
} }
} }

View File

@ -457,7 +457,7 @@ static void recalcData_nla(TransInfo *t)
if (BKE_nlatrack_has_space(track, strip->start, strip->end) && if (BKE_nlatrack_has_space(track, strip->start, strip->end) &&
!BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) { !BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) {
/* move strip to this track */ /* move strip to this track */
BLI_remlink(&tdn->nlt->strips, strip); BKE_nlatrack_remove_strip(tdn->nlt, strip);
BKE_nlatrack_add_strip(track, strip, is_liboverride); BKE_nlatrack_add_strip(track, strip, is_liboverride);
tdn->nlt = track; tdn->nlt = track;
@ -477,7 +477,7 @@ static void recalcData_nla(TransInfo *t)
if (BKE_nlatrack_has_space(track, strip->start, strip->end) && if (BKE_nlatrack_has_space(track, strip->start, strip->end) &&
!BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) { !BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) {
/* move strip to this track */ /* move strip to this track */
BLI_remlink(&tdn->nlt->strips, strip); BKE_nlatrack_remove_strip(tdn->nlt, strip);
BKE_nlatrack_add_strip(track, strip, is_liboverride); BKE_nlatrack_add_strip(track, strip, is_liboverride);
tdn->nlt = track; tdn->nlt = track;

View File

@ -50,15 +50,15 @@ static bool lib_id_preview_editing_poll(bContext *C)
return false; return false;
} }
if (ID_IS_LINKED(id)) { if (ID_IS_LINKED(id)) {
CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit external library data")); CTX_wm_operator_poll_msg_set(C, "Can't edit external library data");
return false; return false;
} }
if (ID_IS_OVERRIDE_LIBRARY(id)) { if (ID_IS_OVERRIDE_LIBRARY(id)) {
CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit previews of overridden library data")); CTX_wm_operator_poll_msg_set(C, "Can't edit previews of overridden library data");
return false; return false;
} }
if (!BKE_previewimg_id_get_p(id)) { if (!BKE_previewimg_id_get_p(id)) {
CTX_wm_operator_poll_msg_set(C, TIP_("Data-block does not support previews")); CTX_wm_operator_poll_msg_set(C, "Data-block does not support previews");
return false; return false;
} }
@ -118,7 +118,7 @@ static bool lib_id_generate_preview_poll(bContext *C)
const PointerRNA idptr = CTX_data_pointer_get(C, "id"); const PointerRNA idptr = CTX_data_pointer_get(C, "id");
const ID *id = (ID *)idptr.data; const ID *id = (ID *)idptr.data;
if (GS(id->name) == ID_NT) { if (GS(id->name) == ID_NT) {
CTX_wm_operator_poll_msg_set(C, TIP_("Can't generate automatic preview for node group")); CTX_wm_operator_poll_msg_set(C, "Can't generate automatic preview for node group");
return false; return false;
} }

View File

@ -71,7 +71,7 @@ void solve_length_and_collision_constraints(const OffsetIndices<int> points_by_c
BKE_bvhtree_from_mesh_get(&surface_bvh, &surface, BVHTREE_FROM_LOOPTRI, 2); BKE_bvhtree_from_mesh_get(&surface_bvh, &surface, BVHTREE_FROM_LOOPTRI, 2);
BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); }); BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); });
const float radius = 0.001f; const float radius = 0.005f;
const int max_collisions = 5; const int max_collisions = 5;
threading::parallel_for(curve_selection.index_range(), 64, [&](const IndexRange range) { threading::parallel_for(curve_selection.index_range(), 64, [&](const IndexRange range) {

View File

@ -104,6 +104,7 @@ set(SRC
GPU_primitive.h GPU_primitive.h
GPU_select.h GPU_select.h
GPU_shader.h GPU_shader.h
GPU_shader_builtin.h
GPU_shader_shared.h GPU_shader_shared.h
GPU_state.h GPU_state.h
GPU_storage_buffer.h GPU_storage_buffer.h

View File

@ -249,8 +249,10 @@ typedef enum {
} GPUUniformBuiltin; } GPUUniformBuiltin;
#define GPU_NUM_UNIFORMS (GPU_UNIFORM_SRGB_TRANSFORM + 1) #define GPU_NUM_UNIFORMS (GPU_UNIFORM_SRGB_TRANSFORM + 1)
/** TODO: To be moved as private API. Not really used outside of gpu_matrix.cc and doesn't really /**
* offer a noticeable perf boost. */ * TODO: To be moved as private API. Not really used outside of gpu_matrix.cc and doesn't really
* offer a noticeable performance boost.
*/
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin); int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin);
/** DEPRECATED: Use hardcoded buffer location instead. */ /** DEPRECATED: Use hardcoded buffer location instead. */

View File

@ -11,6 +11,11 @@
typedef struct TestOutputRawData TestOutputRawData; typedef struct TestOutputRawData TestOutputRawData;
#endif #endif
/* NOTE: float3 has differing stride and alignment rules across different GPU backends. If 12 byte
* stride and alignment is essential, use `packed_float3` to avoid data read issues. This is
* required in the common use-case where a float3 and an int/float are paired together for optimal
* data transfer. */
enum eGPUKeyframeShapes { enum eGPUKeyframeShapes {
GPU_KEYFRAME_SHAPE_DIAMOND = (1u << 0u), GPU_KEYFRAME_SHAPE_DIAMOND = (1u << 0u),
GPU_KEYFRAME_SHAPE_CIRCLE = (1u << 1u), GPU_KEYFRAME_SHAPE_CIRCLE = (1u << 1u),
@ -70,7 +75,7 @@ BLI_STATIC_ASSERT_ALIGN(struct GPUClipPlanes, 16)
struct SimpleLightingData { struct SimpleLightingData {
float4 l_color; float4 l_color;
float3 light; packed_float3 light;
float _pad; float _pad;
}; };
BLI_STATIC_ASSERT_ALIGN(struct SimpleLightingData, 16) BLI_STATIC_ASSERT_ALIGN(struct SimpleLightingData, 16)

View File

@ -59,6 +59,7 @@
# define bool2 bvec2 # define bool2 bvec2
# define bool3 bvec3 # define bool3 bvec3
# define bool4 bvec4 # define bool4 bvec4
# define packed_float3 vec3
# endif # endif
#else /* C / C++ */ #else /* C / C++ */
@ -83,6 +84,7 @@ using bool1 = int;
using bool2 = blender::int2; using bool2 = blender::int2;
using bool3 = blender::int3; using bool3 = blender::int3;
using bool4 = blender::int4; using bool4 = blender::int4;
using packed_float3 = blender::float3;
# else /* C */ # else /* C */
typedef float float2[2]; typedef float float2[2];
@ -99,6 +101,7 @@ typedef int bool1;
typedef int bool2[2]; typedef int bool2[2];
typedef int bool3[2]; typedef int bool3[2];
typedef int bool4[4]; typedef int bool4[4];
typedef float3 packed_float3;
# endif # endif
#endif #endif

View File

@ -810,6 +810,8 @@ struct GPUSource {
} }
dependencies.append_non_duplicates(dependency_source); dependencies.append_non_duplicates(dependency_source);
} }
/* Precedes an eternal loop (quiet CLANG's `unreachable-code` warning). */
BLI_assert_unreachable();
return 0; return 0;
} }

View File

@ -14,17 +14,17 @@ namespace blender::gpu {
/** /**
* `VK_ALLOCATION_CALLBACKS` initializes allocation callbacks for host allocations. * `VK_ALLOCATION_CALLBACKS` initializes allocation callbacks for host allocations.
* The macro creates a local static variable with the name `vk_allocation_callbacks` * The macro creates a local static variable with the name `vk_allocation_callbacks`
* that can be passed to vulkan API functions that expect * that can be passed to VULKAN API functions that expect
* `const VkAllocationCallbacks *pAllocator`. * `const VkAllocationCallbacks *pAllocator`.
* *
* When Blender is compiled with `WITH_VULKAN_GUARDEDALLOC` this will use * When Blender is compiled with `WITH_VULKAN_GUARDEDALLOC` this will use
* `MEM_guardedalloc` for host allocations that the driver does on behalf * `MEM_guardedalloc` for host allocations that the driver does on behalf
* of blender. More internal allocations are still being allocated via the * of blender. More internal allocations are still being allocated via the
* implemention inside the vulkan device driver. * implementation inside the VULKAN device driver.
* *
* When `WITH_VULKAN_GUARDEDALLOC=Off` the memory allocation implemented * When `WITH_VULKAN_GUARDEDALLOC=Off` the memory allocation implemented
* in the vulkan device driver is used for both internal and application * in the vulkan device driver is used for both internal and application
* focussed memory operations. * focused memory operations.
*/ */
#ifdef WITH_VULKAN_GUARDEDALLOC #ifdef WITH_VULKAN_GUARDEDALLOC

View File

@ -83,6 +83,7 @@ set(SRC
intern/usd_reader_mesh.cc intern/usd_reader_mesh.cc
intern/usd_reader_nurbs.cc intern/usd_reader_nurbs.cc
intern/usd_reader_prim.cc intern/usd_reader_prim.cc
intern/usd_reader_shape.cc
intern/usd_reader_stage.cc intern/usd_reader_stage.cc
intern/usd_reader_volume.cc intern/usd_reader_volume.cc
intern/usd_reader_xform.cc intern/usd_reader_xform.cc
@ -111,6 +112,7 @@ set(SRC
intern/usd_reader_mesh.h intern/usd_reader_mesh.h
intern/usd_reader_nurbs.h intern/usd_reader_nurbs.h
intern/usd_reader_prim.h intern/usd_reader_prim.h
intern/usd_reader_shape.h
intern/usd_reader_stage.h intern/usd_reader_stage.h
intern/usd_reader_volume.h intern/usd_reader_volume.h
intern/usd_reader_xform.h intern/usd_reader_xform.h
@ -145,8 +147,8 @@ blender_add_lib(bf_usd "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
if(WITH_GTESTS) if(WITH_GTESTS)
set(TEST_SRC set(TEST_SRC
tests/usd_stage_creation_test.cc
tests/usd_export_test.cc tests/usd_export_test.cc
tests/usd_stage_creation_test.cc
tests/usd_tests_common.cc tests/usd_tests_common.cc
tests/usd_tests_common.h tests/usd_tests_common.h

View File

@ -0,0 +1,245 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Nvidia. All rights reserved. */
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "DNA_cachefile_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_windowmanager_types.h"
#include "WM_api.h"
#include "usd_reader_shape.h"
#include <pxr/usd/usdGeom/capsule.h>
#include <pxr/usd/usdGeom/cone.h>
#include <pxr/usd/usdGeom/cube.h>
#include <pxr/usd/usdGeom/cylinder.h>
#include <pxr/usd/usdGeom/sphere.h>
#include <pxr/usdImaging/usdImaging/capsuleAdapter.h>
#include <pxr/usdImaging/usdImaging/coneAdapter.h>
#include <pxr/usdImaging/usdImaging/cubeAdapter.h>
#include <pxr/usdImaging/usdImaging/cylinderAdapter.h>
#include <pxr/usdImaging/usdImaging/sphereAdapter.h>
namespace blender::io::usd {
USDShapeReader::USDShapeReader(const pxr::UsdPrim &prim,
const USDImportParams &import_params,
const ImportSettings &settings)
: USDGeomReader(prim, import_params, settings)
{
}
void USDShapeReader::create_object(Main *bmain, double /*motionSampleTime*/)
{
Mesh *mesh = BKE_mesh_add(bmain, name_.c_str());
object_ = BKE_object_add_only_object(bmain, OB_MESH, name_.c_str());
object_->data = mesh;
}
void USDShapeReader::read_object_data(Main *bmain, double motionSampleTime)
{
Mesh *mesh = (Mesh *)object_->data;
Mesh *read_mesh = this->read_mesh(
mesh, motionSampleTime, import_params_.mesh_read_flag, nullptr);
if (read_mesh != mesh) {
BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_);
if (is_time_varying()) {
USDGeomReader::add_cache_modifier();
}
}
USDXformReader::read_object_data(bmain, motionSampleTime);
}
template<typename Adapter>
void USDShapeReader::read_values(const double motionSampleTime,
pxr::VtVec3fArray &positions,
pxr::VtIntArray &face_indices,
pxr::VtIntArray &face_counts) const
{
Adapter adapter;
pxr::VtValue points_val = adapter.GetPoints(prim_, motionSampleTime);
if (points_val.IsHolding<pxr::VtVec3fArray>()) {
positions = points_val.Get<pxr::VtVec3fArray>();
}
pxr::VtValue topology_val = adapter.GetTopology(prim_, pxr::SdfPath(), motionSampleTime);
if (topology_val.IsHolding<pxr::HdMeshTopology>()) {
const pxr::HdMeshTopology &topology = topology_val.Get<pxr::HdMeshTopology>();
face_counts = topology.GetFaceVertexCounts();
face_indices = topology.GetFaceVertexIndices();
}
}
bool USDShapeReader::read_mesh_values(double motionSampleTime,
pxr::VtVec3fArray &positions,
pxr::VtIntArray &face_indices,
pxr::VtIntArray &face_counts) const
{
if (prim_.IsA<pxr::UsdGeomCapsule>()) {
read_values<pxr::UsdImagingCapsuleAdapter>(
motionSampleTime, positions, face_indices, face_counts);
return true;
}
if (prim_.IsA<pxr::UsdGeomCylinder>()) {
read_values<pxr::UsdImagingCylinderAdapter>(
motionSampleTime, positions, face_indices, face_counts);
return true;
}
if (prim_.IsA<pxr::UsdGeomCone>()) {
read_values<pxr::UsdImagingConeAdapter>(
motionSampleTime, positions, face_indices, face_counts);
return true;
}
if (prim_.IsA<pxr::UsdGeomCube>()) {
read_values<pxr::UsdImagingCubeAdapter>(
motionSampleTime, positions, face_indices, face_counts);
return true;
}
if (prim_.IsA<pxr::UsdGeomSphere>()) {
read_values<pxr::UsdImagingSphereAdapter>(
motionSampleTime, positions, face_indices, face_counts);
return true;
}
WM_reportf(RPT_ERROR,
"Unhandled Gprim type: %s (%s)",
prim_.GetTypeName().GetText(),
prim_.GetPath().GetText());
return false;
}
Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh,
double motionSampleTime,
int /*read_flag*/,
const char ** /*err_str*/)
{
pxr::VtIntArray face_indices;
pxr::VtIntArray face_counts;
if (!prim_) {
return existing_mesh;
}
/* Should have a good set of data by this point-- copy over. */
Mesh *active_mesh = mesh_from_prim(existing_mesh, motionSampleTime, face_indices, face_counts);
if (active_mesh == existing_mesh) {
return existing_mesh;
}
MutableSpan<MPoly> polys = active_mesh->polys_for_write();
MutableSpan<MLoop> loops = active_mesh->loops_for_write();
const char should_smooth = prim_.IsA<pxr::UsdGeomCube>() ? 0 : ME_SMOOTH;
int loop_index = 0;
for (int i = 0; i < face_counts.size(); i++) {
const int face_size = face_counts[i];
MPoly &poly = polys[i];
poly.loopstart = loop_index;
poly.totloop = face_size;
/* Don't smooth-shade cubes; we're not worrying about sharpness for Gprims. */
poly.flag |= should_smooth;
for (int f = 0; f < face_size; ++f, ++loop_index) {
loops[loop_index].v = face_indices[loop_index];
}
}
BKE_mesh_calc_edges(active_mesh, false, false);
return active_mesh;
}
Mesh *USDShapeReader::mesh_from_prim(Mesh *existing_mesh,
double motionSampleTime,
pxr::VtIntArray &face_indices,
pxr::VtIntArray &face_counts) const
{
pxr::VtVec3fArray positions;
if (!read_mesh_values(motionSampleTime, positions, face_indices, face_counts)) {
return existing_mesh;
}
const bool poly_counts_match = existing_mesh ? face_counts.size() == existing_mesh->totpoly :
false;
const bool position_counts_match = existing_mesh ? positions.size() == existing_mesh->totvert :
false;
Mesh *active_mesh = nullptr;
if (!position_counts_match || !poly_counts_match) {
active_mesh = BKE_mesh_new_nomain_from_template(
existing_mesh, positions.size(), 0, 0, face_indices.size(), face_counts.size());
}
else {
active_mesh = existing_mesh;
}
MutableSpan<float3> vert_positions = active_mesh->vert_positions_for_write();
for (int i = 0; i < positions.size(); i++) {
vert_positions[i][0] = positions[i][0];
vert_positions[i][1] = positions[i][1];
vert_positions[i][2] = positions[i][2];
}
return active_mesh;
}
bool USDShapeReader::is_time_varying()
{
if (prim_.IsA<pxr::UsdGeomCapsule>()) {
pxr::UsdGeomCapsule geom(prim_);
return (geom.GetAxisAttr().ValueMightBeTimeVarying() ||
geom.GetHeightAttr().ValueMightBeTimeVarying() ||
geom.GetRadiusAttr().ValueMightBeTimeVarying());
}
if (prim_.IsA<pxr::UsdGeomCylinder>()) {
pxr::UsdGeomCylinder geom(prim_);
return (geom.GetAxisAttr().ValueMightBeTimeVarying() ||
geom.GetHeightAttr().ValueMightBeTimeVarying() ||
geom.GetRadiusAttr().ValueMightBeTimeVarying());
}
if (prim_.IsA<pxr::UsdGeomCone>()) {
pxr::UsdGeomCone geom(prim_);
return (geom.GetAxisAttr().ValueMightBeTimeVarying() ||
geom.GetHeightAttr().ValueMightBeTimeVarying() ||
geom.GetRadiusAttr().ValueMightBeTimeVarying());
}
if (prim_.IsA<pxr::UsdGeomCube>()) {
pxr::UsdGeomCube geom(prim_);
return geom.GetSizeAttr().ValueMightBeTimeVarying();
}
if (prim_.IsA<pxr::UsdGeomSphere>()) {
pxr::UsdGeomSphere geom(prim_);
return geom.GetRadiusAttr().ValueMightBeTimeVarying();
}
WM_reportf(RPT_ERROR,
"Unhandled Gprim type: %s (%s)",
prim_.GetTypeName().GetText(),
prim_.GetPath().GetText());
return false;
}
} // namespace blender::io::usd

View File

@ -0,0 +1,62 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Nvidia. All rights reserved. */
#pragma once
#include "usd.h"
#include "usd_reader_geom.h"
#include "usd_reader_xform.h"
#include <pxr/usd/usdGeom/gprim.h>
struct Mesh;
namespace blender::io::usd {
/*
* Read USDGeom primitive shapes as Blender Meshes. This class uses the same adapter functions
* as the GL viewport to generate geometry for each of the supported types.
*/
class USDShapeReader : public USDGeomReader {
private:
/* Template required to read mesh information out of Shape prims,
* as each prim type has a separate subclass. */
template<typename Adapter>
void read_values(double motionSampleTime,
pxr::VtVec3fArray &positions,
pxr::VtIntArray &face_indices,
pxr::VtIntArray &face_counts) const;
/* Wrapper for the templated method read_values, calling the correct template
* instantiation based on the introspected prim type. */
bool read_mesh_values(double motionSampleTime,
pxr::VtVec3fArray &positions,
pxr::VtIntArray &face_indices,
pxr::VtIntArray &face_counts) const;
/* Read the pxr:UsdGeomMesh values and convert them to a Blender Mesh,
* also returning face_indices and counts for further loop processing. */
Mesh *mesh_from_prim(Mesh *existing_mesh,
double motionSampleTime,
pxr::VtIntArray &face_indices,
pxr::VtIntArray &face_counts) const;
public:
USDShapeReader(const pxr::UsdPrim &prim,
const USDImportParams &import_params,
const ImportSettings &settings);
void create_object(Main *bmain, double /*motionSampleTime*/) override;
void read_object_data(Main *bmain, double motionSampleTime) override;
Mesh *read_mesh(Mesh *existing_mesh,
double motionSampleTime,
int /*read_flag*/,
const char ** /*err_str*/) override;
bool is_time_varying();
virtual bool topology_changed(const Mesh * /*existing_mesh*/, double /*motionSampleTime*/)
{
return false;
};
};
} // namespace blender::io::usd

View File

@ -9,16 +9,22 @@
#include "usd_reader_mesh.h" #include "usd_reader_mesh.h"
#include "usd_reader_nurbs.h" #include "usd_reader_nurbs.h"
#include "usd_reader_prim.h" #include "usd_reader_prim.h"
#include "usd_reader_shape.h"
#include "usd_reader_volume.h" #include "usd_reader_volume.h"
#include "usd_reader_xform.h" #include "usd_reader_xform.h"
#include <pxr/pxr.h> #include <pxr/pxr.h>
#include <pxr/usd/usd/primRange.h> #include <pxr/usd/usd/primRange.h>
#include <pxr/usd/usdGeom/camera.h> #include <pxr/usd/usdGeom/camera.h>
#include <pxr/usd/usdGeom/capsule.h>
#include <pxr/usd/usdGeom/cone.h>
#include <pxr/usd/usdGeom/cube.h>
#include <pxr/usd/usdGeom/curves.h> #include <pxr/usd/usdGeom/curves.h>
#include <pxr/usd/usdGeom/cylinder.h>
#include <pxr/usd/usdGeom/mesh.h> #include <pxr/usd/usdGeom/mesh.h>
#include <pxr/usd/usdGeom/nurbsCurves.h> #include <pxr/usd/usdGeom/nurbsCurves.h>
#include <pxr/usd/usdGeom/scope.h> #include <pxr/usd/usdGeom/scope.h>
#include <pxr/usd/usdGeom/sphere.h>
#include <pxr/usd/usdGeom/xform.h> #include <pxr/usd/usdGeom/xform.h>
#include <pxr/usd/usdShade/material.h> #include <pxr/usd/usdShade/material.h>
@ -57,8 +63,18 @@ bool USDStageReader::valid() const
return stage_; return stage_;
} }
bool USDStageReader::is_primitive_prim(const pxr::UsdPrim &prim) const
{
return (prim.IsA<pxr::UsdGeomCapsule>() || prim.IsA<pxr::UsdGeomCylinder>() ||
prim.IsA<pxr::UsdGeomCone>() || prim.IsA<pxr::UsdGeomCube>() ||
prim.IsA<pxr::UsdGeomSphere>());
}
USDPrimReader *USDStageReader::create_reader_if_allowed(const pxr::UsdPrim &prim) USDPrimReader *USDStageReader::create_reader_if_allowed(const pxr::UsdPrim &prim)
{ {
if (params_.import_shapes && is_primitive_prim(prim)) {
return new USDShapeReader(prim, params_, settings_);
}
if (params_.import_cameras && prim.IsA<pxr::UsdGeomCamera>()) { if (params_.import_cameras && prim.IsA<pxr::UsdGeomCamera>()) {
return new USDCameraReader(prim, params_, settings_); return new USDCameraReader(prim, params_, settings_);
} }
@ -91,6 +107,9 @@ USDPrimReader *USDStageReader::create_reader_if_allowed(const pxr::UsdPrim &prim
USDPrimReader *USDStageReader::create_reader(const pxr::UsdPrim &prim) USDPrimReader *USDStageReader::create_reader(const pxr::UsdPrim &prim)
{ {
if (is_primitive_prim(prim)) {
return new USDShapeReader(prim, params_, settings_);
}
if (prim.IsA<pxr::UsdGeomCamera>()) { if (prim.IsA<pxr::UsdGeomCamera>()) {
return new USDCameraReader(prim, params_, settings_); return new USDCameraReader(prim, params_, settings_);
} }

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