Mesh: Set active attribute values edit mode operator #104426

Merged
Hans Goudey merged 8 commits from HooglyBoogly/blender:mesh-edit-attribute-set-operator into main 2023-02-15 04:35:03 +01:00
130 changed files with 1915 additions and 912 deletions
Showing only changes of commit 9004cfdd32 - Show all commits

View File

@ -524,7 +524,7 @@ endif()
if(NOT APPLE)
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" ON)
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(CYCLES_HIP_BINARIES_ARCH)
endif()

View File

@ -299,7 +299,11 @@ else
ifneq ("$(wildcard $(DEPS_BUILD_DIR)/build.ninja)","")
DEPS_BUILD_COMMAND:=ninja
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
@ -398,7 +402,7 @@ endif
deps: .FORCE
@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)" \
-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

@ -295,7 +295,7 @@ unset(MATERIALX_LIB_FOLDER_EXISTS)
if(NOT MSVC_CLANG AND # Available with MSVC 15.7+ but not for CLANG.
NOT WITH_WINDOWS_SCCACHE AND # And not when sccache is enabled
NOT VS_CLANG_TIDY) # Clang-tidy does not like these options
add_compile_options(/experimental:external /external:templates- /external:I "${LIBDIR}" /external:W0)
add_compile_options(/experimental:external /external:I "${LIBDIR}" /external:W0)
endif()
# Add each of our libraries to our cmake_prefix_path so find_package() could work

View File

@ -487,7 +487,7 @@ BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
if BLENDER_REVISION != "Unknown":
# SHA1 Git hash
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_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,
)
return "Undocumented, consider `contributing <https://developer.blender.org/T51061>`__."
return "Undocumented, consider `contributing <https://developer.blender.org/>`__."
def range_str(val):

View File

@ -1679,12 +1679,12 @@ class CyclesPreferences(bpy.types.AddonPreferences):
import sys
if sys.platform[:3] == "win":
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,
icon='BLANK1', translate=False)
elif sys.platform.startswith("linux"):
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',
translate=False)
elif device_type == 'ONEAPI':

View File

@ -51,7 +51,7 @@ static inline bool hipSupportsDevice(const int hipDevId)
hipDeviceGetAttribute(&major, hipDeviceAttributeComputeCapabilityMajor, hipDevId);
hipDeviceGetAttribute(&minor, hipDeviceAttributeComputeCapabilityMinor, hipDevId);
return (major >= 10);
return (major >= 9);
}
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.
* The idea is to have enough information on the screen by increasing the sample count as the
* resolution is decreased. */
/* NOTE: Changeing this formula will change the formula in
* "RenderScheduler::calculate_resolution_divider_for_time()"*/
/* NOTE: Changing this formula will change the formula in
* `RenderScheduler::calculate_resolution_divider_for_time()`. */
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;
/* 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:
* "actual_time / desired_time = sqr(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
* substitution we end up with "actual_time / desired_time = resolution_divider" while the
* `actual_time / desired_time = sqr(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
* 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,
* the relationsip of "actual_time / desired_time = resolution_divider" is no longer true,
* however the sample count retrieved from "get_num_samples_during_navigation()" is still
* 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
* 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
* why pixel_size isn't included in any of the equations. */
* `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. */
const int navigation_samples = get_num_samples_during_navigation(
ceil_to_int(ratio_between_times));

View File

@ -412,11 +412,12 @@ if(WITH_CYCLES_CUDA_BINARIES)
# warn for other versions
if((CUDA_VERSION STREQUAL "101") OR
(CUDA_VERSION STREQUAL "102") OR
(CUDA_VERSION_MAJOR STREQUAL "11"))
(CUDA_VERSION_MAJOR STREQUAL "11") OR
(CUDA_VERSION_MAJOR STREQUAL "12"))
else()
message(WARNING
"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()
# build for each arch
@ -514,6 +515,16 @@ if(WITH_CYCLES_CUDA_BINARIES)
else()
message(STATUS "CUDA binaries for ${arch} require CUDA 10 or earlier, skipped.")
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)
message(STATUS "CUDA binaries for ${arch} require CUDA 10.0+, skipped.")
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;
break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
albedo *= bsdf_principled_hair_albedo(sc);
albedo *= bsdf_principled_hair_albedo(sd, sc);
break;
default:
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;
}
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;
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

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)
{
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) {
/* Support #ptr being null, because C++ `delete` supports that as well. */
return;

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.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.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.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"),
@ -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.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.mesh.bridge_edge_loops*", "modeling/meshes/editing/edge/bridge_edge_loops.html#bpy-ops-mesh-bridge-edge-loops"),
("bpy.ops.mesh.intersect_boolean*", "modeling/meshes/editing/face/intersect_boolean.html#bpy-ops-mesh-intersect-boolean"),
("bpy.ops.mesh.loop_multi_select*", "modeling/meshes/selecting/loops.html#bpy-ops-mesh-loop-multi-select"),
("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.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.jitter*", "sculpt_paint/brush/stroke.html#bpy-types-brush-jitter"),
("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.geometrynode*", "modeling/geometry_nodes/index.html#bpy-types-geometrynode"),

View File

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

View File

@ -6,8 +6,8 @@ from bpy.types import Operator
from bpy.app.translations import pgettext_data as data_
def geometry_node_group_empty_new():
group = bpy.data.node_groups.new(data_("Geometry Nodes"), 'GeometryNodeTree')
def build_default_empty_geometry_node_group(name):
group = bpy.data.node_groups.new(name, 'GeometryNodeTree')
group.inputs.new('NodeSocketGeometry', data_("Geometry"))
group.outputs.new('NodeSocketGeometry', data_("Geometry"))
input_node = group.nodes.new('NodeGroupInput')
@ -20,8 +20,12 @@ def geometry_node_group_empty_new():
input_node.location.x = -200 - input_node.width
output_node.location.x = 200
group.links.new(output_node.inputs[0], input_node.outputs[0])
return group
def geometry_node_group_empty_new():
group = build_default_empty_geometry_node_group(data_("Geometry Nodes"))
group.links.new(group.nodes["Group Input"].outputs[0], group.nodes["Group Output"].inputs[0])
return group
@ -35,6 +39,158 @@ def geometry_modifier_poll(context):
return True
def get_context_modifier(context):
if context.area.type == 'PROPERTIES':
modifier = context.modifier
else:
modifier = context.object.modifiers.active
if modifier is None or modifier.type != 'NODES':
return None
return modifier
def edit_geometry_nodes_modifier_poll(context):
return get_context_modifier(context) is not None
def socket_idname_to_attribute_type(idname):
if idname.startswith("NodeSocketInt"):
return "INT"
elif idname.startswith("NodeSocketColor"):
return "FLOAT_COLOR"
elif idname.startswith("NodeSocketVector"):
return "FLOAT_VECTOR"
elif idname.startswith("NodeSocketBool"):
return "BOOLEAN"
elif idname.startswith("NodeSocketFloat"):
return "FLOAT"
raise ValueError("Unsupported socket type")
return ""
def modifier_attribute_name_get(modifier, identifier):
try:
return modifier[identifier + "_attribute_name"]
except KeyError:
return None
def modifier_input_use_attribute(modifier, identifier):
try:
return modifier[identifier + "_use_attribute"] != 0
except KeyError:
return False
def get_socket_with_identifier(sockets, identifier):
for socket in sockets:
if socket.identifier == identifier:
return socket
return None
def get_enabled_socket_with_name(sockets, name):
for socket in sockets:
if socket.name == name and socket.enabled:
return socket
return None
class MoveModifierToNodes(Operator):
"""Move inputs and outputs from in the modifier to a new node group"""
bl_idname = "object.geometry_nodes_move_to_nodes"
bl_label = "Move to Nodes"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return edit_geometry_nodes_modifier_poll(context)
def execute(self, context):
modifier = get_context_modifier(context)
if not modifier:
return {'CANCELLED'}
old_group = modifier.node_group
if not old_group:
return {'CANCELLED'}
wrapper_name = old_group.name + ".wrapper"
group = build_default_empty_geometry_node_group(wrapper_name)
group_node = group.nodes.new("GeometryNodeGroup")
group_node.node_tree = old_group
group_node.update()
group_input_node = group.nodes["Group Input"]
group_output_node = group.nodes["Group Output"]
# Copy default values for inputs and create named attribute input nodes.
input_nodes = []
first_geometry_input = None
for input_socket in old_group.inputs:
identifier = input_socket.identifier
group_node_input = get_socket_with_identifier(group_node.inputs, identifier)
if modifier_input_use_attribute(modifier, identifier):
input_node = group.nodes.new("GeometryNodeInputNamedAttribute")
input_nodes.append(input_node)
input_node.data_type = socket_idname_to_attribute_type(input_socket.bl_socket_idname)
attribute_name = modifier_attribute_name_get(modifier, identifier)
input_node.inputs["Name"].default_value = attribute_name
output_socket = get_enabled_socket_with_name(input_node.outputs, "Attribute")
group.links.new(output_socket, group_node_input)
elif hasattr(input_socket, "default_value"):
group_node_input.default_value = modifier[identifier]
elif input_socket.bl_socket_idname == 'NodeSocketGeometry':
if not first_geometry_input:
first_geometry_input = group_node_input
group.links.new(group_input_node.outputs[0], first_geometry_input)
# Adjust locations of named attribute input nodes and group input node to make some space.
if input_nodes:
for i, node in enumerate(input_nodes):
node.location.x = -175
node.location.y = i * -50
group_input_node.location.x = -350
# Connect outputs to store named attribute nodes to replace modifier attribute outputs.
store_nodes = []
first_geometry_output = None
for output_socket in old_group.outputs:
identifier = output_socket.identifier
group_node_output = get_socket_with_identifier(group_node.outputs, identifier)
attribute_name = modifier_attribute_name_get(modifier, identifier)
if attribute_name:
store_node = group.nodes.new("GeometryNodeStoreNamedAttribute")
store_nodes.append(store_node)
store_node.data_type = socket_idname_to_attribute_type(output_socket.bl_socket_idname)
store_node.domain = output_socket.attribute_domain
store_node.inputs["Name"].default_value = attribute_name
input_socket = get_enabled_socket_with_name(store_node.inputs, "Value")
group.links.new(group_node_output, input_socket)
elif output_socket.bl_socket_idname == 'NodeSocketGeometry':
if not first_geometry_output:
first_geometry_output = group_node_output
# Adjust locations of store named attribute nodes and move group output.
if store_nodes:
for i, node in enumerate(store_nodes):
node.location.x = (i + 1) * 175
node.location.y = 0
group_output_node.location.x = (len(store_nodes) + 1) * 175
group.links.new(first_geometry_output, store_nodes[0].inputs["Geometry"])
for i in range(len(store_nodes) - 1):
group.links.new(store_nodes[i].outputs["Geometry"], store_nodes[i + 1].inputs["Geometry"])
group.links.new(store_nodes[-1].outputs["Geometry"], group_output_node.inputs["Geometry"])
else:
group.links.new(first_geometry_output, group_output_node.inputs["Geometry"])
modifier.node_group = group
return {'FINISHED'}
class NewGeometryNodesModifier(Operator):
"""Create a new modifier with a new geometry node group"""
@ -48,7 +204,6 @@ class NewGeometryNodesModifier(Operator):
def execute(self, context):
modifier = context.object.modifiers.new(data_("GeometryNodes"), "NODES")
if not modifier:
return {'CANCELLED'}
@ -70,11 +225,7 @@ class NewGeometryNodeTreeAssign(Operator):
return geometry_modifier_poll(context)
def execute(self, context):
if context.area.type == 'PROPERTIES':
modifier = context.modifier
else:
modifier = context.object.modifiers.active
modifier = get_context_modifier(context)
if not modifier:
return {'CANCELLED'}
@ -87,4 +238,5 @@ class NewGeometryNodeTreeAssign(Operator):
classes = (
NewGeometryNodesModifier,
NewGeometryNodeTreeAssign,
MoveModifierToNodes,
)

View File

@ -1249,7 +1249,31 @@ class WM_OT_doc_view_manual(Operator):
# 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.
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:
# 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 verbose:
print(" match found: '%s' --> '%s'" % (pattern, url_suffix))

View File

@ -1141,6 +1141,11 @@ def brush_texture_settings(layout, brush, sculpt):
# texture_sample_bias
layout.prop(brush, "texture_sample_bias", slider=True, text="Sample Bias")
if brush.sculpt_tool == 'DRAW':
col = layout.column()
col.active = tex_slot.map_mode == 'AREA_PLANE'
col.prop(brush, "use_color_as_displacement", text="Vector Displacement")
def brush_mask_texture_settings(layout, brush):
mask_tex_slot = brush.mask_texture_slot

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"
def draw(self, context):
self._draw_items(context,
(({"property": "use_sculpt_tools_tilt"},
("blender/blender/issues/82877",
"#82877")),
({"property": "use_extended_asset_browser"},
("blender/blender/projects/10",
"Pipeline, Assets & IO Project Page")),
({"property": "use_override_templates"},
("blender/blender/issues/73318",
"Milestone 4")),
({"property": "use_new_volume_nodes"},
("blender/blender/issues/103248",
"#103248")),
),
)
self._draw_items(
context, (
({"property": "use_sculpt_tools_tilt"}, ("blender/blender/issues/82877", "#82877")),
({"property": "use_extended_asset_browser"},
("blender/blender/projects/10", "Pipeline, Assets & IO Project Page")),
({"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):

View File

@ -6756,6 +6756,13 @@ class VIEW3D_PT_overlay_sculpt_curves(Panel):
row.active = overlay.show_overlays
row.prop(overlay, "sculpt_mode_mask_opacity", text="Selection Opacity")
row = layout.row(align=True)
row.active = overlay.show_overlays
row.prop(overlay, "sculpt_curves_cage", text="")
subrow = row.row(align=True)
subrow.active = overlay.sculpt_curves_cage
subrow.prop(overlay, "sculpt_curves_cage_opacity", text="Cage Opacity")
class VIEW3D_PT_overlay_bones(Panel):
bl_space_type = 'VIEW_3D'

View File

@ -67,6 +67,9 @@ class AssetLibrary {
std::unique_ptr<AssetCatalogService> catalog_service;
/** Assets owned by this library should never be linked. */
bool never_link = false;
friend class AssetLibraryService;
public:

View File

@ -22,6 +22,8 @@ const char *AS_asset_representation_name_get(const AssetRepresentation *asset)
AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
bool AS_asset_representation_is_local_id(const AssetRepresentation *asset) ATTR_WARN_UNUSED_RESULT;
bool AS_asset_representation_is_never_link(const AssetRepresentation *asset)
ATTR_WARN_UNUSED_RESULT;
#ifdef __cplusplus
}

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup asset_system
*/
#pragma once
#include "BLI_string_ref.hh"
namespace blender::asset_system {
StringRefNull essentials_directory_path();
}

View File

@ -17,6 +17,7 @@ set(SRC
intern/asset_catalog.cc
intern/asset_catalog_path.cc
intern/asset_catalog_tree.cc
intern/asset_essentials_library.cc
intern/asset_identifier.cc
intern/asset_library.cc
intern/asset_library_service.cc
@ -30,6 +31,7 @@ set(SRC
AS_asset_identifier.hh
AS_asset_library.hh
AS_asset_representation.hh
AS_essentials_library.hh
intern/asset_library_service.hh
intern/asset_storage.hh
intern/utils.hh

View File

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup asset_system
*/
#include "BLI_path_util.h"
#include "BKE_appdir.h"
#include "AS_essentials_library.hh"
namespace blender::asset_system {
StringRefNull essentials_directory_path()
{
static std::string path = []() {
const char *datafiles_path = BKE_appdir_folder_id(BLENDER_DATAFILES, "assets");
return datafiles_path;
}();
return path;
}
} // namespace blender::asset_system

View File

@ -260,6 +260,12 @@ StringRefNull AssetLibrary::root_path() const
Vector<AssetLibraryReference> all_valid_asset_library_refs()
{
Vector<AssetLibraryReference> result;
{
AssetLibraryReference library_ref{};
library_ref.custom_library_index = -1;
library_ref.type = ASSET_LIBRARY_ESSENTIALS;
result.append(library_ref);
}
int i;
LISTBASE_FOREACH_INDEX (const bUserAssetLibrary *, asset_library, &U.asset_libraries, i) {
if (!BLI_is_dir(asset_library->path)) {

View File

@ -16,6 +16,7 @@
#include "AS_asset_catalog_tree.hh"
#include "AS_asset_library.hh"
#include "AS_essentials_library.hh"
#include "asset_library_service.hh"
#include "utils.hh"
@ -60,6 +61,12 @@ AssetLibrary *AssetLibraryService::get_asset_library(
const eAssetLibraryType type = eAssetLibraryType(library_reference.type);
switch (type) {
case ASSET_LIBRARY_ESSENTIALS: {
const StringRefNull root_path = essentials_directory_path();
AssetLibrary *asset_library = get_asset_library_on_disk(root_path);
asset_library->never_link = true;
return asset_library;
}
case ASSET_LIBRARY_LOCAL: {
/* For the "Current File" library we get the asset library root path based on main. */
std::string root_path = bmain ? AS_asset_library_find_suitable_root_path_from_main(bmain) :

View File

@ -10,6 +10,7 @@
#include "DNA_asset_types.h"
#include "AS_asset_identifier.hh"
#include "AS_asset_library.hh"
#include "AS_asset_representation.h"
#include "AS_asset_representation.hh"
@ -126,4 +127,11 @@ bool AS_asset_representation_is_local_id(const AssetRepresentation *asset_handle
return asset->is_local_id();
}
bool AS_asset_representation_is_never_link(const AssetRepresentation *asset_handle)
{
const asset_system::AssetRepresentation *asset =
reinterpret_cast<const asset_system::AssetRepresentation *>(asset_handle);
return asset->owner_asset_library().never_link;
}
/** \} */

View File

@ -46,6 +46,7 @@ struct GeometryDeformation {
* function either retrieves the deformation data from the evaluated object, or falls back to
* returning the original data.
*/
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig);
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
const Object &ob_orig);

View File

@ -305,8 +305,8 @@ void CustomData_copy_data(const struct CustomData *source,
int source_index,
int dest_index,
int count);
void CustomData_copy_data_layer(const CustomData *source,
CustomData *dest,
void CustomData_copy_data_layer(const struct CustomData *source,
struct CustomData *dest,
int src_layer_index,
int dst_layer_index,
int src_index,
@ -445,7 +445,7 @@ void *CustomData_get_layer_named_for_write(CustomData *data,
int totelem);
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_layer_index(const struct CustomData *data, int type);
@ -520,7 +520,6 @@ void CustomData_bmesh_free_block_data_exclude_by_type(struct CustomData *data,
void *block,
eCustomDataMask mask_exclude);
/**
* Query info over types.
*/
@ -729,7 +728,7 @@ void CustomData_blend_write(BlendWriter *writer,
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
struct DynStr;

View File

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

View File

@ -596,7 +596,7 @@ void BKE_crazyspace_api_eval_clear(Object *object)
namespace blender::bke::crazyspace {
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval,
const Object &ob_orig)
{
BLI_assert(ob_orig.type == OB_CURVES);
@ -608,7 +608,6 @@ GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
/* Use the undeformed positions by default. */
deformation.positions = curves_orig.positions();
const Object *ob_eval = DEG_get_evaluated_object(&depsgraph, const_cast<Object *>(&ob_orig));
if (ob_eval == nullptr) {
return deformation;
}
@ -653,4 +652,11 @@ GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
return deformation;
}
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
const Object &ob_orig)
{
const Object *ob_eval = DEG_get_evaluated_object(&depsgraph, const_cast<Object *>(&ob_orig));
return get_evaluated_curves_deformation(ob_eval, ob_orig);
}
} // namespace blender::bke::crazyspace

View File

@ -5203,7 +5203,7 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
} // 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;
}

View File

@ -92,4 +92,3 @@ TEST(nla_track, BKE_nlatrack_remove_strip)
}
} // 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
* 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;
if (geometry != nullptr) {
dob->instance_idx[next_instance] = int(instance_index);
@ -1821,7 +1821,7 @@ static bool find_geonode_attribute_rgba(const DupliObject *dupli,
using namespace blender;
/* 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. */
if (dupli->instance_data[i] == nullptr) {
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. */
if (is_selected && (G.moving & G_TRANSFORM_OBJ)) {
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)
{
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_len = 0;
}

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)); \
} \
inline _enum_type &operator^=(_enum_type &a, _enum_type b) \
{ \
return a = (_enum_type)(uint64_t(a) ^ uint64_t(b)); \
} \
} /* extern "C++" */
#else

View File

@ -281,10 +281,10 @@ set(SRC
BLI_math_solvers.h
BLI_math_statistics.h
BLI_math_time.h
BLI_math_vector_mpq_types.hh
BLI_math_vector_types.hh
BLI_math_vector.h
BLI_math_vector.hh
BLI_math_vector_mpq_types.hh
BLI_math_vector_types.hh
BLI_memarena.h
BLI_memblock.h
BLI_memiter.h
@ -490,13 +490,13 @@ if(WITH_GTESTS)
tests/BLI_math_bits_test.cc
tests/BLI_math_color_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_types_test.cc
tests/BLI_math_rotation_test.cc
tests/BLI_math_solvers_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_types_test.cc
tests/BLI_memiter_test.cc
tests/BLI_memory_utils_test.cc
tests/BLI_mesh_boolean_test.cc

View File

@ -3926,6 +3926,18 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
v3d->overlay.flag |= V3D_OVERLAY_SCULPT_CURVES_CAGE;
v3d->overlay.sculpt_curves_cage_opacity = 0.5f;
}
}
}
}
/* Keep this block, even when empty. */
}
}

View File

@ -186,7 +186,7 @@ static Vector<MeshToBMeshLayerInfo> mesh_to_bm_copy_info_calc(const CustomData &
std::array<int, CD_NUMTYPES> per_type_index;
per_type_index.fill(0);
for (const int i : IndexRange(bm_data.totlayer)) {
CustomDataLayer &bm_layer = bm_data.layers[i];
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' ?
@ -1079,7 +1079,7 @@ static Vector<BMeshToMeshLayerInfo> bm_to_mesh_copy_info_calc(const CustomData &
std::array<int, CD_NUMTYPES> per_type_index;
per_type_index.fill(0);
for (const int i : IndexRange(mesh_data.totlayer)) {
CustomDataLayer &mesh_layer = mesh_data.layers[i];
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' ?
@ -1166,7 +1166,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(layer_name, sub_layer_name));
/* If ever the uv map associated bool layers become optional in BMesh as well (like in Mesh)
* this assert needs to be removed. For now it is a bug if they doin't exist. */
* 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 :

View File

@ -1197,8 +1197,8 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data)
{
BMwFaceLoopWalker *lwalk, owalk, *owalk_pt;
BMEdge *e = data;
/* BMesh *bm = walker->bm; */ /* UNUSED */
/* int fcount = BM_edge_face_count(e); */ /* UNUSED */
// BMesh *bm = walker->bm; /* UNUSED */
// int fcount = BM_edge_face_count(e); /* UNUSED */
if (!bmw_FaceLoopWalker_edge_begins_loop(walker, e)) {
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);
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
* also - we could attempt to interpolate the loop data,
* this would be much slower but more useful too. */

View File

@ -702,6 +702,7 @@ set(GLSL_SRC
engines/overlay/shaders/overlay_point_varying_color_frag.glsl
engines/overlay/shaders/overlay_point_varying_color_varying_outline_aa_frag.glsl
engines/overlay/shaders/overlay_pointcloud_only_vert.glsl
engines/overlay/shaders/overlay_sculpt_curves_cage_vert.glsl
engines/overlay/shaders/overlay_sculpt_curves_selection_frag.glsl
engines/overlay/shaders/overlay_sculpt_curves_selection_vert.glsl
engines/overlay/shaders/overlay_sculpt_mask_frag.glsl

View File

@ -21,8 +21,7 @@ void main()
float light_count = 0.0;
uint light_cull = 0u;
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];
light_cull |= 1u << l_idx;
light_count += 1.0;

View File

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

View File

@ -38,4 +38,4 @@ void main()
}
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_y = pages_infos_buf.page_size / SHADOW_PAGE_CLEAR_GROUP_SIZE;
clear_dispatch_buf.num_groups_z = 0;
}
}

View File

@ -51,4 +51,4 @@ void main()
}
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);
shadow_tag_usage(vP, P, pixel);
}
}

View File

@ -12,4 +12,4 @@
void main()
{
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);
}
LIGHT_FOREACH_END
}
}

View File

@ -19,4 +19,4 @@ void main()
interp.vP = point_world_to_view(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);
}
}
}
}

View File

@ -74,4 +74,4 @@ void main()
* thread 0. */
}
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. */
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;
}
}
}
}

View File

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

View File

@ -5,10 +5,14 @@
* \ingroup draw_engine
*/
#include "BKE_curves.h"
#include "DRW_render.h"
#include "ED_view3d.h"
#include "DEG_depsgraph_query.h"
#include "draw_cache_impl.h"
#include "overlay_private.hh"
@ -17,7 +21,10 @@ void OVERLAY_edit_curves_init(OVERLAY_Data *vedata)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
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);
/* Create view with depth offset. */
@ -39,10 +46,12 @@ void OVERLAY_edit_curves_cache_init(OVERLAY_Data *vedata)
/* Run Twice for in-front passes. */
for (int i = 0; i < 2; i++) {
DRW_PASS_CREATE(psl->edit_curves_points_ps[i], (state | pd->clipping_state));
sh = OVERLAY_shader_edit_particle_point();
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);
if (pd->edit_curves.do_points) {
DRW_PASS_CREATE(psl->edit_curves_points_ps[i], (state | pd->clipping_state));
sh = OVERLAY_shader_edit_particle_point();
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));
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);
DRWShadingGroup *point_shgrp = pd->edit_curves_points_grp[in_front];
struct GPUBatch *geom_points = DRW_curves_batch_cache_get_edit_points(curves);
DRW_shgroup_call_no_cull(point_shgrp, geom_points, ob);
if (pd->edit_curves.do_points) {
DRWShadingGroup *point_shgrp = pd->edit_curves_points_grp[in_front];
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];
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) {
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]);
}
else {
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]);
}
}

View File

@ -632,6 +632,10 @@ static void OVERLAY_draw_scene(void *vedata)
GPU_framebuffer_bind(fbl->overlay_line_fb);
}
if (pd->ctx_mode == CTX_MODE_SCULPT_CURVES) {
OVERLAY_sculpt_curves_draw_wires(data);
}
OVERLAY_wireframe_draw(data);
OVERLAY_armature_draw(data);
OVERLAY_particle_draw(data);

View File

@ -120,6 +120,7 @@ typedef struct OVERLAY_PassList {
DRWPass *pointcloud_ps;
DRWPass *sculpt_mask_ps;
DRWPass *sculpt_curves_selection_ps;
DRWPass *sculpt_curves_cage_ps;
DRWPass *volume_ps;
DRWPass *wireframe_ps;
DRWPass *wireframe_xray_ps;
@ -287,6 +288,7 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *pointcloud_dots_grp;
DRWShadingGroup *sculpt_mask_grp;
DRWShadingGroup *sculpt_curves_selection_grp;
DRWShadingGroup *sculpt_curves_cage_lines_grp;
DRWShadingGroup *viewer_attribute_curve_grp;
DRWShadingGroup *viewer_attribute_curves_grp;
DRWShadingGroup *viewer_attribute_mesh_grp;
@ -362,6 +364,7 @@ typedef struct OVERLAY_PrivateData {
int flag; /** Copy of #v3d->overlay.edit_flag. */
} edit_mesh;
struct {
bool do_points;
bool do_zbufclip;
} edit_curves;
struct {
@ -686,6 +689,7 @@ void OVERLAY_sculpt_draw(OVERLAY_Data *vedata);
void OVERLAY_sculpt_curves_cache_init(OVERLAY_Data *vedata);
void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_sculpt_curves_draw(OVERLAY_Data *vedata);
void OVERLAY_sculpt_curves_draw_wires(OVERLAY_Data *vedata);
void OVERLAY_viewer_attribute_cache_init(OVERLAY_Data *vedata);
void OVERLAY_viewer_attribute_cache_populate(OVERLAY_Data *vedata, Object *object);
@ -775,6 +779,7 @@ GPUShader *OVERLAY_shader_particle_dot(void);
GPUShader *OVERLAY_shader_particle_shape(void);
GPUShader *OVERLAY_shader_sculpt_mask(void);
GPUShader *OVERLAY_shader_sculpt_curves_selection(void);
GPUShader *OVERLAY_shader_sculpt_curves_cage(void);
GPUShader *OVERLAY_shader_viewer_attribute_curve(void);
GPUShader *OVERLAY_shader_viewer_attribute_curves(void);
GPUShader *OVERLAY_shader_viewer_attribute_mesh(void);

View File

@ -11,23 +11,41 @@
#include "overlay_private.hh"
#include "BKE_attribute.hh"
#include "BKE_crazyspace.hh"
#include "BKE_curves.hh"
#include "DEG_depsgraph_query.h"
void OVERLAY_sculpt_curves_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
const View3DOverlay &overlay = vedata->stl->pd->overlay;
const DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->sculpt_curves_selection_ps, state | pd->clipping_state);
/* Selection overlay. */
{
const DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->sculpt_curves_selection_ps, state | pd->clipping_state);
GPUShader *sh = OVERLAY_shader_sculpt_curves_selection();
pd->sculpt_curves_selection_grp = DRW_shgroup_create(sh, psl->sculpt_curves_selection_ps);
DRWShadingGroup *grp = pd->sculpt_curves_selection_grp;
GPUShader *sh = OVERLAY_shader_sculpt_curves_selection();
pd->sculpt_curves_selection_grp = DRW_shgroup_create(sh, psl->sculpt_curves_selection_ps);
DRWShadingGroup *grp = pd->sculpt_curves_selection_grp;
/* Reuse the same mask opacity from sculpt mode, since it wasn't worth it to add a different
* property yet. */
DRW_shgroup_uniform_float_copy(grp, "selection_opacity", pd->overlay.sculpt_mode_mask_opacity);
/* Reuse the same mask opacity from sculpt mode, since it wasn't worth it to add a different
* property yet. */
DRW_shgroup_uniform_float_copy(grp, "selection_opacity", pd->overlay.sculpt_mode_mask_opacity);
}
/* Cage overlay. */
{
const DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL |
DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->sculpt_curves_cage_ps, state | pd->clipping_state);
GPUShader *sh = OVERLAY_shader_sculpt_curves_cage();
pd->sculpt_curves_cage_lines_grp = DRW_shgroup_create(sh, psl->sculpt_curves_cage_ps);
DRW_shgroup_uniform_float_copy(
pd->sculpt_curves_cage_lines_grp, "opacity", overlay.sculpt_curves_cage_opacity);
}
}
static bool everything_selected(const Curves &curves_id)
@ -39,7 +57,7 @@ static bool everything_selected(const Curves &curves_id)
return selection.is_single() && selection.get_internal_single();
}
void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object)
static void populate_selection_overlay(OVERLAY_Data *vedata, Object *object)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
Curves *curves = static_cast<Curves *>(object->data);
@ -68,16 +86,35 @@ void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object)
DRW_shgroup_buffer_texture(grp, "selection_tx", *texture);
}
static void populate_edit_overlay(OVERLAY_Data *vedata, Object *object)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
Curves *curves = static_cast<Curves *>(object->data);
GPUBatch *geom_lines = DRW_curves_batch_cache_get_edit_lines(curves);
DRW_shgroup_call_no_cull(pd->sculpt_curves_cage_lines_grp, geom_lines, object);
}
void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object)
{
populate_selection_overlay(vedata, object);
const View3DOverlay &overlay = vedata->stl->pd->overlay;
if ((overlay.flag & V3D_OVERLAY_SCULPT_CURVES_CAGE) &&
overlay.sculpt_curves_cage_opacity > 0.0f) {
populate_edit_overlay(vedata, object);
}
}
void OVERLAY_sculpt_curves_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
OVERLAY_FramebufferList *fbl = vedata->fbl;
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(pd->painting.in_front ? fbl->overlay_in_front_fb :
fbl->overlay_default_fb);
}
DRW_draw_pass(psl->sculpt_curves_selection_ps);
}
void OVERLAY_sculpt_curves_draw_wires(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_draw_pass(psl->sculpt_curves_cage_ps);
}

View File

@ -91,6 +91,7 @@ struct OVERLAY_Shaders {
GPUShader *particle_shape;
GPUShader *pointcloud_dot;
GPUShader *sculpt_mask;
GPUShader *sculpt_curves_cage;
GPUShader *sculpt_curves_selection;
GPUShader *uniform_color;
GPUShader *uniform_color_pointcloud;
@ -856,6 +857,18 @@ GPUShader *OVERLAY_shader_sculpt_curves_selection(void)
return sh_data->sculpt_curves_selection;
}
GPUShader *OVERLAY_shader_sculpt_curves_cage(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->sculpt_curves_cage) {
sh_data->sculpt_curves_cage = GPU_shader_create_from_info_name(
(draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? "overlay_sculpt_curves_cage_clipped" :
"overlay_sculpt_curves_cage");
}
return sh_data->sculpt_curves_cage;
}
GPUShader *OVERLAY_shader_viewer_attribute_mesh(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();

View File

@ -496,7 +496,7 @@ GPU_SHADER_CREATE_INFO(overlay_edit_lattice_wire_clipped)
GPU_SHADER_CREATE_INFO(overlay_edit_particle_strand)
.do_static_compilation(true)
.vertex_in(0, Type::VEC3, "pos")
.vertex_in(1, Type::FLOAT, "color")
.vertex_in(1, Type::FLOAT, "selection")
.sampler(0, ImageType::FLOAT_1D, "weightTex")
.push_constant(Type::BOOL, "useWeight")
.vertex_out(overlay_edit_smooth_color_iface)
@ -512,7 +512,7 @@ GPU_SHADER_CREATE_INFO(overlay_edit_particle_strand_clipped)
GPU_SHADER_CREATE_INFO(overlay_edit_particle_point)
.do_static_compilation(true)
.vertex_in(0, Type::VEC3, "pos")
.vertex_in(1, Type::FLOAT, "color")
.vertex_in(1, Type::FLOAT, "selection")
.vertex_out(overlay_edit_flat_color_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.vertex_source("overlay_edit_particle_point_vert.glsl")

View File

@ -19,3 +19,24 @@ GPU_SHADER_CREATE_INFO(overlay_sculpt_curves_selection)
GPU_SHADER_CREATE_INFO(overlay_sculpt_curves_selection_clipped)
.do_static_compilation(true)
.additional_info("overlay_sculpt_curves_selection", "drw_clipped");
GPU_SHADER_INTERFACE_INFO(overlay_sculpt_curves_cage_iface, "")
.no_perspective(Type::VEC2, "edgePos")
.flat(Type::VEC2, "edgeStart")
.smooth(Type::VEC4, "finalColor");
GPU_SHADER_CREATE_INFO(overlay_sculpt_curves_cage)
.do_static_compilation(true)
.vertex_in(0, Type::VEC3, "pos")
.vertex_in(1, Type::FLOAT, "selection")
.vertex_out(overlay_sculpt_curves_cage_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.fragment_out(1, Type::VEC4, "lineOutput")
.push_constant(Type::FLOAT, "opacity")
.vertex_source("overlay_sculpt_curves_cage_vert.glsl")
.fragment_source("overlay_extra_frag.glsl")
.additional_info("draw_modelmat", "draw_view", "draw_globals");
GPU_SHADER_CREATE_INFO(overlay_sculpt_curves_cage_clipped)
.do_static_compilation(true)
.additional_info("overlay_sculpt_curves_cage", "drw_clipped");

View File

@ -7,7 +7,7 @@ void main()
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
finalColor = mix(colorWire, colorVertexSelect, color);
finalColor = mix(colorWire, colorVertexSelect, selection);
gl_PointSize = sizeVertex * 2.0;

View File

@ -25,10 +25,10 @@ void main()
gl_Position = point_world_to_ndc(world_pos);
if (useWeight) {
finalColor = vec4(weight_to_rgb(color), 1.0);
finalColor = vec4(weight_to_rgb(selection), 1.0);
}
else {
finalColor = mix(colorWire, colorVertexSelect, color);
finalColor = mix(colorWire, colorVertexSelect, selection);
}
view_clipping_distances(world_pos);

View File

@ -0,0 +1,15 @@
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
finalColor = vec4(selection);
finalColor.a *= opacity;
/* Convert to screen position [0..sizeVp]. */
edgePos = edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
}

View File

@ -684,8 +684,7 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
MeshRenderData *mr = mesh_render_data_create(
object, me, is_editmode, is_paint_mode, is_mode_active, obmat, do_final, do_uvedit, ts);
mr->use_hide = use_hide;
mr->use_subsurf_fdots = mr->me &&
mr->me->runtime->subsurf_face_dot_tags.size() == mr->me->totvert;
mr->use_subsurf_fdots = mr->me && !mr->me->runtime->subsurf_face_dot_tags.is_empty();
mr->use_final_mesh = do_final;
#ifdef DEBUG_TIME

View File

@ -25,6 +25,7 @@
#include "DEG_depsgraph_query.h"
#include "BKE_crazyspace.hh"
#include "BKE_curves.hh"
#include "BKE_geometry_set.hh"
@ -40,11 +41,9 @@
#include "draw_curves_private.hh" /* own include */
#include "draw_shader.h"
using blender::ColorGeometry4f;
using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
namespace blender::draw {
/* ---------------------------------------------------------------------- */
/* Curves GPUBatch Cache */
@ -55,11 +54,11 @@ struct CurvesBatchCache {
GPUBatch *edit_points;
GPUBatch *edit_lines;
/* Editmode (original) point positions. */
/* Crazy-space point positions for original points. */
GPUVertBuf *edit_points_pos;
/* Editmode data (such as selection). */
GPUVertBuf *edit_points_data;
/* Selection of original points. */
GPUVertBuf *edit_points_selection;
GPUIndexBuf *edit_lines_ibo;
@ -114,7 +113,7 @@ static void curves_batch_cache_clear_edit_data(CurvesBatchCache *cache)
{
/* TODO: more granular update tagging. */
GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_pos);
GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_data);
GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_selection);
GPU_INDEXBUF_DISCARD_SAFE(cache->edit_lines_ibo);
GPU_BATCH_DISCARD_SAFE(cache->edit_points);
@ -150,70 +149,12 @@ static void curves_batch_cache_clear(Curves &curves)
curves_batch_cache_clear_edit_data(cache);
}
void DRW_curves_batch_cache_validate(Curves *curves)
{
if (!curves_batch_cache_valid(*curves)) {
curves_batch_cache_clear(*curves);
curves_batch_cache_init(*curves);
}
}
static CurvesBatchCache &curves_batch_cache_get(Curves &curves)
{
DRW_curves_batch_cache_validate(&curves);
return *static_cast<CurvesBatchCache *>(curves.batch_cache);
}
void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode)
{
CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves->batch_cache);
if (cache == nullptr) {
return;
}
switch (mode) {
case BKE_CURVES_BATCH_DIRTY_ALL:
cache->is_dirty = true;
break;
default:
BLI_assert_unreachable();
}
}
void DRW_curves_batch_cache_free(Curves *curves)
{
curves_batch_cache_clear(*curves);
MEM_delete(static_cast<CurvesBatchCache *>(curves->batch_cache));
curves->batch_cache = nullptr;
}
void DRW_curves_batch_cache_free_old(Curves *curves, int ctime)
{
CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves->batch_cache);
if (cache == nullptr) {
return;
}
bool do_discard = false;
for (const int i : IndexRange(MAX_HAIR_SUBDIV)) {
CurvesEvalFinalCache &final_cache = cache->curves_cache.final[i];
if (drw_attributes_overlap(&final_cache.attr_used_over_time, &final_cache.attr_used)) {
final_cache.last_attr_matching_time = ctime;
}
if (ctime - final_cache.last_attr_matching_time > U.vbotimeout) {
do_discard = true;
}
drw_attributes_clear(&final_cache.attr_used_over_time);
}
if (do_discard) {
curves_discard_attributes(cache->curves_cache);
}
}
static void ensure_seg_pt_count(const Curves &curves, CurvesEvalCache &curves_cache)
{
if (curves_cache.proc_point_buf != nullptr) {
@ -231,13 +172,11 @@ struct PositionAndParameter {
};
static void curves_batch_cache_fill_segments_proc_pos(
const Curves &curves_id,
const bke::CurvesGeometry &curves,
MutableSpan<PositionAndParameter> posTime_data,
MutableSpan<float> hairLength_data)
{
using namespace blender;
/* TODO: use hair radius layer if available. */
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
const OffsetIndices points_by_curve = curves.points_by_curve();
const Span<float3> positions = curves.positions();
@ -270,7 +209,7 @@ static void curves_batch_cache_fill_segments_proc_pos(
});
}
static void curves_batch_cache_ensure_procedural_pos(const Curves &curves,
static void curves_batch_cache_ensure_procedural_pos(const bke::CurvesGeometry &curves,
CurvesEvalCache &cache,
GPUMaterial * /*gpu_material*/)
{
@ -301,12 +240,10 @@ static void curves_batch_cache_ensure_procedural_pos(const Curves &curves,
}
}
static void curves_batch_cache_ensure_edit_points_pos(const Curves &curves_id,
static void curves_batch_cache_ensure_edit_points_pos(const bke::CurvesGeometry &curves,
Span<float3> deformed_positions,
CurvesBatchCache &cache)
{
using namespace blender;
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
static GPUVertFormat format_pos = {0};
static uint pos;
if (format_pos.attr_len == 0) {
@ -315,35 +252,32 @@ static void curves_batch_cache_ensure_edit_points_pos(const Curves &curves_id,
GPU_vertbuf_init_with_format(cache.edit_points_pos, &format_pos);
GPU_vertbuf_data_alloc(cache.edit_points_pos, curves.points_num());
Span<float3> positions = curves.positions();
GPU_vertbuf_attr_fill(cache.edit_points_pos, pos, positions.data());
GPU_vertbuf_attr_fill(cache.edit_points_pos, pos, deformed_positions.data());
}
static void curves_batch_cache_ensure_edit_points_data(const Curves &curves_id,
CurvesBatchCache &cache)
static void curves_batch_cache_ensure_edit_points_selection(const bke::CurvesGeometry &curves,
const eAttrDomain selection_domain,
CurvesBatchCache &cache)
{
using namespace blender;
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
static GPUVertFormat format_data = {0};
static uint color;
static uint selection_id;
if (format_data.attr_len == 0) {
color = GPU_vertformat_attr_add(&format_data, "color", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
selection_id = GPU_vertformat_attr_add(
&format_data, "selection", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
}
GPU_vertbuf_init_with_format(cache.edit_points_data, &format_data);
GPU_vertbuf_data_alloc(cache.edit_points_data, curves.points_num());
GPU_vertbuf_init_with_format(cache.edit_points_selection, &format_data);
GPU_vertbuf_data_alloc(cache.edit_points_selection, curves.points_num());
const OffsetIndices points_by_curve = curves.points_by_curve();
const VArray<bool> selection = curves.attributes().lookup_or_default<bool>(
".selection", eAttrDomain(curves_id.selection_domain), true);
switch (curves_id.selection_domain) {
".selection", selection_domain, true);
switch (selection_domain) {
case ATTR_DOMAIN_POINT:
for (const int point_i : selection.index_range()) {
const float point_selection = selection[point_i] ? 1.0f : 0.0f;
GPU_vertbuf_attr_set(cache.edit_points_data, color, point_i, &point_selection);
GPU_vertbuf_attr_set(cache.edit_points_selection, selection_id, point_i, &point_selection);
}
break;
case ATTR_DOMAIN_CURVE:
@ -351,18 +285,19 @@ static void curves_batch_cache_ensure_edit_points_data(const Curves &curves_id,
const float curve_selection = selection[curve_i] ? 1.0f : 0.0f;
const IndexRange points = points_by_curve[curve_i];
for (const int point_i : points) {
GPU_vertbuf_attr_set(cache.edit_points_data, color, point_i, &curve_selection);
GPU_vertbuf_attr_set(
cache.edit_points_selection, selection_id, point_i, &curve_selection);
}
}
break;
default:
break;
}
}
static void curves_batch_cache_ensure_edit_lines(const Curves &curves_id, CurvesBatchCache &cache)
static void curves_batch_cache_ensure_edit_lines(const bke::CurvesGeometry &curves,
CurvesBatchCache &cache)
{
using namespace blender;
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
const int vert_len = curves.points_num();
const int curve_len = curves.curves_num();
const int index_len = vert_len + curve_len;
@ -383,14 +318,6 @@ static void curves_batch_cache_ensure_edit_lines(const Curves &curves_id, Curves
GPU_indexbuf_build_in_place(&elb, cache.edit_lines_ibo);
}
void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32])
{
char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
/* Attributes use auto-name. */
BLI_snprintf(r_sampler_name, 32, "a%s", attr_safe_name);
}
static void curves_batch_cache_ensure_procedural_final_attr(CurvesEvalCache &cache,
const GPUVertFormat *format,
const int subdiv,
@ -413,7 +340,6 @@ static void curves_batch_ensure_attribute(const Curves &curves,
const int subdiv,
const int index)
{
using namespace blender;
GPU_VERTBUF_DISCARD_SAFE(cache.proc_attributes_buf[index]);
char sampler_name[32];
@ -458,11 +384,10 @@ static void curves_batch_ensure_attribute(const Curves &curves,
}
}
static void curves_batch_cache_fill_strands_data(const Curves &curves_id,
static void curves_batch_cache_fill_strands_data(const bke::CurvesGeometry &curves,
GPUVertBufRaw &data_step,
GPUVertBufRaw &seg_step)
{
const blender::bke::CurvesGeometry &curves = curves_id.geometry.wrap();
const blender::OffsetIndices points_by_curve = curves.points_by_curve();
for (const int i : IndexRange(curves.curves_num())) {
@ -473,7 +398,7 @@ static void curves_batch_cache_fill_strands_data(const Curves &curves_id,
}
}
static void curves_batch_cache_ensure_procedural_strand_data(Curves &curves,
static void curves_batch_cache_ensure_procedural_strand_data(const bke::CurvesGeometry &curves,
CurvesEvalCache &cache)
{
GPUVertBufRaw data_step, seg_step;
@ -513,15 +438,12 @@ static void curves_batch_cache_ensure_procedural_final_points(CurvesEvalCache &c
cache.final[subdiv].strands_res * cache.strands_len);
}
static void curves_batch_cache_fill_segments_indices(const Curves &curves,
static void curves_batch_cache_fill_segments_indices(const bke::CurvesGeometry &curves,
const int res,
GPUIndexBufBuilder &elb)
{
const int curves_num = curves.geometry.curve_num;
uint curr_point = 0;
for ([[maybe_unused]] const int i : IndexRange(curves_num)) {
for ([[maybe_unused]] const int i : IndexRange(curves.curves_num())) {
for (int k = 0; k < res; k++) {
GPU_indexbuf_add_generic_vert(&elb, curr_point++);
}
@ -529,7 +451,7 @@ static void curves_batch_cache_fill_segments_indices(const Curves &curves,
}
}
static void curves_batch_cache_ensure_procedural_indices(Curves &curves,
static void curves_batch_cache_ensure_procedural_indices(const bke::CurvesGeometry &curves,
CurvesEvalCache &cache,
const int thickness_res,
const int subdiv)
@ -624,64 +546,6 @@ static bool curves_ensure_attributes(const Curves &curves,
return need_tf_update;
}
bool curves_ensure_procedural_data(Curves *curves,
CurvesEvalCache **r_hair_cache,
GPUMaterial *gpu_material,
const int subdiv,
const int thickness_res)
{
bool need_ft_update = false;
CurvesBatchCache &cache = curves_batch_cache_get(*curves);
*r_hair_cache = &cache.curves_cache;
const int steps = 3; /* TODO: don't hard-code? */
(*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv);
/* Refreshed on combing and simulation. */
if ((*r_hair_cache)->proc_point_buf == nullptr) {
ensure_seg_pt_count(*curves, cache.curves_cache);
curves_batch_cache_ensure_procedural_pos(*curves, cache.curves_cache, gpu_material);
need_ft_update = true;
}
/* Refreshed if active layer or custom data changes. */
if ((*r_hair_cache)->proc_strand_buf == nullptr) {
curves_batch_cache_ensure_procedural_strand_data(*curves, cache.curves_cache);
}
/* Refreshed only on subdiv count change. */
if ((*r_hair_cache)->final[subdiv].proc_buf == nullptr) {
curves_batch_cache_ensure_procedural_final_points(cache.curves_cache, subdiv);
need_ft_update = true;
}
if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == nullptr) {
curves_batch_cache_ensure_procedural_indices(
*curves, cache.curves_cache, thickness_res, subdiv);
}
need_ft_update |= curves_ensure_attributes(*curves, cache, gpu_material, subdiv);
return need_ft_update;
}
int DRW_curves_material_count_get(Curves *curves)
{
return max_ii(1, curves->totcol);
}
GPUBatch *DRW_curves_batch_cache_get_edit_points(Curves *curves)
{
CurvesBatchCache &cache = curves_batch_cache_get(*curves);
return DRW_batch_request(&cache.edit_points);
}
GPUBatch *DRW_curves_batch_cache_get_edit_lines(Curves *curves)
{
CurvesBatchCache &cache = curves_batch_cache_get(*curves);
return DRW_batch_request(&cache.edit_lines);
}
static void request_attribute(Curves &curves, const char *name)
{
CurvesBatchCache &cache = curves_batch_cache_get(curves);
@ -709,10 +573,145 @@ static void request_attribute(Curves &curves, const char *name)
drw_attributes_merge(&final_cache.attr_used, &attributes, cache.render_mutex);
}
} // namespace blender::draw
void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32])
{
char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
/* Attributes use auto-name. */
BLI_snprintf(r_sampler_name, 32, "a%s", attr_safe_name);
}
bool curves_ensure_procedural_data(Curves *curves_id,
CurvesEvalCache **r_hair_cache,
GPUMaterial *gpu_material,
const int subdiv,
const int thickness_res)
{
using namespace blender;
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
bool need_ft_update = false;
draw::CurvesBatchCache &cache = draw::curves_batch_cache_get(*curves_id);
*r_hair_cache = &cache.curves_cache;
const int steps = 3; /* TODO: don't hard-code? */
(*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv);
/* Refreshed on combing and simulation. */
if ((*r_hair_cache)->proc_point_buf == nullptr) {
draw::ensure_seg_pt_count(*curves_id, cache.curves_cache);
draw::curves_batch_cache_ensure_procedural_pos(curves, cache.curves_cache, gpu_material);
need_ft_update = true;
}
/* Refreshed if active layer or custom data changes. */
if ((*r_hair_cache)->proc_strand_buf == nullptr) {
draw::curves_batch_cache_ensure_procedural_strand_data(curves, cache.curves_cache);
}
/* Refreshed only on subdiv count change. */
if ((*r_hair_cache)->final[subdiv].proc_buf == nullptr) {
draw::curves_batch_cache_ensure_procedural_final_points(cache.curves_cache, subdiv);
need_ft_update = true;
}
if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == nullptr) {
draw::curves_batch_cache_ensure_procedural_indices(
curves, cache.curves_cache, thickness_res, subdiv);
}
need_ft_update |= draw::curves_ensure_attributes(*curves_id, cache, gpu_material, subdiv);
return need_ft_update;
}
void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode)
{
using namespace blender::draw;
CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves->batch_cache);
if (cache == nullptr) {
return;
}
switch (mode) {
case BKE_CURVES_BATCH_DIRTY_ALL:
cache->is_dirty = true;
break;
default:
BLI_assert_unreachable();
}
}
void DRW_curves_batch_cache_validate(Curves *curves)
{
using namespace blender::draw;
if (!curves_batch_cache_valid(*curves)) {
curves_batch_cache_clear(*curves);
curves_batch_cache_init(*curves);
}
}
void DRW_curves_batch_cache_free(Curves *curves)
{
using namespace blender::draw;
curves_batch_cache_clear(*curves);
MEM_delete(static_cast<CurvesBatchCache *>(curves->batch_cache));
curves->batch_cache = nullptr;
}
void DRW_curves_batch_cache_free_old(Curves *curves, int ctime)
{
using namespace blender::draw;
CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves->batch_cache);
if (cache == nullptr) {
return;
}
bool do_discard = false;
for (const int i : IndexRange(MAX_HAIR_SUBDIV)) {
CurvesEvalFinalCache &final_cache = cache->curves_cache.final[i];
if (drw_attributes_overlap(&final_cache.attr_used_over_time, &final_cache.attr_used)) {
final_cache.last_attr_matching_time = ctime;
}
if (ctime - final_cache.last_attr_matching_time > U.vbotimeout) {
do_discard = true;
}
drw_attributes_clear(&final_cache.attr_used_over_time);
}
if (do_discard) {
curves_discard_attributes(cache->curves_cache);
}
}
int DRW_curves_material_count_get(Curves *curves)
{
return max_ii(1, curves->totcol);
}
GPUBatch *DRW_curves_batch_cache_get_edit_points(Curves *curves)
{
using namespace blender::draw;
CurvesBatchCache &cache = curves_batch_cache_get(*curves);
return DRW_batch_request(&cache.edit_points);
}
GPUBatch *DRW_curves_batch_cache_get_edit_lines(Curves *curves)
{
using namespace blender::draw;
CurvesBatchCache &cache = curves_batch_cache_get(*curves);
return DRW_batch_request(&cache.edit_lines);
}
GPUVertBuf **DRW_curves_texture_for_evaluated_attribute(Curves *curves,
const char *name,
bool *r_is_point_domain)
{
using namespace blender::draw;
CurvesBatchCache &cache = curves_batch_cache_get(*curves);
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene = draw_ctx->scene;
@ -747,28 +746,37 @@ GPUVertBuf **DRW_curves_texture_for_evaluated_attribute(Curves *curves,
void DRW_curves_batch_cache_create_requested(Object *ob)
{
Curves *curves = static_cast<Curves *>(ob->data);
Object *orig = DEG_get_original_object(ob);
Curves *curves_orig = static_cast<Curves *>(orig->data);
using namespace blender;
Curves *curves_id = static_cast<Curves *>(ob->data);
Object *ob_orig = DEG_get_original_object(ob);
if (ob_orig == nullptr) {
return;
}
Curves *curves_orig_id = static_cast<Curves *>(ob_orig->data);
CurvesBatchCache &cache = curves_batch_cache_get(*curves);
draw::CurvesBatchCache &cache = draw::curves_batch_cache_get(*curves_id);
bke::CurvesGeometry &curves_orig = curves_orig_id->geometry.wrap();
const bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(ob, *ob_orig);
if (DRW_batch_requested(cache.edit_points, GPU_PRIM_POINTS)) {
DRW_vbo_request(cache.edit_points, &cache.edit_points_pos);
DRW_vbo_request(cache.edit_points, &cache.edit_points_data);
DRW_vbo_request(cache.edit_points, &cache.edit_points_selection);
}
if (DRW_batch_requested(cache.edit_lines, GPU_PRIM_LINE_STRIP)) {
DRW_ibo_request(cache.edit_lines, &cache.edit_lines_ibo);
DRW_vbo_request(cache.edit_lines, &cache.edit_points_pos);
DRW_vbo_request(cache.edit_lines, &cache.edit_points_data);
DRW_vbo_request(cache.edit_lines, &cache.edit_points_selection);
}
if (DRW_vbo_requested(cache.edit_points_pos)) {
curves_batch_cache_ensure_edit_points_pos(*curves_orig, cache);
curves_batch_cache_ensure_edit_points_pos(curves_orig, deformation.positions, cache);
}
if (DRW_vbo_requested(cache.edit_points_data)) {
curves_batch_cache_ensure_edit_points_data(*curves_orig, cache);
if (DRW_vbo_requested(cache.edit_points_selection)) {
curves_batch_cache_ensure_edit_points_selection(
curves_orig, eAttrDomain(curves_id->selection_domain), cache);
}
if (DRW_ibo_requested(cache.edit_lines_ibo)) {
curves_batch_cache_ensure_edit_lines(*curves_orig, cache);
curves_batch_cache_ensure_edit_lines(curves_orig, cache);
}
}

View File

@ -89,21 +89,21 @@ typedef struct HairAttributeID {
typedef struct EditStrandData {
float pos[3];
float color;
float selection;
} EditStrandData;
static GPUVertFormat *edit_points_vert_format_get(uint *r_pos_id, uint *r_color_id)
static GPUVertFormat *edit_points_vert_format_get(uint *r_pos_id, uint *r_selection_id)
{
static GPUVertFormat edit_point_format = {0};
static uint pos_id, color_id;
static uint pos_id, selection_id;
if (edit_point_format.attr_len == 0) {
/* Keep in sync with EditStrandData */
pos_id = GPU_vertformat_attr_add(&edit_point_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
color_id = GPU_vertformat_attr_add(
&edit_point_format, "color", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
selection_id = GPU_vertformat_attr_add(
&edit_point_format, "selection", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
}
*r_pos_id = pos_id;
*r_color_id = color_id;
*r_selection_id = selection_id;
return &edit_point_format;
}
@ -697,11 +697,11 @@ static int particle_batch_cache_fill_segments_edit(
if (particle) {
float weight = particle_key_weight(particle, i, strand_t);
/* NaN or unclamped become 1.0f */
seg_data->color = (weight < 1.0f) ? weight : 1.0f;
seg_data->selection = (weight < 1.0f) ? weight : 1.0f;
}
else {
/* Computed in psys_cache_edit_paths_iter(). */
seg_data->color = path[j].col[0];
seg_data->selection = path[j].col[0];
}
GPU_indexbuf_add_generic_vert(elb, curr_point);
curr_point++;
@ -1530,8 +1530,8 @@ static void particle_batch_cache_ensure_edit_pos_and_seg(PTCacheEdit *edit,
GPUVertBufRaw data_step;
GPUIndexBufBuilder elb;
uint pos_id, color_id;
GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
uint pos_id, selection_id;
GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &selection_id);
hair_cache->pos = GPU_vertbuf_create_with_format(edit_point_format);
GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len);
@ -1594,8 +1594,8 @@ static void particle_batch_cache_ensure_edit_inner_pos(PTCacheEdit *edit,
return;
}
uint pos_id, color_id;
GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
uint pos_id, selection_id;
GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &selection_id);
cache->edit_inner_pos = GPU_vertbuf_create_with_format(edit_point_format);
GPU_vertbuf_data_alloc(cache->edit_inner_pos, cache->edit_inner_point_len);
@ -1608,9 +1608,9 @@ static void particle_batch_cache_ensure_edit_inner_pos(PTCacheEdit *edit,
}
for (int key_index = 0; key_index < point->totkey - 1; key_index++) {
PTCacheEditKey *key = &point->keys[key_index];
float color = (key->flag & PEK_SELECT) ? 1.0f : 0.0f;
float selection = (key->flag & PEK_SELECT) ? 1.0f : 0.0f;
GPU_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co);
GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, &color);
GPU_vertbuf_attr_set(cache->edit_inner_pos, selection_id, global_key_index, &selection);
global_key_index++;
}
}
@ -1652,8 +1652,8 @@ static void particle_batch_cache_ensure_edit_tip_pos(PTCacheEdit *edit, Particle
return;
}
uint pos_id, color_id;
GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
uint pos_id, selection_id;
GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &selection_id);
cache->edit_tip_pos = GPU_vertbuf_create_with_format(edit_point_format);
GPU_vertbuf_data_alloc(cache->edit_tip_pos, cache->edit_tip_point_len);
@ -1665,10 +1665,10 @@ static void particle_batch_cache_ensure_edit_tip_pos(PTCacheEdit *edit, Particle
continue;
}
PTCacheEditKey *key = &point->keys[point->totkey - 1];
float color = (key->flag & PEK_SELECT) ? 1.0f : 0.0f;
float selection = (key->flag & PEK_SELECT) ? 1.0f : 0.0f;
GPU_vertbuf_attr_set(cache->edit_tip_pos, pos_id, global_point_index, key->world_co);
GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, global_point_index, &color);
GPU_vertbuf_attr_set(cache->edit_tip_pos, selection_id, global_point_index, &selection);
global_point_index++;
}
}

View File

@ -698,7 +698,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob)
drw_call_calc_orco(ob, ob_infos->orcotexfac);
/* Random float value. */
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
* 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);

View File

@ -401,9 +401,9 @@ static void add_verts_to_dgroups(ReportList *reports,
vertsfilled = 1;
}
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
* subsurfed position, like for 'optimal'. */
* subdivision-surfaced position, like for 'optimal'. */
subsurf_calculate_limit_positions(mesh, verts);
vertsfilled = 1;
}

View File

@ -47,7 +47,7 @@ AssetLibraryReference ED_asset_library_reference_from_enum_value(int value)
if (value < ASSET_LIBRARY_CUSTOM) {
library.type = value;
library.custom_library_index = -1;
BLI_assert(ELEM(value, ASSET_LIBRARY_ALL, ASSET_LIBRARY_LOCAL));
BLI_assert(ELEM(value, ASSET_LIBRARY_ALL, ASSET_LIBRARY_LOCAL, ASSET_LIBRARY_ESSENTIALS));
return library;
}
@ -57,7 +57,7 @@ AssetLibraryReference ED_asset_library_reference_from_enum_value(int value)
/* Note that there is no check if the path exists here. If an invalid library path is used, the
* Asset Browser can give a nice hint on what's wrong. */
if (!user_library) {
library.type = ASSET_LIBRARY_LOCAL;
library.type = ASSET_LIBRARY_ALL;
library.custom_library_index = -1;
}
else {
@ -87,6 +87,11 @@ const EnumPropertyItem *ED_asset_library_reference_to_rna_enum_itemf(const bool
ICON_CURRENT_FILE,
"Current File",
"Show the assets currently available in this Blender session"},
{ASSET_LIBRARY_ESSENTIALS,
"ESSENTIALS",
ICON_NONE,
"Essentials",
"Show the basic building blocks and utilities coming with Blender"},
{0, nullptr, 0, nullptr, nullptr},
};

View File

@ -372,6 +372,7 @@ std::optional<eFileSelectType> AssetListStorage::asset_library_reference_to_file
switch (eAssetLibraryType(library_reference.type)) {
case ASSET_LIBRARY_ALL:
return FILE_ASSET_LIBRARY_ALL;
case ASSET_LIBRARY_ESSENTIALS:
case ASSET_LIBRARY_CUSTOM:
return FILE_ASSET_LIBRARY;
case ASSET_LIBRARY_LOCAL:

View File

@ -44,6 +44,8 @@
/* The same as in `draw_cache.c` */
#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])
{
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);
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_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. */
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");
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_final_no_offset[4][4];
Dial *dial;
bool use_temp_uniform;
} 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)
{
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,
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,
* no matter the size of the rectangle, mouse coords are scaled to unit space.
* 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'.
*/
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 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;
gz_prop = WM_gizmo_target_property_find(gz, "matrix");

View File

@ -86,8 +86,7 @@ struct Dial3dParams {
float arc_inner_factor;
float *clip_plane;
};
static void dial_3d_draw_util(const float matrix_basis[4][4],
const float matrix_final[4][4],
static void dial_3d_draw_util(const float matrix_final[4][4],
const float line_width,
const float color[4],
const bool select,
@ -96,7 +95,7 @@ static void dial_3d_draw_util(const float matrix_basis[4][4],
static void dial_geom_draw(const float color[4],
const float line_width,
const bool select,
const float axis_modal_mat[4][4],
const float clip_plane_mat[4][4],
const float clip_plane[4],
const float arc_partial_angle,
const float arc_inner_factor,
@ -118,7 +117,7 @@ static void dial_geom_draw(const float color[4],
immBindBuiltinProgram(filled ? GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR :
GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR);
immUniform4fv("ClipPlane", clip_plane);
immUniformMatrix4fv("ModelMatrix", axis_modal_mat);
immUniformMatrix4fv("ModelMatrix", clip_plane_mat);
}
else {
immBindBuiltinProgram(filled ? GPU_SHADER_3D_UNIFORM_COLOR :
@ -432,8 +431,7 @@ static void dial_draw_intern(
}
}
dial_3d_draw_util(gz->matrix_basis,
matrix_final,
dial_3d_draw_util(matrix_final,
gz->line_width,
color,
select,
@ -613,8 +611,7 @@ static int gizmo_dial_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *ev
/** \name Dial Gizmo API
* \{ */
static void dial_3d_draw_util(const float matrix_basis[4][4],
const float matrix_final[4][4],
static void dial_3d_draw_util(const float matrix_final[4][4],
const float line_width,
const float color[4],
const bool select,
@ -650,7 +647,7 @@ static void dial_3d_draw_util(const float matrix_basis[4][4],
dial_geom_draw(color,
line_width,
select,
matrix_basis,
matrix_final,
params->clip_plane,
params->arc_partial_angle,
params->arc_inner_factor,

View File

@ -279,7 +279,7 @@ static void annotation_draw_stroke_point(const bGPDspoint *points,
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
}
else {
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
/* get 2D coordinates of point */
float co[3] = {0.0f};

View File

@ -528,7 +528,7 @@ static short annotation_stroke_addpoint(tGPsdata *p,
/* store settings */
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->strength = 1.0f;
pt->time = (float)(curtime - p->inittime);
@ -544,7 +544,7 @@ static short annotation_stroke_addpoint(tGPsdata *p,
/* store settings */
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->strength = 1.0f;
pt->time = (float)(curtime - p->inittime);
@ -620,7 +620,7 @@ static short annotation_stroke_addpoint(tGPsdata *p,
/* store settings */
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->strength = 1.0f;
pt->time = (float)(curtime - p->inittime);

View File

@ -4059,12 +4059,11 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
ot->prop = RNA_def_enum(
ot->srna, "type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", "");
prop = RNA_def_boolean(
ot->srna,
"keep_original",
0,
"Keep Original",
"Keep original strokes and create a copy before reprojecting");
prop = RNA_def_boolean(ot->srna,
"keep_original",
0,
"Keep Original",
"Keep original strokes and create a copy before reprojecting");
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);

View File

@ -993,23 +993,25 @@ static void draw_mouse_position(tGPDfill *tgpf)
if (tgpf->gps_mouse == NULL) {
return;
}
uchar mouse_color[4] = {0, 0, 255, 255};
bGPDspoint *pt = &tgpf->gps_mouse->points[0];
float point_size = (tgpf->zoom == 1.0f) ? 4.0f * tgpf->fill_factor :
(0.5f * tgpf->zoom) + tgpf->fill_factor;
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
/* Draw mouse click position in Blue. */
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immUniform1f("size", point_size * M_SQRT2);
GPU_program_point_size(true);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
immBegin(GPU_PRIM_POINTS, 1);
immAttr4ubv(col, mouse_color);
immAttr1f(size, point_size * M_SQRT2);
immAttr4f(color, 0.0f, 0.0f, 1.0f, 1.0f);
immVertex3fv(pos, &pt->x);
immEnd();
immUnbindProgram();
GPU_program_point_size(false);
}
/* Helper: Check if must skip the layer */

View File

@ -764,7 +764,7 @@ static short gpencil_stroke_addpoint(tGPsdata *p,
/* store settings */
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->strength = 1.0f;
pt->time = (float)(curtime - p->inittime);
@ -780,7 +780,7 @@ static short gpencil_stroke_addpoint(tGPsdata *p,
/* store settings */
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->strength = 1.0f;
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 -
* prevents Dkey to insert drivers. */
* prevents D-key to insert drivers. */
if (ISKEYBOARD(event->type)) {
if (ELEM(event->type, EVT_LEFTARROWKEY, EVT_DOWNARROWKEY, EVT_RIGHTARROWKEY, EVT_UPARROWKEY)) {
/* allow some keys:

View File

@ -54,7 +54,7 @@ typedef struct {
BMBackup mesh_backup;
bool is_valid;
bool is_dirty;
} * backup;
} *backup;
int backup_len;
} BisectData;
@ -528,15 +528,7 @@ static void gizmo_mesh_bisect_update_from_op(GizmoGroup *ggd)
normalize_v3(ggd->data.rotate_up);
WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_c, plane_no);
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);
WM_gizmo_set_matrix_rotation_from_z_axis(ggd->rotate_c, ggd->data.rotate_axis);
}
}

View File

@ -966,7 +966,7 @@ static void min_distance_edit_draw(bContext *C, int /*x*/, int /*y*/, void *cust
const uint pos3d = GPU_vertformat_attr_add(format3d, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
const uint col3d = GPU_vertformat_attr_add(format3d, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immUniform1f("size", 4.0f);
immBegin(GPU_PRIM_POINTS, points_wo.size());

View File

@ -37,6 +37,7 @@
#include "WM_api.h"
#include "wm_cursors.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "ED_image.h"
@ -200,10 +201,18 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
y = len * sinf(angle);
}
if (col) {
float rgba[4];
float avg;
float rgba[4];
paint_get_tex_pixel(mtex, x, y, pool, thread_id, &avg, rgba);
paint_get_tex_pixel_col(mtex, x, y, rgba, pool, thread_id, convert_to_linear, colorspace);
if (col) {
if (convert_to_linear) {
IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace);
}
linearrgb_to_srgb_v3_v3(rgba, rgba);
clamp_v4(rgba, 0.0f, 1.0f);
buffer[index * 4] = rgba[0] * 255;
buffer[index * 4 + 1] = rgba[1] * 255;
@ -211,8 +220,6 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
buffer[index * 4 + 3] = rgba[3] * 255;
}
else {
float avg = paint_get_tex_pixel(mtex, x, y, pool, thread_id);
avg += br->texture_sample_bias;
/* Clamp to avoid precision overflow. */

View File

@ -352,16 +352,17 @@ void paint_calc_redraw_planes(float planes[4][4],
float paint_calc_object_space_radius(struct ViewContext *vc,
const float center[3],
float pixel_radius);
float paint_get_tex_pixel(
const struct MTex *mtex, float u, float v, struct ImagePool *pool, int thread);
void paint_get_tex_pixel_col(const struct MTex *mtex,
float u,
float v,
float rgba[4],
struct ImagePool *pool,
int thread,
bool convert,
struct ColorSpace *colorspace);
/**
* Returns true when a color was sampled and false when a value was sampled.
*/
bool paint_get_tex_pixel(const struct MTex *mtex,
float u,
float v,
struct ImagePool *pool,
int thread,
float *r_intensity,
float r_rgba[4]);
/**
* Used for both 3D view and image window.

View File

@ -146,45 +146,29 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo
return len_v3(delta) / scale;
}
float paint_get_tex_pixel(const MTex *mtex, float u, float v, struct ImagePool *pool, int thread)
{
float intensity;
float rgba_dummy[4];
const float co[3] = {u, v, 0.0f};
RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba_dummy);
return intensity;
}
void paint_get_tex_pixel_col(const MTex *mtex,
float u,
float v,
float rgba[4],
struct ImagePool *pool,
int thread,
bool convert_to_linear,
struct ColorSpace *colorspace)
bool paint_get_tex_pixel(const MTex *mtex,
float u,
float v,
struct ImagePool *pool,
int thread,
/* Return arguments. */
float *r_intensity,
float r_rgba[4])
{
const float co[3] = {u, v, 0.0f};
float intensity;
const bool has_rgb = RE_texture_evaluate(
mtex, co, thread, pool, false, false, &intensity, r_rgba);
*r_intensity = intensity;
const bool hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba);
if (!hasrgb) {
rgba[0] = intensity;
rgba[1] = intensity;
rgba[2] = intensity;
rgba[3] = 1.0f;
if (!has_rgb) {
r_rgba[0] = intensity;
r_rgba[1] = intensity;
r_rgba[2] = intensity;
r_rgba[3] = 1.0f;
}
if (convert_to_linear) {
IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace);
}
linearrgb_to_srgb_v3_v3(rgba, rgba);
clamp_v4(rgba, 0.0f, 1.0f);
return has_rgb;
}
void paint_stroke_operator_properties(wmOperatorType *ot)

View File

@ -54,6 +54,7 @@
#include "BKE_scene.h"
#include "BKE_subdiv_ccg.h"
#include "BKE_subsurf.h"
#include "BLI_math_vector.hh"
#include "NOD_texture.h"
@ -2555,80 +2556,12 @@ static float brush_strength(const Sculpt *sd,
}
}
float SCULPT_brush_strength_factor(SculptSession *ss,
const Brush *br,
const float brush_point[3],
float len,
const float vno[3],
const float fno[3],
float mask,
const PBVHVertRef vertex,
const int thread_id,
AutomaskingNodeData *automask_data)
static float sculpt_apply_hardness(const SculptSession *ss, const float input_len)
{
StrokeCache *cache = ss->cache;
const Scene *scene = cache->vc->scene;
const MTex *mtex = BKE_brush_mask_texture_get(br, OB_MODE_SCULPT);
float avg = 1.0f;
float rgba[4];
float point[3];
sub_v3_v3v3(point, brush_point, cache->plane_offset);
if (!mtex->tex) {
avg = 1.0f;
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
/* Get strength by feeding the vertex location directly into a texture. */
avg = BKE_brush_sample_tex_3d(scene, br, mtex, point, rgba, 0, ss->tex_pool);
}
else {
float symm_point[3], point_2d[2];
/* Quite warnings. */
float x = 0.0f, y = 0.0f;
/* If the active area is being applied for symmetry, flip it
* across the symmetry axis and rotate it back to the original
* position in order to project it. This insures that the
* brush texture will be oriented correctly. */
if (cache->radial_symmetry_pass) {
mul_m4_v3(cache->symm_rot_mat_inv, point);
}
flip_v3_v3(symm_point, point, cache->mirror_symmetry_pass);
ED_view3d_project_float_v2_m4(cache->vc->region, symm_point, point_2d, cache->projection_mat);
/* Still no symmetry supported for other paint modes.
* Sculpt does it DIY. */
if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) {
/* Similar to fixed mode, but projects from brush angle
* rather than view direction. */
mul_m4_v3(cache->brush_local_mat, symm_point);
x = symm_point[0];
y = symm_point[1];
x *= mtex->size[0];
y *= mtex->size[1];
x += mtex->ofs[0];
y += mtex->ofs[1];
avg = paint_get_tex_pixel(mtex, x, y, ss->tex_pool, thread_id);
avg += br->texture_sample_bias;
}
else {
const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
avg = BKE_brush_sample_tex_3d(scene, br, mtex, point_3d, rgba, 0, ss->tex_pool);
}
}
/* Hardness. */
float final_len = len;
const StrokeCache *cache = ss->cache;
float final_len = input_len;
const float hardness = cache->paint_brush.hardness;
float p = len / cache->radius;
float p = input_len / cache->radius;
if (p < hardness) {
final_len = 0.0f;
}
@ -2640,9 +2573,100 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
final_len = p * cache->radius;
}
return final_len;
}
static void sculpt_apply_texture(const SculptSession *ss,
const Brush *brush,
const float brush_point[3],
const int thread_id,
float *r_value,
float r_rgba[4])
{
StrokeCache *cache = ss->cache;
const Scene *scene = cache->vc->scene;
const MTex *mtex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
if (!mtex->tex) {
*r_value = 1.0f;
copy_v4_fl(r_rgba, 1.0f);
return;
}
float point[3];
sub_v3_v3v3(point, brush_point, cache->plane_offset);
if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
/* Get strength by feeding the vertex location directly into a texture. */
*r_value = BKE_brush_sample_tex_3d(scene, brush, mtex, point, r_rgba, 0, ss->tex_pool);
}
else {
float symm_point[3];
/* If the active area is being applied for symmetry, flip it
* across the symmetry axis and rotate it back to the original
* position in order to project it. This insures that the
* brush texture will be oriented correctly. */
if (cache->radial_symmetry_pass) {
mul_m4_v3(cache->symm_rot_mat_inv, point);
}
flip_v3_v3(symm_point, point, cache->mirror_symmetry_pass);
/* Still no symmetry supported for other paint modes.
* Sculpt does it DIY. */
if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) {
/* Similar to fixed mode, but projects from brush angle
* rather than view direction. */
mul_m4_v3(cache->brush_local_mat, symm_point);
float x = symm_point[0];
float y = symm_point[1];
x *= mtex->size[0];
y *= mtex->size[1];
x += mtex->ofs[0];
y += mtex->ofs[1];
paint_get_tex_pixel(mtex, x, y, ss->tex_pool, thread_id, r_value, r_rgba);
add_v3_fl(r_rgba, brush->texture_sample_bias); // v3 -> Ignore alpha
*r_value -= brush->texture_sample_bias;
}
else {
float point_2d[2];
ED_view3d_project_float_v2_m4(
cache->vc->region, symm_point, point_2d, cache->projection_mat);
const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
*r_value = BKE_brush_sample_tex_3d(scene, brush, mtex, point_3d, r_rgba, 0, ss->tex_pool);
}
}
}
float SCULPT_brush_strength_factor(SculptSession *ss,
const Brush *brush,
const float brush_point[3],
float len,
const float vno[3],
const float fno[3],
float mask,
const PBVHVertRef vertex,
int thread_id,
AutomaskingNodeData *automask_data)
{
StrokeCache *cache = ss->cache;
float avg = 1.0f;
float rgba[4];
sculpt_apply_texture(ss, brush, brush_point, thread_id, &avg, rgba);
/* Hardness. */
const float final_len = sculpt_apply_hardness(ss, len);
/* Falloff curve. */
avg *= BKE_brush_curve_strength(br, final_len, cache->radius);
avg *= frontface(br, cache->view_normal, vno, fno);
avg *= BKE_brush_curve_strength(brush, final_len, cache->radius);
avg *= frontface(brush, cache->view_normal, vno, fno);
/* Paint mask. */
avg *= 1.0f - mask;
@ -2653,6 +2677,69 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
return avg;
}
void SCULPT_brush_strength_color(SculptSession *ss,
const Brush *brush,
const float brush_point[3],
float len,
const float vno[3],
const float fno[3],
float mask,
const PBVHVertRef vertex,
int thread_id,
AutomaskingNodeData *automask_data,
float r_rgba[4])
{
StrokeCache *cache = ss->cache;
float avg = 1.0f;
sculpt_apply_texture(ss, brush, brush_point, thread_id, &avg, r_rgba);
/* Hardness. */
const float final_len = sculpt_apply_hardness(ss, len);
/* Falloff curve. */
const float falloff = BKE_brush_curve_strength(brush, final_len, cache->radius) *
frontface(brush, cache->view_normal, vno, fno);
/* Paint mask. */
const float paint_mask = 1.0f - mask;
/* Auto-masking. */
const float automasking_factor = SCULPT_automasking_factor_get(
cache->automasking, ss, vertex, automask_data);
const float masks_combined = falloff * paint_mask * automasking_factor;
mul_v4_fl(r_rgba, masks_combined);
}
void SCULPT_calc_vertex_displacement(SculptSession *ss,
const Brush *brush,
float rgba[4],
float out_offset[3])
{
mul_v3_fl(rgba, ss->cache->bstrength);
/* Handle brush inversion */
if (ss->cache->bstrength < 0) {
rgba[0] *= -1;
rgba[1] *= -1;
}
/* Apply texture size */
for (int i = 0; i < 3; ++i) {
rgba[i] *= blender::math::safe_divide(1.0f, pow2f(brush->mtex.size[i]));
}
/* Transform vector to object space */
mul_mat3_m4_v3(ss->cache->brush_local_mat_inv, rgba);
/* Handle symmetry */
if (ss->cache->radial_symmetry_pass) {
mul_m4_v3(ss->cache->symm_rot_mat, rgba);
}
flip_v3_v3(out_offset, rgba, ss->cache->mirror_symmetry_pass);
}
bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v)
{
SculptSearchSphereData *data = static_cast<SculptSearchSphereData *>(data_v);
@ -2920,7 +3007,10 @@ static void calc_local_y(ViewContext *vc, const float center[3], float y[3])
mul_m4_v3(ob->world_to_object, y);
}
static void calc_brush_local_mat(const MTex *mtex, Object *ob, float local_mat[4][4])
static void calc_brush_local_mat(const MTex *mtex,
Object *ob,
float local_mat[4][4],
float local_mat_inv[4][4])
{
const StrokeCache *cache = ob->sculpt->cache;
float tmat[4][4];
@ -2966,6 +3056,8 @@ static void calc_brush_local_mat(const MTex *mtex, Object *ob, float local_mat[4
scale_m4_fl(scale, radius);
mul_m4_m4m4(tmat, mat, scale);
/* Return tmat as is (for converting from local area coords to model-space coords). */
copy_m4_m4(local_mat_inv, tmat);
/* Return inverse (for converting from model-space coords to local area coords). */
invert_m4_m4(local_mat, tmat);
}
@ -3000,7 +3092,7 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob)
if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0) {
const Brush *brush = BKE_paint_brush(&sd->paint);
const MTex *mask_tex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
calc_brush_local_mat(mask_tex, ob, cache->brush_local_mat);
calc_brush_local_mat(mask_tex, ob, cache->brush_local_mat, cache->brush_local_mat_inv);
}
}

View File

@ -265,18 +265,35 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata,
SCULPT_automasking_node_update(ss, &automask_data, &vd);
/* Offset vertex. */
const float fade = SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data);
mul_v3_v3fl(proxy[vd.i], offset, fade);
if (ss->cache->brush->flag2 & BRUSH_USE_COLOR_AS_DISPLACEMENT &&
(brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)) {
float r_rgba[4];
SCULPT_brush_strength_color(ss,
brush,
vd.co,
sqrtf(test.dist),
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data,
r_rgba);
SCULPT_calc_vertex_displacement(ss, brush, r_rgba, proxy[vd.i]);
}
else {
float fade = SCULPT_brush_strength_factor(ss,
brush,
vd.co,
sqrtf(test.dist),
vd.no,
vd.fno,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
&automask_data);
mul_v3_v3fl(proxy[vd.i], offset, fade);
}
if (vd.is_mesh) {
BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex);

View File

@ -586,8 +586,13 @@ struct StrokeCache {
float sculpt_normal_symm[3];
/* Used for area texture mode, local_mat gets calculated by
* calc_brush_local_mat() and used in tex_strength(). */
* calc_brush_local_mat() and used in sculpt_apply_texture().
* Transforms from model-space coords to local area coords.
*/
float brush_local_mat[4][4];
/* The matrix from local area coords to model-space coords is used to calculate the vector
* displacement in area plane mode. */
float brush_local_mat_inv[4][4];
float plane_offset[3]; /* used to shift the plane around when doing tiled strokes */
int tile_pass;
@ -1241,6 +1246,30 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
int thread_id,
AutomaskingNodeData *automask_data);
/**
* Return a color of a brush texture on a particular vertex multiplied by active masks.
*/
void SCULPT_brush_strength_color(SculptSession *ss,
const Brush *brush,
const float brush_point[3],
float len,
const float vno[3],
const float fno[3],
float mask,
const PBVHVertRef vertex,
int thread_id,
AutomaskingNodeData *automask_data,
float r_rgba[4]);
/**
* Calculates the vertex offset for a single vertex depending on the brush setting rgb as vector
* displacement.
*/
void SCULPT_calc_vertex_displacement(SculptSession *ss,
const Brush *brush,
float rgba[3],
float out_offset[3]);
/**
* Tilts a normal by the x and y tilt values using the view axis.
*/

View File

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

View File

@ -55,6 +55,8 @@
#include "GPU_immediate_util.h"
#include "GPU_state.h"
#include "AS_asset_representation.h"
#include "filelist.h"
#include "file_intern.h" /* own include */
@ -126,6 +128,19 @@ static void draw_tile_background(const rcti *draw_rect, int colorid, int shade)
UI_draw_roundbox_aa(&draw_rect_fl, true, 5.0f, color);
}
static eFileAssetImportType get_asset_import_type(const SpaceFile *sfile, const FileDirEntry *file)
{
const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
BLI_assert(asset_params != NULL);
if (asset_params->import_type != FILE_ASSET_IMPORT_LINK) {
return asset_params->import_type;
}
if (AS_asset_representation_is_never_link(file->asset)) {
return FILE_ASSET_IMPORT_APPEND_REUSE;
}
return FILE_ASSET_IMPORT_LINK;
}
static void file_draw_icon(const SpaceFile *sfile,
uiBlock *block,
const FileDirEntry *file,
@ -165,13 +180,10 @@ static void file_draw_icon(const SpaceFile *sfile,
ImBuf *preview_image = filelist_file_getimage(file);
char blend_path[FILE_MAX_LIBEXTRA];
if (BLO_library_path_explode(path, blend_path, NULL, NULL)) {
const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
BLI_assert(asset_params != NULL);
UI_but_drag_set_asset(but,
&(AssetHandle){.file_data = file},
BLI_strdup(blend_path),
asset_params->import_type,
get_asset_import_type(sfile, file),
icon,
preview_image,
UI_DPI_FAC);
@ -558,13 +570,10 @@ static void file_draw_preview(const SpaceFile *sfile,
char blend_path[FILE_MAX_LIBEXTRA];
if (BLO_library_path_explode(path, blend_path, NULL, NULL)) {
const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
BLI_assert(asset_params != NULL);
UI_but_drag_set_asset(but,
&(AssetHandle){.file_data = file},
BLI_strdup(blend_path),
asset_params->import_type,
get_asset_import_type(sfile, file),
icon,
imb,
scale);
@ -986,7 +995,7 @@ void file_draw_list(const bContext *C, ARegion *region)
UI_GetThemeColor4ubv(TH_TEXT, text_col);
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;
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_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 autocomplete_directory(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;
/* 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
* (only generated on demand, and freed as soon as possible).
* Persistent part (mere list of paths + stat info)
* 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;
@ -2737,13 +2741,13 @@ int filelist_needs_reading(FileList *filelist)
uint filelist_entry_select_set(const FileList *filelist,
const FileDirEntry *entry,
FileSelType select,
uint flag,
const eDirEntry_SelectFlag flag,
FileCheckType check)
{
/* Default nullptr pointer if not found is fine here! */
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;
const uint org_entry_flag = entry_flag;
eDirEntry_SelectFlag entry_flag = eDirEntry_SelectFlag(es_p ? POINTER_AS_UINT(*es_p) : 0);
const eDirEntry_SelectFlag org_entry_flag = entry_flag;
BLI_assert(entry);
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;
}
void filelist_entry_select_index_set(
FileList *filelist, const int index, FileSelType select, uint flag, FileCheckType check)
void filelist_entry_select_index_set(FileList *filelist,
const int index,
FileSelType select,
const eDirEntry_SelectFlag flag,
FileCheckType check)
{
FileDirEntry *entry = filelist_file(filelist, index);
@ -2792,8 +2799,11 @@ void filelist_entry_select_index_set(
}
}
void filelist_entries_select_index_range_set(
FileList *filelist, FileSelection *sel, FileSelType select, uint flag, FileCheckType check)
void filelist_entries_select_index_range_set(FileList *filelist,
FileSelection *sel,
FileSelType select,
const eDirEntry_SelectFlag flag,
FileCheckType check)
{
/* select all valid files between first and last indicated */
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(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)) ||
((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR))) {
/* Default nullptr pointer if not found is fine here! */
return POINTER_AS_UINT(
BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(entry->uid)));
return eDirEntry_SelectFlag(POINTER_AS_UINT(
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);
@ -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 0;
return eDirEntry_SelectFlag(0);
}
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
* "not selected". */
const uint selection_state = POINTER_AS_UINT(
BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(intern_entry->uid)));
const eDirEntry_SelectFlag selection_state = eDirEntry_SelectFlag(POINTER_AS_UINT(
BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(intern_entry->uid))));
return selection_state != 0;
}
void filelist_entry_parent_select_set(FileList *filelist,
FileSelType select,
uint flag,
const eDirEntry_SelectFlag flag,
FileCheckType check)
{
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,
const struct FileDirEntry *entry,
FileSelType select,
unsigned int flag,
const eDirEntry_SelectFlag flag,
FileCheckType check);
void filelist_entry_select_index_set(struct FileList *filelist,
int index,
FileSelType select,
unsigned int flag,
eDirEntry_SelectFlag flag,
FileCheckType check);
void filelist_entries_select_index_range_set(struct FileList *filelist,
FileSelection *sel,
FileSelType select,
unsigned int 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,
eDirEntry_SelectFlag flag,
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);
/**
* Set selection of the '..' parent entry, but only if it's actually visible.
*/
void filelist_entry_parent_select_set(struct FileList *filelist,
FileSelType select,
unsigned int flag,
eDirEntry_SelectFlag flag,
FileCheckType check);
void filelist_setrecursion(struct FileList *filelist, int recursion_level);

View File

@ -58,6 +58,8 @@
#include "UI_interface_icons.h"
#include "UI_view2d.h"
#include "AS_essentials_library.hh"
#include "file_intern.h"
#include "filelist.h"
@ -102,7 +104,7 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile)
asset_params = sfile->asset_params = static_cast<FileAssetSelectParams *>(
MEM_callocN(sizeof(*asset_params), "FileAssetSelectParams"));
asset_params->base_params.details_flags = U_default.file_space_data.details_flags;
asset_params->asset_library_ref.type = ASSET_LIBRARY_LOCAL;
asset_params->asset_library_ref.type = ASSET_LIBRARY_ALL;
asset_params->asset_library_ref.custom_library_index = -1;
asset_params->import_type = FILE_ASSET_IMPORT_APPEND_REUSE;
}
@ -420,11 +422,17 @@ static void fileselect_refresh_asset_params(FileAssetSelectParams *asset_params)
user_library = BKE_preferences_asset_library_find_from_index(&U,
library->custom_library_index);
if (!user_library) {
library->type = ASSET_LIBRARY_LOCAL;
library->type = ASSET_LIBRARY_ALL;
}
}
switch (library->type) {
switch (eAssetLibraryType(library->type)) {
case ASSET_LIBRARY_ESSENTIALS:
BLI_strncpy(base_params->dir,
blender::asset_system::essentials_directory_path().c_str(),
sizeof(base_params->dir));
base_params->type = FILE_ASSET_LIBRARY;
break;
case ASSET_LIBRARY_ALL:
base_params->dir[0] = '\0';
base_params->type = FILE_ASSET_LIBRARY_ALL;
@ -1124,7 +1132,7 @@ void ED_file_change_dir(bContext *C)
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;
sel.first = 0;

View File

@ -148,7 +148,7 @@ static bool node_under_mouse_tweak(const bNodeTree &ntree, const float2 &mouse)
switch (node->type) {
case NODE_REROUTE: {
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;
}
break;

View File

@ -1104,7 +1104,7 @@ static void draw_rotation_guide(const RegionView3D *rv3d)
immUnbindProgram();
/* -- draw rotation center -- */
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immUniform1f("size", 7.0f);
immBegin(GPU_PRIM_POINTS, 1);
immAttr4ubv(col, color);

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