UI Code Quality: Rename UI_ACTIVE button flag to UI_HOVER #114113

Merged
Julian Eisel merged 5 commits from JulianEisel/blender:temp-rename-uibut-active-flag into main 2023-10-25 18:36:38 +02:00
31 changed files with 1706 additions and 1264 deletions
Showing only changes of commit 7f33f71186 - Show all commits

View File

@ -37,6 +37,16 @@ else()
PREFIX ${BUILD_DIR}/ssl
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/ssl/src/external_ssl/ && ${SSL_CONFIGURE_COMMAND} --prefix=${LIBDIR}/ssl
--openssldir=${LIBDIR}/ssl
# Without this: Python will use the build directories:
# To see these values in use, check the output of `ssl.get_default_verify_paths()`.
# This definition causes the following values to be set:
# - `capath='/etc/ssl/certs'`
# - `openssl_cafile='/etc/ssl/cert.pem'`
# - `openssl_capath='/etc/ssl/certs'`
# Note that the output from the command `openssl info -configdir` on the users system
# would be ideal but this is more involved.
# See #111132 & https://github.com/openssl/openssl/issues/20185 for details.
-DOPENSSLDIR=\\"/etc/ssl\\"
no-shared
no-idea no-mdc2 no-rc5 no-zlib no-ssl3 enable-unit-test no-ssl3-method enable-rfc3779 enable-cms
--config=${CMAKE_CURRENT_SOURCE_DIR}/cmake/ssl.conf

View File

@ -26,6 +26,7 @@ class MetalDevice : public Device {
id<MTLLibrary> mtlLibrary[PSO_NUM] = {nil};
id<MTLArgumentEncoder> mtlBufferKernelParamsEncoder =
nil; /* encoder used for fetching device pointers from MTLBuffers */
id<MTLCommandQueue> mtlComputeCommandQueue = nil;
id<MTLCommandQueue> mtlGeneralCommandQueue = nil;
id<MTLArgumentEncoder> mtlAncillaryArgEncoder =
nil; /* encoder used for fetching device pointers from MTLBuffers */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6377,7 +6377,9 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co
/* NOTE(@ideasman42): it's important to write the XKB state back to #GWL_KeyboardDepressedState
* otherwise changes to modifiers in the future wont generate events.
* This can cause modifiers to be stuck when switching between windows in GNOME because
* window activation is handled before the keyboard enter callback runs, see: #107314. */
* window activation is handled before the keyboard enter callback runs, see: #107314.
* Now resolved upstream, keep this for GNOME 45 and older releases & misbehaving compositors
* as the workaround doesn't have significant down-sides. */
int16_t &depressed_l = seat->key_depressed.mods[GHOST_KEY_MODIFIER_TO_INDEX(mod_info.key_l)];
int16_t &depressed_r = seat->key_depressed.mods[GHOST_KEY_MODIFIER_TO_INDEX(mod_info.key_r)];
bool val_l = depressed_l > 0;

View File

@ -73,6 +73,8 @@ struct WGL_LibDecor_Window {
/** The window has been configured (see #xdg_surface_ack_configure). */
bool initial_configure_seen = false;
/** The window state has been configured. */
bool initial_state_seen = false;
};
static void gwl_libdecor_window_destroy(WGL_LibDecor_Window *decor)
@ -1274,7 +1276,14 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
* #wp_fractional_scale_v1_listener::preferred_scale provides fractional scaling values. */
decor.scale_fractional_from_output = 0;
decor.initial_configure_seen = true;
if (decor.initial_configure_seen == false) {
decor.initial_configure_seen = true;
}
else {
if (decor.initial_state_seen == false) {
decor.initial_state_seen = true;
}
}
}
}
@ -1614,7 +1623,21 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
}
xdg_toplevel *toplevel = libdecor_frame_get_xdg_toplevel(decor.frame);
gwl_window_state_set_for_xdg(toplevel, state, GHOST_kWindowStateNormal);
gwl_window_state_set_for_xdg(toplevel, state, gwl_window_state_get(window_));
/* Needed for maximize to use the size of the maximized frame instead of the size
* from `width` & `height`, see #113961 (follow up comments). */
int roundtrip_count = 0;
while (!decor.initial_state_seen) {
/* Use round-trip so as not to block in the case setting
* the state is ignored by the compositor. */
wl_display_roundtrip(system_->wl_display_get());
/* Avoid waiting continuously if the requested state is ignored
* (2x round-trips should be enough). */
if (++roundtrip_count >= 2) {
break;
}
}
}
else
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */

View File

@ -454,12 +454,9 @@ class NODE_PT_geometry_node_tool_object_types(Panel):
col = layout.column()
col.active = group.is_tool
for prop, name, icon in types:
row = col.row()
row_checkbox = row.row()
row_checkbox.prop(group, prop, text="")
row_label = row.row()
row_label.label(text=name, icon=icon)
row_label.active = getattr(group, prop)
row = col.row(align=True)
row.label(text=name, icon=icon)
row.prop(group, prop, text="")
class NODE_PT_geometry_node_tool_mode(Panel):
@ -482,12 +479,9 @@ class NODE_PT_geometry_node_tool_mode(Panel):
col = layout.column()
col.active = group.is_tool
for prop, name, icon in modes:
row = col.row()
row_checkbox = row.row()
row_checkbox.prop(group, prop, text="")
row_label = row.row()
row_label.label(text=name, icon=icon)
row_label.active = getattr(group, prop)
row = col.row(align=True)
row.label(text=name, icon=icon)
row.prop(group, prop, text="")
class NODE_PT_node_color_presets(PresetPanel, Panel):

View File

@ -3520,7 +3520,7 @@ class VIEW3D_MT_paint_weight(Menu):
class VIEW3D_MT_sculpt(Menu):
bl_label = "Sculpt"
def draw(self, _context):
def draw(self, context):
layout = self.layout
layout.operator("transform.translate")
@ -3613,6 +3613,11 @@ class VIEW3D_MT_sculpt(Menu):
# Rebuild BVH
layout.operator("sculpt.optimize")
layout.operator(
"sculpt.dynamic_topology_toggle",
icon='CHECKBOX_HLT' if context.sculpt_object.use_dynamic_topology_sculpting else 'CHECKBOX_DEHLT',
)
layout.separator()
layout.operator("object.transfer_mode", text="Transfer Sculpt Mode")

View File

@ -79,10 +79,15 @@ struct CustomDataLayer *BKE_id_attribute_find(const struct ID *id,
eCustomDataType type,
eAttrDomain domain);
struct CustomDataLayer *BKE_id_attribute_search(struct ID *id,
const char *name,
eCustomDataMask type,
eAttrDomainMask domain_mask);
const struct CustomDataLayer *BKE_id_attribute_search(const struct ID *id,
const char *name,
eCustomDataMask type,
eAttrDomainMask domain_mask);
struct CustomDataLayer *BKE_id_attribute_search_for_write(struct ID *id,
const char *name,
eCustomDataMask type,
eAttrDomainMask domain_mask);
eAttrDomain BKE_id_attribute_domain(const struct ID *id, const struct CustomDataLayer *layer);
int BKE_id_attribute_data_length(struct ID *id, struct CustomDataLayer *layer);

View File

@ -158,7 +158,7 @@ static bool bke_id_attribute_rename_if_exists(ID *id,
const char *new_name,
ReportList *reports)
{
CustomDataLayer *layer = BKE_id_attribute_search(
CustomDataLayer *layer = BKE_id_attribute_search_for_write(
id, old_name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
if (layer == nullptr) {
return false;
@ -194,7 +194,7 @@ bool BKE_id_attribute_rename(ID *id,
}
}
CustomDataLayer *layer = BKE_id_attribute_search(
CustomDataLayer *layer = BKE_id_attribute_search_for_write(
id, old_name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
if (layer == nullptr) {
BKE_report(reports, RPT_ERROR, "Attribute is not part of this geometry");
@ -383,7 +383,7 @@ CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList
BKE_uv_map_pin_name_get(uniquename, buffer_dst));
}
return BKE_id_attribute_search(id, uniquename, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
return BKE_id_attribute_search_for_write(id, uniquename, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
}
static int color_name_to_index(ID *id, const char *name)
@ -540,10 +540,10 @@ CustomDataLayer *BKE_id_attribute_find(const ID *id,
return nullptr;
}
CustomDataLayer *BKE_id_attribute_search(ID *id,
const char *name,
const eCustomDataMask type_mask,
const eAttrDomainMask domain_mask)
const CustomDataLayer *BKE_id_attribute_search(const ID *id,
const char *name,
const eCustomDataMask type_mask,
const eAttrDomainMask domain_mask)
{
if (!name) {
return nullptr;
@ -574,6 +574,28 @@ CustomDataLayer *BKE_id_attribute_search(ID *id,
return nullptr;
}
CustomDataLayer *BKE_id_attribute_search_for_write(ID *id,
const char *name,
const eCustomDataMask type_mask,
const eAttrDomainMask domain_mask)
{
/* Reuse the implementation of the const version.
* Implicit sharing for the layer's data is handled below. */
CustomDataLayer *layer = const_cast<CustomDataLayer *>(
BKE_id_attribute_search(id, name, type_mask, domain_mask));
if (!layer) {
return nullptr;
}
DomainInfo info[ATTR_DOMAIN_NUM];
get_domains(id, info);
const eAttrDomain domain = BKE_id_attribute_domain(id, layer);
CustomData_ensure_data_is_mutable(layer, info[domain].length);
return layer;
}
int BKE_id_attributes_length(const ID *id, eAttrDomainMask domain_mask, eCustomDataMask mask)
{
DomainInfo info[ATTR_DOMAIN_NUM];

View File

@ -677,7 +677,9 @@ GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object
const GreasePencil &grease_pencil_orig = *static_cast<const GreasePencil *>(ob_orig.data);
const int eval_frame = grease_pencil.runtime->eval_frame;
const int drawing_index = grease_pencil_orig.layers()[layer_index]->drawing_index_at(eval_frame);
const Span<const bke::greasepencil::Layer *> layers_orig = grease_pencil_orig.layers();
BLI_assert(layer_index >= 0 && layer_index < layers_orig.size());
const int drawing_index = layers_orig[layer_index]->drawing_index_at(eval_frame);
if (drawing_index == -1) {
return {};
}
@ -707,11 +709,12 @@ GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object
if (edit_hints != nullptr && &edit_hints->grease_pencil_id_orig == &grease_pencil_orig &&
edit_hints->drawing_hints.has_value())
{
BLI_assert(edit_hints->drawing_hints->size() == grease_pencil_orig.layers().size());
BLI_assert(edit_hints->drawing_hints->size() == layers_orig.size());
const GreasePencilDrawingEditHints &drawing_hints =
edit_hints->drawing_hints.value()[layer_index];
if (drawing_hints.positions.has_value()) {
deformation.positions = *drawing_hints.positions;
return deformation;
}
}
@ -721,18 +724,21 @@ GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object
{
if (const GreasePencil *grease_pencil_eval = grease_pencil_component_eval->get()) {
Span<const bke::greasepencil::Layer *> layers_eval = grease_pencil_eval->layers();
const bke::greasepencil::Layer *layer_eval = layers_eval[layer_index];
const int drawing_index_eval = layer_eval->drawing_index_at(eval_frame);
if (drawing_index_eval != -1) {
const GreasePencilDrawingBase *drawing_base_eval = grease_pencil_eval->drawing(
drawing_index_eval);
if (drawing_base_eval->type != GP_DRAWING) {
return {};
}
const bke::greasepencil::Drawing &drawing_eval =
reinterpret_cast<const GreasePencilDrawing *>(drawing_base_eval)->wrap();
if (drawing_eval.strokes().points_num() == drawing_orig.strokes().points_num()) {
deformation.positions = drawing_eval.strokes().positions();
if (layers_eval.size() != layers_orig.size()) {
const bke::greasepencil::Layer *layer_eval = layers_eval[layer_index];
const int drawing_index_eval = layer_eval->drawing_index_at(eval_frame);
if (drawing_index_eval != -1) {
const GreasePencilDrawingBase *drawing_base_eval = grease_pencil_eval->drawing(
drawing_index_eval);
if (drawing_base_eval->type != GP_DRAWING) {
return deformation;
}
const bke::greasepencil::Drawing &drawing_eval =
reinterpret_cast<const GreasePencilDrawing *>(drawing_base_eval)->wrap();
if (drawing_eval.strokes().points_num() == drawing_orig.strokes().points_num()) {
deformation.positions = drawing_eval.strokes().positions();
return deformation;
}
}
}
}

View File

@ -22,6 +22,14 @@
namespace blender::bke {
static int segments_num_no_duplicate_edge(const int points_num, const bool cyclic)
{
if (points_num <= 2) {
return curves::segments_num(points_num, false);
}
return curves::segments_num(points_num, cyclic);
}
static void fill_mesh_topology(const int vert_offset,
const int edge_offset,
const int face_offset,
@ -36,7 +44,7 @@ static void fill_mesh_topology(const int vert_offset,
MutableSpan<int> corner_edges,
MutableSpan<int> face_offsets)
{
const int main_segment_num = curves::segments_num(main_point_num, main_cyclic);
const int main_segment_num = segments_num_no_duplicate_edge(main_point_num, main_cyclic);
const int profile_segment_num = curves::segments_num(profile_point_num, profile_cyclic);
if (profile_point_num == 1) {
@ -46,7 +54,7 @@ static void fill_mesh_topology(const int vert_offset,
edge[1] = vert_offset + i + 1;
}
if (main_cyclic && main_segment_num > 1) {
if (main_cyclic && main_segment_num > 2) {
int2 &edge = edges[edge_offset + main_segment_num - 1];
edge[0] = vert_offset + main_point_num - 1;
edge[1] = vert_offset;
@ -268,7 +276,7 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool
for (const int i_main : main_offsets.index_range()) {
const bool main_cyclic = info.main_cyclic[i_main];
const int main_point_num = main_offsets[i_main].size();
const int main_segment_num = curves::segments_num(main_point_num, main_cyclic);
const int main_segment_num = segments_num_no_duplicate_edge(main_point_num, main_cyclic);
for (const int i_profile : profile_offsets.index_range()) {
result.vert[mesh_index] = vert_offset;
result.edge[mesh_index] = edge_offset;

View File

@ -1199,7 +1199,9 @@ void BKE_grease_pencil_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
grease_pencil_evaluate_modifiers(depsgraph, scene, object, geometry_set);
if (!geometry_set.has_grease_pencil()) {
geometry_set.replace_grease_pencil(BKE_grease_pencil_new_nomain());
GreasePencil *empty_grease_pencil = BKE_grease_pencil_new_nomain();
empty_grease_pencil->runtime->eval_frame = int(DEG_get_ctime(depsgraph));
geometry_set.replace_grease_pencil(empty_grease_pencil);
}
/* For now the evaluated data is not const. We could use #get_grease_pencil_for_write, but that

View File

@ -805,17 +805,15 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
pbvh->looptri_faces = mesh->looptri_faces();
if (!pbvh->deformed) {
/* Deformed positions not matching the original mesh are owned directly by the PBVH, and are
/* Deformed data not matching the original mesh are owned directly by the PBVH, and are
* set separately by #BKE_pbvh_vert_coords_apply. */
pbvh->vert_positions = mesh->vert_positions_for_write();
pbvh->vert_normals = mesh->vert_normals();
pbvh->face_normals = mesh->face_normals();
}
BKE_pbvh_update_hide_attributes_from_mesh(pbvh);
/* Make sure cached normals start out calculated. */
pbvh->vert_normals = mesh->vert_normals();
pbvh->face_normals = mesh->face_normals();
pbvh->vert_data = &mesh->vert_data;
pbvh->loop_data = &mesh->loop_data;
pbvh->face_data = &mesh->face_data;
@ -1276,6 +1274,38 @@ static bool update_search(PBVHNode *node, const int flag)
return true;
}
static void normals_calc_faces(const Span<float3> positions,
const blender::OffsetIndices<int> faces,
const Span<int> corner_verts,
const Span<int> mask,
MutableSpan<float3> face_normals)
{
using namespace blender;
using namespace blender::bke;
threading::parallel_for(mask.index_range(), 512, [&](const IndexRange range) {
for (const int i : mask.slice(range)) {
face_normals[i] = mesh::face_normal_calc(positions, corner_verts.slice(faces[i]));
}
});
}
static void normals_calc_verts_simple(const blender::GroupedSpan<int> vert_to_face_map,
const Span<float3> face_normals,
const Span<int> mask,
MutableSpan<float3> vert_normals)
{
using namespace blender;
threading::parallel_for(mask.index_range(), 1024, [&](const IndexRange range) {
for (const int vert : mask.slice(range)) {
float3 normal(0.0f);
for (const int face : vert_to_face_map[vert]) {
normal += face_normals[face];
}
vert_normals[vert] = math::normalize(normal);
}
});
}
static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes, Mesh &mesh)
{
using namespace blender;
@ -1302,13 +1332,17 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes, Mesh &
VectorSet<int> verts_to_update;
threading::parallel_invoke(
[&]() {
mesh.runtime->face_normals_cache.update([&](Vector<float3> &r_data) {
threading::parallel_for(faces_to_update.index_range(), 512, [&](const IndexRange range) {
for (const int i : faces_to_update.as_span().slice(range)) {
r_data[i] = mesh::face_normal_calc(positions, corner_verts.slice(faces[i]));
}
if (pbvh->deformed) {
normals_calc_faces(
positions, faces, corner_verts, faces_to_update, pbvh->face_normals_deformed);
}
else {
mesh.runtime->face_normals_cache.update([&](Vector<float3> &r_data) {
normals_calc_faces(positions, faces, corner_verts, faces_to_update, r_data);
});
});
/* #SharedCache::update() reallocates cached vectors if they were shared initially. */
pbvh->face_normals = mesh.runtime->face_normals_cache.data();
}
},
[&]() {
/* Update all normals connected to affected faces, even if not explicitly tagged. */
@ -1325,22 +1359,16 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes, Mesh &
}
});
const Span<float3> face_normals = mesh.face_normals();
mesh.runtime->vert_normals_cache.update([&](Vector<float3> &r_data) {
threading::parallel_for(verts_to_update.index_range(), 1024, [&](const IndexRange range) {
for (const int vert : verts_to_update.as_span().slice(range)) {
float3 normal(0.0f);
for (const int face : pbvh->pmap[vert]) {
normal += face_normals[face];
}
r_data[vert] = math::normalize(normal);
}
if (pbvh->deformed) {
normals_calc_verts_simple(
pbvh->pmap, pbvh->face_normals, verts_to_update, pbvh->vert_normals_deformed);
}
else {
mesh.runtime->vert_normals_cache.update([&](Vector<float3> &r_data) {
normals_calc_verts_simple(pbvh->pmap, pbvh->face_normals, verts_to_update, r_data);
});
});
/* #SharedCache::update() reallocates the cached vectors if they were shared initially. */
pbvh->face_normals = mesh.runtime->face_normals_cache.data();
pbvh->vert_normals = mesh.runtime->vert_normals_cache.data();
pbvh->vert_normals = mesh.runtime->vert_normals_cache.data();
}
}
static void node_update_mask_redraw(PBVH &pbvh, PBVHNode &node)
@ -1402,7 +1430,7 @@ static void pbvh_update_BB_redraw(PBVH *pbvh, Span<PBVHNode *> nodes, int flag)
bool BKE_pbvh_get_color_layer(Mesh *me, CustomDataLayer **r_layer, eAttrDomain *r_domain)
{
*r_layer = BKE_id_attribute_search(
*r_layer = BKE_id_attribute_search_for_write(
&me->id, me->active_color_attribute, CD_MASK_COLOR_ALL, ATTR_DOMAIN_MASK_COLOR);
*r_domain = *r_layer ? BKE_id_attribute_domain(&me->id, *r_layer) : ATTR_DOMAIN_POINT;
return *r_layer != nullptr;
@ -2967,14 +2995,21 @@ void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const float (*vertCos)[3], const int
if (!pbvh->deformed) {
if (!pbvh->vert_positions.is_empty()) {
/* if pbvh is not already deformed, verts/faces points to the */
/* original data and applying new coords to this arrays would lead to */
/* unneeded deformation -- duplicate verts/faces to avoid this */
pbvh->vert_positions_deformed = blender::Array<float3>(pbvh->vert_positions.as_span());
/* When the PBVH is deformed, it creates a separate vertex position array that it owns
* directly. Conceptually these copies often aren't and often adds extra indirection, but:
* - Sculpting shape keys, the deformations are flushed back to the keys as a separate step.
* - Sculpting on a deformed mesh, deformations are also flushed to original positions
* separately.
* - The PBVH currently always assumes we want to change positions, and has no way to avoid
* calculating normals if it's only used for painting, for example. */
pbvh->vert_positions_deformed = pbvh->vert_positions.as_span();
pbvh->vert_positions = pbvh->vert_positions_deformed;
/* No need to dupalloc pbvh->looptri, this one is 'totally owned' by pbvh,
* it's never some mesh data. */
pbvh->vert_normals_deformed = pbvh->vert_normals;
pbvh->vert_normals = pbvh->vert_normals_deformed;
pbvh->face_normals_deformed = pbvh->face_normals;
pbvh->face_normals = pbvh->face_normals_deformed;
pbvh->deformed = true;
}

View File

@ -154,13 +154,19 @@ struct PBVH {
/* Mesh data */
Mesh *mesh;
/** Local array used when not sculpting base mesh positions directly. */
blender::Array<blender::float3> vert_positions_deformed;
/** Local array used when not sculpting base mesh positions directly. */
blender::Array<blender::float3> vert_normals_deformed;
/** Local array used when not sculpting base mesh positions directly. */
blender::Array<blender::float3> face_normals_deformed;
blender::MutableSpan<blender::float3> vert_positions;
blender::Span<blender::float3> vert_normals;
blender::Span<blender::float3> face_normals;
bool *hide_vert;
blender::MutableSpan<blender::float3> vert_positions;
/** Local vertex positions owned by the PVBH when not sculpting base mesh positions directly. */
blender::Array<blender::float3> vert_positions_deformed;
blender::OffsetIndices<int> faces;
bool *hide_vert;
bool *hide_poly;
/** Only valid for polygon meshes. */
blender::Span<int> corner_verts;

View File

@ -77,11 +77,10 @@ void transform(Context &context,
}
else {
input.pass_through(output);
const float3x3 translation_matrix = math::from_location<float3x3>(translation);
output.transform(translation_matrix);
}
/* Translation transformations are delayed and are only stored in the result. */
const float3x3 translation_matrix = math::from_location<float3x3>(translation);
output.transform(translation_matrix);
output.get_realization_options().interpolation = interpolation;
}

View File

@ -747,12 +747,15 @@ void film_process_data(ivec2 texel_film, out vec4 out_color, out float out_depth
ao_accum);
film_sample_accum_mist(src, mist_accum);
}
/* Monochrome render passes that have colored outputs. Set alpha to 1. */
vec4 shadow_accum_color = vec4(vec3(shadow_accum), weight_accum);
vec4 ao_accum_color = vec4(vec3(ao_accum), weight_accum);
film_store_color(dst, uniform_buf.film.diffuse_color_id, diffuse_color_accum, out_color);
film_store_color(dst, uniform_buf.film.specular_color_id, specular_color_accum, out_color);
film_store_color(dst, uniform_buf.film.environment_id, environment_accum, out_color);
film_store_color(dst, uniform_buf.film.shadow_id, vec4(vec3(shadow_accum), 1.0), out_color);
film_store_color(
dst, uniform_buf.film.ambient_occlusion_id, vec4(vec3(ao_accum), 1.0), out_color);
film_store_color(dst, uniform_buf.film.shadow_id, shadow_accum_color, out_color);
film_store_color(dst, uniform_buf.film.ambient_occlusion_id, ao_accum_color, out_color);
film_store_value(dst, uniform_buf.film.mist_id, mist_accum, out_color);
}

View File

@ -745,7 +745,7 @@ void UI_panel_header_buttons_end(Panel *panel)
/* Repurpose the first header button group if it is empty, in case the first button added to
* the panel doesn't add a new group (if the button is created directly rather than through an
* interface layout call). */
if (block->button_groups.size() > 0) {
if (block->button_groups.size() == 1 && button_group.buttons.is_empty()) {
button_group.flag &= ~UI_BUTTON_GROUP_PANEL_HEADER;
}
else {

View File

@ -59,7 +59,13 @@ struct EraseOperationExecutor {
int2 mouse_position_pixels{};
int64_t eraser_squared_radius_pixels{};
EraseOperationExecutor(const bContext & /*C*/) {}
bke::greasepencil::DrawingTransforms transforms_;
EraseOperationExecutor(const bContext &C)
{
Object *object = CTX_data_active_object(&C);
transforms_ = bke::greasepencil::DrawingTransforms(*object);
}
/**
* Computes the intersections between a 2D line segment and a circle with integer values.
@ -759,10 +765,12 @@ struct EraseOperationExecutor {
Array<float2> screen_space_positions(src.points_num());
threading::parallel_for(src.points_range(), 4096, [&](const IndexRange src_points) {
for (const int src_point : src_points) {
ED_view3d_project_float_global(region,
deformation.positions[src_point],
screen_space_positions[src_point],
V3D_PROJ_TEST_NOP);
ED_view3d_project_float_global(
region,
math::transform_point(transforms_.layer_space_to_world_space,
deformation.positions[src_point]),
screen_space_positions[src_point],
V3D_PROJ_TEST_NOP);
}
});

View File

@ -1766,7 +1766,7 @@ static void sculpt_undo_set_active_layer(bContext *C, SculptAttrRef *attr)
* domain and just unconvert it.
*/
if (!layer) {
layer = BKE_id_attribute_search(&me->id, attr->name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
layer = BKE_id_attribute_search_for_write(&me->id, attr->name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
if (layer) {
if (ED_geometry_attribute_convert(
me, attr->name, eCustomDataType(attr->type), attr->domain, nullptr))

View File

@ -916,7 +916,7 @@ static TransConvertTypeInfo *convert_type_get(const TransInfo *t, Object **r_obj
if (t->options & CTX_EDGE_DATA) {
return &TransConvertType_MeshEdge;
}
if (t->options & CTX_GPENCIL_STROKES) {
if ((t->options & CTX_GPENCIL_STROKES) && (t->spacetype == SPACE_VIEW3D)) {
if (t->obedit_type == OB_GREASE_PENCIL) {
return &TransConvertType_GreasePencil;
}

View File

@ -6,69 +6,9 @@
#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_material_voronoi.glsl)
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
#define FRACTAL_VORONOI_X_FX(T) \
VoronoiOutput fractal_voronoi_x_fx(VoronoiParams params, T coord) \
{ \
float amplitude = 1.0; \
float max_amplitude = 0.0; \
float scale = 1.0; \
\
VoronoiOutput Output; \
Output.Distance = 0.0; \
Output.Color = vec3(0.0, 0.0, 0.0); \
Output.Position = vec4(0.0, 0.0, 0.0, 0.0); \
bool zero_input = params.detail == 0.0 || params.roughness == 0.0; \
\
for (int i = 0; i <= ceil(params.detail); ++i) { \
VoronoiOutput octave; \
if (params.feature == SHD_VORONOI_F2) { \
octave = voronoi_f2(params, coord * scale); \
} \
else if (params.feature == SHD_VORONOI_SMOOTH_F1 && params.smoothness != 0.0) { \
octave = voronoi_smooth_f1(params, coord * scale); \
} \
else { \
octave = voronoi_f1(params, coord * scale); \
} \
\
if (zero_input) { \
max_amplitude = 1.0; \
Output = octave; \
break; \
} \
else if (i <= params.detail) { \
max_amplitude += amplitude; \
Output.Distance += octave.Distance * amplitude; \
Output.Color += octave.Color * amplitude; \
Output.Position = mix(Output.Position, octave.Position / scale, amplitude); \
scale *= params.lacunarity; \
amplitude *= params.roughness; \
} \
else { \
float remainder = params.detail - floor(params.detail); \
if (remainder != 0.0) { \
max_amplitude = mix(max_amplitude, max_amplitude + amplitude, remainder); \
Output.Distance = mix( \
Output.Distance, Output.Distance + octave.Distance * amplitude, remainder); \
Output.Color = mix(Output.Color, Output.Color + octave.Color * amplitude, remainder); \
Output.Position = mix(Output.Position, \
mix(Output.Position, octave.Position / scale, amplitude), \
remainder); \
} \
} \
} \
\
if (params.normalize) { \
Output.Distance /= max_amplitude * params.max_distance; \
Output.Color /= max_amplitude; \
} \
\
Output.Position = safe_divide(Output.Position, params.scale); \
\
return Output; \
}
/* TODO(jbakker): Deduplicate code when OpenGL backend has been removed.
* `fractal_voronoi_x_fx` functions are identical, except for the input parameter.
* It used to be a macro, but didn't work on legacy drivers. */
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
@ -115,24 +55,264 @@
/* **** 1D Fractal Voronoi **** */
FRACTAL_VORONOI_X_FX(float)
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
VoronoiOutput fractal_voronoi_x_fx(VoronoiParams params, float coord)
{
float amplitude = 1.0;
float max_amplitude = 0.0;
float scale = 1.0;
VoronoiOutput Output;
Output.Distance = 0.0;
Output.Color = vec3(0.0, 0.0, 0.0);
Output.Position = vec4(0.0, 0.0, 0.0, 0.0);
bool zero_input = params.detail == 0.0 || params.roughness == 0.0;
for (int i = 0; i <= ceil(params.detail); ++i) {
VoronoiOutput octave;
if (params.feature == SHD_VORONOI_F2) {
octave = voronoi_f2(params, coord * scale);
}
else if (params.feature == SHD_VORONOI_SMOOTH_F1 && params.smoothness != 0.0) {
octave = voronoi_smooth_f1(params, coord * scale);
}
else {
octave = voronoi_f1(params, coord * scale);
}
if (zero_input) {
max_amplitude = 1.0;
Output = octave;
break;
}
else if (i <= params.detail) {
max_amplitude += amplitude;
Output.Distance += octave.Distance * amplitude;
Output.Color += octave.Color * amplitude;
Output.Position = mix(Output.Position, octave.Position / scale, amplitude);
scale *= params.lacunarity;
amplitude *= params.roughness;
}
else {
float remainder = params.detail - floor(params.detail);
if (remainder != 0.0) {
max_amplitude = mix(max_amplitude, max_amplitude + amplitude, remainder);
Output.Distance = mix(
Output.Distance, Output.Distance + octave.Distance * amplitude, remainder);
Output.Color = mix(Output.Color, Output.Color + octave.Color * amplitude, remainder);
Output.Position = mix(
Output.Position, mix(Output.Position, octave.Position / scale, amplitude), remainder);
}
}
}
if (params.normalize) {
Output.Distance /= max_amplitude * params.max_distance;
Output.Color /= max_amplitude;
}
Output.Position = safe_divide(Output.Position, params.scale);
return Output;
}
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(float)
/* **** 2D Fractal Voronoi **** */
FRACTAL_VORONOI_X_FX(vec2)
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
VoronoiOutput fractal_voronoi_x_fx(VoronoiParams params, vec2 coord)
{
float amplitude = 1.0;
float max_amplitude = 0.0;
float scale = 1.0;
VoronoiOutput Output;
Output.Distance = 0.0;
Output.Color = vec3(0.0, 0.0, 0.0);
Output.Position = vec4(0.0, 0.0, 0.0, 0.0);
bool zero_input = params.detail == 0.0 || params.roughness == 0.0;
for (int i = 0; i <= ceil(params.detail); ++i) {
VoronoiOutput octave;
if (params.feature == SHD_VORONOI_F2) {
octave = voronoi_f2(params, coord * scale);
}
else if (params.feature == SHD_VORONOI_SMOOTH_F1 && params.smoothness != 0.0) {
octave = voronoi_smooth_f1(params, coord * scale);
}
else {
octave = voronoi_f1(params, coord * scale);
}
if (zero_input) {
max_amplitude = 1.0;
Output = octave;
break;
}
else if (i <= params.detail) {
max_amplitude += amplitude;
Output.Distance += octave.Distance * amplitude;
Output.Color += octave.Color * amplitude;
Output.Position = mix(Output.Position, octave.Position / scale, amplitude);
scale *= params.lacunarity;
amplitude *= params.roughness;
}
else {
float remainder = params.detail - floor(params.detail);
if (remainder != 0.0) {
max_amplitude = mix(max_amplitude, max_amplitude + amplitude, remainder);
Output.Distance = mix(
Output.Distance, Output.Distance + octave.Distance * amplitude, remainder);
Output.Color = mix(Output.Color, Output.Color + octave.Color * amplitude, remainder);
Output.Position = mix(
Output.Position, mix(Output.Position, octave.Position / scale, amplitude), remainder);
}
}
}
if (params.normalize) {
Output.Distance /= max_amplitude * params.max_distance;
Output.Color /= max_amplitude;
}
Output.Position = safe_divide(Output.Position, params.scale);
return Output;
}
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(vec2)
/* **** 3D Fractal Voronoi **** */
FRACTAL_VORONOI_X_FX(vec3)
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
VoronoiOutput fractal_voronoi_x_fx(VoronoiParams params, vec3 coord)
{
float amplitude = 1.0;
float max_amplitude = 0.0;
float scale = 1.0;
VoronoiOutput Output;
Output.Distance = 0.0;
Output.Color = vec3(0.0, 0.0, 0.0);
Output.Position = vec4(0.0, 0.0, 0.0, 0.0);
bool zero_input = params.detail == 0.0 || params.roughness == 0.0;
for (int i = 0; i <= ceil(params.detail); ++i) {
VoronoiOutput octave;
if (params.feature == SHD_VORONOI_F2) {
octave = voronoi_f2(params, coord * scale);
}
else if (params.feature == SHD_VORONOI_SMOOTH_F1 && params.smoothness != 0.0) {
octave = voronoi_smooth_f1(params, coord * scale);
}
else {
octave = voronoi_f1(params, coord * scale);
}
if (zero_input) {
max_amplitude = 1.0;
Output = octave;
break;
}
else if (i <= params.detail) {
max_amplitude += amplitude;
Output.Distance += octave.Distance * amplitude;
Output.Color += octave.Color * amplitude;
Output.Position = mix(Output.Position, octave.Position / scale, amplitude);
scale *= params.lacunarity;
amplitude *= params.roughness;
}
else {
float remainder = params.detail - floor(params.detail);
if (remainder != 0.0) {
max_amplitude = mix(max_amplitude, max_amplitude + amplitude, remainder);
Output.Distance = mix(
Output.Distance, Output.Distance + octave.Distance * amplitude, remainder);
Output.Color = mix(Output.Color, Output.Color + octave.Color * amplitude, remainder);
Output.Position = mix(
Output.Position, mix(Output.Position, octave.Position / scale, amplitude), remainder);
}
}
}
if (params.normalize) {
Output.Distance /= max_amplitude * params.max_distance;
Output.Color /= max_amplitude;
}
Output.Position = safe_divide(Output.Position, params.scale);
return Output;
}
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(vec3)
/* **** 4D Fractal Voronoi **** */
FRACTAL_VORONOI_X_FX(vec4)
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
VoronoiOutput fractal_voronoi_x_fx(VoronoiParams params, vec4 coord)
{
float amplitude = 1.0;
float max_amplitude = 0.0;
float scale = 1.0;
VoronoiOutput Output;
Output.Distance = 0.0;
Output.Color = vec3(0.0, 0.0, 0.0);
Output.Position = vec4(0.0, 0.0, 0.0, 0.0);
bool zero_input = params.detail == 0.0 || params.roughness == 0.0;
for (int i = 0; i <= ceil(params.detail); ++i) {
VoronoiOutput octave;
if (params.feature == SHD_VORONOI_F2) {
octave = voronoi_f2(params, coord * scale);
}
else if (params.feature == SHD_VORONOI_SMOOTH_F1 && params.smoothness != 0.0) {
octave = voronoi_smooth_f1(params, coord * scale);
}
else {
octave = voronoi_f1(params, coord * scale);
}
if (zero_input) {
max_amplitude = 1.0;
Output = octave;
break;
}
else if (i <= params.detail) {
max_amplitude += amplitude;
Output.Distance += octave.Distance * amplitude;
Output.Color += octave.Color * amplitude;
Output.Position = mix(Output.Position, octave.Position / scale, amplitude);
scale *= params.lacunarity;
amplitude *= params.roughness;
}
else {
float remainder = params.detail - floor(params.detail);
if (remainder != 0.0) {
max_amplitude = mix(max_amplitude, max_amplitude + amplitude, remainder);
Output.Distance = mix(
Output.Distance, Output.Distance + octave.Distance * amplitude, remainder);
Output.Color = mix(Output.Color, Output.Color + octave.Color * amplitude, remainder);
Output.Position = mix(
Output.Position, mix(Output.Position, octave.Position / scale, amplitude), remainder);
}
}
}
if (params.normalize) {
Output.Distance /= max_amplitude * params.max_distance;
Output.Color /= max_amplitude;
}
Output.Position = safe_divide(Output.Position, params.scale);
return Output;
}
FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(vec4)

View File

@ -181,6 +181,12 @@ static std::optional<eCustomDataType> convert_usd_type_to_blender(
map.add_new(pxr::SdfValueTypeNames->TexCoord3fArray, CD_PROP_FLOAT2);
map.add_new(pxr::SdfValueTypeNames->TexCoord3hArray, CD_PROP_FLOAT2);
map.add_new(pxr::SdfValueTypeNames->Float3Array, CD_PROP_FLOAT3);
map.add_new(pxr::SdfValueTypeNames->Point3fArray, CD_PROP_FLOAT3);
map.add_new(pxr::SdfValueTypeNames->Point3dArray, CD_PROP_FLOAT3);
map.add_new(pxr::SdfValueTypeNames->Point3hArray, CD_PROP_FLOAT3);
map.add_new(pxr::SdfValueTypeNames->Normal3fArray, CD_PROP_FLOAT3);
map.add_new(pxr::SdfValueTypeNames->Normal3dArray, CD_PROP_FLOAT3);
map.add_new(pxr::SdfValueTypeNames->Normal3hArray, CD_PROP_FLOAT3);
map.add_new(pxr::SdfValueTypeNames->Vector3fArray, CD_PROP_FLOAT3);
map.add_new(pxr::SdfValueTypeNames->Vector3hArray, CD_PROP_FLOAT3);
map.add_new(pxr::SdfValueTypeNames->Vector3dArray, CD_PROP_FLOAT3);
@ -190,6 +196,8 @@ static std::optional<eCustomDataType> convert_usd_type_to_blender(
map.add_new(pxr::SdfValueTypeNames->StringArray, CD_PROP_STRING);
map.add_new(pxr::SdfValueTypeNames->BoolArray, CD_PROP_BOOL);
map.add_new(pxr::SdfValueTypeNames->QuatfArray, CD_PROP_QUATERNION);
map.add_new(pxr::SdfValueTypeNames->QuatdArray, CD_PROP_QUATERNION);
map.add_new(pxr::SdfValueTypeNames->QuathArray, CD_PROP_QUATERNION);
return map;
}();
@ -902,6 +910,11 @@ void USDMeshReader::read_custom_data(const ImportSettings *settings,
continue;
}
if (!pv.GetAttr().GetTypeName().IsArray()) {
/* Non-array attributes are technically improper USD. */
continue;
}
const pxr::SdfValueTypeName type = pv.GetTypeName();
const pxr::TfToken varying_type = pv.GetInterpolation();
const pxr::TfToken name = pv.StripPrimvarsName(pv.GetPrimvarName());
@ -914,6 +927,16 @@ void USDMeshReader::read_custom_data(const ImportSettings *settings,
continue;
}
if (ELEM(type,
pxr::SdfValueTypeNames->StringArray,
pxr::SdfValueTypeNames->QuatfArray,
pxr::SdfValueTypeNames->QuatdArray,
pxr::SdfValueTypeNames->QuathArray))
{
/* Skip creating known unsupported types, and avoid spammy error prints. */
continue;
}
/* Read Color primvars. */
if (convert_usd_type_to_blender(type, reports()) == CD_PROP_COLOR) {
if ((settings->read_flag & MOD_MESHSEQ_READ_COLOR) != 0) {

View File

@ -590,10 +590,11 @@ static void rna_AttributeGroup_update_active(Main *bmain, Scene *scene, PointerR
static PointerRNA rna_AttributeGroup_active_color_get(PointerRNA *ptr)
{
ID *id = ptr->owner_id;
CustomDataLayer *layer = BKE_id_attribute_search(ptr->owner_id,
BKE_id_attributes_active_color_name(id),
CD_MASK_COLOR_ALL,
ATTR_DOMAIN_MASK_COLOR);
CustomDataLayer *layer = BKE_id_attribute_search_for_write(
ptr->owner_id,
BKE_id_attributes_active_color_name(id),
CD_MASK_COLOR_ALL,
ATTR_DOMAIN_MASK_COLOR);
PointerRNA attribute_ptr = RNA_pointer_create(id, &RNA_Attribute, layer);
return attribute_ptr;

View File

@ -1080,7 +1080,7 @@ DEFINE_CUSTOMDATA_LAYER_COLLECTION(vertex_color, ldata, CD_PROP_BYTE_COLOR)
static PointerRNA rna_Mesh_vertex_color_active_get(PointerRNA *ptr)
{
Mesh *mesh = (Mesh *)ptr->data;
CustomDataLayer *layer = BKE_id_attribute_search(
CustomDataLayer *layer = BKE_id_attribute_search_for_write(
&mesh->id, mesh->active_color_attribute, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_CORNER);
return rna_pointer_inherit_refine(ptr, &RNA_MeshLoopColorLayer, layer);
}
@ -1102,7 +1102,7 @@ static void rna_Mesh_vertex_color_active_set(PointerRNA *ptr,
static int rna_Mesh_vertex_color_active_index_get(PointerRNA *ptr)
{
Mesh *mesh = (Mesh *)ptr->data;
CustomDataLayer *layer = BKE_id_attribute_search(
const CustomDataLayer *layer = BKE_id_attribute_search(
&mesh->id, mesh->active_color_attribute, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_CORNER);
if (!layer) {
return 0;

View File

@ -11,11 +11,11 @@
#include "BLI_utildefines.h"
#include "BLI_kdtree.h"
#include "BLI_map.hh"
#include "BLI_math_matrix.h"
#include "BLI_math_rotation.h"
#include "BLI_math_vector.h"
#include "BLI_rand.h"
#include "BLI_vector_set.hh"
#include "BLT_translation.h"
@ -208,9 +208,9 @@ static void createFacepa(ExplodeModifierData *emd, ParticleSystemModifierData *p
BLI_rng_free(rng);
}
static int edgecut_get(const blender::VectorSet<blender::OrderedEdge> &edgehash, uint v1, uint v2)
static int edgecut_get(const blender::Map<blender::OrderedEdge, int> &edgehash, uint v1, uint v2)
{
return edgehash.index_of({int(v1), int(v2)});
return edgehash.lookup({int(v1), int(v2)});
}
static const short add_faces[24] = {
@ -249,7 +249,7 @@ static void remap_faces_3_6_9_12(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -319,7 +319,7 @@ static void remap_faces_5_10(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -377,7 +377,7 @@ static void remap_faces_15(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -463,7 +463,7 @@ static void remap_faces_7_11_13_14(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -534,7 +534,7 @@ static void remap_faces_19_21_22(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -590,7 +590,7 @@ static void remap_faces_23(Mesh *mesh,
int *facepa,
const int *vertpa,
int i,
const blender::VectorSet<blender::OrderedEdge> &eh,
const blender::Map<blender::OrderedEdge, int> &eh,
int cur,
int v1,
int v2,
@ -670,7 +670,8 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */
int layers_num;
blender::VectorSet<blender::OrderedEdge> edgehash;
int totesplit = totvert;
blender::Map<blender::OrderedEdge, int> edgehash;
/* recreate vertpa from facepa calculation */
for (i = 0, mf = mface; i < totface; i++, mf++) {
@ -689,12 +690,12 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
v3 = vertpa[mf->v3];
if (v1 != v2) {
edgehash.add({mf->v1, mf->v2});
edgehash.lookup_or_add_cb({mf->v1, mf->v2}, [&]() { return totesplit++; });
(*fs) |= 1;
}
if (v2 != v3) {
edgehash.add({mf->v2, mf->v3});
edgehash.lookup_or_add_cb({mf->v2, mf->v3}, [&]() { return totesplit++; });
(*fs) |= 2;
}
@ -702,25 +703,25 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
v4 = vertpa[mf->v4];
if (v3 != v4) {
edgehash.add({mf->v3, mf->v4});
edgehash.lookup_or_add_cb({mf->v3, mf->v4}, [&]() { return totesplit++; });
(*fs) |= 4;
}
if (v1 != v4) {
edgehash.add({mf->v1, mf->v4});
edgehash.lookup_or_add_cb({mf->v1, mf->v4}, [&]() { return totesplit++; });
(*fs) |= 8;
}
/* mark center vertex as a fake edge split */
if (*fs == 15) {
edgehash.add({mf->v1, mf->v3});
edgehash.lookup_or_add_cb({mf->v1, mf->v3}, [&]() { return totesplit++; });
}
}
else {
(*fs) |= 16; /* mark face as tri */
if (v1 != v3) {
edgehash.add({mf->v1, mf->v3});
edgehash.lookup_or_add_cb({mf->v1, mf->v3}, [&]() { return totesplit++; });
(*fs) |= 4;
}
}
@ -734,7 +735,7 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
}
split_m = BKE_mesh_new_nomain_from_template_ex(
mesh, totvert + edgehash.size(), 0, totface + totfsplit, 0, 0, CD_MASK_EVERYTHING);
mesh, totesplit, 0, totface + totfsplit, 0, 0, CD_MASK_EVERYTHING);
layers_num = CustomData_number_of_layers(&split_m->fdata_legacy, CD_MTFACE);
@ -757,9 +758,9 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
emd->facepa = facepa;
/* create new verts */
for (const int esplit : edgehash.index_range()) {
const int ed_v1 = edgehash[esplit].v_low;
const int ed_v2 = edgehash[esplit].v_high;
for (const auto [edge, esplit] : edgehash.items()) {
const int ed_v1 = edge.v_low;
const int ed_v2 = edge.v_high;
CustomData_free_elem(&split_m->vert_data, esplit, 1);
CustomData_copy_data(&split_m->vert_data, &split_m->vert_data, ed_v2, esplit, 1);
@ -912,7 +913,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
float ctime;
// float timestep;
const int *facepa = emd->facepa;
int totvert = 0, totface = 0, totpart = 0, delface = 0;
int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0;
int i, u;
uint mindex = 0;
@ -933,7 +934,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
ctime = BKE_scene_ctime_get(scene);
/* hash table for vertex <-> particle relations */
blender::VectorSet<blender::OrderedEdge> vertpahash;
blender::Map<blender::OrderedEdge, int> vertpahash;
for (i = 0; i < totface; i++) {
if (facepa[i] != totpart) {
@ -962,17 +963,17 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
mf = &mface[i];
/* set face vertices to exist in particle group */
vertpahash.add({mf->v1, mindex});
vertpahash.add({mf->v2, mindex});
vertpahash.add({mf->v3, mindex});
vertpahash.lookup_or_add_cb({mf->v1, mindex}, [&]() { return totdup++; });
vertpahash.lookup_or_add_cb({mf->v2, mindex}, [&]() { return totdup++; });
vertpahash.lookup_or_add_cb({mf->v3, mindex}, [&]() { return totdup++; });
if (mf->v4) {
vertpahash.add({mf->v4, mindex});
vertpahash.lookup_or_add_cb({mf->v4, mindex}, [&]() { return totdup++; });
}
}
/* the final duplicated vertices */
explode = BKE_mesh_new_nomain_from_template_ex(
mesh, vertpahash.size(), 0, totface - delface, 0, 0, CD_MASK_EVERYTHING);
mesh, totdup, 0, totface - delface, 0, 0, CD_MASK_EVERYTHING);
MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer_named_for_write(
&explode->fdata_legacy, CD_MTFACE, emd->uvname, explode->totface_legacy));
@ -985,10 +986,9 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
const blender::Span<blender::float3> positions = mesh->vert_positions();
blender::MutableSpan<blender::float3> explode_positions = explode->vert_positions_for_write();
for (const int v : vertpahash.index_range()) {
/* get particle + vertex from hash */
int ed_v1 = vertpahash[v].v_low;
int ed_v2 = vertpahash[v].v_high;
for (const auto [edge, v] : vertpahash.items()) {
int ed_v1 = edge.v_low;
int ed_v2 = edge.v_high;
ed_v2 -= totvert;
copy_v3_v3(explode_positions[v], positions[ed_v1]);

View File

@ -616,6 +616,7 @@ void WM_exit_ex(bContext *C, const bool do_python_exit, const bool do_user_exit_
BKE_vfont_clipboard_free();
ED_node_clipboard_free();
UV_clipboard_free();
wm_clipboard_free();
#ifdef WITH_COMPOSITOR_CPU
COM_deinitialize();

View File

@ -827,8 +827,6 @@ static bool operator_last_properties_init_impl(wmOperator *op, IDProperty *last_
IDPropertyTemplate val = {0};
IDProperty *replaceprops = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
CLOG_INFO(WM_LOG_OPERATORS, 1, "loading previous properties for '%s'", op->type->idname);
PropertyRNA *iterprop = RNA_struct_iterator_property(op->type->srna);
RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) {
@ -854,6 +852,9 @@ static bool operator_last_properties_init_impl(wmOperator *op, IDProperty *last_
}
RNA_PROP_END;
if (changed) {
CLOG_INFO(WM_LOG_OPERATORS, 1, "loading previous properties for '%s'", op->type->idname);
}
IDP_MergeGroup(op->properties, replaceprops, true);
IDP_FreeProperty(replaceprops);
return changed;
@ -882,7 +883,9 @@ bool WM_operator_last_properties_store(wmOperator *op)
}
if (op->properties) {
CLOG_INFO(WM_LOG_OPERATORS, 1, "storing properties for '%s'", op->type->idname);
if (!BLI_listbase_is_empty(&op->properties->data.group)) {
CLOG_INFO(WM_LOG_OPERATORS, 1, "storing properties for '%s'", op->type->idname);
}
op->type->last_properties = IDP_CopyProperty(op->properties);
}

View File

@ -1813,6 +1813,10 @@ static bool wm_main_playanim_intern(int argc, const char **argv, PlayArgs *args_
exit(EXIT_FAILURE);
}
/* Select GPU backend. */
GPU_backend_type_selection_detect();
/* Init GHOST and open window. */
GHOST_EventConsumerHandle ghost_event_consumer = nullptr;
{
ghost_event_consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps);
@ -1840,7 +1844,7 @@ static bool wm_main_playanim_intern(int argc, const char **argv, PlayArgs *args_
// GHOST_ActivateWindowDrawingContext(ps.ghost_data.window);
/* Initialize GPU immediate mode. */
/* Init Blender GPU context. */
ps.ghost_data.gpu_context = GPU_context_create(ps.ghost_data.window, nullptr);
GPU_init();

View File

@ -2110,6 +2110,70 @@ void WM_event_timer_remove_notifier(wmWindowManager *wm, wmWindow *win, wmTimer
/** \} */
/* -------------------------------------------------------------------- */
/** \name Clipboard Wrappers
*
* GHOST function wrappers that support a "fake" clipboard used when simulating events.
* This is useful user actions can be simulated while the system is in use without the system's
* clipboard getting overwritten.
* \{ */
struct {
char *buffers[2];
} *g_wm_clipboard_text_simulate = nullptr;
void wm_clipboard_free()
{
if (g_wm_clipboard_text_simulate == nullptr) {
return;
}
for (int i = 0; i < ARRAY_SIZE(g_wm_clipboard_text_simulate->buffers); i++) {
char *buf = g_wm_clipboard_text_simulate->buffers[i];
if (buf) {
MEM_freeN(buf);
}
}
MEM_freeN(g_wm_clipboard_text_simulate);
g_wm_clipboard_text_simulate = nullptr;
}
static char *wm_clipboard_text_get_impl(bool selection)
{
if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) {
if (g_wm_clipboard_text_simulate == nullptr) {
return nullptr;
}
const char *buf_src = g_wm_clipboard_text_simulate->buffers[int(selection)];
if (buf_src == nullptr) {
return nullptr;
}
size_t size = strlen(buf_src) + 1;
char *buf = static_cast<char *>(malloc(size));
memcpy(buf, buf_src, size);
return buf;
}
return GHOST_getClipboard(selection);
}
static void wm_clipboard_text_set_impl(const char *buf, bool selection)
{
if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) {
if (g_wm_clipboard_text_simulate == nullptr) {
g_wm_clipboard_text_simulate = static_cast<decltype(g_wm_clipboard_text_simulate)>(
MEM_callocN(sizeof(*g_wm_clipboard_text_simulate), __func__));
}
char **buf_src_p = &(g_wm_clipboard_text_simulate->buffers[int(selection)]);
MEM_SAFE_FREE(*buf_src_p);
*buf_src_p = BLI_strdup(buf);
return;
}
GHOST_putClipboard(buf, selection);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Clipboard
* \{ */
@ -2124,7 +2188,7 @@ static char *wm_clipboard_text_get_ex(bool selection,
return nullptr;
}
char *buf = GHOST_getClipboard(selection);
char *buf = wm_clipboard_text_get_impl(selection);
if (!buf) {
*r_len = 0;
return nullptr;
@ -2213,10 +2277,10 @@ void WM_clipboard_text_set(const char *buf, bool selection)
}
*p2 = '\0';
GHOST_putClipboard(newbuf, selection);
wm_clipboard_text_set_impl(newbuf, selection);
MEM_freeN(newbuf);
#else
GHOST_putClipboard(buf, selection);
wm_clipboard_text_set_impl(buf, selection);
#endif
}
}

View File

@ -28,6 +28,8 @@ void wm_ghost_init(bContext *C);
void wm_ghost_init_background();
void wm_ghost_exit();
void wm_clipboard_free();
/**
* This one should correctly check for apple top header...
* done for Cocoa: returns window contents (and not frame) max size.