Refactoring: Geometry Node: Avoid copy last buffer in result for Blur Attribute node #106860

Merged
Jacques Lucke merged 7 commits from mod_moder/blender:blur_avoid_extra_copy into main 2023-04-17 08:09:15 +02:00
143 changed files with 2095 additions and 1645 deletions
Showing only changes of commit 53d10b4e0f - Show all commits

View File

@ -815,64 +815,49 @@ if(CMAKE_COMPILER_IS_GNUCC)
string(PREPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO "${GCC_EXTRA_FLAGS_RELEASE} ")
unset(GCC_EXTRA_FLAGS_RELEASE)
# NOTE(@campbellbarton): Eventually mold will be able to use `-fuse-ld=mold`,
# however at the moment this only works for GCC 12.1+ (unreleased at time of writing).
# So a workaround is used here "-B" which points to another path to find system commands
# such as `ld`.
if(WITH_LINKER_MOLD AND _IS_LINKER_DEFAULT)
find_program(MOLD_BIN "mold")
mark_as_advanced(MOLD_BIN)
if(NOT MOLD_BIN)
message(STATUS "The \"mold\" binary could not be found, using system linker.")
set(WITH_LINKER_MOLD OFF)
elseif(CMAKE_C_COMPILER_VERSION VERSION_LESS 12.1)
message(STATUS "GCC 12.1 or newer is required for th MOLD linker.")
set(WITH_LINKER_MOLD OFF)
else()
# By default mold installs the binary to:
# - `{PREFIX}/bin/mold` as well as a symbolic-link in...
# - `{PREFIX}/lib/mold/ld`.
# (where `PREFIX` is typically `/usr/`).
#
# This block of code finds `{PREFIX}/lib/mold` from the `mold` binary.
# Other methods of searching for the path could also be made to work,
# we could even make our own directory and symbolic-link, however it's more
# convenient to use the one provided by mold.
#
# Use the binary path to "mold", to find the common prefix which contains "lib/mold".
# The parent directory: e.g. `/usr/bin/mold` -> `/usr/bin/`.
get_filename_component(MOLD_PREFIX "${MOLD_BIN}" DIRECTORY)
# The common prefix path: e.g. `/usr/bin/` -> `/usr/` to use as a hint.
get_filename_component(MOLD_PREFIX "${MOLD_PREFIX}" DIRECTORY)
# Find `{PREFIX}/lib/mold/ld`, store the directory component (without the `ld`).
# Then pass `-B {PREFIX}/lib/mold` to GCC so the `ld` located there overrides the default.
find_path(
MOLD_BIN_DIR "ld"
HINTS "${MOLD_PREFIX}"
# The default path is `libexec`, Arch Linux for e.g.
# replaces this with `lib` so check both.
PATH_SUFFIXES "libexec/mold" "lib/mold" "lib64/mold"
NO_DEFAULT_PATH
NO_CACHE
get_filename_component(MOLD_BIN_DIR "${MOLD_BIN}" DIRECTORY)
# Check if the `-B` argument is required.
# This will happen when `MOLD_BIN` points to a non-standard location.
# Keep this option as mold is not yet a standard system component and
# users may have it installed in some unexpected place.
set(_mold_args "-fuse-ld=mold")
execute_process(
COMMAND ${CMAKE_C_COMPILER} -B ${MOLD_BIN_DIR} ${_mold_args} -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION_WITH_DIR
)
if(NOT MOLD_BIN_DIR)
message(STATUS
"The mold linker could not find the directory containing the linker command "
"(typically "
"\"${MOLD_PREFIX}/libexec/mold/ld\") or "
"\"${MOLD_PREFIX}/lib/mold/ld\") using system linker."
)
set(WITH_LINKER_MOLD OFF)
execute_process(
COMMAND ${CMAKE_C_COMPILER} ${_mold_args} -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION
)
if(NOT (LD_VERSION STREQUAL LD_VERSION_WITH_DIR))
string(PREPEND _mold_args "-B \"${MOLD_BIN_DIR}\" ")
set(LD_VERSION "${LD_VERSION_WITH_DIR}")
endif()
unset(MOLD_PREFIX)
endif()
if(WITH_LINKER_MOLD)
# GCC will search for `ld` in this directory first.
string(APPEND CMAKE_EXE_LINKER_FLAGS " -B \"${MOLD_BIN_DIR}\"")
string(APPEND CMAKE_SHARED_LINKER_FLAGS " -B \"${MOLD_BIN_DIR}\"")
string(APPEND CMAKE_MODULE_LINKER_FLAGS " -B \"${MOLD_BIN_DIR}\"")
set(_IS_LINKER_DEFAULT OFF)
if("${LD_VERSION}" MATCHES "mold ")
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${_mold_args}")
string(APPEND CMAKE_SHARED_LINKER_FLAGS " ${_mold_args}")
string(APPEND CMAKE_MODULE_LINKER_FLAGS " ${_mold_args}")
set(_IS_LINKER_DEFAULT OFF)
else()
message(STATUS "GNU mold linker isn't available, using the default system linker.")
endif()
unset(_mold_args)
unset(MOLD_BIN_DIR)
unset(LD_VERSION)
endif()
unset(MOLD_BIN)
unset(MOLD_BIN_DIR)
endif()
if(WITH_LINKER_GOLD AND _IS_LINKER_DEFAULT)

View File

@ -172,6 +172,8 @@ def system_info():
def list_render_passes(scene, srl):
import _cycles
crl = srl.cycles
# Combined pass.
@ -250,6 +252,12 @@ def list_render_passes(scene, srl):
for lightgroup in srl.lightgroups:
yield ("Combined_%s" % lightgroup.name, "RGB", 'COLOR')
# Path guiding debug passes.
if _cycles.with_debug:
yield ("Guiding Color", "RGB", 'COLOR')
yield ("Guiding Probability", "X", 'VALUE')
yield ("Guiding Average Roughness", "X", 'VALUE')
def register_passes(engine, scene, view_layer):
for name, channelids, channeltype in list_render_passes(scene, view_layer):

View File

@ -634,6 +634,10 @@ static bool get_known_pass_type(BL::RenderPass &b_pass, PassType &type, PassMode
MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER, false);
MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT, false);
MAP_PASS("Guiding Color", PASS_GUIDING_COLOR, false);
MAP_PASS("Guiding Probability", PASS_GUIDING_PROBABILITY, false);
MAP_PASS("Guiding Average Roughness", PASS_GUIDING_AVG_ROUGHNESS, false);
if (string_startswith(name, cryptomatte_prefix)) {
type = PASS_CRYPTOMATTE;
mode = PassMode::DENOISED;
@ -684,18 +688,6 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
}
scene->film->set_cryptomatte_passes(cryptomatte_passes);
/* Path guiding debug passes. */
#ifdef WITH_CYCLES_DEBUG
b_engine.add_pass("Guiding Color", 3, "RGB", b_view_layer.name().c_str());
pass_add(scene, PASS_GUIDING_COLOR, "Guiding Color", PassMode::NOISY);
b_engine.add_pass("Guiding Probability", 1, "X", b_view_layer.name().c_str());
pass_add(scene, PASS_GUIDING_PROBABILITY, "Guiding Probability", PassMode::NOISY);
b_engine.add_pass("Guiding Average Roughness", 1, "X", b_view_layer.name().c_str());
pass_add(scene, PASS_GUIDING_AVG_ROUGHNESS, "Guiding Average Roughness", PassMode::NOISY);
#endif
unordered_set<string> expected_passes;
/* Custom AOV passes. */

View File

@ -357,8 +357,12 @@ void PathTraceWorkCPU::guiding_push_sample_data_to_global_storage(
# if PATH_GUIDING_LEVEL >= 2
const bool use_direct_light = kernel_data.integrator.use_guiding_direct_light;
const bool use_mis_weights = kernel_data.integrator.use_guiding_mis_weights;
# if OPENPGL_VERSION_MINOR >= 5
kg->opgl_path_segment_storage->PrepareSamples(use_mis_weights, use_direct_light, false);
# else
kg->opgl_path_segment_storage->PrepareSamples(
false, nullptr, use_mis_weights, use_direct_light, false);
# endif
# endif
# ifdef WITH_CYCLES_DEBUG

View File

@ -454,8 +454,13 @@ ccl_device_forceinline bool guiding_bsdf_init(KernelGlobals kg,
ccl_private float &rand)
{
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
# if OPENPGL_VERSION_MINOR >= 5
if (kg->opgl_surface_sampling_distribution->Init(
kg->opgl_guiding_field, guiding_point3f(P), rand)) {
# else
if (kg->opgl_surface_sampling_distribution->Init(
kg->opgl_guiding_field, guiding_point3f(P), rand, true)) {
# endif
kg->opgl_surface_sampling_distribution->ApplyCosineProduct(guiding_point3f(N));
return true;
}
@ -506,8 +511,13 @@ ccl_device_forceinline bool guiding_phase_init(KernelGlobals kg,
return false;
}
# if OPENPGL_VERSION_MINOR >= 5
if (kg->opgl_volume_sampling_distribution->Init(
kg->opgl_guiding_field, guiding_point3f(P), rand)) {
# else
if (kg->opgl_volume_sampling_distribution->Init(
kg->opgl_guiding_field, guiding_point3f(P), rand, true)) {
# endif
kg->opgl_volume_sampling_distribution->ApplySingleLobeHenyeyGreensteinProduct(guiding_vec3f(D),
g);
return true;

View File

@ -1390,19 +1390,128 @@ ccl_device_extern void osl_noiseparams_set_impulses(ccl_private OSLNoiseOptions
res->y = n; \
res->z = n; \
} \
ccl_device_extern void name##_vv(ccl_private float3 *res, const float3 *v) \
ccl_device_extern void name##_vv(ccl_private float3 *res, ccl_private const float3 *v) \
{ \
const float n = name##_fv(v); \
res->x = n; \
res->y = n; \
res->z = n; \
} \
ccl_device_extern void name##_vvf(ccl_private float3 *res, const float3 *v, float w) \
ccl_device_extern void name##_vvf( \
ccl_private float3 *res, ccl_private const float3 *v, float w) \
{ \
const float n = name##_fvf(v, w); \
res->x = n; \
res->y = n; \
res->z = n; \
} \
ccl_device_extern void name##_dfdf(ccl_private float *res, ccl_private const float *x) \
{ \
res[0] = name##_ff(x[0]); \
res[1] = name##_ff(x[1]); \
res[2] = name##_ff(x[2]); \
} \
ccl_device_extern void name##_dfdff( \
ccl_private float *res, ccl_private const float *x, float y) \
{ \
res[0] = name##_fff(x[0], y); \
res[1] = name##_fff(x[1], y); \
res[2] = name##_fff(x[2], y); \
} \
ccl_device_extern void name##_dffdf( \
ccl_private float *res, float x, ccl_private const float *y) \
{ \
res[0] = name##_fff(x, y[0]); \
res[1] = name##_fff(x, y[1]); \
res[2] = name##_fff(x, y[2]); \
} \
ccl_device_extern void name##_dfdfdf( \
ccl_private float *res, ccl_private const float *x, ccl_private const float *y) \
{ \
res[0] = name##_fff(x[0], y[0]); \
res[1] = name##_fff(x[1], y[1]); \
res[2] = name##_fff(x[2], y[2]); \
} \
ccl_device_extern void name##_dfdv(ccl_private float *res, ccl_private const float3 *v) \
{ \
res[0] = name##_fv(&v[0]); \
res[1] = name##_fv(&v[1]); \
res[2] = name##_fv(&v[2]); \
} \
ccl_device_extern void name##_dfdvf( \
ccl_private float *res, ccl_private const float3 *v, float w) \
{ \
res[0] = name##_fvf(&v[0], w); \
res[1] = name##_fvf(&v[1], w); \
res[2] = name##_fvf(&v[2], w); \
} \
ccl_device_extern void name##_dfvdf( \
ccl_private float *res, ccl_private const float3 *v, ccl_private const float *w) \
{ \
res[0] = name##_fvf(v, w[0]); \
res[1] = name##_fvf(v, w[1]); \
res[2] = name##_fvf(v, w[2]); \
} \
ccl_device_extern void name##_dfdvdf( \
ccl_private float *res, ccl_private const float3 *v, ccl_private const float *w) \
{ \
res[0] = name##_fvf(&v[0], w[0]); \
res[1] = name##_fvf(&v[1], w[1]); \
res[2] = name##_fvf(&v[2], w[2]); \
} \
ccl_device_extern void name##_dvdf(ccl_private float3 *res, ccl_private const float *x) \
{ \
name##_vf(&res[0], x[0]); \
name##_vf(&res[1], x[1]); \
name##_vf(&res[2], x[2]); \
} \
ccl_device_extern void name##_dvdff( \
ccl_private float3 *res, ccl_private const float *x, float y) \
{ \
name##_vff(&res[0], x[0], y); \
name##_vff(&res[1], x[1], y); \
name##_vff(&res[2], x[2], y); \
} \
ccl_device_extern void name##_dvfdf( \
ccl_private float3 *res, float x, ccl_private const float *y) \
{ \
name##_vff(&res[0], x, y[0]); \
name##_vff(&res[1], x, y[1]); \
name##_vff(&res[2], x, y[2]); \
} \
ccl_device_extern void name##_dvdfdf( \
ccl_private float3 *res, ccl_private const float *x, ccl_private const float *y) \
{ \
name##_vff(&res[0], x[0], y[0]); \
name##_vff(&res[1], x[1], y[1]); \
name##_vff(&res[2], x[2], y[2]); \
} \
ccl_device_extern void name##_dvdv(ccl_private float3 *res, ccl_private const float3 *v) \
{ \
name##_vv(&res[0], &v[0]); \
name##_vv(&res[1], &v[1]); \
name##_vv(&res[2], &v[2]); \
} \
ccl_device_extern void name##_dvdvf( \
ccl_private float3 *res, ccl_private const float3 *v, float w) \
{ \
name##_vvf(&res[0], &v[0], w); \
name##_vvf(&res[1], &v[1], w); \
name##_vvf(&res[2], &v[2], w); \
} \
ccl_device_extern void name##_dvvdf( \
ccl_private float3 *res, ccl_private const float3 *v, ccl_private const float *w) \
{ \
name##_vvf(&res[0], v, w[0]); \
name##_vvf(&res[1], v, w[1]); \
name##_vvf(&res[2], v, w[2]); \
} \
ccl_device_extern void name##_dvdvdf( \
ccl_private float3 *res, ccl_private const float3 *v, ccl_private const float *w) \
{ \
name##_vvf(&res[0], &v[0], w[0]); \
name##_vvf(&res[1], &v[1], w[1]); \
name##_vvf(&res[2], &v[2], w[2]); \
}
ccl_device_forceinline float hashnoise_1d(float p)

View File

@ -1400,7 +1400,9 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
[[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
}
GHOST_Window *window = (GHOST_Window *)m_windowManager->getActiveWindow();
GHOST_Window *window = m_windowManager->getWindows().empty() ?
NULL :
(GHOST_Window *)m_windowManager->getWindows().front();
if (!window) {
return NO;

View File

@ -1978,16 +1978,6 @@ bool GHOST_WindowWayland::outputs_changed_update_scale()
fractional_scale_next = fractional_scale_from_output;
scale_next = fractional_scale_next / FRACTIONAL_DENOMINATOR;
}
else {
/* NOTE(@ideasman42): This often overrides #wp_fractional_scale_v1_listener::preferred_scale
* in favor of using the greatest overlapping scale.
* This was requested by the studio to prevent a tablet's built-in display of 75%
* from causing the main-display being up-scaled (showing pixelated). */
if (fractional_scale_next < fractional_scale_from_output) {
fractional_scale_next = fractional_scale_from_output;
scale_next = fractional_scale_next / FRACTIONAL_DENOMINATOR;
}
}
bool changed = false;

View File

@ -123,7 +123,7 @@ def expand(line, cursor, namespace, *, private=True):
[white_space + m[len(word_prefix):]
if (word_prefix and m.startswith(word_prefix))
else
white_space + m.split('.')[-1]
white_space + m.rsplit('.', 1)[-1]
for m in matches])
no_calltip = True

View File

@ -28,7 +28,7 @@ def rna_backup_gen(data, include_props=None, exclude_props=None, root=()):
# only writable properties...
for p in data.bl_rna.properties:
pid = p.identifier
if pid == "rna_type" or pid == "original":
if pid in {"rna_type", "original"}:
continue
path = root + (pid,)
if include_props is not None and path not in include_props:

View File

@ -94,9 +94,7 @@ def keyconfig_test(kc):
if testEntry(kc, child, src, parent):
result = True
else:
for i in range(len(km.keymap_items)):
src = km.keymap_items[i]
for i, src in enumerate(km.keymap_items):
for child in children:
if testEntry(kc, child, src, km):
result = True

View File

@ -417,7 +417,7 @@ def ngon_tessellate(from_data, indices, fix_loops=True, debug_print=True):
if not flip:
for i, fi in enumerate(fill):
fill[i] = tuple([ii for ii in reversed(fi)])
fill[i] = tuple(reversed(fi))
return fill

View File

@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
__all__ = (
"connect_virtual_socket",
"find_node_input",
)

View File

@ -5600,9 +5600,13 @@ def km_font(params):
("font.move_select", {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True, "repeat": True},
{"properties": [("type", 'NEXT_PAGE')]}),
("font.change_spacing", {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True, "repeat": True},
{"properties": [("delta", -1)]}),
{"properties": [("delta", -1.0)]}),
("font.change_spacing", {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True, "repeat": True},
{"properties": [("delta", 1)]}),
{"properties": [("delta", 1.0)]}),
("font.change_spacing", {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True, "alt": True, "repeat": True},
{"properties": [("delta", -0.1)]}),
("font.change_spacing", {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True, "alt": True, "repeat": True},
{"properties": [("delta", 0.1)]}),
("font.change_character", {"type": 'UP_ARROW', "value": 'PRESS', "alt": True, "repeat": True},
{"properties": [("delta", 1)]}),
("font.change_character", {"type": 'DOWN_ARROW', "value": 'PRESS', "alt": True, "repeat": True},

View File

@ -239,7 +239,6 @@ def find_next(ele_dst, ele_src):
# expose for operators
def select_next(bm, report):
import bmesh
ele_pair = [None, None]
for i, ele in enumerate(reversed(bm.select_history)):
ele_pair[i] = ele

View File

@ -488,7 +488,7 @@ class CLIP_OT_constraint_to_fcurve(Operator):
efra = max(efra, track.markers[-1].frame)
if sfra is None or efra is None:
return
return {'CANCELLED'}
# Store object matrices.
for x in range(sfra, efra + 1):
@ -516,6 +516,8 @@ class CLIP_OT_constraint_to_fcurve(Operator):
scene.frame_set(frame_current)
return {'FINISHED'}
def execute(self, context):
scene = context.scene
# XXX, should probably use context.selected_editable_objects
@ -662,8 +664,7 @@ class CLIP_OT_setup_tracking_scene(Operator):
if collection.collection.name == collection_name:
setattr(collection, attr_name, True)
break
else:
setup_collection_recursively(collection.children, collection_name, attr_name)
setup_collection_recursively(collection.children, collection_name, attr_name)
collections = context.scene.collection.children
vlayers = context.scene.view_layers

View File

@ -101,9 +101,9 @@ class MeshMirrorUV(Operator):
for i, j in pmap.items():
if not puvsel[i] or not puvsel[j]:
continue
elif DIR == 0 and pcents[i][0] < 0.0:
if DIR == 0 and pcents[i][0] < 0.0:
continue
elif DIR == 1 and pcents[i][0] > 0.0:
if DIR == 1 and pcents[i][0] > 0.0:
continue
# copy UVs

View File

@ -9,8 +9,6 @@ from bpy.types import (
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
IntProperty,
StringProperty,
)

View File

@ -476,7 +476,7 @@ class QuickSmoke(ObjectModeOperator, Operator):
# setup smoke domain
bpy.ops.object.modifier_add(type='FLUID')
obj.modifiers[-1].fluid_type = 'DOMAIN'
if self.style == 'FIRE' or self.style == 'BOTH':
if self.style == {'FIRE', 'BOTH'}:
obj.modifiers[-1].domain_settings.use_noise = True
# ensure correct cache file format for smoke

View File

@ -22,8 +22,11 @@ def randomize_selected(context, seed, delta,
obj.delta_location += rand_vec(loc)
else:
obj.location += rand_vec(loc)
else: # otherwise the values change under us
uniform(0.0, 0.0), uniform(0.0, 0.0), uniform(0.0, 0.0)
else:
# Otherwise the values change under us.
uniform(0.0, 0.0)
uniform(0.0, 0.0)
uniform(0.0, 0.0)
if rot:
vec = rand_vec(rot)
@ -68,7 +71,9 @@ def randomize_selected(context, seed, delta,
else:
obj.scale = aX, aY, aZ
else:
uniform(0.0, 0.0), uniform(0.0, 0.0), uniform(0.0, 0.0)
uniform(0.0, 0.0)
uniform(0.0, 0.0)
uniform(0.0, 0.0)
from bpy.props import (

View File

@ -8,6 +8,7 @@ from bpy.app.translations import pgettext_tip as tip_
def guess_player_path(preset):
import os
import sys
if preset == 'INTERNAL':

View File

@ -1170,7 +1170,7 @@ class PREFERENCES_OT_script_directory_new(Operator):
new_dir.directory = self.directory
new_dir.name = os.path.basename(self.directory.rstrip(os.sep))
assert context.preferences.is_dirty == True
assert context.preferences.is_dirty is True
return {'FINISHED'}
@ -1197,10 +1197,11 @@ class PREFERENCES_OT_script_directory_remove(Operator):
script_directories.remove(script_directory)
break
assert context.preferences.is_dirty == True
assert context.preferences.is_dirty is True
return {'FINISHED'}
classes = (
PREFERENCES_OT_addon_disable,
PREFERENCES_OT_addon_enable,

View File

@ -220,8 +220,6 @@ def lightmap_uvpack(
PREF_SEL_ONLY=True,
PREF_NEW_UVLAYER=False,
PREF_PACK_IN_ONE=False,
PREF_APPLY_IMAGE=False,
PREF_IMG_PX_SIZE=512,
PREF_BOX_DIV=8,
PREF_MARGIN_DIV=512,
):
@ -240,8 +238,6 @@ def lightmap_uvpack(
t = time.time()
if PREF_PACK_IN_ONE:
if PREF_APPLY_IMAGE:
image = bpy.data.images.new(name="lightmap", width=PREF_IMG_PX_SIZE, height=PREF_IMG_PX_SIZE, alpha=False)
face_groups = [[]]
else:
face_groups = []
@ -520,20 +516,6 @@ def lightmap_uvpack(
# pf.place(box[1][1], box[1][2], packWidth, packHeight, margin_w, margin_h)
print("done")
if PREF_APPLY_IMAGE:
pass
# removed with texface
'''
if not PREF_PACK_IN_ONE:
image = bpy.data.images.new(name="lightmap",
width=PREF_IMG_PX_SIZE,
height=PREF_IMG_PX_SIZE,
)
for f in face_sel:
f.image = image
'''
for me in meshes:
me.update()
@ -544,11 +526,14 @@ def unwrap(operator, context, **kwargs):
# switch to object mode
is_editmode = context.object and context.object.mode == 'EDIT'
if is_editmode:
objects = context.objects_in_mode_unique_data
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
else:
objects = context.selected_objects
# define list of meshes
meshes = list({
me for obj in context.selected_objects
me for obj in objects
if obj.type == 'MESH'
if (me := obj.data).polygons and me.library is None
})
@ -606,20 +591,6 @@ class LightMapPack(Operator):
description="Create a new UV map for every mesh packed",
default=False,
)
PREF_APPLY_IMAGE: BoolProperty(
name="New Image",
description=(
"Assign new images for every mesh (only one if "
"Share Texture Space is enabled)"
),
default=False,
)
PREF_IMG_PX_SIZE: IntProperty(
name="Image Size",
description="Width and height for the new image",
min=64, max=5000,
default=512,
)
# UV Packing...
PREF_BOX_DIV: IntProperty(
name="Pack Quality",
@ -648,8 +619,6 @@ class LightMapPack(Operator):
layout.prop(self, "PREF_PACK_IN_ONE")
layout.prop(self, "PREF_NEW_UVLAYER")
layout.prop(self, "PREF_APPLY_IMAGE")
layout.prop(self, "PREF_IMG_PX_SIZE")
layout.prop(self, "PREF_BOX_DIV")
layout.prop(self, "PREF_MARGIN_DIV")

View File

@ -120,15 +120,15 @@ def _draw_add_remove_buttons(
list_length,
):
"""Draw the +/- buttons to add and remove list entries."""
add_op = layout.operator(UILIST_OT_entry_add.bl_idname, text="", icon='ADD')
add_op.list_path = list_path
add_op.active_index_path = active_index_path
props = layout.operator(UILIST_OT_entry_add.bl_idname, text="", icon='ADD')
props.list_path = list_path
props.active_index_path = active_index_path
row = layout.row()
row.enabled = list_length > 0
remove_op = row.operator(UILIST_OT_entry_remove.bl_idname, text="", icon='REMOVE')
remove_op.list_path = list_path
remove_op.active_index_path = active_index_path
props = row.operator(UILIST_OT_entry_remove.bl_idname, text="", icon='REMOVE')
props.list_path = list_path
props.active_index_path = active_index_path
def _draw_move_buttons(
@ -141,15 +141,15 @@ def _draw_move_buttons(
"""Draw the up/down arrows to move elements in the list."""
col = layout.column()
col.enabled = list_length > 1
move_up_op = layout.operator(UILIST_OT_entry_move.bl_idname, text="", icon='TRIA_UP')
move_up_op.direction = 'UP'
move_up_op.list_path = list_path
move_up_op.active_index_path = active_index_path
props = layout.operator(UILIST_OT_entry_move.bl_idname, text="", icon='TRIA_UP')
props.direction = 'UP'
props.list_path = list_path
props.active_index_path = active_index_path
move_down_op = layout.operator(UILIST_OT_entry_move.bl_idname, text="", icon='TRIA_DOWN')
move_down_op.direction = 'DOWN'
move_down_op.list_path = list_path
move_down_op.active_index_path = active_index_path
props = layout.operator(UILIST_OT_entry_move.bl_idname, text="", icon='TRIA_DOWN')
props.direction = 'DOWN'
props.list_path = list_path
props.active_index_path = active_index_path
def _get_context_attr(context, data_path):

View File

@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
from bpy.types import Menu
from bpy.app.translations import (
pgettext_iface as iface_,
contexts as i18n_contexts,

View File

@ -423,13 +423,13 @@ class NODE_MT_geometry_node_mesh_topology(Menu):
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "GeometryNodeCornersOfFace"),
node_add_menu.add_node_type(layout, "GeometryNodeCornersOfVertex"),
node_add_menu.add_node_type(layout, "GeometryNodeEdgesOfCorner"),
node_add_menu.add_node_type(layout, "GeometryNodeEdgesOfVertex"),
node_add_menu.add_node_type(layout, "GeometryNodeFaceOfCorner"),
node_add_menu.add_node_type(layout, "GeometryNodeOffsetCornerInFace"),
node_add_menu.add_node_type(layout, "GeometryNodeVertexOfCorner"),
node_add_menu.add_node_type(layout, "GeometryNodeCornersOfFace")
node_add_menu.add_node_type(layout, "GeometryNodeCornersOfVertex")
node_add_menu.add_node_type(layout, "GeometryNodeEdgesOfCorner")
node_add_menu.add_node_type(layout, "GeometryNodeEdgesOfVertex")
node_add_menu.add_node_type(layout, "GeometryNodeFaceOfCorner")
node_add_menu.add_node_type(layout, "GeometryNodeOffsetCornerInFace")
node_add_menu.add_node_type(layout, "GeometryNodeVertexOfCorner")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)

View File

@ -63,12 +63,12 @@ class MESH_MT_shape_key_context_menu(Menu):
layout.operator("object.join_shapes")
layout.operator("object.shape_key_transfer")
layout.separator()
op = layout.operator("object.shape_key_remove", icon='X', text="Delete All Shape Keys")
op.all = True
op.apply_mix = False
op = layout.operator("object.shape_key_remove", text="Apply All Shape Keys")
op.all = True
op.apply_mix = True
props = layout.operator("object.shape_key_remove", icon='X', text="Delete All Shape Keys")
props.all = True
props.apply_mix = False
props = layout.operator("object.shape_key_remove", text="Apply All Shape Keys")
props.all = True
props.apply_mix = True
layout.separator()
layout.operator("object.shape_key_move", icon='TRIA_UP_BAR', text="Move to Top").type = 'TOP'
layout.operator("object.shape_key_move", icon='TRIA_DOWN_BAR', text="Move to Bottom").type = 'BOTTOM'
@ -674,12 +674,12 @@ class MESH_UL_color_attributes(UIList, ColorAttributesListBase):
row = layout.row()
row.emboss = 'NONE'
prop = row.operator(
props = row.operator(
"geometry.color_attribute_render_set",
text="",
icon='RESTRICT_RENDER_OFF' if active_render else 'RESTRICT_RENDER_ON',
)
prop.name = attribute.name
props.name = attribute.name
class MESH_UL_color_attributes_selector(UIList, ColorAttributesListBase):

View File

@ -739,15 +739,15 @@ class VIEWLAYER_PT_freestyle_linestyle_color(ViewLayerFreestyleLineStyle, Panel)
elif modifier.type == 'DISTANCE_FROM_OBJECT':
box.prop(modifier, "target")
draw_modifier_color_ramp_common(box, modifier, True)
prop = box.operator("scene.freestyle_fill_range_by_selection")
prop.type = 'COLOR'
prop.name = modifier.name
props = box.operator("scene.freestyle_fill_range_by_selection")
props.type = 'COLOR'
props.name = modifier.name
elif modifier.type == 'DISTANCE_FROM_CAMERA':
draw_modifier_color_ramp_common(box, modifier, True)
prop = box.operator("scene.freestyle_fill_range_by_selection")
prop.type = 'COLOR'
prop.name = modifier.name
props = box.operator("scene.freestyle_fill_range_by_selection")
props.type = 'COLOR'
props.name = modifier.name
elif modifier.type == 'MATERIAL':
row = box.row()
@ -842,15 +842,15 @@ class VIEWLAYER_PT_freestyle_linestyle_alpha(ViewLayerFreestyleLineStyle, Panel)
elif modifier.type == 'DISTANCE_FROM_OBJECT':
box.prop(modifier, "target")
draw_modifier_curve_common(box, modifier, True, False)
prop = box.operator("scene.freestyle_fill_range_by_selection")
prop.type = 'ALPHA'
prop.name = modifier.name
props = box.operator("scene.freestyle_fill_range_by_selection")
props.type = 'ALPHA'
props.name = modifier.name
elif modifier.type == 'DISTANCE_FROM_CAMERA':
draw_modifier_curve_common(box, modifier, True, False)
prop = box.operator("scene.freestyle_fill_range_by_selection")
prop.type = 'ALPHA'
prop.name = modifier.name
props = box.operator("scene.freestyle_fill_range_by_selection")
props.type = 'ALPHA'
props.name = modifier.name
elif modifier.type == 'MATERIAL':
box.prop(modifier, "material_attribute", text="Material Attribute")
@ -934,15 +934,15 @@ class VIEWLAYER_PT_freestyle_linestyle_thickness(ViewLayerFreestyleLineStyle, Pa
elif modifier.type == 'DISTANCE_FROM_OBJECT':
box.prop(modifier, "target")
draw_modifier_curve_common(box, modifier, True, True)
prop = box.operator("scene.freestyle_fill_range_by_selection")
prop.type = 'THICKNESS'
prop.name = modifier.name
props = box.operator("scene.freestyle_fill_range_by_selection")
props.type = 'THICKNESS'
props.name = modifier.name
elif modifier.type == 'DISTANCE_FROM_CAMERA':
draw_modifier_curve_common(box, modifier, True, True)
prop = box.operator("scene.freestyle_fill_range_by_selection")
prop.type = 'THICKNESS'
prop.name = modifier.name
props = box.operator("scene.freestyle_fill_range_by_selection")
props.type = 'THICKNESS'
props.name = modifier.name
elif modifier.type == 'MATERIAL':
box.prop(modifier, "material_attribute", text="Material Attribute")

View File

@ -106,10 +106,14 @@ class GreasePencilDisplayPanel:
settings = tool_settings.gpencil_vertex_paint
brush = settings.brush
gp_settings = brush.gpencil_settings
ob = context.active_object
if ob.mode == 'PAINT_GPENCIL':
if self.is_popover and ob.mode not in {'PAINT_GPENCIL', 'VERTEX_GPENCIL'}:
row = layout.row(align=True)
row.use_property_split = False
row.prop(settings, "show_brush", text="Display Cursor")
if ob.mode == 'PAINT_GPENCIL':
if self.is_popover:
row = layout.row(align=True)
row.prop(settings, "show_brush", text="Display Cursor")
@ -135,8 +139,7 @@ class GreasePencilDisplayPanel:
elif ob.mode == 'VERTEX_GPENCIL':
row = layout.row(align=True)
row.prop(settings, "show_brush", text="")
row.label(text="Display Cursor")
row.prop(settings, "show_brush", text="Display Cursor")
class GreasePencilBrushFalloff:
@ -145,16 +148,16 @@ class GreasePencilBrushFalloff:
def draw(self, context):
layout = self.layout
ts = context.tool_settings
tool_settings = context.tool_settings
settings = None
if context.mode == 'PAINT_GPENCIL':
settings = ts.gpencil_paint
settings = tool_settings.gpencil_paint
if context.mode == 'SCULPT_GPENCIL':
settings = ts.gpencil_sculpt_paint
settings = tool_settings.gpencil_sculpt_paint
elif context.mode == 'WEIGHT_GPENCIL':
settings = ts.gpencil_weight_paint
settings = tool_settings.gpencil_weight_paint
elif context.mode == 'VERTEX_GPENCIL':
settings = ts.gpencil_vertex_paint
settings = tool_settings.gpencil_vertex_paint
if settings:
brush = settings.brush
@ -585,9 +588,9 @@ class GreasePencilVertexcolorPanel:
layout.use_property_split = True
layout.use_property_decorate = False
ts = context.scene.tool_settings
tool_settings = context.scene.tool_settings
is_vertex = context.mode == 'VERTEX_GPENCIL'
gpencil_paint = ts.gpencil_vertex_paint if is_vertex else ts.gpencil_paint
gpencil_paint = tool_settings.gpencil_vertex_paint if is_vertex else tool_settings.gpencil_paint
brush = gpencil_paint.brush
gp_settings = brush.gpencil_settings
tool = brush.gpencil_vertex_tool if is_vertex else brush.gpencil_tool
@ -855,30 +858,30 @@ class GreasePencilFlipTintColors(Operator):
@classmethod
def poll(cls, context):
ts = context.tool_settings
tool_settings = context.tool_settings
settings = None
if context.mode == 'PAINT_GPENCIL':
settings = ts.gpencil_paint
settings = tool_settings.gpencil_paint
if context.mode == 'SCULPT_GPENCIL':
settings = ts.gpencil_sculpt_paint
settings = tool_settings.gpencil_sculpt_paint
elif context.mode == 'WEIGHT_GPENCIL':
settings = ts.gpencil_weight_paint
settings = tool_settings.gpencil_weight_paint
elif context.mode == 'VERTEX_GPENCIL':
settings = ts.gpencil_vertex_paint
settings = tool_settings.gpencil_vertex_paint
return settings and settings.brush
def execute(self, context):
ts = context.tool_settings
tool_settings = context.tool_settings
settings = None
if context.mode == 'PAINT_GPENCIL':
settings = ts.gpencil_paint
settings = tool_settings.gpencil_paint
if context.mode == 'SCULPT_GPENCIL':
settings = ts.gpencil_sculpt_paint
settings = tool_settings.gpencil_sculpt_paint
elif context.mode == 'WEIGHT_GPENCIL':
settings = ts.gpencil_weight_paint
settings = tool_settings.gpencil_weight_paint
elif context.mode == 'VERTEX_GPENCIL':
settings = ts.gpencil_vertex_paint
settings = tool_settings.gpencil_vertex_paint
brush = settings.brush
color = brush.color

View File

@ -378,7 +378,9 @@ class SmoothStrokePanel(BrushPanel):
settings = self.paint_settings(context)
brush = settings.brush
self.layout.prop(brush, "use_smooth_stroke", text="")
self.layout.use_property_split = False
self.layout.prop(brush, "use_smooth_stroke",
text=self.bl_label if self.is_popover else "")
def draw(self, context):
layout = self.layout
@ -472,8 +474,8 @@ class DisplayPanel(BrushPanel):
if self.is_popover:
row = layout.row(align=True)
row.prop(settings, "show_brush", text="")
row.label(text="Display Cursor")
row.use_property_split = False
row.prop(settings, "show_brush", text="Display Cursor")
col = layout.column()
col.active = brush.brush_capabilities.has_overlay and settings.show_brush

View File

@ -328,7 +328,7 @@ class PARTICLE_PT_emission_source(ParticleButtonsPanel, Panel):
col = layout.column()
col.prop(part, "emit_from")
col.prop(part, "use_modifier_stack")
if part.emit_from == 'FACE' or part.emit_from == 'VOLUME':
if part.emit_from in {'FACE', 'VOLUME'}:
col.prop(part, "distribution")
if part.emit_from == 'VERT':
@ -340,7 +340,7 @@ class PARTICLE_PT_emission_source(ParticleButtonsPanel, Panel):
col.prop(part, "use_emit_random", text="Random Order")
col.prop(part, "use_even_distribution")
if part.emit_from == 'FACE' or part.emit_from == 'VOLUME':
if part.emit_from in {'FACE', 'VOLUME'}:
if part.distribution == 'JIT':
col.prop(part, "userjit", text="Particles/Face")

View File

@ -37,6 +37,7 @@ def physics_add(layout, md, name, type, typeicon, toggles):
text_ctxt=i18n_contexts.default,
icon=typeicon,
).type = type
return None
def physics_add_special(layout, data, name, addop, removeop, typeicon):

View File

@ -82,8 +82,7 @@ class PhysicButtonsPanel:
md = context.fluid
flow = md.flow_settings
if (flow.flow_behavior == 'OUTFLOW'):
return True
return (flow.flow_behavior == 'OUTFLOW')
@staticmethod
def poll_fluid_flow_liquid(context):
@ -92,8 +91,7 @@ class PhysicButtonsPanel:
md = context.fluid
flow = md.flow_settings
if (flow.flow_type == 'LIQUID'):
return True
return (flow.flow_type == 'LIQUID')
class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):

View File

@ -76,31 +76,6 @@ class VIEWLAYER_PT_eevee_layer_passes_data(ViewLayerButtonsPanel, Panel):
col.prop(view_layer, "use_pass_normal")
class VIEWLAYER_PT_eevee_next_layer_passes_data(ViewLayerButtonsPanel, Panel):
bl_label = "Data"
bl_parent_id = "VIEWLAYER_PT_layer_passes"
COMPAT_ENGINES = {'BLENDER_EEVEE_NEXT'}
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
scene = context.scene
view_layer = context.view_layer
col = layout.column()
col.prop(view_layer, "use_pass_combined")
col.prop(view_layer, "use_pass_z")
col.prop(view_layer, "use_pass_mist")
col.prop(view_layer, "use_pass_normal")
col.prop(view_layer, "use_pass_position")
sub = col.column()
sub.active = not scene.eevee.use_motion_blur
sub.prop(view_layer, "use_pass_vector")
class VIEWLAYER_PT_eevee_next_layer_passes_data(ViewLayerButtonsPanel, Panel):
bl_label = "Data"
bl_parent_id = "VIEWLAYER_PT_layer_passes"

View File

@ -1079,10 +1079,11 @@ class CLIP_PT_2d_cursor(Panel):
@classmethod
def poll(cls, context):
sc = context.space_data
if not CLIP_PT_clip_view_panel.poll(context):
return False
if CLIP_PT_clip_view_panel.poll(context):
return sc.pivot_point == 'CURSOR' or sc.mode == 'MASK'
sc = context.space_data
return sc.pivot_point == 'CURSOR' or sc.mode == 'MASK'
def draw(self, context):
layout = self.layout
@ -1732,13 +1733,13 @@ class CLIP_MT_marker_pie(Menu):
layout = self.layout
pie = layout.menu_pie()
# Use Location Tracking
prop = pie.operator("wm.context_set_enum", text="Location")
prop.data_path = "space_data.clip.tracking.tracks.active.motion_model"
prop.value = "Loc"
props = pie.operator("wm.context_set_enum", text="Location")
props.data_path = "space_data.clip.tracking.tracks.active.motion_model"
props.value = "Loc"
# Use Affine Tracking
prop = pie.operator("wm.context_set_enum", text="Affine")
prop.data_path = "space_data.clip.tracking.tracks.active.motion_model"
prop.value = "Affine"
props = pie.operator("wm.context_set_enum", text="Affine")
props.data_path = "space_data.clip.tracking.tracks.active.motion_model"
props.value = "Affine"
# Copy Settings From Active To Selected
pie.operator("clip.track_settings_to_track", icon='COPYDOWN')
# Make Settings Default
@ -1749,13 +1750,13 @@ class CLIP_MT_marker_pie(Menu):
# Use Brute Force
pie.prop(track_active, "use_brute", text="Use Brute Force")
# Match Keyframe
prop = pie.operator("wm.context_set_enum", text="Match Previous", icon='KEYFRAME_HLT')
prop.data_path = "space_data.clip.tracking.tracks.active.pattern_match"
prop.value = 'PREV_FRAME'
props = pie.operator("wm.context_set_enum", text="Match Previous", icon='KEYFRAME_HLT')
props.data_path = "space_data.clip.tracking.tracks.active.pattern_match"
props.value = 'PREV_FRAME'
# Match Previous Frame
prop = pie.operator("wm.context_set_enum", text="Match Keyframe", icon='KEYFRAME')
prop.data_path = "space_data.clip.tracking.tracks.active.pattern_match"
prop.value = 'KEYFRAME'
props = pie.operator("wm.context_set_enum", text="Match Keyframe", icon='KEYFRAME')
props.data_path = "space_data.clip.tracking.tracks.active.pattern_match"
props.value = 'KEYFRAME'
class CLIP_MT_tracking_pie(Menu):
@ -1773,13 +1774,13 @@ class CLIP_MT_tracking_pie(Menu):
pie = layout.menu_pie()
# Track Backwards
prop = pie.operator("clip.track_markers", icon='TRACKING_BACKWARDS')
prop.backwards = True
prop.sequence = True
props = pie.operator("clip.track_markers", icon='TRACKING_BACKWARDS')
props.backwards = True
props.sequence = True
# Track Forwards
prop = pie.operator("clip.track_markers", icon='TRACKING_FORWARDS')
prop.backwards = False
prop.sequence = True
props = pie.operator("clip.track_markers", icon='TRACKING_FORWARDS')
props.backwards = False
props.sequence = True
# Disable Marker
pie.operator("clip.disable_markers", icon='HIDE_OFF').action = 'TOGGLE'
# Detect Features
@ -1831,11 +1832,11 @@ class CLIP_MT_solving_pie(Menu):
icon='KEYFRAME',
).keyframe = 'KEYFRAME_B'
# Clean Tracks
prop = pie.operator("clip.clean_tracks", icon='X')
props = pie.operator("clip.clean_tracks", icon='X')
props.frames = 15
props.error = 2
# Filter Tracks
pie.operator("clip.filter_tracks", icon='FILTER')
prop.frames = 15
prop.error = 2
class CLIP_MT_reconstruction_pie(Menu):

View File

@ -7,8 +7,7 @@ class CONSOLE_HT_header(Header):
bl_space_type = 'CONSOLE'
def draw(self, context):
layout = self.layout.row()
layout = self.layout
layout.template_header()
CONSOLE_MT_editor_menus.draw_collapsible(context, layout)

View File

@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from bpy.types import Header, Menu, Panel
from bl_ui_utils.layout import operator_context
from bl_ui.space_dopesheet import (
DopesheetFilterPopoverBase,
dopesheet_filter,
@ -241,6 +240,8 @@ class GRAPH_MT_key(Menu):
bl_label = "Key"
def draw(self, _context):
from bl_ui_utils.layout import operator_context
layout = self.layout
layout.menu("GRAPH_MT_key_transform", text="Transform")

View File

@ -4,7 +4,6 @@ from bpy.types import Header, Menu, Panel
from bpy.app.translations import (
contexts as i18n_contexts,
pgettext_iface as iface_,
)

View File

@ -135,8 +135,6 @@ class SEQUENCER_HT_tool_header(Header):
# TODO: options popover.
def draw_tool_settings(self, context):
pass
layout = self.layout
# Active Tool
@ -621,17 +619,17 @@ class SEQUENCER_MT_change(Menu):
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator_menu_enum("sequencer.change_effect_input", "swap")
layout.operator_menu_enum("sequencer.change_effect_type", "type")
prop = layout.operator("sequencer.change_path", text="Path/Files")
props = layout.operator("sequencer.change_path", text="Path/Files")
if strip:
strip_type = strip.type
if strip_type == 'IMAGE':
prop.filter_image = True
props.filter_image = True
elif strip_type == 'MOVIE':
prop.filter_movie = True
props.filter_movie = True
elif strip_type == 'SOUND':
prop.filter_sound = True
props.filter_sound = True
class SEQUENCER_MT_navigation(Menu):
@ -865,18 +863,18 @@ class SEQUENCER_MT_strip_input(Menu):
layout.operator("sequencer.reload", text="Reload Strips")
layout.operator("sequencer.reload", text="Reload Strips and Adjust Length").adjust_length = True
prop = layout.operator("sequencer.change_path", text="Change Path/Files")
props = layout.operator("sequencer.change_path", text="Change Path/Files")
layout.operator("sequencer.swap_data", text="Swap Data")
if strip:
strip_type = strip.type
if strip_type == 'IMAGE':
prop.filter_image = True
props.filter_image = True
elif strip_type == 'MOVIE':
prop.filter_movie = True
props.filter_movie = True
elif strip_type == 'SOUND':
prop.filter_sound = True
props.filter_sound = True
class SEQUENCER_MT_strip_lock_mute(Menu):
@ -2006,7 +2004,7 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel):
split.prop(strip, "pan", text="")
split.enabled = pan_enabled
if audio_channels != 'MONO' and audio_channels != 'STEREO':
if audio_channels not in {'MONO', 'STEREO'}:
split = col.split(factor=0.4)
split.alignment = 'RIGHT'
split.label(text="Pan Angle")

View File

@ -451,6 +451,7 @@ class _defs_view3d_add:
for item in km.keymap_items:
if item.propvalue == propvalue:
return item
return None
if km is not None:
kmi_snap = keymap_item_from_propvalue('SNAP_ON')
@ -2094,13 +2095,13 @@ class _defs_gpencil_paint:
class _defs_gpencil_edit:
def is_segment(context):
ts = context.scene.tool_settings
tool_settings = context.scene.tool_settings
if context.mode == 'EDIT_GPENCIL':
return ts.gpencil_selectmode_edit == 'SEGMENT'
return tool_settings.gpencil_selectmode_edit == 'SEGMENT'
elif context.mode == 'SCULPT_GPENCIL':
return ts.use_gpencil_select_mask_segment
return tool_settings.use_gpencil_select_mask_segment
elif context.mode == 'VERTEX_GPENCIL':
return ts.use_gpencil_vertex_select_mask_segment
return tool_settings.use_gpencil_vertex_select_mask_segment
else:
return False
@ -2283,10 +2284,15 @@ class _defs_gpencil_sculpt:
if context is None:
return True
ob = context.active_object
ts = context.scene.tool_settings
return ob and ob.type == 'GPENCIL' and (ts.use_gpencil_select_mask_point or
ts.use_gpencil_select_mask_stroke or
ts.use_gpencil_select_mask_segment)
tool_settings = context.scene.tool_settings
return (
ob is not None and
ob.type == 'GPENCIL' and (
tool_settings.use_gpencil_select_mask_point or
tool_settings.use_gpencil_select_mask_stroke or
tool_settings.use_gpencil_select_mask_segment
)
)
@staticmethod
def generate_from_brushes(context):
@ -2427,10 +2433,15 @@ class _defs_gpencil_vertex:
if context is None:
return True
ob = context.active_object
ts = context.scene.tool_settings
return ob and ob.type == 'GPENCIL' and (ts.use_gpencil_vertex_select_mask_point or
ts.use_gpencil_vertex_select_mask_stroke or
ts.use_gpencil_vertex_select_mask_segment)
tool_settings = context.scene.tool_settings
return (
ob is not None and
ob.type == 'GPENCIL' and (
tool_settings.use_gpencil_vertex_select_mask_point or
tool_settings.use_gpencil_vertex_select_mask_stroke or
tool_settings.use_gpencil_vertex_select_mask_segment
)
)
@staticmethod
def generate_from_brushes(context):
@ -2652,7 +2663,6 @@ class _defs_sequencer_select:
row = layout.row()
row.use_property_split = False
row.prop(props, "mode", text="", expand=True, icon_only=True)
pass
return dict(
idname="builtin.select_box",
label="Select Box",

View File

@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
from bpy.types import Header, Menu, Panel
from bl_ui_utils.layout import operator_context
from bpy.app.translations import (
pgettext_iface as iface_,
@ -236,34 +235,34 @@ class TOPBAR_MT_file_cleanup(Menu):
layout = self.layout
layout.separator()
op_props = layout.operator("outliner.orphans_purge", text="Unused Data-Blocks")
op_props.do_local_ids = True
op_props.do_linked_ids = True
op_props.do_recursive = False
op_props = layout.operator("outliner.orphans_purge", text="Recursive Unused Data-Blocks")
op_props.do_local_ids = True
op_props.do_linked_ids = True
op_props.do_recursive = True
props = layout.operator("outliner.orphans_purge", text="Unused Data-Blocks")
props.do_local_ids = True
props.do_linked_ids = True
props.do_recursive = False
props = layout.operator("outliner.orphans_purge", text="Recursive Unused Data-Blocks")
props.do_local_ids = True
props.do_linked_ids = True
props.do_recursive = True
layout.separator()
op_props = layout.operator("outliner.orphans_purge", text="Unused Linked Data-Blocks")
op_props.do_local_ids = False
op_props.do_linked_ids = True
op_props.do_recursive = False
op_props = layout.operator("outliner.orphans_purge", text="Recursive Unused Linked Data-Blocks")
op_props.do_local_ids = False
op_props.do_linked_ids = True
op_props.do_recursive = True
props = layout.operator("outliner.orphans_purge", text="Unused Linked Data-Blocks")
props.do_local_ids = False
props.do_linked_ids = True
props.do_recursive = False
props = layout.operator("outliner.orphans_purge", text="Recursive Unused Linked Data-Blocks")
props.do_local_ids = False
props.do_linked_ids = True
props.do_recursive = True
layout.separator()
op_props = layout.operator("outliner.orphans_purge", text="Unused Local Data-Blocks")
op_props.do_local_ids = True
op_props.do_linked_ids = False
op_props.do_recursive = False
op_props = layout.operator("outliner.orphans_purge", text="Recursive Unused Local Data-Blocks")
op_props.do_local_ids = True
op_props.do_linked_ids = False
op_props.do_recursive = True
props = layout.operator("outliner.orphans_purge", text="Unused Local Data-Blocks")
props.do_local_ids = True
props.do_linked_ids = False
props.do_recursive = False
props = layout.operator("outliner.orphans_purge", text="Recursive Unused Local Data-Blocks")
props.do_local_ids = True
props.do_linked_ids = False
props.do_recursive = True
class TOPBAR_MT_file(Menu):
@ -643,11 +642,10 @@ class TOPBAR_MT_window(Menu):
def draw(self, context):
import sys
from bl_ui_utils.layout import operator_context
layout = self.layout
operator_context_default = layout.operator_context
layout.operator("wm.window_new")
layout.operator("wm.window_new_main")

View File

@ -2205,12 +2205,12 @@ class StudioLightPanelMixin:
row.template_icon(layout.icon(studio_light), scale=3.0)
col = row.column()
op = col.operator("preferences.studiolight_uninstall", text="", icon='REMOVE')
op.index = studio_light.index
props = col.operator("preferences.studiolight_uninstall", text="", icon='REMOVE')
props.index = studio_light.index
if studio_light.type == 'STUDIO':
op = col.operator("preferences.studiolight_copy_settings", text="", icon='IMPORT')
op.index = studio_light.index
props = col.operator("preferences.studiolight_copy_settings", text="", icon='IMPORT')
props.index = studio_light.index
box.label(text=studio_light.name)
@ -2247,9 +2247,9 @@ class USERPREF_PT_studiolight_lights(StudioLightPanel, StudioLightPanelMixin, Pa
def draw_header_preset(self, _context):
layout = self.layout
op = layout.operator("preferences.studiolight_install", icon='IMPORT', text="Install...")
op.type = 'STUDIO'
op.filter_glob = ".sl"
props = layout.operator("preferences.studiolight_install", icon='IMPORT', text="Install...")
props.type = 'STUDIO'
props.filter_glob = ".sl"
layout.separator()
def get_error_message(self):

View File

@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
from bl_ui_utils.layout import operator_context
from bpy.types import (
Header,
Menu,
@ -570,6 +569,8 @@ class _draw_tool_settings_context_mode:
elif curves_tool == "SLIDE":
layout.popover("VIEW3D_PT_tools_brush_falloff")
return True
class VIEW3D_HT_header(Header):
bl_space_type = 'VIEW_3D'
@ -928,7 +929,7 @@ class VIEW3D_MT_editor_menus(Menu):
edit_object = context.edit_object
gp_edit = obj and obj.mode in {'EDIT_GPENCIL', 'PAINT_GPENCIL', 'SCULPT_GPENCIL',
'WEIGHT_GPENCIL', 'VERTEX_GPENCIL'}
ts = context.scene.tool_settings
tool_settings = context.scene.tool_settings
layout.menu("VIEW3D_MT_view")
@ -937,9 +938,9 @@ class VIEW3D_MT_editor_menus(Menu):
if mode_string not in {'PAINT_GPENCIL', 'WEIGHT_GPENCIL'}:
if (
mode_string == 'SCULPT_GPENCIL' and
(ts.use_gpencil_select_mask_point or
ts.use_gpencil_select_mask_stroke or
ts.use_gpencil_select_mask_segment)
(tool_settings.use_gpencil_select_mask_point or
tool_settings.use_gpencil_select_mask_stroke or
tool_settings.use_gpencil_select_mask_segment)
):
layout.menu("VIEW3D_MT_select_gpencil")
elif mode_string == 'EDIT_GPENCIL':
@ -1443,8 +1444,6 @@ class VIEW3D_MT_select_object_more_less(Menu):
def draw(self, _context):
layout = self.layout
layout = self.layout
layout.operator("object.select_more", text="More")
layout.operator("object.select_less", text="Less")
@ -1509,8 +1508,6 @@ class VIEW3D_MT_select_pose_more_less(Menu):
def draw(self, _context):
layout = self.layout
layout = self.layout
props = layout.operator("pose.select_hierarchy", text="Parent")
props.extend = False
props.direction = 'PARENT'
@ -1619,6 +1616,7 @@ class VIEW3D_MT_edit_mesh_select_by_trait(Menu):
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
if tool_settings.mesh_select_mode[2] is False:
layout.operator("mesh.select_non_manifold", text="Non Manifold")
layout.operator("mesh.select_loose", text="Loose Geometry")
@ -1855,8 +1853,6 @@ class VIEW3D_MT_edit_lattice_context_menu(Menu):
def draw(self, _context):
layout = self.layout
layout = self.layout
layout.menu("VIEW3D_MT_mirror")
layout.operator_menu_enum("lattice.flip", "axis")
layout.menu("VIEW3D_MT_snap")
@ -2036,8 +2032,8 @@ class VIEW3D_MT_select_paint_mask_vertex(Menu):
layout.operator("paint.vert_select_all", text="None").action = 'DESELECT'
layout.operator("paint.vert_select_all", text="Invert").action = 'INVERT'
layout.operator("paint.vert_select_more"),
layout.operator("paint.vert_select_less"),
layout.operator("paint.vert_select_more")
layout.operator("paint.vert_select_less")
layout.separator()
@ -2207,9 +2203,10 @@ class TOPBAR_MT_edit_curve_add(Menu):
bl_translation_context = i18n_contexts.operator_default
def draw(self, context):
layout = self.layout
is_surf = context.active_object.type == 'SURFACE'
layout = self.layout
layout.operator_context = 'EXEC_REGION_WIN'
if is_surf:
@ -2537,8 +2534,8 @@ class VIEW3D_MT_object_context_menu(Menu):
bl_label = "Object Context Menu"
def draw(self, context):
layout = self.layout
view = context.space_data
obj = context.object
@ -2766,6 +2763,7 @@ class VIEW3D_MT_object_apply(Menu):
def draw(self, _context):
layout = self.layout
# Need invoke for the popup confirming the multi-user data operation
layout.operator_context = 'INVOKE_DEFAULT'
@ -2831,6 +2829,8 @@ class VIEW3D_MT_object_parent(Menu):
bl_label = "Parent"
def draw(self, _context):
from bl_ui_utils.layout import operator_context
layout = self.layout
layout.operator_enum("object.parent_set", "type")
@ -3142,36 +3142,36 @@ class VIEW3D_MT_paint_weight_lock(Menu):
def draw(self, _context):
layout = self.layout
op = layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All")
op.action, op.mask = 'LOCK', 'ALL'
props = layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All")
props.action, props.mask = 'LOCK', 'ALL'
op = layout.operator("object.vertex_group_lock", text="Lock Selected")
op.action, op.mask = 'LOCK', 'SELECTED'
props = layout.operator("object.vertex_group_lock", text="Lock Selected")
props.action, props.mask = 'LOCK', 'SELECTED'
op = layout.operator("object.vertex_group_lock", text="Lock Unselected")
op.action, op.mask = 'LOCK', 'UNSELECTED'
props = layout.operator("object.vertex_group_lock", text="Lock Unselected")
props.action, props.mask = 'LOCK', 'UNSELECTED'
op = layout.operator("object.vertex_group_lock", text="Lock Only Selected")
op.action, op.mask = 'LOCK', 'INVERT_UNSELECTED'
props = layout.operator("object.vertex_group_lock", text="Lock Only Selected")
props.action, props.mask = 'LOCK', 'INVERT_UNSELECTED'
op = layout.operator("object.vertex_group_lock", text="Lock Only Unselected")
op.action, op.mask = 'UNLOCK', 'INVERT_UNSELECTED'
props = layout.operator("object.vertex_group_lock", text="Lock Only Unselected")
props.action, props.mask = 'UNLOCK', 'INVERT_UNSELECTED'
layout.separator()
op = layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock All")
op.action, op.mask = 'UNLOCK', 'ALL'
props = layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock All")
props.action, props.mask = 'UNLOCK', 'ALL'
op = layout.operator("object.vertex_group_lock", text="Unlock Selected")
op.action, op.mask = 'UNLOCK', 'SELECTED'
props = layout.operator("object.vertex_group_lock", text="Unlock Selected")
props.action, props.mask = 'UNLOCK', 'SELECTED'
op = layout.operator("object.vertex_group_lock", text="Unlock Unselected")
op.action, op.mask = 'UNLOCK', 'UNSELECTED'
props = layout.operator("object.vertex_group_lock", text="Unlock Unselected")
props.action, props.mask = 'UNLOCK', 'UNSELECTED'
layout.separator()
op = layout.operator("object.vertex_group_lock", icon='ARROW_LEFTRIGHT', text="Invert Locks")
op.action, op.mask = 'INVERT', 'ALL'
props = layout.operator("object.vertex_group_lock", icon='ARROW_LEFTRIGHT', text="Invert Locks")
props.action, props.mask = 'INVERT', 'ALL'
class VIEW3D_MT_paint_weight(Menu):
@ -3416,14 +3416,14 @@ class VIEW3D_MT_face_sets(Menu):
def draw(self, _context):
layout = self.layout
op = layout.operator("sculpt.face_sets_create", text="Face Set from Masked")
op.mode = 'MASKED'
props = layout.operator("sculpt.face_sets_create", text="Face Set from Masked")
props.mode = 'MASKED'
op = layout.operator("sculpt.face_sets_create", text="Face Set from Visible")
op.mode = 'VISIBLE'
props = layout.operator("sculpt.face_sets_create", text="Face Set from Visible")
props.mode = 'VISIBLE'
op = layout.operator("sculpt.face_sets_create", text="Face Set from Edit Mode Selection")
op.mode = 'SELECTION'
props = layout.operator("sculpt.face_sets_create", text="Face Set from Edit Mode Selection")
props.mode = 'SELECTION'
layout.separator()
@ -3431,11 +3431,11 @@ class VIEW3D_MT_face_sets(Menu):
layout.separator()
op = layout.operator("sculpt.face_set_edit", text="Grow Face Set")
op.mode = 'GROW'
props = layout.operator("sculpt.face_set_edit", text="Grow Face Set")
props.mode = 'GROW'
op = layout.operator("sculpt.face_set_edit", text="Shrink Face Set")
op.mode = 'SHRINK'
props = layout.operator("sculpt.face_set_edit", text="Shrink Face Set")
props.mode = 'SHRINK'
layout.separator()
@ -3453,18 +3453,18 @@ class VIEW3D_MT_face_sets(Menu):
layout.separator()
op = layout.operator("mesh.face_set_extract", text="Extract Face Set")
props = layout.operator("mesh.face_set_extract", text="Extract Face Set")
layout.separator()
op = layout.operator("sculpt.face_set_change_visibility", text="Invert Visible Face Sets")
op.mode = 'INVERT'
props = layout.operator("sculpt.face_set_change_visibility", text="Invert Visible Face Sets")
props.mode = 'INVERT'
op = layout.operator("sculpt.reveal_all", text="Show All Face Sets")
props = layout.operator("sculpt.reveal_all", text="Show All Face Sets")
layout.separator()
op = layout.operator("sculpt.face_sets_randomize_colors", text="Randomize Colors")
props = layout.operator("sculpt.face_sets_randomize_colors", text="Randomize Colors")
class VIEW3D_MT_sculpt_set_pivot(Menu):
@ -3495,32 +3495,32 @@ class VIEW3D_MT_face_sets_init(Menu):
def draw(self, _context):
layout = self.layout
op = layout.operator("sculpt.face_sets_init", text="By Loose Parts")
op.mode = 'LOOSE_PARTS'
props = layout.operator("sculpt.face_sets_init", text="By Loose Parts")
props.mode = 'LOOSE_PARTS'
op = layout.operator("sculpt.face_sets_init", text="By Face Set Boundaries")
op.mode = 'FACE_SET_BOUNDARIES'
props = layout.operator("sculpt.face_sets_init", text="By Face Set Boundaries")
props.mode = 'FACE_SET_BOUNDARIES'
op = layout.operator("sculpt.face_sets_init", text="By Materials")
op.mode = 'MATERIALS'
props = layout.operator("sculpt.face_sets_init", text="By Materials")
props.mode = 'MATERIALS'
op = layout.operator("sculpt.face_sets_init", text="By Normals")
op.mode = 'NORMALS'
props = layout.operator("sculpt.face_sets_init", text="By Normals")
props.mode = 'NORMALS'
op = layout.operator("sculpt.face_sets_init", text="By UV Seams")
op.mode = 'UV_SEAMS'
props = layout.operator("sculpt.face_sets_init", text="By UV Seams")
props.mode = 'UV_SEAMS'
op = layout.operator("sculpt.face_sets_init", text="By Edge Creases")
op.mode = 'CREASES'
props = layout.operator("sculpt.face_sets_init", text="By Edge Creases")
props.mode = 'CREASES'
op = layout.operator("sculpt.face_sets_init", text="By Edge Bevel Weight")
op.mode = 'BEVEL_WEIGHT'
props = layout.operator("sculpt.face_sets_init", text="By Edge Bevel Weight")
props.mode = 'BEVEL_WEIGHT'
op = layout.operator("sculpt.face_sets_init", text="By Sharp Edges")
op.mode = 'SHARP_EDGES'
props = layout.operator("sculpt.face_sets_init", text="By Sharp Edges")
props.mode = 'SHARP_EDGES'
op = layout.operator("sculpt.face_sets_init", text="By Face Maps")
op.mode = 'FACE_MAPS'
props = layout.operator("sculpt.face_sets_init", text="By Face Maps")
props.mode = 'FACE_MAPS'
class VIEW3D_MT_random_mask(Menu):
@ -3529,14 +3529,14 @@ class VIEW3D_MT_random_mask(Menu):
def draw(self, _context):
layout = self.layout
op = layout.operator("sculpt.mask_init", text="Per Vertex")
op.mode = 'RANDOM_PER_VERTEX'
props = layout.operator("sculpt.mask_init", text="Per Vertex")
props.mode = 'RANDOM_PER_VERTEX'
op = layout.operator("sculpt.mask_init", text="Per Face Set")
op.mode = 'RANDOM_PER_FACE_SET'
props = layout.operator("sculpt.mask_init", text="Per Face Set")
props.mode = 'RANDOM_PER_FACE_SET'
op = layout.operator("sculpt.mask_init", text="Per Loose Part")
op.mode = 'RANDOM_PER_LOOSE_PART'
props = layout.operator("sculpt.mask_init", text="Per Loose Part")
props.mode = 'RANDOM_PER_LOOSE_PART'
class VIEW3D_MT_particle(Menu):
@ -4430,17 +4430,17 @@ class VIEW3D_MT_edit_mesh_normals_select_strength(Menu):
def draw(self, _context):
layout = self.layout
op = layout.operator("mesh.mod_weighted_strength", text="Weak")
op.set = False
op.face_strength = 'WEAK'
props = layout.operator("mesh.mod_weighted_strength", text="Weak")
props.set = False
props.face_strength = 'WEAK'
op = layout.operator("mesh.mod_weighted_strength", text="Medium")
op.set = False
op.face_strength = 'MEDIUM'
props = layout.operator("mesh.mod_weighted_strength", text="Medium")
props.set = False
props.face_strength = 'MEDIUM'
op = layout.operator("mesh.mod_weighted_strength", text="Strong")
op.set = False
op.face_strength = 'STRONG'
props = layout.operator("mesh.mod_weighted_strength", text="Strong")
props.set = False
props.face_strength = 'STRONG'
class VIEW3D_MT_edit_mesh_normals_set_strength(Menu):
@ -4449,17 +4449,17 @@ class VIEW3D_MT_edit_mesh_normals_set_strength(Menu):
def draw(self, _context):
layout = self.layout
op = layout.operator("mesh.mod_weighted_strength", text="Weak")
op.set = True
op.face_strength = 'WEAK'
props = layout.operator("mesh.mod_weighted_strength", text="Weak")
props.set = True
props.face_strength = 'WEAK'
op = layout.operator("mesh.mod_weighted_strength", text="Medium")
op.set = True
op.face_strength = 'MEDIUM'
props = layout.operator("mesh.mod_weighted_strength", text="Medium")
props.set = True
props.face_strength = 'MEDIUM'
op = layout.operator("mesh.mod_weighted_strength", text="Strong")
op.set = True
op.face_strength = 'STRONG'
props = layout.operator("mesh.mod_weighted_strength", text="Strong")
props.set = True
props.face_strength = 'STRONG'
class VIEW3D_MT_edit_mesh_normals_average(Menu):
@ -4865,8 +4865,8 @@ class VIEW3D_MT_edit_font_kerning(Menu):
text = ob.data
kerning = text.edit_format.kerning
layout.operator("font.change_spacing", text="Decrease Kerning").delta = -1
layout.operator("font.change_spacing", text="Increase Kerning").delta = 1
layout.operator("font.change_spacing", text="Decrease Kerning").delta = -1.0
layout.operator("font.change_spacing", text="Increase Kerning").delta = 1.0
layout.operator("font.change_spacing", text="Reset Kerning").delta = -kerning
@ -5275,9 +5275,9 @@ class VIEW3D_MT_edit_gpencil_stroke(Menu):
layout.separator()
# Convert
op = layout.operator("gpencil.stroke_cyclical_set", text="Close")
op.type = 'CLOSE'
op.geometry = True
props = layout.operator("gpencil.stroke_cyclical_set", text="Close")
props.type = 'CLOSE'
props.geometry = True
layout.operator("gpencil.stroke_cyclical_set", text="Toggle Cyclic").type = 'TOGGLE'
layout.operator_menu_enum("gpencil.stroke_caps_set", text="Toggle Caps", property="type")
layout.operator("gpencil.stroke_flip", text="Switch Direction")
@ -5568,25 +5568,25 @@ class VIEW3D_MT_sculpt_mask_edit_pie(Menu):
layout = self.layout
pie = layout.menu_pie()
op = pie.operator("paint.mask_flood_fill", text="Invert Mask")
op.mode = 'INVERT'
op = pie.operator("paint.mask_flood_fill", text="Clear Mask")
op.mode = 'VALUE'
op.value = 0.0
op = pie.operator("sculpt.mask_filter", text="Smooth Mask")
op.filter_type = 'SMOOTH'
op = pie.operator("sculpt.mask_filter", text="Sharpen Mask")
op.filter_type = 'SHARPEN'
op = pie.operator("sculpt.mask_filter", text="Grow Mask")
op.filter_type = 'GROW'
op = pie.operator("sculpt.mask_filter", text="Shrink Mask")
op.filter_type = 'SHRINK'
op = pie.operator("sculpt.mask_filter", text="Increase Contrast")
op.filter_type = 'CONTRAST_INCREASE'
op.auto_iteration_count = False
op = pie.operator("sculpt.mask_filter", text="Decrease Contrast")
op.filter_type = 'CONTRAST_DECREASE'
op.auto_iteration_count = False
props = pie.operator("paint.mask_flood_fill", text="Invert Mask")
props.mode = 'INVERT'
props = pie.operator("paint.mask_flood_fill", text="Clear Mask")
props.mode = 'VALUE'
props.value = 0.0
props = pie.operator("sculpt.mask_filter", text="Smooth Mask")
props.filter_type = 'SMOOTH'
props = pie.operator("sculpt.mask_filter", text="Sharpen Mask")
props.filter_type = 'SHARPEN'
props = pie.operator("sculpt.mask_filter", text="Grow Mask")
props.filter_type = 'GROW'
props = pie.operator("sculpt.mask_filter", text="Shrink Mask")
props.filter_type = 'SHRINK'
props = pie.operator("sculpt.mask_filter", text="Increase Contrast")
props.filter_type = 'CONTRAST_INCREASE'
props.auto_iteration_count = False
props = pie.operator("sculpt.mask_filter", text="Decrease Contrast")
props.filter_type = 'CONTRAST_DECREASE'
props.auto_iteration_count = False
class VIEW3D_MT_sculpt_automasking_pie(Menu):
@ -5633,16 +5633,16 @@ class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
layout = self.layout
pie = layout.menu_pie()
op = pie.operator("sculpt.face_sets_create", text="Face Set from Masked")
op.mode = 'MASKED'
props = pie.operator("sculpt.face_sets_create", text="Face Set from Masked")
props.mode = 'MASKED'
op = pie.operator("sculpt.face_sets_create", text="Face Set from Visible")
op.mode = 'VISIBLE'
props = pie.operator("sculpt.face_sets_create", text="Face Set from Visible")
props.mode = 'VISIBLE'
op = pie.operator("sculpt.face_set_change_visibility", text="Invert Visible")
op.mode = 'INVERT'
props = pie.operator("sculpt.face_set_change_visibility", text="Invert Visible")
props.mode = 'INVERT'
op = pie.operator("sculpt.reveal_all", text="Show All")
props = pie.operator("sculpt.reveal_all", text="Show All")
class VIEW3D_MT_wpaint_vgroup_lock_pie(Menu):
@ -5653,29 +5653,29 @@ class VIEW3D_MT_wpaint_vgroup_lock_pie(Menu):
pie = layout.menu_pie()
# 1: Left
op = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All")
op.action, op.mask = 'LOCK', 'ALL'
props = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All")
props.action, props.mask = 'LOCK', 'ALL'
# 2: Right
op = pie.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock All")
op.action, op.mask = 'UNLOCK', 'ALL'
props = pie.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock All")
props.action, props.mask = 'UNLOCK', 'ALL'
# 3: Down
op = pie.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock Selected")
op.action, op.mask = 'UNLOCK', 'SELECTED'
props = pie.operator("object.vertex_group_lock", icon='UNLOCKED', text="Unlock Selected")
props.action, props.mask = 'UNLOCK', 'SELECTED'
# 4: Up
op = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Selected")
op.action, op.mask = 'LOCK', 'SELECTED'
props = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Selected")
props.action, props.mask = 'LOCK', 'SELECTED'
# 5: Up/Left
op = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Unselected")
op.action, op.mask = 'LOCK', 'UNSELECTED'
props = pie.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Unselected")
props.action, props.mask = 'LOCK', 'UNSELECTED'
# 6: Up/Right
op = pie.operator("object.vertex_group_lock", text="Lock Only Selected")
op.action, op.mask = 'LOCK', 'INVERT_UNSELECTED'
props = pie.operator("object.vertex_group_lock", text="Lock Only Selected")
props.action, props.mask = 'LOCK', 'INVERT_UNSELECTED'
# 7: Down/Left
op = pie.operator("object.vertex_group_lock", text="Lock Only Unselected")
op.action, op.mask = 'UNLOCK', 'INVERT_UNSELECTED'
props = pie.operator("object.vertex_group_lock", text="Lock Only Unselected")
props.action, props.mask = 'UNLOCK', 'INVERT_UNSELECTED'
# 8: Down/Right
op = pie.operator("object.vertex_group_lock", text="Invert Locks")
op.action, op.mask = 'INVERT', 'ALL'
props = pie.operator("object.vertex_group_lock", text="Invert Locks")
props.action, props.mask = 'INVERT', 'ALL'
# ********** Panel **********
@ -6812,7 +6812,6 @@ class VIEW3D_PT_overlay_sculpt(Panel):
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
view = context.space_data
overlay = view.overlay
@ -6843,8 +6842,6 @@ class VIEW3D_PT_overlay_sculpt_curves(Panel):
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
sculpt = tool_settings.sculpt
view = context.space_data
overlay = view.overlay
@ -6978,6 +6975,7 @@ class VIEW3D_PT_overlay_weight_paint(Panel):
view = context.space_data
overlay = view.overlay
display_all = overlay.show_overlays
tool_settings = context.tool_settings
col = layout.column()
col.active = display_all
@ -6986,7 +6984,7 @@ class VIEW3D_PT_overlay_weight_paint(Panel):
row = col.split(factor=0.33)
row.label(text="Zero Weights")
sub = row.row()
sub.prop(context.tool_settings, "vertex_group_user", expand=True)
sub.prop(tool_settings, "vertex_group_user", expand=True)
col.prop(overlay, "show_wpaint_contours")
col.prop(overlay, "show_paint_wire")
@ -7157,11 +7155,13 @@ class VIEW3D_PT_gpencil_lock(Panel):
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
layout.label(text="Drawing Plane")
row = layout.row()
col = row.column()
col.prop(context.tool_settings.gpencil_sculpt, "lock_axis", expand=True)
col.prop(tool_settings.gpencil_sculpt, "lock_axis", expand=True)
class VIEW3D_PT_gpencil_guide(Panel):
@ -7427,10 +7427,12 @@ class VIEW3D_PT_gpencil_multi_frame(Panel):
bl_label = "Multi Frame"
def draw(self, context):
gpd = context.gpencil_data
settings = context.tool_settings.gpencil_sculpt
layout = self.layout
tool_settings = context.tool_settings
gpd = context.gpencil_data
settings = tool_settings.gpencil_sculpt
col = layout.column(align=True)
col.prop(settings, "use_multiframe_falloff")
@ -7460,12 +7462,12 @@ class VIEW3D_MT_gpencil_edit_context_menu(Menu):
bl_label = ""
def draw(self, context):
is_point_mode = context.tool_settings.gpencil_selectmode_edit == 'POINT'
is_stroke_mode = context.tool_settings.gpencil_selectmode_edit == 'STROKE'
is_segment_mode = context.tool_settings.gpencil_selectmode_edit == 'SEGMENT'
layout = self.layout
tool_settings = context.tool_settings
is_point_mode = tool_settings.gpencil_selectmode_edit == 'POINT'
is_stroke_mode = tool_settings.gpencil_selectmode_edit == 'STROKE'
is_segment_mode = tool_settings.gpencil_selectmode_edit == 'SEGMENT'
layout.operator_context = 'INVOKE_REGION_WIN'
@ -7607,8 +7609,8 @@ class VIEW3D_PT_gpencil_sculpt_automasking(Panel):
def draw(self, context):
layout = self.layout
tool_settings = context.scene.tool_settings
layout.label(text="Auto-masking")
col = layout.column(align=True)
@ -7627,11 +7629,11 @@ class VIEW3D_PT_gpencil_sculpt_context_menu(Panel):
bl_ui_units_x = 12
def draw(self, context):
ts = context.tool_settings
settings = ts.gpencil_sculpt_paint
brush = settings.brush
layout = self.layout
tool_settings = context.tool_settings
settings = tool_settings.gpencil_sculpt_paint
brush = settings.brush
layout.prop(brush, "size", slider=True)
layout.prop(brush, "strength")
@ -7647,8 +7649,8 @@ class VIEW3D_PT_gpencil_weight_context_menu(Panel):
bl_ui_units_x = 12
def draw(self, context):
ts = context.tool_settings
settings = ts.gpencil_weight_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_weight_paint
brush = settings.brush
layout = self.layout
@ -7668,12 +7670,12 @@ class VIEW3D_PT_gpencil_draw_context_menu(Panel):
bl_ui_units_x = 12
def draw(self, context):
ts = context.tool_settings
settings = ts.gpencil_paint
layout = self.layout
tool_settings = context.tool_settings
settings = tool_settings.gpencil_paint
brush = settings.brush
gp_settings = brush.gpencil_settings
layout = self.layout
is_pin_vertex = gp_settings.brush_draw_mode == 'VERTEXCOLOR'
is_vertex = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT' or is_pin_vertex
@ -7707,8 +7709,8 @@ class VIEW3D_PT_gpencil_vertex_context_menu(Panel):
def draw(self, context):
layout = self.layout
ts = context.tool_settings
settings = ts.gpencil_vertex_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_vertex_paint
brush = settings.brush
gp_settings = brush.gpencil_settings

View File

@ -61,17 +61,17 @@ class VIEW3D_MT_brush_gpencil_context_menu(Menu):
def draw(self, context):
layout = self.layout
ts = context.tool_settings
tool_settings = context.tool_settings
settings = None
if context.mode == 'PAINT_GPENCIL':
settings = ts.gpencil_paint
settings = tool_settings.gpencil_paint
if context.mode == 'SCULPT_GPENCIL':
settings = ts.gpencil_sculpt_paint
settings = tool_settings.gpencil_sculpt_paint
elif context.mode == 'WEIGHT_GPENCIL':
settings = ts.gpencil_weight_paint
settings = tool_settings.gpencil_weight_paint
elif context.mode == 'VERTEX_GPENCIL':
settings = ts.gpencil_vertex_paint
settings = tool_settings.gpencil_vertex_paint
brush = getattr(settings, "brush", None)
# skip if no active brush
@ -203,8 +203,9 @@ class VIEW3D_PT_tools_meshedit_options_automerge(View3DPanel, Panel):
def draw_header(self, context):
tool_settings = context.tool_settings
self.layout.prop(tool_settings, "use_mesh_automerge", text="", toggle=False)
self.layout.use_property_split = False
self.layout.prop(tool_settings, "use_mesh_automerge",
text=self.bl_label if self.is_popover else "", toggle=False)
def draw(self, context):
layout = self.layout
@ -612,7 +613,8 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
def draw_header(self, context):
ipaint = context.tool_settings.image_paint
self.layout.prop(ipaint, "use_stencil_layer", text="")
self.layout.prop(ipaint, "use_stencil_layer",
text=self.bl_label if self.is_popover else "")
def draw(self, context):
layout = self.layout
@ -794,7 +796,8 @@ class VIEW3D_PT_tools_brush_falloff_frontface(View3DPaintPanel, Panel):
settings = self.paint_settings(context)
brush = settings.brush
self.layout.prop(brush, "use_frontface_falloff", text="")
self.layout.prop(brush, "use_frontface_falloff",
text=self.bl_label if self.is_popover else "")
def draw(self, context):
settings = self.paint_settings(context)
@ -823,7 +826,8 @@ class VIEW3D_PT_tools_brush_falloff_normal(View3DPaintPanel, Panel):
tool_settings = context.tool_settings
ipaint = tool_settings.image_paint
self.layout.prop(ipaint, "use_normal_falloff", text="")
self.layout.prop(ipaint, "use_normal_falloff",
text=self.bl_label if self.is_popover else "")
def draw(self, context):
tool_settings = context.tool_settings
@ -1273,7 +1277,8 @@ class VIEW3D_PT_tools_imagepaint_options_cavity(View3DPaintPanel, Panel):
tool_settings = context.tool_settings
ipaint = tool_settings.image_paint
self.layout.prop(ipaint, "use_cavity", text="")
self.layout.prop(ipaint, "use_cavity",
text=self.bl_label if self.is_popover else "")
def draw(self, context):
layout = self.layout
@ -1615,8 +1620,9 @@ class VIEW3D_PT_tools_grease_pencil_brush_stroke(Panel, View3DPanel):
return brush is not None and brush.gpencil_tool == 'DRAW'
def draw(self, _context):
# layout = self.layout
pass
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(Panel, View3DPanel):
@ -1632,12 +1638,11 @@ class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(Panel, View3DPanel):
return brush is not None and brush.gpencil_tool == 'DRAW'
def draw_header(self, context):
if self.is_popover:
return
brush = context.tool_settings.gpencil_paint.brush
gp_settings = brush.gpencil_settings
self.layout.prop(gp_settings, "use_settings_stabilizer", text="")
self.layout.use_property_split = False
self.layout.prop(gp_settings, "use_settings_stabilizer",
text=self.bl_label if self.is_popover else "")
def draw(self, context):
layout = self.layout
@ -1647,11 +1652,6 @@ class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(Panel, View3DPanel):
brush = context.tool_settings.gpencil_paint.brush
gp_settings = brush.gpencil_settings
if self.is_popover:
row = layout.row()
row.prop(gp_settings, "use_settings_stabilizer", text="")
row.label(text=self.bl_label)
col = layout.column()
col.active = gp_settings.use_settings_stabilizer
@ -1672,12 +1672,11 @@ class VIEW3D_PT_tools_grease_pencil_brush_post_processing(View3DPanel, Panel):
return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL', 'TINT'}
def draw_header(self, context):
if self.is_popover:
return
brush = context.tool_settings.gpencil_paint.brush
gp_settings = brush.gpencil_settings
self.layout.prop(gp_settings, "use_settings_postprocess", text="")
self.layout.use_property_split = False
self.layout.prop(gp_settings, "use_settings_postprocess",
text=self.bl_label if self.is_popover else "")
def draw(self, context):
layout = self.layout
@ -1687,11 +1686,6 @@ class VIEW3D_PT_tools_grease_pencil_brush_post_processing(View3DPanel, Panel):
brush = context.tool_settings.gpencil_paint.brush
gp_settings = brush.gpencil_settings
if self.is_popover:
row = layout.row()
row.prop(gp_settings, "use_settings_postprocess", text="")
row.label(text=self.bl_label)
col = layout.column()
col.active = gp_settings.use_settings_postprocess
@ -1734,12 +1728,11 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL', 'TINT'}
def draw_header(self, context):
if self.is_popover:
return
brush = context.tool_settings.gpencil_paint.brush
gp_settings = brush.gpencil_settings
self.layout.prop(gp_settings, "use_settings_random", text="")
self.layout.use_property_split = False
self.layout.prop(gp_settings, "use_settings_random",
text=self.bl_label if self.is_popover else "")
def draw(self, context):
layout = self.layout
@ -1751,11 +1744,6 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
mode = tool_settings.gpencil_paint.color_mode
gp_settings = brush.gpencil_settings
if self.is_popover:
row = layout.row()
row.prop(gp_settings, "use_settings_random", text="")
row.label(text=self.bl_label)
col = layout.column()
col.enabled = gp_settings.use_settings_random
@ -1828,8 +1816,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_paint_falloff(GreasePencilBrushFalloff
@classmethod
def poll(cls, context):
ts = context.tool_settings
settings = ts.gpencil_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_paint
brush = settings.brush
if brush is None:
return False
@ -1946,8 +1934,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_sculpt_falloff(GreasePencilBrushFallof
@classmethod
def poll(cls, context):
ts = context.tool_settings
settings = ts.gpencil_sculpt_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_sculpt_paint
return (settings and settings.brush and settings.brush.curve)
@ -2055,8 +2043,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_weight_falloff(GreasePencilBrushFallof
@classmethod
def poll(cls, context):
ts = context.tool_settings
settings = ts.gpencil_weight_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_weight_paint
brush = settings.brush
return (brush and brush.curve)
@ -2131,8 +2119,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_vertex_color(View3DPanel, Panel):
@classmethod
def poll(cls, context):
ob = context.object
ts = context.tool_settings
settings = ts.gpencil_vertex_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_vertex_paint
brush = settings.brush
if ob is None or brush is None:
@ -2147,8 +2135,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_vertex_color(View3DPanel, Panel):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
ts = context.tool_settings
settings = ts.gpencil_vertex_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_vertex_paint
brush = settings.brush
col = layout.column()
@ -2169,8 +2157,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff(GreasePencilBrushFallof
@classmethod
def poll(cls, context):
ts = context.tool_settings
settings = ts.gpencil_vertex_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_vertex_paint
return (settings and settings.brush and settings.brush.curve)
@ -2183,8 +2171,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_vertex_palette(View3DPanel, Panel):
@classmethod
def poll(cls, context):
ob = context.object
ts = context.tool_settings
settings = ts.gpencil_vertex_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_vertex_paint
brush = settings.brush
if ob is None or brush is None:
@ -2199,8 +2187,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_vertex_palette(View3DPanel, Panel):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
ts = context.tool_settings
settings = ts.gpencil_vertex_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_vertex_paint
col = layout.column()
@ -2218,8 +2206,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_mixcolor(View3DPanel, Panel):
@classmethod
def poll(cls, context):
ob = context.object
ts = context.tool_settings
settings = ts.gpencil_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_paint
brush = settings.brush
if ob is None or brush is None:
@ -2243,8 +2231,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_mixcolor(View3DPanel, Panel):
def draw(self, context):
layout = self.layout
ts = context.tool_settings
settings = ts.gpencil_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_paint
brush = settings.brush
gp_settings = brush.gpencil_settings
@ -2282,8 +2270,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_mix_palette(View3DPanel, Panel):
@classmethod
def poll(cls, context):
ob = context.object
ts = context.tool_settings
settings = ts.gpencil_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_paint
brush = settings.brush
if ob is None or brush is None:
@ -2306,8 +2294,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_mix_palette(View3DPanel, Panel):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
ts = context.tool_settings
settings = ts.gpencil_paint
tool_settings = context.tool_settings
settings = tool_settings.gpencil_paint
brush = settings.brush
col = layout.column()

View File

@ -29,8 +29,8 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_fluid_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_freestyle_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_genfile.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_modifier_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_legacy_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_modifier_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpu_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_image_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_ipo_types.h

View File

@ -802,7 +802,6 @@ class CustomDataAttributes {
std::optional<blender::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id);
bool create(const AttributeIDRef &attribute_id, eCustomDataType data_type);
bool create_by_move(const AttributeIDRef &attribute_id, eCustomDataType data_type, void *buffer);
bool remove(const AttributeIDRef &attribute_id);
bool foreach_attribute(const AttributeForeachCallback callback, eAttrDomain domain) const;

View File

@ -11,6 +11,8 @@
#include "DNA_color_types.h"
#include "DNA_object_enums.h"
#include "BKE_paint.h" /* for ePaintMode */
#ifdef __cplusplus
extern "C" {
#endif
@ -185,6 +187,11 @@ void BKE_brush_scale_size(int *r_brush_size,
float new_unprojected_radius,
float old_unprojected_radius);
/* Returns true if a brush requires a cube
* (often presented to the user as a square) tip inside a specific paint mode.
*/
bool BKE_brush_has_cube_tip(const struct Brush *brush, ePaintMode paint_mode);
/* Accessors */
#define BKE_brush_tool_get(brush, p) \
(CHECK_TYPE_ANY(brush, struct Brush *, const struct Brush *), \

View File

@ -8,6 +8,7 @@
#pragma once
#include "BLI_implicit_sharing.h"
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
#ifdef __cplusplus
@ -74,14 +75,8 @@ extern const CustomData_MeshMasks CD_MASK_EVERYTHING;
/** Add/copy/merge allocation types. */
typedef enum eCDAllocType {
/** Use the data pointer. */
CD_ASSIGN = 0,
/** Allocate and set to default, which is usually just zeroed memory. */
CD_SET_DEFAULT = 2,
/** Use data pointers, set layer flag NOFREE. */
CD_REFERENCE = 3,
/** Do a full copy of all layers, only allowed if source has same number of elements. */
CD_DUPLICATE = 4,
/**
* Default construct new layer values. Does nothing for trivial types. This should be used
* if all layer values will be set by the caller after creating the layer.
@ -158,28 +153,43 @@ void CustomData_data_multiply(eCustomDataType type, void *data, float fac);
void CustomData_data_add(eCustomDataType type, void *data1, const void *data2);
/**
* Initializes a CustomData object with the same layer setup as source.
* mask is a bit-field where `(mask & (1 << (layer type)))` indicates
* if a layer should be copied or not. alloctype must be one of the above.
* Initializes a CustomData object with the same layer setup as source. `mask` is a bit-field where
* `(mask & (1 << (layer type)))` indicates if a layer should be copied or not. Data layers using
* implicit-sharing will not actually be copied but will be shared between source and destination.
*/
void CustomData_copy(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem);
/**
* Initializes a CustomData object with the same layers as source. The data is not copied from the
* source. Instead, the new layers are initialized using the given `alloctype`.
*/
void CustomData_copy_layout(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem);
/* BMESH_TODO, not really a public function but readfile.c needs it */
void CustomData_update_typemap(struct CustomData *data);
/**
* Same as the above, except that this will preserve existing layers, and only
* add the layers that were not there yet.
* Copies all layers from source to destination that don't exist there yet.
*/
bool CustomData_merge(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem);
/**
* Copies all layers from source to destination that don't exist there yet. The layer data is not
* copied. Instead the newly created layers are initialized using the given `alloctype`.
*/
bool CustomData_merge_layout(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem);
/**
* Reallocate custom data to a new element count. If the new size is larger, the new values use
@ -189,16 +199,16 @@ bool CustomData_merge(const struct CustomData *source,
void CustomData_realloc(struct CustomData *data, int old_size, int new_size);
/**
* BMesh version of CustomData_merge; merges the layouts of source and `dest`,
* BMesh version of CustomData_merge_layout; merges the layouts of source and `dest`,
* then goes through the mesh and makes sure all the custom-data blocks are
* consistent with the new layout.
*/
bool CustomData_bmesh_merge(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
struct BMesh *bm,
char htype);
bool CustomData_bmesh_merge_layout(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
struct BMesh *bm,
char htype);
/**
* Remove layers that aren't stored in BMesh or are stored as flags on BMesh.
@ -229,18 +239,25 @@ void CustomData_free_typemask(struct CustomData *data, int totelem, eCustomDataM
void CustomData_free_temporary(struct CustomData *data, int totelem);
/**
* Adds a data layer of the given type to the #CustomData object, optionally
* backed by an external data array. the different allocation types are
* defined above. returns the data of the layer.
* Adds a layer of the given type to the #CustomData object. The new layer is initialized based on
* the given alloctype.
* \return The layer data.
*/
void *CustomData_add_layer(struct CustomData *data,
eCustomDataType type,
eCDAllocType alloctype,
int totelem);
/**
* Adds a layer of the given type to the #CustomData object. The new layer takes ownership of the
* passed in `layer_data`. If a #ImplicitSharingInfoHandle is passed in, its user count is
* increased.
*/
const void *CustomData_add_layer_with_data(struct CustomData *data,
eCustomDataType type,
void *layer_data,
int totelem);
int totelem,
const ImplicitSharingInfoHandle *sharing_info);
/**
* Same as above but accepts a name.
@ -250,17 +267,26 @@ void *CustomData_add_layer_named(struct CustomData *data,
eCDAllocType alloctype,
int totelem,
const char *name);
const void *CustomData_add_layer_named_with_data(struct CustomData *data,
eCustomDataType type,
void *layer_data,
int totelem,
const char *name);
const char *name,
const ImplicitSharingInfoHandle *sharing_info);
void *CustomData_add_layer_anonymous(struct CustomData *data,
eCustomDataType type,
eCDAllocType alloctype,
void *layer,
int totelem,
const AnonymousAttributeIDHandle *anonymous_id);
const void *CustomData_add_layer_anonymous_with_data(
struct CustomData *data,
eCustomDataType type,
const AnonymousAttributeIDHandle *anonymous_id,
int totelem,
void *layer_data,
const ImplicitSharingInfoHandle *sharing_info);
/**
* Frees the active or first data layer with the give type.
@ -296,11 +322,6 @@ int CustomData_number_of_layers(const struct CustomData *data, eCustomDataType t
int CustomData_number_of_anonymous_layers(const struct CustomData *data, eCustomDataType type);
int CustomData_number_of_layers_typemask(const struct CustomData *data, eCustomDataMask mask);
/**
* Duplicate all the layers with flag NOFREE, and remove the flag from duplicated layers.
*/
void CustomData_duplicate_referenced_layers(CustomData *data, int totelem);
/**
* Set the #CD_FLAG_NOCOPY flag in custom data layers where the mask is
* zero for the layer type, so only layer types specified by the mask will be copied

View File

@ -122,7 +122,18 @@ void BKE_mesh_looptri_get_real_edges(const struct MEdge *edges,
* Only use for undo, in most cases `BKE_id_free(nullptr, me)` should be used.
*/
void BKE_mesh_free_data_for_undo(struct Mesh *me);
/**
* Remove all geometry and derived data like caches from the mesh.
*/
void BKE_mesh_clear_geometry(struct Mesh *me);
/**
* Same as #BKE_mesh_clear_geometry, but also clears attribute meta-data like active attribute
* names and vertex group names. Used when the geometry is *entirely* replaced.
*/
void BKE_mesh_clear_geometry_and_metadata(struct Mesh *me);
struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
void BKE_mesh_free_editmesh(struct Mesh *mesh);

View File

@ -48,6 +48,7 @@ struct PaintCurve;
struct PaintModeSettings;
struct Palette;
struct PaletteColor;
struct RegionView3D;
struct Scene;
struct StrokeCache;
struct Sculpt;
@ -238,7 +239,8 @@ void BKE_paint_face_set_overlay_color_get(int face_set, int seed, uchar r_color[
bool paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups,
struct Brush *brush,
const float mouse_pos[2]);
const float mouse_pos[2],
ePaintMode paint_mode);
void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups,
struct Brush *brush,
float rotation);

View File

@ -13,6 +13,10 @@
# include "BLI_bounds_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_shared_cache.hh"
# include "DNA_pointcloud_types.h"
# include "BKE_customdata.h"
#endif
#ifdef __cplusplus
@ -45,6 +49,21 @@ struct PointCloudRuntime {
};
} // namespace blender::bke
inline blender::Span<blender::float3> PointCloud::positions() const
{
return {static_cast<const blender::float3 *>(
CustomData_get_layer_named(&this->pdata, CD_PROP_FLOAT3, "position")),
this->totpoint};
}
inline blender::MutableSpan<blender::float3> PointCloud::positions_for_write()
{
return {static_cast<blender::float3 *>(CustomData_get_layer_named_for_write(
&this->pdata, CD_PROP_FLOAT3, "position", this->totpoint)),
this->totpoint};
}
#endif
void *BKE_pointcloud_add(struct Main *bmain, const char *name);

View File

@ -144,9 +144,9 @@ set(SRC
intern/geometry_fields.cc
intern/geometry_set.cc
intern/geometry_set_instances.cc
intern/gpencil_legacy.c
intern/gpencil_curve_legacy.c
intern/gpencil_geom_legacy.cc
intern/gpencil_legacy.c
intern/gpencil_modifier_legacy.c
intern/gpencil_update_cache_legacy.c
intern/icons.cc
@ -384,9 +384,9 @@ set(SRC
BKE_geometry_set.hh
BKE_geometry_set_instances.hh
BKE_global.h
BKE_gpencil_legacy.h
BKE_gpencil_curve_legacy.h
BKE_gpencil_geom_legacy.h
BKE_gpencil_legacy.h
BKE_gpencil_modifier_legacy.h
BKE_gpencil_update_cache_legacy.h
BKE_icons.h

View File

@ -207,11 +207,12 @@ void DM_from_template(DerivedMesh *dm,
int numPolys)
{
const CustomData_MeshMasks *mask = &CD_MASK_DERIVEDMESH;
CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_SET_DEFAULT, numVerts);
CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_SET_DEFAULT, numEdges);
CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_SET_DEFAULT, numTessFaces);
CustomData_copy(&source->loopData, &dm->loopData, mask->lmask, CD_SET_DEFAULT, numLoops);
CustomData_copy(&source->polyData, &dm->polyData, mask->pmask, CD_SET_DEFAULT, numPolys);
CustomData_copy_layout(&source->vertData, &dm->vertData, mask->vmask, CD_SET_DEFAULT, numVerts);
CustomData_copy_layout(&source->edgeData, &dm->edgeData, mask->emask, CD_SET_DEFAULT, numEdges);
CustomData_copy_layout(
&source->faceData, &dm->faceData, mask->fmask, CD_SET_DEFAULT, numTessFaces);
CustomData_copy_layout(&source->loopData, &dm->loopData, mask->lmask, CD_SET_DEFAULT, numLoops);
CustomData_copy_layout(&source->polyData, &dm->polyData, mask->pmask, CD_SET_DEFAULT, numPolys);
dm->poly_offsets = static_cast<int *>(MEM_dupallocN(source->poly_offsets));
dm->type = type;
@ -699,7 +700,12 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
* places that wish to use the original mesh but with deformed
* coordinates (like vertex paint). */
if (r_deform) {
mesh_deform = BKE_mesh_copy_for_eval(mesh_final, false);
if (mesh_final) {
mesh_deform = BKE_mesh_copy_for_eval(mesh_final, false);
}
else {
mesh_deform = BKE_mesh_copy_for_eval(mesh_input, false);
}
}
}

View File

@ -201,13 +201,16 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
return true;
}
case AttributeInit::Type::MoveArray: {
void *source_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
const void *data = CustomData_add_layer_with_data(
&custom_data, data_type, source_data, domain_num);
if (data == nullptr) {
MEM_freeN(source_data);
void *src_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
const void *stored_data = CustomData_add_layer_with_data(
&custom_data, data_type, src_data, domain_num, nullptr);
if (stored_data == nullptr) {
return false;
}
if (stored_data != src_data) {
MEM_freeN(src_data);
return true;
}
return true;
}
}
@ -230,25 +233,26 @@ static void *add_generic_custom_data_layer(CustomData &custom_data,
}
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous(
&custom_data, data_type, alloctype, nullptr, domain_size, &anonymous_id);
&custom_data, data_type, alloctype, domain_size, &anonymous_id);
}
static const void *add_generic_custom_data_layer_with_existing_data(
CustomData &custom_data,
const eCustomDataType data_type,
void *layer_data,
const AttributeIDRef &attribute_id,
const int domain_size,
const AttributeIDRef &attribute_id)
void *layer_data,
const ImplicitSharingInfo *sharing_info)
{
if (!attribute_id.is_anonymous()) {
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named_with_data(
&custom_data, data_type, layer_data, domain_size, attribute_name_c);
if (attribute_id.is_anonymous()) {
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous_with_data(
&custom_data, data_type, &anonymous_id, domain_size, layer_data, sharing_info);
}
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous(
&custom_data, data_type, CD_ASSIGN, layer_data, domain_size, &anonymous_id);
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named_with_data(
&custom_data, data_type, layer_data, domain_size, attribute_name_c, sharing_info);
}
static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attribute_id,
@ -279,9 +283,9 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
break;
}
case AttributeInit::Type::MoveArray: {
void *source_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
void *data = static_cast<const AttributeInitMoveArray &>(initializer).data;
add_generic_custom_data_layer_with_existing_data(
custom_data, data_type, source_data, domain_num, attribute_id);
custom_data, data_type, attribute_id, domain_num, data, nullptr);
break;
}
}
@ -571,7 +575,7 @@ CustomDataAttributes::~CustomDataAttributes()
CustomDataAttributes::CustomDataAttributes(const CustomDataAttributes &other)
{
size_ = other.size_;
CustomData_copy(&other.data, &data, CD_MASK_ALL, CD_DUPLICATE, size_);
CustomData_copy(&other.data, &data, CD_MASK_ALL, size_);
}
CustomDataAttributes::CustomDataAttributes(CustomDataAttributes &&other)
@ -655,15 +659,6 @@ bool CustomDataAttributes::create(const AttributeIDRef &attribute_id,
return result != nullptr;
}
bool CustomDataAttributes::create_by_move(const AttributeIDRef &attribute_id,
const eCustomDataType data_type,
void *buffer)
{
const void *result = add_generic_custom_data_layer_with_existing_data(
data, data_type, buffer, size_, attribute_id);
return result != nullptr;
}
bool CustomDataAttributes::remove(const AttributeIDRef &attribute_id)
{
for (const int i : IndexRange(data.totlayer)) {

View File

@ -2576,3 +2576,26 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool
return im;
}
bool BKE_brush_has_cube_tip(const Brush *brush, ePaintMode paint_mode)
{
switch (paint_mode) {
case PAINT_MODE_SCULPT: {
if (brush->sculpt_tool == SCULPT_TOOL_MULTIPLANE_SCRAPE) {
return true;
}
if (ELEM(brush->sculpt_tool, SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_PAINT) &&
brush->tip_roundness < 1.0f) {
return true;
}
break;
}
default: {
break;
}
}
return false;
}

View File

@ -26,6 +26,7 @@
#include "BKE_editmesh.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h"
#include "BKE_pointcloud.h"
#include "MEM_guardedalloc.h"
@ -1425,10 +1426,7 @@ BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data,
return nullptr;
}
blender::bke::AttributeAccessor attributes = pointcloud->attributes();
blender::VArraySpan<blender::float3> positions = attributes.lookup_or_default<blender::float3>(
"position", ATTR_DOMAIN_POINT, blender::float3(0));
const Span<float3> positions = pointcloud->positions();
for (const int i : positions.index_range()) {
BLI_bvhtree_insert(tree, i, positions[i], 1);
}

View File

@ -147,9 +147,7 @@ static CDDerivedMesh *cdDM_create(const char *desc)
return cddm;
}
static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
eCDAllocType alloctype,
const CustomData_MeshMasks *mask)
static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh, const CustomData_MeshMasks *mask)
{
CDDerivedMesh *cddm = cdDM_create(__func__);
DerivedMesh *dm = &cddm->dm;
@ -167,15 +165,14 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
mesh->totloop,
mesh->totpoly);
CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, alloctype, mesh->totvert);
CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, alloctype, mesh->totedge);
CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, mesh->totvert);
CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, mesh->totedge);
CustomData_merge(&mesh->fdata,
&dm->faceData,
cddata_masks.fmask | CD_MASK_ORIGINDEX,
alloctype,
0 /* `mesh->totface` */);
CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, alloctype, mesh->totloop);
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, alloctype, mesh->totpoly);
CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, mesh->totloop);
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, mesh->totpoly);
cddm->vert_positions = static_cast<float(*)[3]>(CustomData_get_layer_named_for_write(
&dm->vertData, CD_PROP_FLOAT3, "position", mesh->totvert));
@ -203,5 +200,5 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
DerivedMesh *CDDM_from_mesh(Mesh *mesh)
{
return cdDM_from_mesh_ex(mesh, CD_REFERENCE, &CD_MASK_MESH);
return cdDM_from_mesh_ex(mesh, &CD_MASK_MESH);
}

View File

@ -80,6 +80,9 @@ static KnotsMode knots_mode_from_legacy(const short flag)
Curves *curve_legacy_to_curves(const Curve &curve_legacy, const ListBase &nurbs_list)
{
const Vector<const Nurb *> src_curves(nurbs_list);
if (src_curves.is_empty()) {
return nullptr;
}
Curves *curves_id = curves_new_nomain(0, src_curves.size());
CurvesGeometry &curves = curves_id->geometry.wrap();
@ -104,10 +107,6 @@ Curves *curve_legacy_to_curves(const Curve &curve_legacy, const ListBase &nurbs_
curves.update_curve_types();
if (curves.curves_num() == 0) {
return curves_id;
}
const OffsetIndices points_by_curve = curves.points_by_curve();
MutableSpan<float3> positions = curves.positions_for_write();
SpanAttributeWriter<float> radius_attribute =

View File

@ -62,45 +62,18 @@ static void curves_init_data(ID *id)
new (&curves->geometry) blender::bke::CurvesGeometry();
}
static void curves_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void curves_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
{
using namespace blender;
Curves *curves_dst = (Curves *)id_dst;
const Curves *curves_src = (const Curves *)id_src;
curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
const bke::CurvesGeometry &src = curves_src->geometry.wrap();
bke::CurvesGeometry &dst = curves_dst->geometry.wrap();
/* We need special handling here because the generic ID management code has already done a
* shallow copy from the source to the destination, and because the copy-on-write functionality
* isn't supported more generically yet. */
dst.point_num = src.point_num;
dst.curve_num = src.curve_num;
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, alloc_type, dst.point_num);
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, alloc_type, dst.curve_num);
dst.curve_offsets = static_cast<int *>(MEM_dupallocN(src.curve_offsets));
new (&curves_dst->geometry) blender::bke::CurvesGeometry(curves_src->geometry.wrap());
if (curves_src->surface_uv_map != nullptr) {
curves_dst->surface_uv_map = BLI_strdup(curves_src->surface_uv_map);
}
dst.runtime = MEM_new<bke::CurvesGeometryRuntime>(__func__);
dst.runtime->type_counts = src.runtime->type_counts;
dst.runtime->evaluated_offsets_cache = src.runtime->evaluated_offsets_cache;
dst.runtime->nurbs_basis_cache = src.runtime->nurbs_basis_cache;
dst.runtime->evaluated_position_cache = src.runtime->evaluated_position_cache;
dst.runtime->bounds_cache = src.runtime->bounds_cache;
dst.runtime->evaluated_length_cache = src.runtime->evaluated_length_cache;
dst.runtime->evaluated_tangent_cache = src.runtime->evaluated_tangent_cache;
dst.runtime->evaluated_normal_cache = src.runtime->evaluated_normal_cache;
curves_dst->batch_cache = nullptr;
}
@ -156,11 +129,6 @@ static void curves_blend_read_data(BlendDataReader *reader, ID *id)
BLO_read_data_address(reader, &curves->surface_uv_map);
curves->geometry.runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
/* Recalculate curve type count cache that isn't saved in files. */
curves->geometry.wrap().update_curve_types();
/* Materials */
BLO_read_pointer_array(reader, (void **)&curves->mat);
}

View File

@ -80,8 +80,8 @@ static void copy_curves_geometry(CurvesGeometry &dst, const CurvesGeometry &src)
CustomData_free(&dst.curve_data, dst.curve_num);
dst.point_num = src.point_num;
dst.curve_num = src.curve_num;
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, CD_DUPLICATE, dst.point_num);
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, CD_DUPLICATE, dst.curve_num);
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, dst.point_num);
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, dst.curve_num);
MEM_SAFE_FREE(dst.curve_offsets);
dst.curve_offsets = (int *)MEM_malloc_arrayN(dst.point_num + 1, sizeof(int), __func__);
@ -100,8 +100,7 @@ static void copy_curves_geometry(CurvesGeometry &dst, const CurvesGeometry &src)
dst.runtime->evaluated_normal_cache = src.runtime->evaluated_normal_cache;
}
CurvesGeometry::CurvesGeometry(const CurvesGeometry &other)
: CurvesGeometry(other.point_num, other.curve_num)
CurvesGeometry::CurvesGeometry(const CurvesGeometry &other) : CurvesGeometry()
{
copy_curves_geometry(*this, other);
}
@ -133,8 +132,7 @@ static void move_curves_geometry(CurvesGeometry &dst, CurvesGeometry &src)
std::swap(dst.runtime, src.runtime);
}
CurvesGeometry::CurvesGeometry(CurvesGeometry &&other)
: CurvesGeometry(other.point_num, other.curve_num)
CurvesGeometry::CurvesGeometry(CurvesGeometry &&other) : CurvesGeometry()
{
move_curves_geometry(*this, other);
}
@ -1582,10 +1580,15 @@ GVArray CurvesGeometry::adapt_domain(const GVArray &varray,
void CurvesGeometry::blend_read(BlendDataReader &reader)
{
this->runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
CustomData_blend_read(&reader, &this->point_data, this->point_num);
CustomData_blend_read(&reader, &this->curve_data, this->curve_num);
BLO_read_int32_array(&reader, this->curve_num + 1, &this->curve_offsets);
/* Recalculate curve type count cache that isn't saved in files. */
this->update_curve_types();
}
void CurvesGeometry::blend_write(BlendWriter &writer, ID &id)

View File

@ -101,11 +101,8 @@ void fill_points(const OffsetIndices<int> points_by_curve,
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
{
bke::CurvesGeometry dst_curves(0, src_curves.curves_num());
CustomData_copy(&src_curves.curve_data,
&dst_curves.curve_data,
CD_MASK_ALL,
CD_DUPLICATE,
src_curves.curves_num());
CustomData_copy(
&src_curves.curve_data, &dst_curves.curve_data, CD_MASK_ALL, src_curves.curves_num());
dst_curves.runtime->type_counts = src_curves.runtime->type_counts;
return dst_curves;
}

View File

@ -59,6 +59,7 @@
#include "data_transfer_intern.h"
using blender::float2;
using blender::ImplicitSharingInfo;
using blender::IndexRange;
using blender::Set;
using blender::Span;
@ -2158,12 +2159,14 @@ void customData_mask_layers__print(const CustomData_MeshMasks *mask)
static void customData_update_offsets(CustomData *data);
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
eCustomDataType type,
eCDAllocType alloctype,
void *layerdata,
int totelem,
const char *name);
static CustomDataLayer *customData_add_layer__internal(
CustomData *data,
eCustomDataType type,
std::optional<eCDAllocType> alloctype,
void *layer_data_to_assign,
const ImplicitSharingInfo *sharing_info_to_assign,
int totelem,
const char *name);
void CustomData_update_typemap(CustomData *data)
{
@ -2192,93 +2195,113 @@ static bool customdata_typemap_is_valid(const CustomData *data)
}
#endif
bool CustomData_merge(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem)
static void *copy_layer_data(const eCustomDataType type, const void *data, const int totelem)
{
const LayerTypeInfo &type_info = *layerType_getInfo(type);
if (type_info.copy) {
void *new_data = MEM_malloc_arrayN(size_t(totelem), type_info.size, __func__);
type_info.copy(data, new_data, totelem);
return new_data;
}
return MEM_dupallocN(data);
}
static void free_layer_data(const eCustomDataType type, const void *data, const int totelem)
{
const LayerTypeInfo &type_info = *layerType_getInfo(type);
if (type_info.free) {
type_info.free(const_cast<void *>(data), totelem, type_info.size);
}
MEM_freeN(const_cast<void *>(data));
}
static bool customdata_merge_internal(const CustomData *source,
CustomData *dest,
const eCustomDataMask mask,
const std::optional<eCDAllocType> alloctype,
const int totelem)
{
// const LayerTypeInfo *typeInfo;
CustomDataLayer *layer, *newlayer;
int lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0;
int number = 0, maxnumber = -1;
bool changed = false;
int last_type = -1;
int last_active = 0;
int last_render = 0;
int last_clone = 0;
int last_mask = 0;
int current_type_layer_count = 0;
int max_current_type_layer_count = -1;
for (int i = 0; i < source->totlayer; i++) {
layer = &source->layers[i];
// typeInfo = layerType_getInfo(eCustomDataType(layer->type)); /* UNUSED */
const CustomDataLayer &src_layer = source->layers[i];
const eCustomDataType type = eCustomDataType(src_layer.type);
const int src_layer_flag = src_layer.flag;
const eCustomDataType type = eCustomDataType(layer->type);
int flag = layer->flag;
if (type != lasttype) {
number = 0;
maxnumber = CustomData_layertype_layers_max(type);
lastactive = layer->active;
lastrender = layer->active_rnd;
lastclone = layer->active_clone;
lastmask = layer->active_mask;
lasttype = type;
if (type != last_type) {
current_type_layer_count = 0;
max_current_type_layer_count = CustomData_layertype_layers_max(type);
last_active = src_layer.active;
last_render = src_layer.active_rnd;
last_clone = src_layer.active_clone;
last_mask = src_layer.active_mask;
last_type = type;
}
else {
number++;
current_type_layer_count++;
}
if (flag & CD_FLAG_NOCOPY) {
if (src_layer_flag & CD_FLAG_NOCOPY) {
/* Don't merge this layer because it's not supposed to leave the source data. */
continue;
}
if (!(mask & CD_TYPE_AS_MASK(type))) {
/* Don't merge this layer because it does not match the type mask. */
continue;
}
if ((maxnumber != -1) && (number >= maxnumber)) {
if ((max_current_type_layer_count != -1) &&
(current_type_layer_count >= max_current_type_layer_count)) {
/* Don't merge this layer because the maximum amount of layers of this type is reached. */
continue;
}
if (CustomData_get_named_layer_index(dest, type, layer->name) != -1) {
if (CustomData_get_named_layer_index(dest, type, src_layer.name) != -1) {
/* Don't merge this layer because it exists in the destination already. */
continue;
}
void *data;
switch (alloctype) {
case CD_ASSIGN:
case CD_REFERENCE:
case CD_DUPLICATE:
data = layer->data;
break;
default:
data = nullptr;
break;
}
if ((alloctype == CD_ASSIGN) && (flag & CD_FLAG_NOFREE)) {
newlayer = customData_add_layer__internal(
dest, type, CD_REFERENCE, data, totelem, layer->name);
}
else {
newlayer = customData_add_layer__internal(dest, type, alloctype, data, totelem, layer->name);
}
if (newlayer) {
newlayer->uid = layer->uid;
newlayer->active = lastactive;
newlayer->active_rnd = lastrender;
newlayer->active_clone = lastclone;
newlayer->active_mask = lastmask;
newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
changed = true;
if (layer->anonymous_id != nullptr) {
newlayer->anonymous_id = layer->anonymous_id;
if (alloctype == CD_ASSIGN) {
layer->anonymous_id = nullptr;
void *layer_data_to_assign = nullptr;
const ImplicitSharingInfo *sharing_info_to_assign = nullptr;
if (!alloctype.has_value()) {
if (src_layer.data != nullptr) {
if (src_layer.sharing_info == nullptr) {
/* Can't share the layer, duplicate it instead. */
layer_data_to_assign = copy_layer_data(type, src_layer.data, totelem);
}
else {
layer->anonymous_id->add_user();
/* Share the layer. */
layer_data_to_assign = src_layer.data;
sharing_info_to_assign = src_layer.sharing_info;
}
}
if (alloctype == CD_ASSIGN) {
layer->data = nullptr;
}
}
CustomDataLayer *new_layer = customData_add_layer__internal(dest,
type,
alloctype,
layer_data_to_assign,
sharing_info_to_assign,
totelem,
src_layer.name);
new_layer->uid = src_layer.uid;
new_layer->flag |= src_layer_flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
new_layer->active = last_active;
new_layer->active_rnd = last_render;
new_layer->active_clone = last_clone;
new_layer->active_mask = last_mask;
changed = true;
if (src_layer.anonymous_id != nullptr) {
new_layer->anonymous_id = src_layer.anonymous_id;
new_layer->anonymous_id->add_user();
}
}
@ -2286,6 +2309,23 @@ bool CustomData_merge(const CustomData *source,
return changed;
}
bool CustomData_merge(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
int totelem)
{
return customdata_merge_internal(source, dest, mask, std::nullopt, totelem);
}
bool CustomData_merge_layout(const CustomData *source,
CustomData *dest,
const eCustomDataMask mask,
const eCDAllocType alloctype,
const int totelem)
{
return customdata_merge_internal(source, dest, mask, alloctype, totelem);
}
CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src,
const eCustomDataMask mask)
{
@ -2311,28 +2351,91 @@ CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData
return dst;
}
/**
* An #ImplicitSharingInfo that knows how to free the entire referenced custom data layer
* (including potentially separately allocated chunks like for vertex groups).
*/
class CustomDataLayerImplicitSharing : public ImplicitSharingInfo {
private:
const void *data_;
const int totelem_;
const eCustomDataType type_;
public:
CustomDataLayerImplicitSharing(const void *data, const int totelem, const eCustomDataType type)
: ImplicitSharingInfo(1), data_(data), totelem_(totelem), type_(type)
{
}
private:
void delete_self_with_data() override
{
free_layer_data(type_, data_, totelem_);
MEM_delete(this);
}
};
/** Create a #ImplicitSharingInfo that takes ownership of the data. */
static ImplicitSharingInfo *make_implicit_sharing_info_for_layer(const eCustomDataType type,
const void *data,
const int totelem)
{
return MEM_new<CustomDataLayerImplicitSharing>(__func__, data, totelem, type);
}
/**
* If the layer data is currently shared (hence it is immutable), create a copy that can be edited.
*/
static void ensure_layer_data_is_mutable(CustomDataLayer &layer, const int totelem)
{
if (layer.data == nullptr) {
return;
}
if (layer.sharing_info == nullptr) {
/* Can not be shared without implicit-sharing data. */
return;
}
if (layer.sharing_info->is_shared()) {
const eCustomDataType type = eCustomDataType(layer.type);
const void *old_data = layer.data;
/* Copy the layer before removing the user because otherwise the data might be freed while
* we're still copying from it here. */
layer.data = copy_layer_data(type, old_data, totelem);
layer.sharing_info->remove_user_and_delete_if_last();
layer.sharing_info = make_implicit_sharing_info_for_layer(type, layer.data, totelem);
}
}
void CustomData_realloc(CustomData *data, const int old_size, const int new_size)
{
BLI_assert(new_size >= 0);
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
const int64_t old_size_in_bytes = int64_t(old_size) * typeInfo->size;
const int64_t new_size_in_bytes = int64_t(new_size) * typeInfo->size;
if (layer->flag & CD_FLAG_NOFREE) {
const void *old_data = layer->data;
layer->data = MEM_malloc_arrayN(new_size, typeInfo->size, __func__);
void *new_layer_data = MEM_mallocN(new_size_in_bytes, __func__);
/* Copy data to new array. */
if (old_size_in_bytes) {
if (typeInfo->copy) {
typeInfo->copy(old_data, layer->data, std::min(old_size, new_size));
typeInfo->copy(layer->data, new_layer_data, std::min(old_size, new_size));
}
else {
std::memcpy(layer->data, old_data, std::min(old_size_in_bytes, new_size_in_bytes));
BLI_assert(layer->data != nullptr);
memcpy(new_layer_data, layer->data, std::min(old_size_in_bytes, new_size_in_bytes));
}
layer->flag &= ~CD_FLAG_NOFREE;
}
else {
layer->data = MEM_reallocN(layer->data, new_size_in_bytes);
/* Remove ownership of old array */
if (layer->sharing_info) {
layer->sharing_info->remove_user_and_delete_if_last();
layer->sharing_info = nullptr;
}
/* Take ownership of new array. */
layer->data = new_layer_data;
if (layer->data) {
layer->sharing_info = make_implicit_sharing_info_for_layer(
eCustomDataType(layer->type), layer->data, new_size);
}
if (new_size > old_size) {
@ -2345,11 +2448,7 @@ void CustomData_realloc(CustomData *data, const int old_size, const int new_size
}
}
void CustomData_copy(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem)
void CustomData_copy(const CustomData *source, CustomData *dest, eCustomDataMask mask, int totelem)
{
CustomData_reset(dest);
@ -2357,28 +2456,40 @@ void CustomData_copy(const CustomData *source,
dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
}
CustomData_merge(source, dest, mask, alloctype, totelem);
CustomData_merge(source, dest, mask, totelem);
}
void CustomData_copy_layout(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem)
{
CustomData_reset(dest);
if (source->external) {
dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
}
CustomData_merge_layout(source, dest, mask, alloctype, totelem);
}
static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem)
{
const LayerTypeInfo *typeInfo;
if (layer->anonymous_id != nullptr) {
layer->anonymous_id->remove_user_and_delete_if_last();
layer->anonymous_id = nullptr;
}
if (!(layer->flag & CD_FLAG_NOFREE) && layer->data) {
typeInfo = layerType_getInfo(eCustomDataType(layer->type));
if (typeInfo->free) {
typeInfo->free(layer->data, totelem, typeInfo->size);
}
const eCustomDataType type = eCustomDataType(layer->type);
if (layer->sharing_info == nullptr) {
if (layer->data) {
MEM_freeN(layer->data);
free_layer_data(type, layer->data, totelem);
}
}
else {
layer->sharing_info->remove_user_and_delete_if_last();
layer->sharing_info = nullptr;
}
}
static void CustomData_external_free(CustomData *data)
@ -2738,76 +2849,26 @@ static void customData_resize(CustomData *data, const int grow_amount)
data->maxlayer += grow_amount;
}
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
const eCustomDataType type,
const eCDAllocType alloctype,
void *layerdata,
const int totelem,
const char *name)
static CustomDataLayer *customData_add_layer__internal(
CustomData *data,
const eCustomDataType type,
const std::optional<eCDAllocType> alloctype,
void *layer_data_to_assign,
const ImplicitSharingInfo *sharing_info_to_assign,
const int totelem,
const char *name)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
const LayerTypeInfo &type_info = *layerType_getInfo(type);
int flag = 0;
/* Some layer types only support a single layer. */
if (!typeInfo->defaultname && CustomData_has_layer(data, type)) {
if (!type_info.defaultname && CustomData_has_layer(data, type)) {
/* This function doesn't support dealing with existing layer data for these layer types when
* the layer already exists. */
BLI_assert(layerdata == nullptr);
BLI_assert(layer_data_to_assign == nullptr);
return &data->layers[CustomData_get_layer_index(data, type)];
}
void *newlayerdata = nullptr;
switch (alloctype) {
case CD_SET_DEFAULT:
if (totelem > 0) {
if (typeInfo->set_default_value) {
newlayerdata = MEM_malloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
typeInfo->set_default_value(newlayerdata, totelem);
}
else {
newlayerdata = MEM_calloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
}
}
break;
case CD_CONSTRUCT:
if (totelem > 0) {
newlayerdata = MEM_malloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
if (typeInfo->construct) {
typeInfo->construct(newlayerdata, totelem);
}
}
break;
case CD_ASSIGN:
if (totelem > 0) {
BLI_assert(layerdata != nullptr);
newlayerdata = layerdata;
}
else {
MEM_SAFE_FREE(layerdata);
}
break;
case CD_REFERENCE:
if (totelem > 0) {
BLI_assert(layerdata != nullptr);
newlayerdata = layerdata;
flag |= CD_FLAG_NOFREE;
}
break;
case CD_DUPLICATE:
if (totelem > 0) {
newlayerdata = MEM_malloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
if (typeInfo->copy) {
typeInfo->copy(layerdata, newlayerdata, totelem);
}
else {
BLI_assert(layerdata != nullptr);
BLI_assert(newlayerdata != nullptr);
memcpy(newlayerdata, layerdata, totelem * typeInfo->size);
}
}
break;
}
int index = data->totlayer;
if (index >= data->maxlayer) {
customData_resize(data, CUSTOMDATA_GROW);
@ -2815,7 +2876,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
data->totlayer++;
/* keep layers ordered by type */
/* Keep layers ordered by type. */
for (; index > 0 && data->layers[index - 1].type > type; index--) {
data->layers[index] = data->layers[index - 1];
}
@ -2827,15 +2888,57 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
* leaks into the new layer. */
memset(&new_layer, 0, sizeof(CustomDataLayer));
if (alloctype.has_value()) {
switch (*alloctype) {
case CD_SET_DEFAULT: {
if (totelem > 0) {
if (type_info.set_default_value) {
new_layer.data = MEM_malloc_arrayN(totelem, type_info.size, layerType_getName(type));
type_info.set_default_value(new_layer.data, totelem);
}
else {
new_layer.data = MEM_calloc_arrayN(totelem, type_info.size, layerType_getName(type));
}
}
break;
}
case CD_CONSTRUCT: {
if (totelem > 0) {
new_layer.data = MEM_malloc_arrayN(totelem, type_info.size, layerType_getName(type));
if (type_info.construct) {
type_info.construct(new_layer.data, totelem);
}
}
break;
}
}
}
else {
if (totelem == 0 && sharing_info_to_assign == nullptr) {
MEM_SAFE_FREE(layer_data_to_assign);
}
else {
new_layer.data = layer_data_to_assign;
new_layer.sharing_info = sharing_info_to_assign;
if (new_layer.sharing_info) {
new_layer.sharing_info->add_user();
}
}
}
if (new_layer.data != nullptr && new_layer.sharing_info == nullptr) {
/* Make layer data shareable. */
new_layer.sharing_info = make_implicit_sharing_info_for_layer(type, new_layer.data, totelem);
}
new_layer.type = type;
new_layer.flag = flag;
new_layer.data = newlayerdata;
/* Set default name if none exists. Note we only call DATA_() once
* we know there is a default name, to avoid overhead of locale lookups
* in the depsgraph. */
if (!name && typeInfo->defaultname) {
name = DATA_(typeInfo->defaultname);
if (!name && type_info.defaultname) {
name = DATA_(type_info.defaultname);
}
if (name) {
@ -2864,16 +2967,15 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
return &data->layers[index];
}
static void *customdata_add_layer(CustomData *data,
const eCustomDataType type,
eCDAllocType alloctype,
void *layerdata,
const int totelem)
void *CustomData_add_layer(CustomData *data,
const eCustomDataType type,
eCDAllocType alloctype,
const int totelem)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, layerdata, totelem, typeInfo->defaultname);
data, type, alloctype, nullptr, nullptr, totelem, typeInfo->defaultname);
CustomData_update_typemap(data);
if (layer) {
@ -2883,31 +2985,16 @@ static void *customdata_add_layer(CustomData *data,
return nullptr;
}
void *CustomData_add_layer(CustomData *data,
const eCustomDataType type,
const eCDAllocType alloctype,
const int totelem)
{
return customdata_add_layer(data, type, alloctype, nullptr, totelem);
}
const void *CustomData_add_layer_with_data(CustomData *data,
const eCustomDataType type,
void *layer_data,
const int totelem)
const int totelem,
const ImplicitSharingInfo *sharing_info)
{
return customdata_add_layer(data, type, CD_ASSIGN, layer_data, totelem);
}
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
static void *customdata_add_layer_named(CustomData *data,
const eCustomDataType type,
const eCDAllocType alloctype,
void *layerdata,
const int totelem,
const char *name)
{
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, layerdata, totelem, name);
data, type, std::nullopt, layer_data, sharing_info, totelem, typeInfo->defaultname);
CustomData_update_typemap(data);
if (layer) {
@ -2923,25 +3010,42 @@ void *CustomData_add_layer_named(CustomData *data,
const int totelem,
const char *name)
{
return customdata_add_layer_named(data, type, alloctype, nullptr, totelem, name);
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, nullptr, nullptr, totelem, name);
CustomData_update_typemap(data);
if (layer) {
return layer->data;
}
return nullptr;
}
const void *CustomData_add_layer_named_with_data(
CustomData *data, const eCustomDataType type, void *layer_data, int totelem, const char *name)
const void *CustomData_add_layer_named_with_data(CustomData *data,
eCustomDataType type,
void *layer_data,
int totelem,
const char *name,
const ImplicitSharingInfo *sharing_info)
{
return customdata_add_layer_named(data, type, CD_ASSIGN, layer_data, totelem, name);
CustomDataLayer *layer = customData_add_layer__internal(
data, type, std::nullopt, layer_data, sharing_info, totelem, name);
CustomData_update_typemap(data);
if (layer) {
return layer->data;
}
return nullptr;
}
void *CustomData_add_layer_anonymous(CustomData *data,
const eCustomDataType type,
const eCDAllocType alloctype,
void *layerdata,
const int totelem,
const AnonymousAttributeIDHandle *anonymous_id)
{
const char *name = anonymous_id->name().c_str();
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, layerdata, totelem, name);
data, type, alloctype, nullptr, nullptr, totelem, name);
CustomData_update_typemap(data);
if (layer == nullptr) {
@ -2953,6 +3057,27 @@ void *CustomData_add_layer_anonymous(CustomData *data,
return layer->data;
}
const void *CustomData_add_layer_anonymous_with_data(
CustomData *data,
const eCustomDataType type,
const AnonymousAttributeIDHandle *anonymous_id,
const int totelem,
void *layer_data,
const ImplicitSharingInfo *sharing_info)
{
const char *name = anonymous_id->name().c_str();
CustomDataLayer *layer = customData_add_layer__internal(
data, type, std::nullopt, layer_data, sharing_info, totelem, name);
CustomData_update_typemap(data);
if (layer == nullptr) {
return nullptr;
}
anonymous_id->add_user();
layer->anonymous_id = anonymous_id;
return layer->data;
}
bool CustomData_free_layer(CustomData *data,
const eCustomDataType type,
const int totelem,
@ -3081,47 +3206,6 @@ int CustomData_number_of_layers_typemask(const CustomData *data, const eCustomDa
return number;
}
static void *customData_duplicate_referenced_layer_index(CustomData *data,
const int layer_index,
const int totelem)
{
if (layer_index == -1) {
return nullptr;
}
CustomDataLayer *layer = &data->layers[layer_index];
if (layer->flag & CD_FLAG_NOFREE) {
/* MEM_dupallocN won't work in case of complex layers, like e.g.
* CD_MDEFORMVERT, which has pointers to allocated data...
* So in case a custom copy function is defined, use it!
*/
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer->type));
if (typeInfo->copy) {
void *dst_data = MEM_malloc_arrayN(
size_t(totelem), typeInfo->size, "CD duplicate ref layer");
typeInfo->copy(layer->data, dst_data, totelem);
layer->data = dst_data;
}
else {
layer->data = MEM_dupallocN(layer->data);
}
layer->flag &= ~CD_FLAG_NOFREE;
}
return layer->data;
}
void CustomData_duplicate_referenced_layers(CustomData *data, const int totelem)
{
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
layer->data = customData_duplicate_referenced_layer_index(data, i, totelem);
}
}
void CustomData_free_temporary(CustomData *data, const int totelem)
{
int i, j;
@ -3299,14 +3383,12 @@ void CustomData_copy_layer_type_data(const CustomData *source,
void CustomData_free_elem(CustomData *data, const int index, const int count)
{
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
if (typeInfo->free) {
size_t offset = size_t(index) * typeInfo->size;
if (typeInfo->free) {
size_t offset = size_t(index) * typeInfo->size;
typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count, typeInfo->size);
}
typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count, typeInfo->size);
}
}
}
@ -3476,7 +3558,12 @@ void *CustomData_get_layer_for_write(CustomData *data,
const int totelem)
{
const int layer_index = CustomData_get_active_layer_index(data, type);
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
if (layer_index == -1) {
return nullptr;
}
CustomDataLayer &layer = data->layers[layer_index];
ensure_layer_data_is_mutable(layer, totelem);
return layer.data;
}
const void *CustomData_get_layer_n(const CustomData *data, const eCustomDataType type, const int n)
@ -3485,7 +3572,6 @@ const void *CustomData_get_layer_n(const CustomData *data, const eCustomDataType
if (layer_index == -1) {
return nullptr;
}
return data->layers[layer_index].data;
}
@ -3495,7 +3581,12 @@ void *CustomData_get_layer_n_for_write(CustomData *data,
const int totelem)
{
const int layer_index = CustomData_get_layer_index_n(data, type, n);
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
if (layer_index == -1) {
return nullptr;
}
CustomDataLayer &layer = data->layers[layer_index];
ensure_layer_data_is_mutable(layer, totelem);
return layer.data;
}
const void *CustomData_get_layer_named(const CustomData *data,
@ -3506,7 +3597,6 @@ const void *CustomData_get_layer_named(const CustomData *data,
if (layer_index == -1) {
return nullptr;
}
return data->layers[layer_index].data;
}
@ -3516,7 +3606,12 @@ void *CustomData_get_layer_named_for_write(CustomData *data,
const int totelem)
{
const int layer_index = CustomData_get_named_layer_index(data, type, name);
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
if (layer_index == -1) {
return nullptr;
}
CustomDataLayer &layer = data->layers[layer_index];
ensure_layer_data_is_mutable(layer, totelem);
return layer.data;
}
int CustomData_get_offset(const CustomData *data, const eCustomDataType type)
@ -3525,7 +3620,6 @@ int CustomData_get_offset(const CustomData *data, const eCustomDataType type)
if (layer_index == -1) {
return -1;
}
return data->layers[layer_index].offset;
}
@ -3610,12 +3704,12 @@ void CustomData_bmesh_init_pool(CustomData *data, const int totelem, const char
}
}
bool CustomData_bmesh_merge(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
BMesh *bm,
const char htype)
bool CustomData_bmesh_merge_layout(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
BMesh *bm,
const char htype)
{
if (CustomData_number_of_layers_typemask(source, mask) == 0) {
@ -3629,7 +3723,7 @@ bool CustomData_bmesh_merge(const CustomData *source,
destold.layers = static_cast<CustomDataLayer *>(MEM_dupallocN(destold.layers));
}
if (CustomData_merge(source, dest, mask, alloctype, 0) == false) {
if (CustomData_merge_layout(source, dest, mask, alloctype, 0) == false) {
if (destold.layers) {
MEM_freeN(destold.layers);
}
@ -3709,13 +3803,11 @@ void CustomData_bmesh_free_block(CustomData *data, void **block)
}
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
if (typeInfo->free) {
int offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(*block, offset), 1, typeInfo->size);
}
if (typeInfo->free) {
int offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(*block, offset), 1, typeInfo->size);
}
}
@ -3732,12 +3824,10 @@ void CustomData_bmesh_free_block_data(CustomData *data, void *block)
return;
}
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
if (typeInfo->free) {
const size_t offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
if (typeInfo->free) {
const size_t offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
}
if (data->totsize) {
@ -3770,10 +3860,8 @@ void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data,
if ((CD_TYPE_AS_MASK(data->layers[i].type) & mask_exclude) == 0) {
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
const size_t offset = data->layers[i].offset;
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
if (typeInfo->free) {
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
if (typeInfo->free) {
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
memset(POINTER_OFFSET(block, offset), 0, typeInfo->size);
}
@ -3951,11 +4039,9 @@ bool CustomData_has_math(const CustomData *data)
bool CustomData_bmesh_has_free(const CustomData *data)
{
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
if (typeInfo->free) {
return true;
}
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
if (typeInfo->free) {
return true;
}
}
return false;
@ -3973,16 +4059,6 @@ bool CustomData_has_interp(const CustomData *data)
return false;
}
bool CustomData_has_referenced(const CustomData *data)
{
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].flag & CD_FLAG_NOFREE) {
return true;
}
}
return false;
}
void CustomData_data_copy_value(const eCustomDataType type, const void *source, void *dest)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@ -5188,11 +5264,15 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, const int
if (layer->flag & CD_FLAG_EXTERNAL) {
layer->flag &= ~CD_FLAG_IN_MEMORY;
}
layer->flag &= ~CD_FLAG_NOFREE;
layer->sharing_info = nullptr;
if (CustomData_verify_versions(data, i)) {
BLO_read_data_address(reader, &layer->data);
if (layer->data != nullptr) {
/* Make layer data shareable. */
layer->sharing_info = make_implicit_sharing_info_for_layer(
eCustomDataType(layer->type), layer->data, count);
}
if (CustomData_layer_ensure_data_exists(layer, count)) {
/* Under normal operations, this shouldn't happen, but...
* For a CD_PROP_BOOL example, see #84935.

View File

@ -72,7 +72,6 @@ using blender::StringRef;
using blender::VArray;
using blender::Vector;
static void mesh_clear_geometry(Mesh *mesh);
static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata);
static void mesh_init_data(ID *id)
@ -151,14 +150,13 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
mesh_dst->default_color_attribute = static_cast<char *>(
MEM_dupallocN(mesh_src->default_color_attribute));
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, alloc_type, mesh_dst->totvert);
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, alloc_type, mesh_dst->totedge);
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, alloc_type, mesh_dst->totloop);
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, alloc_type, mesh_dst->totpoly);
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, mesh_dst->totvert);
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, mesh_dst->totedge);
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, mesh_dst->totloop);
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, mesh_dst->totpoly);
mesh_dst->poly_offset_indices = static_cast<int *>(MEM_dupallocN(mesh_src->poly_offset_indices));
if (do_tessface) {
CustomData_copy(&mesh_src->fdata, &mesh_dst->fdata, mask.fmask, alloc_type, mesh_dst->totface);
CustomData_copy(&mesh_src->fdata, &mesh_dst->fdata, mask.fmask, mesh_dst->totface);
}
else {
mesh_tessface_clear_intern(mesh_dst, false);
@ -193,11 +191,9 @@ static void mesh_free_data(ID *id)
{
Mesh *mesh = (Mesh *)id;
BLI_freelistN(&mesh->vertex_group_names);
BKE_mesh_free_editmesh(mesh);
mesh_clear_geometry(mesh);
BKE_mesh_clear_geometry_and_metadata(mesh);
MEM_SAFE_FREE(mesh->mat);
delete mesh->runtime;
@ -526,9 +522,9 @@ static bool is_sublayer_name(char const *sublayer_name, char const *name)
return true;
}
static bool is_uv_bool_sublayer(CustomDataLayer const *l)
static bool is_uv_bool_sublayer(const CustomDataLayer &layer)
{
char const *name = l->name;
char const *name = layer.name;
if (name[0] != '.') {
return false;
@ -557,7 +553,7 @@ static int customdata_compare(
for (int i = 0; i < c1->totlayer; i++) {
l1 = &c1->layers[i];
if ((CD_TYPE_AS_MASK(l1->type) & cd_mask_all_attr) && l1->anonymous_id == nullptr &&
!is_uv_bool_sublayer(l1)) {
!is_uv_bool_sublayer(*l1)) {
layer_count1++;
}
}
@ -565,7 +561,7 @@ static int customdata_compare(
for (int i = 0; i < c2->totlayer; i++) {
l2 = &c2->layers[i];
if ((CD_TYPE_AS_MASK(l2->type) & cd_mask_all_attr) && l2->anonymous_id == nullptr &&
!is_uv_bool_sublayer(l2)) {
!is_uv_bool_sublayer(*l2)) {
layer_count2++;
}
}
@ -581,7 +577,7 @@ static int customdata_compare(
for (int i1 = 0; i1 < c1->totlayer; i1++) {
l1 = c1->layers + i1;
if (l1->anonymous_id != nullptr || is_uv_bool_sublayer(l1)) {
if (l1->anonymous_id != nullptr || is_uv_bool_sublayer(*l1)) {
continue;
}
bool found_corresponding_layer = false;
@ -905,37 +901,47 @@ void BKE_mesh_free_data_for_undo(Mesh *me)
* Material slots should be kept in sync with the object.
*
* - Edit-Mesh (#Mesh.edit_mesh)
* Since edit-mesh is tied to the objects mode,
* which crashes when called in edit-mode, see: #90972.
* Since edit-mesh is tied to the object's mode, which crashes when called in edit-mode.
* See: #90972.
*/
static void mesh_clear_geometry(Mesh *mesh)
static void mesh_clear_geometry(Mesh &mesh)
{
CustomData_free(&mesh->vdata, mesh->totvert);
CustomData_free(&mesh->edata, mesh->totedge);
CustomData_free(&mesh->fdata, mesh->totface);
CustomData_free(&mesh->ldata, mesh->totloop);
CustomData_free(&mesh->pdata, mesh->totpoly);
MEM_SAFE_FREE(mesh->poly_offset_indices);
CustomData_free(&mesh.vdata, mesh.totvert);
CustomData_free(&mesh.edata, mesh.totedge);
CustomData_free(&mesh.fdata, mesh.totface);
CustomData_free(&mesh.ldata, mesh.totloop);
CustomData_free(&mesh.pdata, mesh.totpoly);
MEM_SAFE_FREE(mesh.poly_offset_indices);
MEM_SAFE_FREE(mesh->mselect);
MEM_SAFE_FREE(mesh.mselect);
mesh->totvert = 0;
mesh->totedge = 0;
mesh->totface = 0;
mesh->totloop = 0;
mesh->totpoly = 0;
mesh->act_face = -1;
mesh->totselect = 0;
mesh.totvert = 0;
mesh.totedge = 0;
mesh.totface = 0;
mesh.totloop = 0;
mesh.totpoly = 0;
mesh.act_face = -1;
mesh.totselect = 0;
}
BLI_freelistN(&mesh->vertex_group_names);
MEM_SAFE_FREE(mesh->active_color_attribute);
MEM_SAFE_FREE(mesh->default_color_attribute);
static void clear_attribute_names(Mesh &mesh)
{
BLI_freelistN(&mesh.vertex_group_names);
MEM_SAFE_FREE(mesh.active_color_attribute);
MEM_SAFE_FREE(mesh.default_color_attribute);
}
void BKE_mesh_clear_geometry(Mesh *mesh)
{
BKE_mesh_runtime_clear_cache(mesh);
mesh_clear_geometry(mesh);
mesh_clear_geometry(*mesh);
}
void BKE_mesh_clear_geometry_and_metadata(Mesh *mesh)
{
BKE_mesh_runtime_clear_cache(mesh);
mesh_clear_geometry(*mesh);
clear_attribute_names(*mesh);
}
static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
@ -963,34 +969,33 @@ void BKE_mesh_poly_offsets_ensure_alloc(Mesh *mesh)
if (mesh->totpoly == 0) {
return;
}
if (!mesh->poly_offset_indices) {
mesh->poly_offset_indices = static_cast<int *>(
MEM_malloc_arrayN(mesh->totpoly + 1, sizeof(int), __func__));
}
mesh->poly_offset_indices = static_cast<int *>(
MEM_malloc_arrayN(mesh->totpoly + 1, sizeof(int), __func__));
#ifdef DEBUG
/* Fill offsets with obviously bad values to simplify finding missing initialization. */
mesh->poly_offsets_for_write().fill(-1);
#endif
mesh->poly_offsets_for_write().last() = mesh->totloop;
mesh->poly_offset_indices[0] = 0;
mesh->poly_offset_indices[mesh->totpoly] = mesh->totloop;
}
/* Custom data layer functions; those assume that totXXX are set correctly. */
static void mesh_ensure_cdlayers_primary(Mesh *mesh)
static void mesh_ensure_cdlayers_primary(Mesh &mesh)
{
if (!CustomData_get_layer_named(&mesh->vdata, CD_PROP_FLOAT3, "position")) {
if (!CustomData_get_layer_named(&mesh.vdata, CD_PROP_FLOAT3, "position")) {
CustomData_add_layer_named(
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, mesh->totvert, "position");
&mesh.vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, mesh.totvert, "position");
}
if (!CustomData_get_layer(&mesh->edata, CD_MEDGE)) {
CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, mesh->totedge);
if (!CustomData_get_layer(&mesh.edata, CD_MEDGE)) {
CustomData_add_layer(&mesh.edata, CD_MEDGE, CD_SET_DEFAULT, mesh.totedge);
}
if (!CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_vert")) {
if (!CustomData_get_layer_named(&mesh.ldata, CD_PROP_INT32, ".corner_vert")) {
CustomData_add_layer_named(
&mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_vert");
&mesh.ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh.totloop, ".corner_vert");
}
if (!CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge")) {
if (!CustomData_get_layer_named(&mesh.ldata, CD_PROP_INT32, ".corner_edge")) {
CustomData_add_layer_named(
&mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_edge");
&mesh.ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh.totloop, ".corner_edge");
}
}
@ -1012,7 +1017,7 @@ Mesh *BKE_mesh_new_nomain(int verts_len, int edges_len, int loops_len, int polys
mesh->totloop = loops_len;
mesh->totpoly = polys_len;
mesh_ensure_cdlayers_primary(mesh);
mesh_ensure_cdlayers_primary(*mesh);
BKE_mesh_poly_offsets_ensure_alloc(mesh);
return mesh;
@ -1096,12 +1101,13 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
BKE_mesh_copy_parameters_for_eval(me_dst, me_src);
CustomData_copy(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_SET_DEFAULT, verts_len);
CustomData_copy(&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_len);
CustomData_copy(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_len);
CustomData_copy(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_len);
CustomData_copy_layout(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_SET_DEFAULT, verts_len);
CustomData_copy_layout(&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_len);
CustomData_copy_layout(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_len);
CustomData_copy_layout(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_len);
if (do_tessface) {
CustomData_copy(&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_len);
CustomData_copy_layout(
&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_len);
}
else {
mesh_tessface_clear_intern(me_dst, false);
@ -1109,7 +1115,7 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
/* The destination mesh should at least have valid primary CD layers,
* even in cases where the source mesh does not. */
mesh_ensure_cdlayers_primary(me_dst);
mesh_ensure_cdlayers_primary(*me_dst);
BKE_mesh_poly_offsets_ensure_alloc(me_dst);
if (do_tessface && !CustomData_get_layer(&me_dst->fdata, CD_MFACE)) {
CustomData_add_layer(&me_dst->fdata, CD_MFACE, CD_SET_DEFAULT, me_dst->totface);
@ -1378,7 +1384,7 @@ void BKE_mesh_orco_ensure(Object *ob, Mesh *mesh)
/* Orcos are stored in normalized 0..1 range by convention. */
float(*orcodata)[3] = BKE_mesh_orco_verts_get(ob);
BKE_mesh_orco_verts_transform(mesh, orcodata, mesh->totvert, false);
CustomData_add_layer_with_data(&mesh->vdata, CD_ORCO, orcodata, mesh->totvert);
CustomData_add_layer_with_data(&mesh->vdata, CD_ORCO, orcodata, mesh->totvert, nullptr);
}
Mesh *BKE_mesh_from_object(Object *ob)

View File

@ -656,15 +656,15 @@ static void merge_vertex_loop_poly_customdata_layers(Mesh *target, MeshesToIMesh
for (int mesh_index = 1; mesh_index < mim.meshes.size(); ++mesh_index) {
const Mesh *me = mim.meshes[mesh_index];
if (me->totvert) {
CustomData_merge(
CustomData_merge_layout(
&me->vdata, &target->vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, target->totvert);
}
if (me->totloop) {
CustomData_merge(
CustomData_merge_layout(
&me->ldata, &target->ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, target->totloop);
}
if (me->totpoly) {
CustomData_merge(
CustomData_merge_layout(
&me->pdata, &target->pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, target->totpoly);
}
}
@ -675,7 +675,7 @@ static void merge_edge_customdata_layers(Mesh *target, MeshesToIMeshInfo &mim)
for (int mesh_index = 0; mesh_index < mim.meshes.size(); ++mesh_index) {
const Mesh *me = mim.meshes[mesh_index];
if (me->totedge) {
CustomData_merge(
CustomData_merge_layout(
&me->edata, &target->edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, target->totedge);
}
}

View File

@ -244,7 +244,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select
/* Free old CustomData and assign new one. */
CustomData_free(&mesh->edata, mesh->totedge);
CustomData_reset(&mesh->edata);
CustomData_add_layer_with_data(&mesh->edata, CD_MEDGE, new_edges.data(), new_totedge);
CustomData_add_layer_with_data(&mesh->edata, CD_MEDGE, new_edges.data(), new_totedge, nullptr);
mesh->totedge = new_totedge;
if (select_new_edges) {

View File

@ -625,7 +625,7 @@ void BKE_pointcloud_from_mesh(const Mesh *me, PointCloud *pointcloud)
{
CustomData_free(&pointcloud->pdata, pointcloud->totpoint);
pointcloud->totpoint = me->totvert;
CustomData_merge(&me->vdata, &pointcloud->pdata, CD_MASK_PROP_ALL, CD_DUPLICATE, me->totvert);
CustomData_merge(&me->vdata, &pointcloud->pdata, CD_MASK_PROP_ALL, me->totvert);
}
void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/, Object *ob)
@ -652,8 +652,7 @@ void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/
void BKE_mesh_from_pointcloud(const PointCloud *pointcloud, Mesh *me)
{
me->totvert = pointcloud->totpoint;
CustomData_merge(
&pointcloud->pdata, &me->vdata, CD_MASK_PROP_ALL, CD_DUPLICATE, pointcloud->totpoint);
CustomData_merge(&pointcloud->pdata, &me->vdata, CD_MASK_PROP_ALL, pointcloud->totpoint);
}
void BKE_pointcloud_to_mesh(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/, Object *ob)
@ -1114,14 +1113,7 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
BLI_assert(mesh_dst == ob->data);
}
BKE_mesh_clear_geometry(mesh_dst);
/* Make sure referenced layers have a single user so assigning them to the mesh in main doesn't
* share them. "Referenced" layers are not expected to be shared between original meshes. */
CustomData_duplicate_referenced_layers(&mesh_src->vdata, mesh_src->totvert);
CustomData_duplicate_referenced_layers(&mesh_src->edata, mesh_src->totedge);
CustomData_duplicate_referenced_layers(&mesh_src->pdata, mesh_src->totpoly);
CustomData_duplicate_referenced_layers(&mesh_src->ldata, mesh_src->totloop);
BKE_mesh_clear_geometry_and_metadata(mesh_dst);
const bool verts_num_changed = mesh_dst->totvert != mesh_src->totvert;
mesh_dst->totvert = mesh_src->totvert;
@ -1131,26 +1123,16 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
/* Using #CD_MASK_MESH ensures that only data that should exist in Main meshes is moved. */
const CustomData_MeshMasks mask = CD_MASK_MESH;
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, CD_ASSIGN, mesh_src->totvert);
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, CD_ASSIGN, mesh_src->totedge);
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, CD_ASSIGN, mesh_src->totpoly);
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, CD_ASSIGN, mesh_src->totloop);
mesh_dst->poly_offset_indices = static_cast<int *>(mesh_src->poly_offset_indices);
mesh_src->poly_offset_indices = nullptr;
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, mesh_src->totvert);
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, mesh_src->totedge);
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, mesh_src->totpoly);
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, mesh_src->totloop);
std::swap(mesh_dst->poly_offset_indices, mesh_src->poly_offset_indices);
/* Make sure active/default color attribute (names) are brought over. */
if (mesh_src->active_color_attribute) {
MEM_SAFE_FREE(mesh_dst->active_color_attribute);
mesh_dst->active_color_attribute = BLI_strdup(mesh_src->active_color_attribute);
}
if (mesh_src->default_color_attribute) {
MEM_SAFE_FREE(mesh_dst->default_color_attribute);
mesh_dst->default_color_attribute = BLI_strdup(mesh_src->default_color_attribute);
}
BLI_freelistN(&mesh_dst->vertex_group_names);
mesh_dst->vertex_group_names = mesh_src->vertex_group_names;
BLI_listbase_clear(&mesh_src->vertex_group_names);
/* Make sure attribute names are moved. */
std::swap(mesh_dst->active_color_attribute, mesh_src->active_color_attribute);
std::swap(mesh_dst->default_color_attribute, mesh_src->default_color_attribute);
std::swap(mesh_dst->vertex_group_names, mesh_src->vertex_group_names);
BKE_mesh_copy_parameters(mesh_dst, mesh_src);

View File

@ -227,7 +227,7 @@ void BKE_mesh_calc_edges_legacy(Mesh *me)
return;
}
edges = (MEdge *)CustomData_add_layer_with_data(&me->edata, CD_MEDGE, edges, totedge);
edges = (MEdge *)CustomData_add_layer_with_data(&me->edata, CD_MEDGE, edges, totedge, nullptr);
me->totedge = totedge;
BKE_mesh_tag_topology_changed(me);
@ -1149,11 +1149,11 @@ static int mesh_tessface_calc(Mesh &mesh,
sizeof(*mface_to_poly_map) * size_t(totface));
}
CustomData_add_layer_with_data(fdata, CD_MFACE, mface, totface);
CustomData_add_layer_with_data(fdata, CD_MFACE, mface, totface, nullptr);
/* #CD_ORIGINDEX will contain an array of indices from tessellation-faces to the polygons
* they are directly tessellated from. */
CustomData_add_layer_with_data(fdata, CD_ORIGINDEX, mface_to_poly_map, totface);
CustomData_add_layer_with_data(fdata, CD_ORIGINDEX, mface_to_poly_map, totface, nullptr);
add_mface_layers(mesh, fdata, ldata, totface);
/* NOTE: quad detection issue - fourth vertex-index vs fourth loop-index:
@ -1297,17 +1297,28 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
return;
}
void *faceset_data = nullptr;
const ImplicitSharingInfo *faceset_sharing_info = nullptr;
for (const int i : IndexRange(mesh->pdata.totlayer)) {
if (mesh->pdata.layers[i].type == CD_SCULPT_FACE_SETS) {
faceset_data = mesh->pdata.layers[i].data;
mesh->pdata.layers[i].data = nullptr;
CustomDataLayer &layer = mesh->pdata.layers[i];
if (layer.type == CD_SCULPT_FACE_SETS) {
faceset_data = layer.data;
faceset_sharing_info = layer.sharing_info;
layer.data = nullptr;
layer.sharing_info = nullptr;
CustomData_free_layer(&mesh->pdata, CD_SCULPT_FACE_SETS, mesh->totpoly, i);
break;
}
}
if (faceset_data != nullptr) {
CustomData_add_layer_named_with_data(
&mesh->pdata, CD_PROP_INT32, faceset_data, mesh->totpoly, ".sculpt_face_set");
CustomData_add_layer_named_with_data(&mesh->pdata,
CD_PROP_INT32,
faceset_data,
mesh->totpoly,
".sculpt_face_set",
faceset_sharing_info);
}
if (faceset_sharing_info != nullptr) {
faceset_sharing_info->remove_user_and_delete_if_last();
}
}
@ -1815,28 +1826,31 @@ void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh)
uv_names[i] = new_name;
CustomData_add_layer_named_with_data(
&mesh->ldata, CD_PROP_FLOAT2, coords, mesh->totloop, new_name);
&mesh->ldata, CD_PROP_FLOAT2, coords, mesh->totloop, new_name, nullptr);
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
if (vert_selection) {
CustomData_add_layer_named_with_data(&mesh->ldata,
CD_PROP_BOOL,
vert_selection,
mesh->totloop,
BKE_uv_map_vert_select_name_get(new_name, buffer));
BKE_uv_map_vert_select_name_get(new_name, buffer),
nullptr);
}
if (edge_selection) {
CustomData_add_layer_named_with_data(&mesh->ldata,
CD_PROP_BOOL,
edge_selection,
mesh->totloop,
BKE_uv_map_edge_select_name_get(new_name, buffer));
BKE_uv_map_edge_select_name_get(new_name, buffer),
nullptr);
}
if (pin) {
CustomData_add_layer_named_with_data(&mesh->ldata,
CD_PROP_BOOL,
pin,
mesh->totloop,
BKE_uv_map_pin_name_get(new_name, buffer));
BKE_uv_map_pin_name_get(new_name, buffer),
nullptr);
}
}
@ -2272,7 +2286,8 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh)
});
CustomData old_poly_data = mesh->pdata;
CustomData_reset(&mesh->pdata);
CustomData_copy(&old_poly_data, &mesh->pdata, CD_MASK_MESH.pmask, CD_CONSTRUCT, mesh->totpoly);
CustomData_copy_layout(
&old_poly_data, &mesh->pdata, CD_MASK_MESH.pmask, CD_CONSTRUCT, mesh->totpoly);
int offset = 0;
for (const int i : orig_indices.index_range()) {

View File

@ -224,6 +224,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
if (mesh->runtime->shrinkwrap_data) {
BKE_shrinkwrap_boundary_data_free(mesh->runtime->shrinkwrap_data);
mesh->runtime->shrinkwrap_data = nullptr;
}
}

View File

@ -1302,12 +1302,7 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, uint level, uint x, uint y
void paint_update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, float rotation)
{
if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) {
ups->brush_rotation = rotation;
}
else {
ups->brush_rotation = 0.0f;
}
ups->brush_rotation = rotation;
if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE) {
ups->brush_rotation_sec = rotation;
@ -1322,17 +1317,19 @@ static bool paint_rake_rotation_active(const MTex &mtex)
return mtex.tex && mtex.brush_angle_mode & MTEX_ANGLE_RAKE;
}
static bool paint_rake_rotation_active(const Brush &brush)
static const bool paint_rake_rotation_active(const Brush &brush, ePaintMode paint_mode)
{
return paint_rake_rotation_active(brush.mtex) || paint_rake_rotation_active(brush.mask_mtex);
return paint_rake_rotation_active(brush.mtex) || paint_rake_rotation_active(brush.mask_mtex) ||
BKE_brush_has_cube_tip(&brush, paint_mode);
}
bool paint_calculate_rake_rotation(UnifiedPaintSettings *ups,
Brush *brush,
const float mouse_pos[2])
const float mouse_pos[2],
ePaintMode paint_mode)
{
bool ok = false;
if (paint_rake_rotation_active(*brush)) {
if (paint_rake_rotation_active(*brush, paint_mode)) {
const float r = RAKE_THRESHHOLD;
float rotation;

View File

@ -64,25 +64,24 @@ static void pointcloud_init_data(ID *id)
CustomData_reset(&pointcloud->pdata);
CustomData_add_layer_named(&pointcloud->pdata,
CD_PROP_FLOAT3,
CD_SET_DEFAULT,
CD_CONSTRUCT,
pointcloud->totpoint,
POINTCLOUD_ATTR_POSITION);
pointcloud->runtime = new blender::bke::PointCloudRuntime();
}
static void pointcloud_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void pointcloud_copy_data(Main * /*bmain*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
{
PointCloud *pointcloud_dst = (PointCloud *)id_dst;
const PointCloud *pointcloud_src = (const PointCloud *)id_src;
pointcloud_dst->mat = static_cast<Material **>(MEM_dupallocN(pointcloud_src->mat));
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&pointcloud_src->pdata,
&pointcloud_dst->pdata,
CD_MASK_ALL,
alloc_type,
pointcloud_dst->totpoint);
CustomData_copy(
&pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, pointcloud_dst->totpoint);
pointcloud_dst->runtime = new blender::bke::PointCloudRuntime();
pointcloud_dst->runtime->bounds_cache = pointcloud_src->runtime->bounds_cache;
@ -203,21 +202,18 @@ static void pointcloud_random(PointCloud *pointcloud)
RNG *rng = BLI_rng_new(0);
blender::bke::MutableAttributeAccessor attributes = pointcloud->attributes_for_write();
blender::bke::SpanAttributeWriter positions =
attributes.lookup_or_add_for_write_only_span<float3>(POINTCLOUD_ATTR_POSITION,
ATTR_DOMAIN_POINT);
blender::MutableSpan<float3> positions = pointcloud->positions_for_write();
blender::bke::SpanAttributeWriter<float> radii =
attributes.lookup_or_add_for_write_only_span<float>(POINTCLOUD_ATTR_RADIUS,
ATTR_DOMAIN_POINT);
for (const int i : positions.span.index_range()) {
positions.span[i] =
float3(BLI_rng_get_float(rng), BLI_rng_get_float(rng), BLI_rng_get_float(rng)) * 2.0f -
1.0f;
for (const int i : positions.index_range()) {
positions[i] = float3(BLI_rng_get_float(rng), BLI_rng_get_float(rng), BLI_rng_get_float(rng)) *
2.0f -
1.0f;
radii.span[i] = 0.05f * BLI_rng_get_float(rng);
}
positions.finish();
radii.finish();
BLI_rng_free(rng);
@ -259,27 +255,12 @@ void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src,
{
BLI_assert(pointcloud_src->id.tag & LIB_TAG_NO_MAIN);
eCDAllocType alloctype = CD_DUPLICATE;
if (take_ownership) {
bool has_any_referenced_layers = CustomData_has_referenced(&pointcloud_src->pdata);
if (!has_any_referenced_layers) {
alloctype = CD_ASSIGN;
}
}
CustomData_free(&pointcloud_dst->pdata, pointcloud_dst->totpoint);
const int totpoint = pointcloud_dst->totpoint = pointcloud_src->totpoint;
CustomData_copy(
&pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, alloctype, totpoint);
CustomData_copy(&pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, totpoint);
if (take_ownership) {
if (alloctype == CD_ASSIGN) {
/* Free the CustomData but keep the layers. */
CustomData_free_typemask(&pointcloud_src->pdata, pointcloud_src->totpoint, 0);
}
BKE_id_free(nullptr, pointcloud_src);
}
}

View File

@ -221,11 +221,11 @@ static void vertex_interpolation_init(const SubdivMeshContext *ctx,
else {
vertex_interpolation->vertex_data = &vertex_interpolation->vertex_data_storage;
/* Allocate storage for loops corresponding to ptex corners. */
CustomData_copy(&ctx->coarse_mesh->vdata,
&vertex_interpolation->vertex_data_storage,
CD_MASK_EVERYTHING.vmask,
CD_SET_DEFAULT,
4);
CustomData_copy_layout(&ctx->coarse_mesh->vdata,
&vertex_interpolation->vertex_data_storage,
CD_MASK_EVERYTHING.vmask,
CD_SET_DEFAULT,
4);
/* Initialize indices. */
vertex_interpolation->vertex_indices[0] = 0;
vertex_interpolation->vertex_indices[1] = 1;
@ -351,11 +351,11 @@ static void loop_interpolation_init(const SubdivMeshContext *ctx,
else {
loop_interpolation->loop_data = &loop_interpolation->loop_data_storage;
/* Allocate storage for loops corresponding to ptex corners. */
CustomData_copy(&ctx->coarse_mesh->ldata,
&loop_interpolation->loop_data_storage,
CD_MASK_EVERYTHING.lmask,
CD_SET_DEFAULT,
4);
CustomData_copy_layout(&ctx->coarse_mesh->ldata,
&loop_interpolation->loop_data_storage,
CD_MASK_EVERYTHING.lmask,
CD_SET_DEFAULT,
4);
/* Initialize indices. */
loop_interpolation->loop_indices[0] = 0;
loop_interpolation->loop_indices[1] = 1;

View File

@ -73,7 +73,7 @@ inline void gather(const VArray<T> &src,
{
BLI_assert(indices.size() == dst.size());
threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) {
src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range).data());
src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range));
});
}

View File

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bli
*
* This file only exists to forward declare `blender::ImplicitSharingInfo` in C code.
*/
#ifdef __cplusplus
namespace blender {
class ImplicitSharingInfo;
}
using ImplicitSharingInfoHandle = blender::ImplicitSharingInfo;
#else
typedef struct ImplicitSharingInfoHandle ImplicitSharingInfoHandle;
#endif

View File

@ -243,6 +243,7 @@ set(SRC
BLI_hash_tables.hh
BLI_heap.h
BLI_heap_simple.h
BLI_implicit_sharing.h
BLI_implicit_sharing.hh
BLI_implicit_sharing_ptr.hh
BLI_index_mask.hh

View File

@ -346,13 +346,15 @@ void extract_normalized_words(StringRef str,
Vector<StringRef, 64> &r_words)
{
const uint32_t unicode_space = uint32_t(' ');
const uint32_t unicode_slash = uint32_t('/');
const uint32_t unicode_right_triangle = UI_MENU_ARROW_SEP_UNICODE;
BLI_assert(unicode_space == BLI_str_utf8_as_unicode(" "));
BLI_assert(unicode_slash == BLI_str_utf8_as_unicode("/"));
BLI_assert(unicode_right_triangle == BLI_str_utf8_as_unicode(UI_MENU_ARROW_SEP));
auto is_separator = [&](uint32_t unicode) {
return ELEM(unicode, unicode_space, unicode_right_triangle);
return ELEM(unicode, unicode_space, unicode_slash, unicode_right_triangle);
};
/* Make a copy of the string so that we can edit it. */

View File

@ -2237,32 +2237,6 @@ static void *restore_pointer_by_name(IDNameLib_Map *id_map, ID *id, ePointerUser
#endif
}
static void lib_link_seq_clipboard_pt_restore(ID *id, IDNameLib_Map *id_map)
{
if (id) {
/* clipboard must ensure this */
BLI_assert(id->newid != nullptr);
id->newid = static_cast<ID *>(restore_pointer_by_name(id_map, id->newid, USER_REAL));
}
}
static bool lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt)
{
IDNameLib_Map *id_map = static_cast<IDNameLib_Map *>(arg_pt);
lib_link_seq_clipboard_pt_restore(reinterpret_cast<ID *>(seq->scene), id_map);
lib_link_seq_clipboard_pt_restore(reinterpret_cast<ID *>(seq->scene_camera), id_map);
lib_link_seq_clipboard_pt_restore(reinterpret_cast<ID *>(seq->clip), id_map);
lib_link_seq_clipboard_pt_restore(reinterpret_cast<ID *>(seq->mask), id_map);
lib_link_seq_clipboard_pt_restore(reinterpret_cast<ID *>(seq->sound), id_map);
return true;
}
static void lib_link_clipboard_restore(IDNameLib_Map *id_map)
{
/* update IDs stored in sequencer clipboard */
SEQ_for_each_callback(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map);
}
static int lib_link_main_data_restore_cb(LibraryIDLinkCallbackData *cb_data)
{
const int cb_flag = cb_data->cb_flag;
@ -2674,9 +2648,6 @@ void blo_lib_link_restore(Main *oldmain,
* that is just some minor harmless double-processing. */
lib_link_main_data_restore(id_map, newmain);
/* update IDs stored in all possible clipboards */
lib_link_clipboard_restore(id_map);
BKE_main_idmap_destroy(id_map);
}

View File

@ -273,19 +273,19 @@ static void customdata_version_242(Mesh *me)
int a, mtfacen, mcoln;
if (!me->vdata.totlayer) {
CustomData_add_layer_with_data(&me->vdata, CD_MVERT, me->mvert, me->totvert);
CustomData_add_layer_with_data(&me->vdata, CD_MVERT, me->mvert, me->totvert, NULL);
if (me->dvert) {
CustomData_add_layer_with_data(&me->vdata, CD_MDEFORMVERT, me->dvert, me->totvert);
CustomData_add_layer_with_data(&me->vdata, CD_MDEFORMVERT, me->dvert, me->totvert, NULL);
}
}
if (!me->edata.totlayer) {
CustomData_add_layer_with_data(&me->edata, CD_MEDGE, me->medge, me->totedge);
CustomData_add_layer_with_data(&me->edata, CD_MEDGE, me->medge, me->totedge, NULL);
}
if (!me->fdata.totlayer) {
CustomData_add_layer_with_data(&me->fdata, CD_MFACE, me->mface, me->totface);
CustomData_add_layer_with_data(&me->fdata, CD_MFACE, me->mface, me->totface, NULL);
if (me->tface) {
if (me->mcol) {
@ -308,7 +308,7 @@ static void customdata_version_242(Mesh *me)
me->tface = NULL;
}
else if (me->mcol) {
CustomData_add_layer_with_data(&me->fdata, CD_MCOL, me->mcol, me->totface);
CustomData_add_layer_with_data(&me->fdata, CD_MCOL, me->mcol, me->totface, NULL);
}
}

View File

@ -517,16 +517,16 @@ void BM_mesh_copy_init_customdata_from_mesh_array(BMesh *bm_dst,
&me_src->ldata, CD_MASK_BMESH.pmask);
if (i == 0) {
CustomData_copy(&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
}
else {
CustomData_merge(&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_merge(&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_merge(&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_merge(&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
CustomData_merge_layout(&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_merge_layout(&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_merge_layout(&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_merge_layout(&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
}
MEM_SAFE_FREE(mesh_vdata.layers);
@ -554,10 +554,10 @@ void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTem
allocsize = &bm_mesh_allocsize_default;
}
CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);

View File

@ -268,10 +268,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
if (me->totvert == 0) {
if (is_new) {
/* No verts? still copy custom-data layout. */
CustomData_copy(&mesh_vdata, &bm->vdata, mask.vmask, CD_CONSTRUCT, 0);
CustomData_copy(&mesh_edata, &bm->edata, mask.emask, CD_CONSTRUCT, 0);
CustomData_copy(&mesh_pdata, &bm->pdata, mask.pmask, CD_CONSTRUCT, 0);
CustomData_copy(&mesh_ldata, &bm->ldata, mask.lmask, CD_CONSTRUCT, 0);
CustomData_copy_layout(&mesh_vdata, &bm->vdata, mask.vmask, CD_CONSTRUCT, 0);
CustomData_copy_layout(&mesh_edata, &bm->edata, mask.emask, CD_CONSTRUCT, 0);
CustomData_copy_layout(&mesh_pdata, &bm->pdata, mask.pmask, CD_CONSTRUCT, 0);
CustomData_copy_layout(&mesh_ldata, &bm->ldata, mask.lmask, CD_CONSTRUCT, 0);
CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
@ -287,16 +287,20 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
}
if (is_new) {
CustomData_copy(&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, 0);
CustomData_copy_layout(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, 0);
}
else {
CustomData_bmesh_merge(&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, bm, BM_VERT);
CustomData_bmesh_merge(&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, bm, BM_EDGE);
CustomData_bmesh_merge(&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, bm, BM_FACE);
CustomData_bmesh_merge(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, bm, BM_LOOP);
CustomData_bmesh_merge_layout(
&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, bm, BM_VERT);
CustomData_bmesh_merge_layout(
&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, bm, BM_EDGE);
CustomData_bmesh_merge_layout(
&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, bm, BM_FACE);
CustomData_bmesh_merge_layout(
&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, bm, BM_LOOP);
}
/* -------------------------------------------------------------------- */
@ -1382,13 +1386,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
using namespace blender;
const int old_verts_num = me->totvert;
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
CustomData_free(&me->ldata, me->totloop);
CustomData_free(&me->pdata, me->totpoly);
MEM_SAFE_FREE(me->poly_offset_indices);
BKE_mesh_runtime_clear_geometry(me);
BKE_mesh_clear_geometry(me);
me->totvert = bm->totvert;
me->totedge = bm->totedge;
@ -1400,10 +1398,10 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
{
CustomData_MeshMasks mask = CD_MASK_MESH;
CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
CustomData_copy(&bm->vdata, &me->vdata, mask.vmask, CD_SET_DEFAULT, me->totvert);
CustomData_copy(&bm->edata, &me->edata, mask.emask, CD_SET_DEFAULT, me->totedge);
CustomData_copy(&bm->ldata, &me->ldata, mask.lmask, CD_SET_DEFAULT, me->totloop);
CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_SET_DEFAULT, me->totpoly);
CustomData_copy_layout(&bm->vdata, &me->vdata, mask.vmask, CD_SET_DEFAULT, me->totvert);
CustomData_copy_layout(&bm->edata, &me->edata, mask.emask, CD_SET_DEFAULT, me->totedge);
CustomData_copy_layout(&bm->ldata, &me->ldata, mask.lmask, CD_SET_DEFAULT, me->totloop);
CustomData_copy_layout(&bm->pdata, &me->pdata, mask.pmask, CD_SET_DEFAULT, me->totpoly);
}
bool need_select_vert = false;
@ -1615,10 +1613,10 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
CustomData_MeshMasks_update(&mask, cd_mask_extra);
}
mask.vmask &= ~CD_MASK_SHAPEKEY;
CustomData_merge(&bm->vdata, &me->vdata, mask.vmask, CD_CONSTRUCT, me->totvert);
CustomData_merge(&bm->edata, &me->edata, mask.emask, CD_CONSTRUCT, me->totedge);
CustomData_merge(&bm->ldata, &me->ldata, mask.lmask, CD_CONSTRUCT, me->totloop);
CustomData_merge(&bm->pdata, &me->pdata, mask.pmask, CD_CONSTRUCT, me->totpoly);
CustomData_merge_layout(&bm->vdata, &me->vdata, mask.vmask, CD_CONSTRUCT, me->totvert);
CustomData_merge_layout(&bm->edata, &me->edata, mask.emask, CD_CONSTRUCT, me->totedge);
CustomData_merge_layout(&bm->ldata, &me->ldata, mask.lmask, CD_CONSTRUCT, me->totloop);
CustomData_merge_layout(&bm->pdata, &me->pdata, mask.pmask, CD_CONSTRUCT, me->totpoly);
me->runtime->deformed_only = true;

View File

@ -26,7 +26,8 @@ void main()
view_clipping_distances(world_pos);
bool show_handle = showCurveHandles;
if ((uint(curveHandleDisplay) == CURVE_HANDLE_SELECTED) && ((data & VERT_SELECTED_BEZT_HANDLE) == 0u)) {
if ((uint(curveHandleDisplay) == CURVE_HANDLE_SELECTED) &&
((data & VERT_SELECTED_BEZT_HANDLE) == 0u)) {
show_handle = false;
}

View File

@ -766,12 +766,17 @@ class Texture : NonCopyable {
return GPU_texture_height(tx_);
}
int depth() const
{
return GPU_texture_depth(tx_);
}
int pixel_count() const
{
return GPU_texture_width(tx_) * GPU_texture_height(tx_);
}
bool depth() const
bool is_depth() const
{
return GPU_texture_has_depth_format(tx_);
}

View File

@ -250,7 +250,7 @@ static void pointcloud_extract_position_and_radius(const PointCloud &pointcloud,
using namespace blender;
const bke::AttributeAccessor attributes = pointcloud.attributes();
const VArraySpan<float3> positions = attributes.lookup<float3>("position", ATTR_DOMAIN_POINT);
const Span<float3> positions = pointcloud.positions();
const VArray<float> radii = attributes.lookup<float>("radius", ATTR_DOMAIN_POINT);
static GPUVertFormat format = {0};
if (format.attr_len == 0) {

View File

@ -741,7 +741,7 @@ void ANIM_frame_channel_y_extents(bContext *C, bAnimContext *ac)
ListBase anim_data = {NULL, NULL};
const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS |
ANIMFILTER_FCURVESONLY);
ANIMFILTER_FCURVESONLY | ANIMFILTER_CURVE_VISIBLE);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
rctf bounds = {.xmin = FLT_MAX, .xmax = -FLT_MAX, .ymin = FLT_MAX, .ymax = -FLT_MAX};

View File

@ -381,7 +381,7 @@ static int insert_into_textbuf(Object *obedit, uintptr_t c)
}
ef->textbuf[ef->pos] = c;
ef->textbufinfo[ef->pos] = cu->curinfo;
ef->textbufinfo[ef->pos].kern = 0;
ef->textbufinfo[ef->pos].kern = 0.0f;
ef->textbufinfo[ef->pos].mat_nr = obedit->actcol;
ef->pos++;
@ -1346,7 +1346,7 @@ static int change_spacing_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
int kern, delta = RNA_int_get(op->ptr, "delta");
float kern, delta = RNA_float_get(op->ptr, "delta");
int selstart, selend;
bool changed = false;
@ -1361,7 +1361,6 @@ static int change_spacing_exec(bContext *C, wmOperator *op)
for (int i = selstart; i <= selend; i++) {
kern = ef->textbufinfo[i].kern + delta;
CLAMP(kern, -20, 20);
if (ef->textbufinfo[i].kern != kern) {
ef->textbufinfo[i].kern = kern;
@ -1392,15 +1391,15 @@ void FONT_OT_change_spacing(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
RNA_def_int(ot->srna,
"delta",
1,
-20,
20,
"Delta",
"Amount to decrease or increase character spacing with",
-20,
20);
RNA_def_float(ot->srna,
"delta",
1.0,
0.0,
0.0,
"Delta",
"Amount to decrease or increase character spacing with",
0.0,
0.0);
}
/** \} */

View File

@ -57,3 +57,8 @@ void ED_curves_transverts_create(Curves *curves_id, TransVertStore *tvs)
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
ed::curves::transverts_from_curves_positions_create(curves, tvs);
}
int *ED_curves_offsets_for_write(Curves *curves_id)
{
return curves_id->geometry.wrap().offsets_for_write().data();
}

View File

@ -7,6 +7,8 @@
#pragma once
#define DIAL_RESOLUTION 48
/**
* Data for common interactions. Used in gizmo_library_utils.c functions.
*/
@ -73,6 +75,13 @@ bool gizmo_window_project_2d(bContext *C,
bool gizmo_window_project_3d(
bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset, float r_co[3]);
/* -------------------------------------------------------------------- */
/* Gizmo RNA Utils. */
struct wmGizmo *gizmo_find_from_properties(const struct IDProperty *properties,
const int spacetype,
const int regionid);
/* -------------------------------------------------------------------- */
/* Gizmo drawing */

View File

@ -15,12 +15,15 @@
#include "DNA_view3d_types.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "RNA_access.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "CLG_log.h"
@ -245,3 +248,38 @@ bool gizmo_window_project_3d(
copy_v2_v2(r_co, co);
return true;
}
/* -------------------------------------------------------------------- */
/** \name RNA Utils
* \{ */
/* Based on 'rna_GizmoProperties_find_operator'. */
wmGizmo *gizmo_find_from_properties(const struct IDProperty *properties,
const int spacetype,
const int regionid)
{
for (bScreen *screen = G_MAIN->screens.first; screen; screen = screen->id.next) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (!ELEM(spacetype, SPACE_TYPE_ANY, area->spacetype)) {
continue;
}
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
if (region->gizmo_map == NULL) {
continue;
}
if (!ELEM(regionid, RGN_TYPE_ANY, region->regiontype)) {
continue;
}
LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, WM_gizmomap_group_list(region->gizmo_map)) {
LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
if (gz->properties == properties) {
return gz;
}
}
}
}
}
}
return NULL;
}

View File

@ -48,7 +48,7 @@
#include "../gizmo_library_intern.h"
/* to use custom arrows exported to geom_arrow_gizmo.c */
//#define USE_GIZMO_CUSTOM_ARROWS
// #define USE_GIZMO_CUSTOM_ARROWS
/* Margin to add when selecting the arrow. */
#define ARROW_SELECT_THRESHOLD_PX (5)
@ -115,6 +115,29 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow,
immUniform1f("lineWidth", arrow->gizmo.line_width * U.pixelsize);
wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_LOOP);
}
else if (draw_style == ED_GIZMO_ARROW_STYLE_PLANE) {
const float scale = 0.1f;
const float verts[4][3] = {
{0, 0, 0},
{scale, 0, scale},
{0, 0, 2 * scale},
{-scale, 0, scale},
};
const float color_inner[4] = {UNPACK3(color), color[3] * 0.5f};
/* Translate to line end. */
GPU_matrix_push();
GPU_matrix_translate_3f(0.0f, 0.0f, arrow_length);
immUniform1f("lineWidth", arrow->gizmo.line_width * U.pixelsize);
wm_gizmo_vec_draw(color, verts, ARRAY_SIZE(verts), pos, GPU_PRIM_LINE_LOOP);
immUnbindProgram();
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
wm_gizmo_vec_draw(color_inner, verts, ARRAY_SIZE(verts), pos, GPU_PRIM_TRI_FAN);
GPU_matrix_pop();
}
else {
#ifdef USE_GIZMO_CUSTOM_ARROWS
wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_arrow, select, color);
@ -177,6 +200,19 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow,
if (unbind_shader) {
immUnbindProgram();
}
if (draw_options & ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN) {
const float point_size = 10 * U.pixelsize;
GPU_program_point_size(true);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immUniform1f("size", point_size);
immUniformColor4fv(color);
immBegin(GPU_PRIM_POINTS, 1);
immVertex3f(pos, 0.0f, 0.0f, 0.0f);
immEnd();
immUnbindProgram();
GPU_program_point_size(false);
}
}
static void arrow_draw_intern(ArrowGizmo3D *arrow, const bool select, const bool highlight)
@ -504,10 +540,12 @@ static void GIZMO_GT_arrow_3d(wmGizmoType *gzt)
{ED_GIZMO_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""},
{ED_GIZMO_ARROW_STYLE_BOX, "BOX", 0, "Box", ""},
{ED_GIZMO_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""},
{ED_GIZMO_ARROW_STYLE_PLANE, "PLANE", 0, "Plane", ""},
{0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem rna_enum_draw_options_items[] = {
{ED_GIZMO_ARROW_DRAW_FLAG_STEM, "STEM", 0, "Stem", ""},
{ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN, "ORIGIN", 0, "Origin", ""},
{0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem rna_enum_transform_items[] = {

View File

@ -71,7 +71,6 @@ typedef struct DialInteraction {
} DialInteraction;
#define DIAL_WIDTH 1.0f
#define DIAL_RESOLUTION 48
/* Could make option, negative to clip more (don't show when view aligned). */
#define DIAL_CLIP_BIAS 0.02

View File

@ -42,6 +42,7 @@
#include "../gizmo_library_intern.h"
#define MVAL_MAX_PX_DIST 12.0f
#define RING_2D_RESOLUTION 32
typedef struct MoveGizmo3D {
wmGizmo gizmo;
@ -116,10 +117,10 @@ static void move_geom_draw(const wmGizmo *gz,
if (draw_style == ED_GIZMO_MOVE_STYLE_RING_2D) {
if (filled) {
imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, radius, DIAL_RESOLUTION);
imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, radius, RING_2D_RESOLUTION);
}
else {
imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, radius, DIAL_RESOLUTION);
imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, radius, RING_2D_RESOLUTION);
}
}
else if (draw_style == ED_GIZMO_MOVE_STYLE_CROSS_2D) {

View File

@ -15,6 +15,8 @@
#include "BLI_math.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "BKE_context.h"
@ -42,36 +44,135 @@ static float verts_plane[4][3] = {
{-1, 1, 0},
};
typedef struct PrimitiveGizmo3D {
wmGizmo gizmo;
int draw_style;
float arc_inner_factor;
bool draw_inner;
} PrimitiveGizmo3D;
/* -------------------------------------------------------------------- */
/** \name RNA callbacks */
static void gizmo_primitive_draw_geom(const float col_inner[4],
const float col_outer[4],
const int draw_style)
static PrimitiveGizmo3D *gizmo_primitive_rna_find_operator(PointerRNA *ptr)
{
float(*verts)[3];
uint vert_count = 0;
if (draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) {
verts = verts_plane;
vert_count = ARRAY_SIZE(verts_plane);
}
if (vert_count > 0) {
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
wm_gizmo_vec_draw(col_inner, verts, vert_count, pos, GPU_PRIM_TRI_FAN);
wm_gizmo_vec_draw(col_outer, verts, vert_count, pos, GPU_PRIM_LINE_LOOP);
immUnbindProgram();
}
return (PrimitiveGizmo3D *)gizmo_find_from_properties(ptr->data, SPACE_TYPE_ANY, RGN_TYPE_ANY);
}
static void gizmo_primitive_draw_intern(wmGizmo *gz,
const bool UNUSED(select),
const bool highlight)
static int gizmo_primitive_rna__draw_style_get_fn(struct PointerRNA *ptr,
struct PropertyRNA *UNUSED(prop))
{
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
return gz_prim->draw_style;
}
static void gizmo_primitive_rna__draw_style_set_fn(struct PointerRNA *ptr,
struct PropertyRNA *UNUSED(prop),
int value)
{
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
gz_prim->draw_style = value;
}
static float gizmo_primitive_rna__arc_inner_factor_get_fn(struct PointerRNA *ptr,
struct PropertyRNA *UNUSED(prop))
{
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
return gz_prim->arc_inner_factor;
}
static void gizmo_primitive_rna__arc_inner_factor_set_fn(struct PointerRNA *ptr,
struct PropertyRNA *UNUSED(prop),
float value)
{
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
gz_prim->arc_inner_factor = value;
}
static bool gizmo_primitive_rna__draw_inner_get_fn(struct PointerRNA *ptr,
struct PropertyRNA *UNUSED(prop))
{
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
return gz_prim->draw_inner;
}
static void gizmo_primitive_rna__draw_inner_set_fn(struct PointerRNA *ptr,
struct PropertyRNA *UNUSED(prop),
bool value)
{
PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr);
gz_prim->draw_inner = value;
}
/* -------------------------------------------------------------------- */
static void gizmo_primitive_draw_geom(PrimitiveGizmo3D *gz_prim,
const float col_inner[4],
const float col_outer[4],
const int nsegments,
const bool draw_inner)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
const bool use_polyline_shader = gz_prim->gizmo.line_width > 1.0f;
if (draw_inner || !use_polyline_shader) {
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
}
if (draw_inner) {
if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) {
wm_gizmo_vec_draw(col_inner, verts_plane, ARRAY_SIZE(verts_plane), pos, GPU_PRIM_TRI_FAN);
}
else {
immUniformColor4fv(col_inner);
if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_CIRCLE) {
imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, 1.0f, nsegments);
}
else {
BLI_assert(gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_ANNULUS);
imm_draw_disk_partial_fill_3d(
pos, 0.0f, 0.0f, 0.0f, gz_prim->arc_inner_factor, 1.0f, nsegments, 0.0f, 360.0f);
}
}
}
/* Draw outline. */
if (use_polyline_shader) {
if (draw_inner) {
immUnbindProgram();
}
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
float viewport[4];
GPU_viewport_size_get_f(viewport);
immUniform2fv("viewportSize", &viewport[2]);
immUniform1f("lineWidth", gz_prim->gizmo.line_width * U.pixelsize);
}
if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) {
wm_gizmo_vec_draw(col_outer, verts_plane, ARRAY_SIZE(verts_plane), pos, GPU_PRIM_LINE_LOOP);
}
else {
immUniformColor4fv(col_outer);
if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_CIRCLE) {
imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, nsegments);
}
else {
imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, gz_prim->arc_inner_factor, nsegments);
imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, nsegments);
}
}
immUnbindProgram();
}
static void gizmo_primitive_draw_intern(wmGizmo *gz, const bool select, const bool highlight)
{
PrimitiveGizmo3D *gz_prim = (PrimitiveGizmo3D *)gz;
float color_inner[4], color_outer[4];
float matrix_final[4][4];
const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
gizmo_color_get(gz, highlight, color_outer);
copy_v4_v4(color_inner, color_outer);
@ -79,12 +180,15 @@ static void gizmo_primitive_draw_intern(wmGizmo *gz,
WM_gizmo_calc_matrix_final(gz, matrix_final);
GPU_blend(GPU_BLEND_ALPHA);
GPU_matrix_push();
GPU_matrix_mul(matrix_final);
GPU_blend(GPU_BLEND_ALPHA);
gizmo_primitive_draw_geom(color_inner, color_outer, draw_style);
GPU_blend(GPU_BLEND_NONE);
gizmo_primitive_draw_geom(gz_prim,
color_inner,
color_outer,
select ? 24 : DIAL_RESOLUTION,
gz_prim->draw_inner || select);
GPU_matrix_pop();
@ -98,12 +202,12 @@ static void gizmo_primitive_draw_intern(wmGizmo *gz,
GPU_matrix_push();
GPU_matrix_mul(inter->init_matrix_final);
GPU_blend(GPU_BLEND_ALPHA);
gizmo_primitive_draw_geom(color_inner, color_outer, draw_style);
GPU_blend(GPU_BLEND_NONE);
gizmo_primitive_draw_geom(
gz_prim, color_inner, color_outer, DIAL_RESOLUTION, gz_prim->draw_inner);
GPU_matrix_pop();
}
GPU_blend(GPU_BLEND_NONE);
}
static void gizmo_primitive_draw_select(const bContext *UNUSED(C), wmGizmo *gz, int select_id)
@ -120,6 +224,12 @@ static void gizmo_primitive_draw(const bContext *UNUSED(C), wmGizmo *gz)
static void gizmo_primitive_setup(wmGizmo *gz)
{
gz->flag |= WM_GIZMO_DRAW_MODAL;
/* Default Values. */
PrimitiveGizmo3D *gz_prim = (PrimitiveGizmo3D *)gz;
gz_prim->draw_style = ED_GIZMO_PRIMITIVE_STYLE_PLANE;
gz_prim->arc_inner_factor = true;
gz_prim->draw_inner = true;
}
static int gizmo_primitive_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *UNUSED(event))
@ -148,18 +258,35 @@ static void GIZMO_GT_primitive_3d(wmGizmoType *gzt)
gzt->setup = gizmo_primitive_setup;
gzt->invoke = gizmo_primitive_invoke;
gzt->struct_size = sizeof(wmGizmo);
gzt->struct_size = sizeof(PrimitiveGizmo3D);
static EnumPropertyItem rna_enum_draw_style[] = {
{ED_GIZMO_PRIMITIVE_STYLE_PLANE, "PLANE", 0, "Plane", ""},
{ED_GIZMO_PRIMITIVE_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
{ED_GIZMO_PRIMITIVE_STYLE_ANNULUS, "ANNULUS", 0, "Annulus", ""},
{0, NULL, 0, NULL, NULL},
};
RNA_def_enum(gzt->srna,
"draw_style",
rna_enum_draw_style,
ED_GIZMO_PRIMITIVE_STYLE_PLANE,
"Draw Style",
"");
PropertyRNA *prop;
prop = RNA_def_enum(gzt->srna,
"draw_style",
rna_enum_draw_style,
ED_GIZMO_PRIMITIVE_STYLE_PLANE,
"Draw Style",
"");
RNA_def_property_enum_funcs_runtime(
prop, gizmo_primitive_rna__draw_style_get_fn, gizmo_primitive_rna__draw_style_set_fn, NULL);
prop = RNA_def_float_factor(
gzt->srna, "arc_inner_factor", 0.0f, 0.0f, FLT_MAX, "Arc Inner Factor", "", 0.0f, 1.0f);
RNA_def_property_float_funcs_runtime(prop,
gizmo_primitive_rna__arc_inner_factor_get_fn,
gizmo_primitive_rna__arc_inner_factor_set_fn,
NULL);
prop = RNA_def_boolean(gzt->srna, "draw_inner", true, "Draw Inner", "");
RNA_def_property_boolean_funcs_runtime(
prop, gizmo_primitive_rna__draw_inner_get_fn, gizmo_primitive_rna__draw_inner_set_fn);
}
void ED_gizmotypes_primitive_3d(void)

View File

@ -123,30 +123,9 @@ void ED_gizmotypes_snap_3d_data_get(const struct bContext *C,
/** \name RNA callbacks
* \{ */
/* Based on 'rna_GizmoProperties_find_operator'. */
static SnapGizmo3D *gizmo_snap_rna_find_operator(PointerRNA *ptr)
{
IDProperty *properties = ptr->data;
for (bScreen *screen = G_MAIN->screens.first; screen; screen = screen->id.next) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (area->spacetype != SPACE_VIEW3D) {
continue;
}
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
if (region->regiontype == RGN_TYPE_WINDOW && region->gizmo_map) {
wmGizmoMap *gzmap = region->gizmo_map;
LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, WM_gizmomap_group_list(gzmap)) {
LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
if (gz->properties == properties) {
return (SnapGizmo3D *)gz;
}
}
}
}
}
}
}
return NULL;
return (SnapGizmo3D *)gizmo_find_from_properties(ptr->data, SPACE_VIEW3D, RGN_TYPE_WINDOW);
}
static V3DSnapCursorState *gizmo_snap_state_from_rna_get(struct PointerRNA *ptr)

View File

@ -38,6 +38,11 @@ float (*ED_curves_point_normals_array_create(const struct Curves *curves_id))[3]
*/
void ED_curves_transverts_create(struct Curves *curves_id, struct TransVertStore *tvs);
/**
* C wrapper for #CurvesGeometry::offsets_for_write().
*/
int *ED_curves_offsets_for_write(struct Curves *curves_id);
/** \} */
#ifdef __cplusplus

View File

@ -64,6 +64,7 @@ enum {
ED_GIZMO_ARROW_STYLE_CROSS = 1,
ED_GIZMO_ARROW_STYLE_BOX = 2,
ED_GIZMO_ARROW_STYLE_CONE = 3,
ED_GIZMO_ARROW_STYLE_PLANE = 4,
};
/* transform */
@ -78,6 +79,7 @@ enum {
enum {
/* Show arrow stem. */
ED_GIZMO_ARROW_DRAW_FLAG_STEM = (1 << 0),
ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN = (1 << 1),
};
/**
@ -233,6 +235,8 @@ enum {
enum {
ED_GIZMO_PRIMITIVE_STYLE_PLANE = 0,
ED_GIZMO_PRIMITIVE_STYLE_CIRCLE,
ED_GIZMO_PRIMITIVE_STYLE_ANNULUS,
};
/* -------------------------------------------------------------------- */

View File

@ -340,7 +340,6 @@ struct FaceIsland {
struct FaceIsland *prev;
struct BMFace **faces;
int faces_len;
rctf bounds_rect;
/**
* \note While this is duplicate information,
* it allows islands from multiple meshes to be stored in the same list.

View File

@ -116,18 +116,18 @@ static void ui_popup_block_position(wmWindow *window,
const int center_x = (block->direction & UI_DIR_CENTER_X) ? size_x / 2 : 0;
const int center_y = (block->direction & UI_DIR_CENTER_Y) ? size_y / 2 : 0;
const int win_x = WM_window_pixels_x(window);
const int win_y = WM_window_pixels_y(window);
/* Take into account maximum size so we don't have to flip on refresh. */
const float max_size_x = max_ff(size_x, handle->max_size_x);
const float max_size_y = max_ff(size_y, handle->max_size_y);
short dir1 = 0, dir2 = 0;
if (!handle->refresh) {
bool left = false, right = false, top = false, down = false;
const int win_x = WM_window_pixels_x(window);
const int win_y = WM_window_pixels_y(window);
/* Take into account maximum size so we don't have to flip on refresh. */
const float max_size_x = max_ff(size_x, handle->max_size_x);
const float max_size_y = max_ff(size_y, handle->max_size_y);
/* check if there's space at all */
if (butrct.xmin - max_size_x + center_x > 0.0f) {
left = true;
@ -237,6 +237,15 @@ static void ui_popup_block_position(wmWindow *window,
}
else if (dir1 == UI_DIR_UP) {
offset_y = (butrct.ymax - block->rect.ymin) - offset_overlap;
if (but->type == UI_BTYPE_COLOR && block->rect.ymax + offset_y > win_y - UI_POPUP_MENU_TOP) {
/* Shift this down, aligning the top edge close to the window top. */
offset_y = win_y - block->rect.ymax - UI_POPUP_MENU_TOP;
/* All four corners should be rounded since this no longer button-aligned. */
block->direction = UI_DIR_CENTER_Y;
dir1 = UI_DIR_CENTER_Y;
}
if (dir2 == UI_DIR_RIGHT) {
offset_x = butrct.xmax - block->rect.xmax + center_x;
}
@ -251,6 +260,15 @@ static void ui_popup_block_position(wmWindow *window,
}
else if (dir1 == UI_DIR_DOWN) {
offset_y = (butrct.ymin - block->rect.ymax) + offset_overlap;
if (but->type == UI_BTYPE_COLOR && block->rect.ymin + offset_y < UI_SCREEN_MARGIN) {
/* Shift this up, aligning the bottom edge close to the window bottom. */
offset_y = -block->rect.ymin + UI_SCREEN_MARGIN;
/* All four corners should be rounded since this no longer button-aligned. */
block->direction = UI_DIR_CENTER_Y;
dir1 = UI_DIR_CENTER_Y;
}
if (dir2 == UI_DIR_RIGHT) {
offset_x = butrct.xmax - block->rect.xmax + center_x;
}

View File

@ -16,6 +16,7 @@
#include "DNA_scene_types.h"
#include "BLI_array_utils.h"
#include "BLI_implicit_sharing.hh"
#include "BLI_listbase.h"
#include "BLI_task.hh"
@ -273,8 +274,18 @@ static void um_arraystore_cd_compact(CustomData *cdata,
}
if (layer->data) {
if (layer->sharing_info) {
/* This assumes that the layer is not shared, which it is not here because it has just
* been created in #BM_mesh_bm_to_me. The situation is a bit tricky here, because the
* layer data may be freed partially below for e.g. vertex groups. A potentially better
* solution might be to not pass "dynamic" layers (see `layer_type_is_dynamic`) to the
* array store at all. */
BLI_assert(layer->sharing_info->is_mutable());
MEM_delete(layer->sharing_info);
}
MEM_freeN(layer->data);
layer->data = nullptr;
layer->sharing_info = nullptr;
}
}

View File

@ -278,7 +278,8 @@ int ED_mesh_uv_add(
CD_PROP_FLOAT2,
MEM_dupallocN(CustomData_get_layer(&me->ldata, CD_PROP_FLOAT2)),
me->totloop,
unique_name);
unique_name,
nullptr);
is_init = true;
}
@ -1143,7 +1144,7 @@ static void mesh_add_verts(Mesh *mesh, int len)
int totvert = mesh->totvert + len;
CustomData vdata;
CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
CustomData_copy_layout(&mesh->vdata, &vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
if (!CustomData_get_layer_named(&vdata, CD_PROP_FLOAT3, "position")) {
@ -1177,7 +1178,7 @@ static void mesh_add_edges(Mesh *mesh, int len)
totedge = mesh->totedge + len;
/* Update custom-data. */
CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
CustomData_copy_layout(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
if (!CustomData_has_layer(&edata, CD_MEDGE)) {
@ -1210,7 +1211,7 @@ static void mesh_add_loops(Mesh *mesh, int len)
totloop = mesh->totloop + len; /* new face count */
/* update customdata */
CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
CustomData_copy_layout(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop);
if (!CustomData_get_layer_named(&ldata, CD_PROP_INT32, ".corner_vert")) {
@ -1247,7 +1248,7 @@ static void mesh_add_polys(Mesh *mesh, int len)
totpoly = mesh->totpoly + len; /* new face count */
/* update customdata */
CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
CustomData_copy_layout(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly);
mesh->poly_offset_indices = static_cast<int *>(

View File

@ -105,7 +105,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
if (me->totvert) {
/* standard data */
CustomData_merge(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
CustomData_merge_layout(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert);
/* vertex groups */
@ -205,7 +205,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
}
if (me->totedge) {
CustomData_merge(&me->edata, edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
CustomData_merge_layout(&me->edata, edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge);
for (a = 0; a < me->totedge; a++, edge++) {
@ -226,7 +226,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
}
}
CustomData_merge(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
CustomData_merge_layout(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop);
for (a = 0; a < me->totloop; a++) {
@ -250,7 +250,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
}
}
CustomData_merge(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
CustomData_merge_layout(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly);
/* Apply matmap. In case we don't have material indices yet, create them if more than one
@ -417,14 +417,6 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* remove tessface to ensure we don't hold references to invalid faces */
BKE_mesh_tessface_clear(me);
/* Clear any run-time data.
* Even though this mesh wont typically have run-time data, the Python API can for e.g.
* create loop-triangle cache here, which is confusing when left in the mesh, see: #90798. */
BKE_mesh_runtime_clear_geometry(me);
/* new material indices and material array */
if (totmat) {
matar = static_cast<Material **>(MEM_callocN(sizeof(*matar) * totmat, __func__));
@ -683,11 +675,8 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
/* return to mesh we're merging to */
me = static_cast<Mesh *>(ob->data);
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->ldata, me->totloop);
CustomData_free(&me->pdata, me->totpoly);
MEM_SAFE_FREE(me->poly_offset_indices);
BKE_mesh_clear_geometry(me);
me->poly_offset_indices = poly_offsets;
me->totvert = totvert;

View File

@ -731,7 +731,7 @@ static void add_shapekey_layers(Mesh &mesh_dest, const Mesh &mesh_src)
}
CustomData_add_layer_named_with_data(
&mesh_dest.vdata, CD_SHAPEKEY, array, mesh_dest.totvert, kb->name);
&mesh_dest.vdata, CD_SHAPEKEY, array, mesh_dest.totvert, kb->name, nullptr);
const int ci = CustomData_get_layer_index_n(&mesh_dest.vdata, CD_SHAPEKEY, i);
mesh_dest.vdata.layers[ci].uid = kb->uid;

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