Cleanup: Reduce binary size by deduplicating attribute processing #107823

Merged
Hans Goudey merged 4 commits from HooglyBoogly/blender:cleanup-remove-convert-to-static-type into main 2023-05-12 14:44:46 +02:00
39 changed files with 553 additions and 204 deletions
Showing only changes of commit af7f93f504 - Show all commits

View File

@ -31,7 +31,8 @@ IF(NOT PYTHON_ROOT_DIR AND NOT $ENV{PYTHON_ROOT_DIR} STREQUAL "")
SET(PYTHON_ROOT_DIR $ENV{PYTHON_ROOT_DIR})
ENDIF()
SET(PYTHON_VERSION 3.10 CACHE STRING "Python Version (major and minor only)")
SET(_PYTHON_VERSION_SUPPORTED 3.10)
SET(PYTHON_VERSION ${_PYTHON_VERSION_SUPPORTED} CACHE STRING "Python Version (major and minor only)")
MARK_AS_ADVANCED(PYTHON_VERSION)
@ -178,8 +179,24 @@ UNSET(_IS_LIB_PATH_DEF)
# handle the QUIETLY and REQUIRED arguments and SET PYTHONLIBSUNIX_FOUND to TRUE IF
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibsUnix DEFAULT_MSG
PYTHON_LIBRARY PYTHON_LIBPATH PYTHON_INCLUDE_DIR PYTHON_INCLUDE_CONFIG_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibsUnix
# NOTE(@ideasman42): Instead of `DEFAULT_MSG` use a custom message because users
# may have newer versions Python and not be using pre-compiled libraries
# (on other UNIX systems or using an esoteric architecture).
# Some Python developers might want to use the newer features of Python too.
# While we could automatically detect and use newer versions but this would result in
# developers using a configuration which isn't officially supported without realizing it.
# So warn that the officially supported Python version is not found and let the developer
# explicitly set the newer version if they wish.
# From a maintenance perspective it's typically not a problem to support newer versions,
# doing so can help ease the process of upgrading too, nevertheless these versions don't
# have the same level of testing & support.
"\
'PYTHON_VERSION=${_PYTHON_VERSION_SUPPORTED}' not found! \
This is the only officially supported version. \
If you wish to use a newer Python version you may set 'PYTHON_VERSION' \
however we do not guarantee full compatibility in this case."
PYTHON_LIBRARY PYTHON_LIBPATH PYTHON_INCLUDE_DIR PYTHON_INCLUDE_CONFIG_DIR)
IF(PYTHONLIBSUNIX_FOUND)
# Assign cache items
@ -215,6 +232,7 @@ IF(PYTHONLIBSUNIX_FOUND)
ENDIF()
UNSET(_PYTHON_ABI_FLAGS)
UNSET(_PYTHON_VERSION_SUPPORTED)
UNSET(_python_SEARCH_DIRS)
MARK_AS_ADVANCED(

View File

@ -122,8 +122,12 @@ bool OneapiDevice::check_peer_access(Device * /*peer_device*/)
bool OneapiDevice::can_use_hardware_raytracing_for_features(uint requested_features) const
{
/* MNEE and Ray-trace kernels currently don't work correctly with HWRT. */
/* MNEE and Raytrace kernels work correctly with Hardware Raytracing starting with Embree 4.1. */
# if defined(RTC_VERSION) && RTC_VERSION < 40100
return !(requested_features & (KERNEL_FEATURE_MNEE | KERNEL_FEATURE_NODE_RAYTRACE));
# else
return true;
# endif
}
BVHLayoutMask OneapiDevice::get_bvh_layout_mask(uint requested_features) const

View File

@ -174,27 +174,30 @@ bool oneapi_kernel_is_required_for_features(const std::string &kernel_name,
return true;
}
bool oneapi_kernel_is_raytrace_or_mnee(const std::string &kernel_name)
bool oneapi_kernel_is_compatible_with_hardware_raytracing(const std::string &kernel_name)
{
return (kernel_name.find(device_kernel_as_string(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE)) !=
std::string::npos) ||
/* MNEE and Raytrace kernels work correctly with Hardware Raytracing starting with Embree 4.1.
*/
# if defined(RTC_VERSION) && RTC_VERSION < 40100
return (kernel_name.find(device_kernel_as_string(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE)) ==
std::string::npos) &&
(kernel_name.find(device_kernel_as_string(
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE)) != std::string::npos);
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE)) == std::string::npos);
# else
return true;
# endif
}
bool oneapi_kernel_is_using_embree(const std::string &kernel_name)
bool oneapi_kernel_has_intersections(const std::string &kernel_name)
{
# ifdef WITH_EMBREE_GPU
/* MNEE and Ray-trace kernels aren't yet enabled to use Embree. */
for (int i = 0; i < (int)DEVICE_KERNEL_NUM; i++) {
DeviceKernel kernel = (DeviceKernel)i;
if (device_kernel_has_intersection(kernel)) {
if (kernel_name.find(device_kernel_as_string(kernel)) != std::string::npos) {
return !oneapi_kernel_is_raytrace_or_mnee(kernel_name);
return true;
}
}
}
# endif
return false;
}
@ -217,7 +220,8 @@ bool oneapi_load_kernels(SyclQueue *queue_,
const std::string &kernel_name = kernel_id.get_name();
if (!oneapi_kernel_is_required_for_features(kernel_name, kernel_features) ||
!oneapi_kernel_is_using_embree(kernel_name))
!(oneapi_kernel_has_intersections(kernel_name) &&
oneapi_kernel_is_compatible_with_hardware_raytracing(kernel_name)))
{
continue;
}
@ -260,14 +264,14 @@ bool oneapi_load_kernels(SyclQueue *queue_,
/* In case HWRT is on, compilation of kernels using Embree is already handled in previous
* block. */
if (!oneapi_kernel_is_required_for_features(kernel_name, kernel_features) ||
(use_hardware_raytracing && oneapi_kernel_is_using_embree(kernel_name)))
(use_hardware_raytracing && oneapi_kernel_has_intersections(kernel_name) &&
oneapi_kernel_is_compatible_with_hardware_raytracing(kernel_name)))
{
continue;
}
# ifdef WITH_EMBREE_GPU
if (oneapi_kernel_is_using_embree(kernel_name) ||
oneapi_kernel_is_raytrace_or_mnee(kernel_name)) {
if (oneapi_kernel_has_intersections(kernel_name)) {
sycl::kernel_bundle<sycl::bundle_state::input> one_kernel_bundle_input =
sycl::get_kernel_bundle<sycl::bundle_state::input>(queue->get_context(), {kernel_id});
one_kernel_bundle_input

View File

@ -614,6 +614,7 @@ class NODE_MT_category_GEO_VOLUME(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeMeanFilterSDFVolume")
node_add_menu.add_node_type(layout, "GeometryNodeOffsetSDFVolume")
node_add_menu.add_node_type(layout, "GeometryNodeSDFVolumeSphere")
node_add_menu.add_node_type(layout, "GeometryNodeInputSignedDistance")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)

View File

@ -435,7 +435,9 @@ class IMAGE_MT_uvs(Menu):
layout.separator()
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("uv.pack_islands")
layout.operator_context = 'EXEC_REGION_WIN'
layout.operator("uv.average_islands_scale")
layout.separator()

View File

@ -1587,6 +1587,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
/* Function nodes use the range starting at 1200. */
#define GEO_NODE_SIMULATION_INPUT 2100
#define GEO_NODE_SIMULATION_OUTPUT 2101
#define GEO_NODE_INPUT_SIGNED_DISTANCE 2102
/** \} */

View File

@ -453,15 +453,14 @@ void OutputOpenExrMultiLayerOperation::update_memory_buffer_partial(MemoryBuffer
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const MemoryBuffer *input_image = inputs[0];
for (int i = 0; i < layers_.size(); i++) {
OutputOpenExrLayer &layer = layers_[i];
int layer_num_channels = COM_data_type_num_channels(layer.datatype);
if (layer.output_buffer) {
MemoryBuffer output_buf(layer.output_buffer,
COM_data_type_num_channels(layer.datatype),
this->get_width(),
this->get_height());
output_buf.copy_from(input_image, area);
MemoryBuffer output_buf(
layer.output_buffer, layer_num_channels, this->get_width(), this->get_height());
/* Input node always has 4 channels. Not all are needed depending on datatype. */
output_buf.copy_from(inputs[i], area, 0, layer_num_channels, 0);
}
}
}

View File

@ -327,6 +327,7 @@ void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
if (!ebone_dst) {
ebone_dst = ED_armature_ebone_get_mirrored(editbones, ebone_src);
}
if (ebone_dst) {
BLI_ghash_insert(name_map, ebone_src->name, ebone_dst->name);
}
@ -334,22 +335,28 @@ void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
LISTBASE_FOREACH (EditBone *, ebone_src, editbones) {
EditBone *ebone_dst = ebone_src->temp.ebone;
if (ebone_dst) {
bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name);
if (pchan_src) {
bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name);
if (pchan_dst) {
if (pchan_src->custom_tx) {
pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx);
}
if (pchan_src->bbone_prev) {
pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev);
}
if (pchan_src->bbone_next) {
pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next);
}
}
}
if (!ebone_dst) {
continue;
}
bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name);
if (!pchan_src) {
continue;
}
bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name);
if (!pchan_dst) {
continue;
}
if (pchan_src->custom_tx) {
pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx);
}
if (pchan_src->bbone_prev) {
pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev);
}
if (pchan_src->bbone_next) {
pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next);
}
}
@ -1120,71 +1127,80 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
scene, view_layer, CTX_wm_view3d(C), &objects_len);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
bArmature *arm = obedit->data;
EditBone *ebone_iter;
/* The beginning of the duplicated mirrored bones in the edbo list */
EditBone *ebone_first_dupe = NULL;
Object *obedit = objects[ob_index];
bArmature *arm = obedit->data;
ED_armature_edit_sync_selection(arm->edbo); /* XXX why is this needed? */
preEditBoneDuplicate(arm->edbo);
/* Select mirrored bones */
/* Deselect ebones depending on input axis and direction.
* A symmetrizable selection contains selected ebones of the input direction
* and unique selected bones with an unique flippable name.
*
* Storing temp ptrs to mirrored unselected ebones. */
for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
char name_flip[MAXBONENAME];
if (!(EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED))) {
/* Skipping invisible selected bones. */
continue;
}
BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
char name_flip[MAXBONENAME];
if (ebone_iter == NULL) {
continue;
}
if (STREQ(name_flip, ebone_iter->name)) {
/* if the name matches, we don't have the potential to be mirrored, just skip */
ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
}
else {
EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip);
BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
if (ebone) {
if ((ebone->flag & BONE_SELECTED) == 0) {
/* simple case, we're selected, the other bone isn't! */
ebone_iter->temp.ebone = ebone;
}
else {
/* complicated - choose which direction to copy */
float axis_delta;
if (STREQ(name_flip, ebone_iter->name)) {
/* Skipping ebones without flippable as they don't have the potential to be mirrored. */
ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
continue;
}
axis_delta = ebone->head[axis] - ebone_iter->head[axis];
if (axis_delta == 0.0f) {
axis_delta = ebone->tail[axis] - ebone_iter->tail[axis];
}
EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip);
if (axis_delta == 0.0f) {
/* Both mirrored bones exist and point to each other and overlap exactly.
*
* in this case there's no well defined solution, so de-select both and skip.
*/
ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
}
else {
EditBone *ebone_src, *ebone_dst;
if (((axis_delta < 0.0f) ? -1 : 1) == direction) {
ebone_src = ebone;
ebone_dst = ebone_iter;
}
else {
ebone_src = ebone_iter;
ebone_dst = ebone;
}
if (!ebone) {
/* The ebone_iter is unique and mirrorable. */
continue;
}
ebone_src->temp.ebone = ebone_dst;
ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
}
}
if (ebone->flag & BONE_SELECTED) {
/* The mirrored ebone and the ebone_iter are selected.
* Deselect based on the input direction and axis. */
float axis_delta;
axis_delta = ebone->head[axis] - ebone_iter->head[axis];
if (axis_delta == 0.0f) {
/* The ebone heads are overlapping. */
axis_delta = ebone->tail[axis] - ebone_iter->tail[axis];
if (axis_delta == 0.0f) {
/* Both mirrored bones point to each other and overlap exactly.
* In this case there's no well defined solution, so de-select both and skip. */
ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
continue;
}
}
/* Deselect depending on direction. */
if (((axis_delta < 0.0f) ? -1 : 1) == direction) {
/* Don't store temp ptr if the iter_bone gets deselected.
* In this case, the ebone.temp should point to the ebone_iter. */
ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
continue;
}
ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
}
/* Set temp pointer to mirrored ebones */
ebone_iter->temp.ebone = ebone;
}
/* Find the selected bones and duplicate them as needed, with mirrored name. */
@ -1206,11 +1222,12 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
ebone_iter->temp.ebone->inherit_scale_mode = ebone_iter->inherit_scale_mode;
continue;
}
char name_flip[MAXBONENAME];
BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
/* bones must have a side-suffix */
/* mirrored bones must have a side-suffix */
if (!STREQ(name_flip, ebone_iter->name)) {
EditBone *ebone;
@ -1254,8 +1271,8 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
*/
if (ebone->head[axis] != 0.0f) {
/* The mirrored bone doesn't start on the mirror axis, so assume that this one should
* not be connected to the old parent */
/* The mirrored bone doesn't start on the mirror axis, so assume that this one
* should not be connected to the old parent */
ebone->flag &= ~BONE_CONNECTED;
}
}

View File

@ -779,6 +779,9 @@ static bConstraint *edit_constraint_property_get(bContext *C, wmOperator *op, Ob
if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
list = ED_object_pose_constraint_list(C);
if (!list) {
return NULL;
}
}
else {
list = &ob->constraints;

View File

@ -1980,8 +1980,7 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
Object *ob = base->object;
/* if hidden but in edit mode, we still display, can happen with animation */
if ((base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) != 0 ||
(ob->mode != OB_MODE_OBJECT))
{
(ob->mode != OB_MODE_OBJECT)) {
CTX_data_id_pointer_set(result, &ob->id);
}
}

View File

@ -18,6 +18,8 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_global.h"
#include "BLI_array.hh"
#include "BLI_convexhull_2d.h"
#include "BLI_linklist.h"
@ -59,6 +61,7 @@
#include "ED_image.h"
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_undo.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
@ -169,6 +172,14 @@ void blender::geometry::UVPackIsland_Params::setUDIMOffsetFromSpaceImage(const S
}
/** \} */
bool blender::geometry::UVPackIsland_Params::isCancelled() const
{
if (stop) {
return *stop;
}
return false;
}
/* -------------------------------------------------------------------- */
/** \name Parametrizer Conversion
* \{ */
@ -1141,6 +1152,7 @@ static bool island_has_pins(const Scene *scene,
* This is needed to perform UV packing on objects that aren't in edit-mode.
* \param udim_source_closest: UDIM source SpaceImage.
* \param original_selection: Pack to original selection.
* \param notify_wm: Notify the WM of any changes. (UI thread only.)
* \param params: Parameters and options to pass to the packing engine.
*/
static void uvedit_pack_islands_multi(const Scene *scene,
@ -1149,6 +1161,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
BMesh **bmesh_override,
const SpaceImage *udim_source_closest,
const bool original_selection,
const bool notify_wm,
blender::geometry::UVPackIsland_Params *params)
{
blender::Vector<FaceIsland *> island_vector;
@ -1271,6 +1284,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
BLI_memarena_free(arena);
const float scale = pack_islands(pack_island_vector, *params);
const bool is_cancelled = params->isCancelled();
float base_offset[2] = {0.0f, 0.0f};
copy_v2_v2(base_offset, params->udim_base_offset);
@ -1309,7 +1323,10 @@ static void uvedit_pack_islands_multi(const Scene *scene,
float matrix[2][2];
float matrix_inverse[2][2];
float pre_translate[2];
for (int64_t i : pack_island_vector.index_range()) {
for (const int64_t i : pack_island_vector.index_range()) {
if (is_cancelled) {
continue;
}
blender::geometry::PackIsland *pack_island = pack_island_vector[i];
FaceIsland *island = island_vector[pack_island->caller_index];
const float island_scale = pack_island->can_scale_(*params) ? scale : 1.0f;
@ -1339,16 +1356,21 @@ static void uvedit_pack_islands_multi(const Scene *scene,
pre_translate[1] = selection_min_co[1] / rescale;
island_uv_transform(island, matrix, pre_translate);
}
}
for (const int64_t i : pack_island_vector.index_range()) {
blender::geometry::PackIsland *pack_island = pack_island_vector[i];
/* Cleanup memory. */
pack_island_vector[i] = nullptr;
delete pack_island;
}
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
if (notify_wm && !is_cancelled) {
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
}
}
for (FaceIsland *island : island_vector) {
@ -1361,6 +1383,9 @@ static void uvedit_pack_islands_multi(const Scene *scene,
/** \name Pack UV Islands Operator
* \{ */
/* TODO: support this, interaction with the job-system needs to be handled carefully. */
// #define USE_INTERACTIVE_PACK
/* Packing targets. */
enum {
PACK_UDIM_SRC_CLOSEST = 0,
@ -1368,6 +1393,70 @@ enum {
PACK_ORIGINAL_AABB,
};
struct UVPackIslandsData {
wmWindowManager *wm;
const Scene *scene;
Object **objects;
uint objects_len;
const SpaceImage *sima;
int udim_source;
bContext *undo_context;
const char *undo_str;
bool use_job;
blender::geometry::UVPackIsland_Params pack_island_params;
};
static void pack_islands_startjob(void *pidv, bool *stop, bool *do_update, float *progress)
{
*progress = 0.02f;
UVPackIslandsData *pid = static_cast<UVPackIslandsData *>(pidv);
pid->pack_island_params.stop = stop;
pid->pack_island_params.do_update = do_update;
pid->pack_island_params.progress = progress;
uvedit_pack_islands_multi(pid->scene,
pid->objects,
pid->objects_len,
nullptr,
(pid->udim_source == PACK_UDIM_SRC_CLOSEST) ? pid->sima : nullptr,
(pid->udim_source == PACK_ORIGINAL_AABB),
!pid->use_job,
&pid->pack_island_params);
*progress = 0.99f;
*do_update = true;
}
static void pack_islands_endjob(void *pidv)
{
UVPackIslandsData *pid = static_cast<UVPackIslandsData *>(pidv);
for (uint ob_index = 0; ob_index < pid->objects_len; ob_index++) {
Object *obedit = pid->objects[ob_index];
DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
}
WM_main_add_notifier(NC_SPACE | ND_SPACE_IMAGE, NULL);
if (pid->undo_str) {
ED_undo_push(pid->undo_context, pid->undo_str);
}
}
static void pack_islands_freejob(void *pidv)
{
WM_cursor_wait(false);
UVPackIslandsData *pid = static_cast<UVPackIslandsData *>(pidv);
MEM_freeN(pid->objects);
WM_set_locked_interface(pid->wm, false);
MEM_freeN(pid);
}
static int pack_islands_exec(bContext *C, wmOperator *op)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
@ -1400,7 +1489,23 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
}
blender::geometry::UVPackIsland_Params pack_island_params;
UVPackIslandsData *pid = static_cast<UVPackIslandsData *>(
MEM_callocN(sizeof(UVPackIslandsData), "pack_islands_data"));
pid->use_job = op->flag & OP_IS_INVOKE;
pid->scene = scene;
pid->objects = objects;
pid->objects_len = objects_len;
pid->sima = sima;
pid->udim_source = udim_source;
pid->wm = CTX_wm_manager(C);
blender::geometry::UVPackIsland_Params &pack_island_params = pid->pack_island_params;
{
/* Call default constructor and copy the defaults. */
blender::geometry::UVPackIsland_Params default_params;
pack_island_params = default_params;
}
pack_island_params.setFromUnwrapOptions(options);
pack_island_params.rotate = RNA_boolean_get(op->ptr, "rotate");
pack_island_params.scale_to_fit = RNA_boolean_get(op->ptr, "scale");
@ -1416,15 +1521,31 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
pack_island_params.setUDIMOffsetFromSpaceImage(sima);
}
uvedit_pack_islands_multi(scene,
objects,
objects_len,
nullptr,
(udim_source == PACK_UDIM_SRC_CLOSEST) ? sima : nullptr,
(udim_source == PACK_ORIGINAL_AABB),
&pack_island_params);
if (pid->use_job) {
/* Setup job. */
if (pid->wm->op_undo_depth == 0) {
/* The job must do it's own undo push. */
pid->undo_context = C;
pid->undo_str = op->type->name;
}
MEM_freeN(objects);
wmJob *wm_job = WM_jobs_get(
pid->wm, CTX_wm_window(C), scene, "Packing UVs", WM_JOB_PROGRESS, WM_JOB_TYPE_UV_PACK);
WM_jobs_customdata_set(wm_job, pid, pack_islands_freejob);
WM_jobs_timer(wm_job, 0.1, 0, 0);
WM_set_locked_interface(pid->wm, true);
WM_jobs_callbacks(wm_job, pack_islands_startjob, nullptr, nullptr, pack_islands_endjob);
WM_cursor_wait(true);
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
return OPERATOR_FINISHED;
}
pack_islands_startjob(pid, nullptr, nullptr, nullptr);
pack_islands_endjob(pid);
MEM_freeN(pid);
return OPERATOR_FINISHED;
}
@ -1452,7 +1573,7 @@ static const EnumPropertyItem pack_shape_method_items[] = {
};
static const EnumPropertyItem pinned_islands_method_items[] = {
{ED_UVPACK_PIN_NORMAL, "NORMAL", 0, "Normal", "Pin information is not used"},
{ED_UVPACK_PIN_DEFAULT, "DEFAULT", 0, "Default", "Pin information is not used"},
{ED_UVPACK_PIN_IGNORED, "IGNORED", 0, "Ignored", "Pinned islands are not packed"},
{ED_UVPACK_PIN_LOCK_SCALE, "SCALE", 0, "Locked scale", "Pinned islands won't rescale"},
{ED_UVPACK_PIN_LOCK_ROTATION, "ROTATION", 0, "Locked rotation", "Pinned islands won't rotate"},
@ -1487,10 +1608,21 @@ void UV_OT_pack_islands(wmOperatorType *ot)
ot->description =
"Transform all islands so that they fill up the UV/UDIM space as much as possible";
#ifdef USE_INTERACTIVE_PACK
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
#else
/* The operator will handle undo, so the job system can push() it after the job completes. */
ot->flag = OPTYPE_REGISTER;
#endif
/* api callbacks */
ot->exec = pack_islands_exec;
#ifdef USE_INTERACTIVE_PACK
ot->invoke = WM_operator_props_popup_call;
#else
ot->invoke = WM_operator_props_popup_confirm;
#endif
ot->poll = ED_operator_uvedit;
/* properties */
@ -1510,7 +1642,7 @@ void UV_OT_pack_islands(wmOperatorType *ot)
RNA_def_enum(ot->srna,
"pin_method",
pinned_islands_method_items,
ED_UVPACK_PIN_NORMAL,
ED_UVPACK_PIN_DEFAULT,
"Pinned Islands",
"");
RNA_def_enum(ot->srna,
@ -2234,7 +2366,7 @@ void ED_uvedit_live_unwrap(const Scene *scene, Object **objects, int objects_len
pack_island_params.margin = scene->toolsettings->uvcalc_margin;
uvedit_pack_islands_multi(
scene, objects, objects_len, nullptr, nullptr, false, &pack_island_params);
scene, objects, objects_len, nullptr, nullptr, false, true, &pack_island_params);
}
}
@ -2377,7 +2509,7 @@ static int unwrap_exec(bContext *C, wmOperator *op)
pack_island_params.margin = RNA_float_get(op->ptr, "margin");
uvedit_pack_islands_multi(
scene, objects, objects_len, nullptr, nullptr, false, &pack_island_params);
scene, objects, objects_len, nullptr, nullptr, false, true, &pack_island_params);
MEM_freeN(objects);
@ -2759,7 +2891,7 @@ static int smart_project_exec(bContext *C, wmOperator *op)
params.margin = RNA_float_get(op->ptr, "island_margin");
uvedit_pack_islands_multi(
scene, objects_changed, object_changed_len, nullptr, nullptr, false, &params);
scene, objects_changed, object_changed_len, nullptr, nullptr, false, true, &params);
/* #uvedit_pack_islands_multi only supports `per_face_aspect = false`. */
const bool per_face_aspect = false;
@ -3747,7 +3879,7 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
params.margin_method = ED_UVPACK_MARGIN_SCALED;
params.margin = 0.001f;
uvedit_pack_islands_multi(scene, &ob, 1, &bm, nullptr, false, &params);
uvedit_pack_islands_multi(scene, &ob, 1, &bm, nullptr, false, true, &params);
/* Write back from BMesh to Mesh. */
BMeshToMeshParams bm_to_me_params{};

View File

@ -37,7 +37,7 @@ enum eUVPackIsland_ShapeMethod {
enum eUVPackIsland_PinMethod {
ED_UVPACK_PIN_IGNORED = 0,
ED_UVPACK_PIN_NORMAL,
ED_UVPACK_PIN_DEFAULT,
ED_UVPACK_PIN_LOCK_ROTATION,
ED_UVPACK_PIN_LOCK_ROTATION_SCALE,
ED_UVPACK_PIN_LOCK_SCALE,
@ -55,6 +55,7 @@ class UVPackIsland_Params {
void setFromUnwrapOptions(const UnwrapOptions &options);
void setUDIMOffsetFromSpaceImage(const SpaceImage *sima);
bool isCancelled() const;
/** Islands can be rotated to improve packing. */
bool rotate;
@ -84,6 +85,12 @@ class UVPackIsland_Params {
float target_aspect_y;
/** Which shape to use when packing. */
eUVPackIsland_ShapeMethod shape_method;
/** Abandon packing early when set by the job system. */
bool *stop;
bool *do_update;
/** How much progress we have made. From wmJob. */
float *progress;
};
class uv_phi;

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_kdtree.h"
#include "BLI_offset_indices.hh"
#include "BLI_task.hh"
#include "DNA_pointcloud_types.h"
@ -80,27 +81,25 @@ PointCloud *point_merge_by_distance(const PointCloud &src_points,
}
/* This array stores an offset into `merge_map` for every result point. */
Array<int> map_offsets(dst_size + 1);
Array<int> map_offsets_data(dst_size + 1);
int offset = 0;
for (const int i : IndexRange(dst_size)) {
map_offsets[i] = offset;
map_offsets_data[i] = offset;
offset += point_merge_counts[i];
}
map_offsets.last() = offset;
map_offsets_data.last() = offset;
OffsetIndices<int> map_offsets(map_offsets_data);
point_merge_counts.fill(0);
/* This array stores all of the source indices for every result point. The size is the source
* size because every input point is either merged with another or copied directly. */
Array<int> merge_map(src_size);
Array<int> merge_map_indices(src_size);
for (const int i : IndexRange(src_size)) {
const int merge_index = merge_indices[i];
const int dst_index = src_to_dst_indices[merge_index];
const IndexRange points(map_offsets[dst_index],
map_offsets[dst_index + 1] - map_offsets[dst_index]);
MutableSpan<int> point_merge_indices = merge_map.as_mutable_span().slice(points);
point_merge_indices[point_merge_counts[dst_index]] = i;
merge_map_indices[map_offsets[dst_index].first() + point_merge_counts[dst_index]] = i;
point_merge_counts[dst_index]++;
}
@ -114,8 +113,7 @@ PointCloud *point_merge_by_distance(const PointCloud &src_points,
threading::parallel_for(IndexRange(dst_size), 1024, [&](IndexRange range) {
for (const int i_dst : range) {
const IndexRange points(map_offsets[i_dst], map_offsets[i_dst + 1] - map_offsets[i_dst]);
dst.span[i_dst] = src[points.first()];
dst.span[i_dst] = src[map_offsets[i_dst].first()];
}
});
@ -143,9 +141,7 @@ PointCloud *point_merge_by_distance(const PointCloud &src_points,
* in the mixer the size of the result point cloud and to improve memory locality. */
bke::attribute_math::DefaultMixer<T> mixer{dst_attribute.span.slice(i_dst, 1)};
const IndexRange points(map_offsets[i_dst],
map_offsets[i_dst + 1] - map_offsets[i_dst]);
Span<int> src_merge_indices = merge_map.as_span().slice(points);
Span<int> src_merge_indices = merge_map_indices.as_span().slice(map_offsets[i_dst]);
for (const int i_src : src_merge_indices) {
mixer.mix_in(0, src[i_src]);
}

View File

@ -6,6 +6,8 @@
#include "GEO_uv_pack.hh"
#include "BKE_global.h"
#include "BLI_array.hh"
#include "BLI_bounds.hh"
#include "BLI_boxpack_2d.h"
@ -329,7 +331,7 @@ UVPackIsland_Params::UVPackIsland_Params()
only_selected_faces = false;
use_seams = false;
correct_aspect = false;
pin_method = ED_UVPACK_PIN_NORMAL;
pin_method = ED_UVPACK_PIN_DEFAULT;
pin_unselected = false;
merge_overlap = false;
margin = 0.001f;
@ -338,6 +340,9 @@ UVPackIsland_Params::UVPackIsland_Params()
udim_base_offset[1] = 0.0f;
target_aspect_y = 1.0f;
shape_method = ED_UVPACK_SHAPE_AABB;
stop = nullptr;
do_update = nullptr;
progress = nullptr;
}
/* Compact representation for AABB packers. */
@ -1200,6 +1205,13 @@ static int64_t pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
while (i < island_indices.size()) {
if (params.stop && G.is_break) {
*params.stop = true;
}
if (params.isCancelled()) {
break;
}
while (traced_islands < i) {
/* Trace an island that's been solved. (Greedy.) */
const int64_t island_index = island_indices[traced_islands]->index;
@ -1308,17 +1320,26 @@ static int64_t pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
else {
scan_line = std::max(0, scan_line - 25); /* `-25` must by odd. */
}
if (params.progress) {
/* We don't (yet) have a good model for how long the pack operation is going
* to take, so just update the progress a little bit. */
const float previous_progress = *params.progress;
*params.do_update = true;
const float reduction = island_indices.size() / (island_indices.size() + 0.5f);
*params.progress = 1.0f - (1.0f - previous_progress) * reduction;
}
}
if (!is_larger(*r_extent, extent, params)) {
return 0;
}
*r_extent = extent;
for (const int64_t i : phis.index_range()) {
const int64_t island_index = island_indices[i]->index;
for (int64_t j = 0; j < i; j++) {
const int64_t island_index = island_indices[j]->index;
r_phis[island_index] = phis[island_index];
}
return phis.size();
return i;
}
/**
@ -1434,7 +1455,7 @@ static float pack_islands_scale_margin(const Span<PackIsland *> islands,
alpaca_cutoff = alpaca_cutoff_fast;
}
}
const int64_t max_box_pack = std::min(alpaca_cutoff, islands.size());
int64_t max_box_pack = std::min(alpaca_cutoff, islands.size());
rctf extent = {0.0f, 1e30f, 0.0f, 1e30f};
@ -1460,13 +1481,13 @@ static float pack_islands_scale_margin(const Span<PackIsland *> islands,
switch (params.shape_method) {
case ED_UVPACK_SHAPE_CONVEX:
case ED_UVPACK_SHAPE_CONCAVE:
pack_island_xatlas(aabbs.as_span().take_front(max_box_pack),
islands,
scale,
margin,
params,
r_phis,
&extent);
max_box_pack = pack_island_xatlas(aabbs.as_span().take_front(max_box_pack),
islands,
scale,
margin,
params,
r_phis,
&extent);
break;
default:
break;

View File

@ -34,8 +34,11 @@ void VKBatch::draw(int vertex_first, int vertex_count, int instance_first, int i
if (draw_indexed) {
index_buffer->upload_data();
index_buffer->bind(context);
context.command_buffer_get().draw(
index_buffer->index_len_get(), instance_count, index_buffer->index_start_get(), vertex_first, instance_first);
context.command_buffer_get().draw(index_buffer->index_len_get(),
instance_count,
index_buffer->index_start_get(),
vertex_first,
instance_first);
}
else {
context.command_buffer_get().draw(vertex_first, vertex_count, instance_first, instance_count);

View File

@ -66,6 +66,8 @@ class VKBuffer {
*
* VKImmediate mode uses a single VKBuffer with multiple vertex layouts. Those layouts are send to
* the command buffer containing an offset.
*
* VKIndexBuffer uses this when it is a subrange of another buffer.
*/
struct VKBufferWithOffset {
VKBuffer &buffer;

View File

@ -116,12 +116,12 @@ void VKCommandBuffer::bind(const uint32_t binding,
vkCmdBindVertexBuffers(vk_command_buffer_, binding, 1, &vk_vertex_buffer, &offset);
}
void VKCommandBuffer::bind(const VKIndexBuffer &index_buffer, VkIndexType index_type)
void VKCommandBuffer::bind(const VKBufferWithOffset &index_buffer, VkIndexType index_type)
{
validate_framebuffer_exists();
ensure_active_framebuffer();
VkBuffer vk_buffer = index_buffer.vk_handle();
vkCmdBindIndexBuffer(vk_command_buffer_, vk_buffer, 0, index_type);
vkCmdBindIndexBuffer(
vk_command_buffer_, index_buffer.buffer.vk_handle(), index_buffer.offset, index_type);
}
void VKCommandBuffer::begin_render_pass(const VKFrameBuffer &framebuffer)

View File

@ -144,7 +144,8 @@ class VKCommandBuffer : NonCopyable, NonMovable {
/* Bind the given buffer as a vertex buffer. */
void bind(const uint32_t binding, const VKBufferWithOffset &vertex_buffer);
void bind(const uint32_t binding, const VkBuffer &vk_vertex_buffer, const VkDeviceSize offset);
void bind(const VKIndexBuffer &index_buffer, VkIndexType index_type);
/* Bind the given buffer as an index buffer. */
void bind(const VKBufferWithOffset &index_buffer, VkIndexType index_type);
void begin_render_pass(const VKFrameBuffer &framebuffer);
void end_render_pass(const VKFrameBuffer &framebuffer);

View File

@ -97,4 +97,6 @@ template<typename T> VkObjectType to_vk_object_type(T /*vk_obj*/)
return VK_OBJECT_TYPE_UNKNOWN;
}
#define NOT_YET_IMPLEMENTED printf("%s not implemented yet\n", __func__);
} // namespace blender::gpu

View File

@ -5,11 +5,16 @@
* \ingroup gpu
*/
#include "GPU_batch.h"
#include "vk_drawlist.hh"
namespace blender::gpu {
void VKDrawList::append(GPUBatch * /*batch*/, int /*i_first*/, int /*i_count*/) {}
void VKDrawList::append(GPUBatch *batch, int instance_first, int instance_count)
{
GPU_batch_draw_advanced(batch, 0, 0, instance_first, instance_count);
}
void VKDrawList::submit() {}

View File

@ -13,7 +13,7 @@ namespace blender::gpu {
class VKDrawList : public DrawList {
public:
void append(GPUBatch *batch, int i_first, int i_count) override;
void append(GPUBatch *batch, int instance_first, int instance_count) override;
void submit() override;
};

View File

@ -35,7 +35,7 @@ void VKIndexBuffer::upload_data()
void VKIndexBuffer::bind(VKContext &context)
{
context.command_buffer_get().bind(*this, to_vk_index_type(index_type_));
context.command_buffer_get().bind(buffer_with_offset(), to_vk_index_type(index_type_));
}
void VKIndexBuffer::bind_as_ssbo(uint binding)
@ -61,9 +61,15 @@ void VKIndexBuffer::read(uint32_t *data) const
buffer_.read(data);
}
void VKIndexBuffer::update_sub(uint /*start*/, uint /*len*/, const void * /*data*/) {}
void VKIndexBuffer::update_sub(uint /*start*/, uint /*len*/, const void * /*data*/)
{
NOT_YET_IMPLEMENTED
}
void VKIndexBuffer::strip_restart_indices() {}
void VKIndexBuffer::strip_restart_indices()
{
NOT_YET_IMPLEMENTED
}
void VKIndexBuffer::allocate()
{
@ -75,4 +81,16 @@ void VKIndexBuffer::allocate()
debug::object_label(buffer_.vk_handle(), "IndexBuffer");
}
VKBufferWithOffset VKIndexBuffer::buffer_with_offset()
{
VKIndexBuffer *src = unwrap(src_);
VKBufferWithOffset result{is_subrange_ ? src->buffer_ : buffer_, index_start_};
BLI_assert_msg(is_subrange_ || result.offset == 0,
"According to design index_start should always be zero when index buffer isn't "
"a subrange");
return result;
}
} // namespace blender::gpu

View File

@ -35,6 +35,7 @@ class VKIndexBuffer : public IndexBuf {
void strip_restart_indices() override;
void allocate();
void ensure_updated();
VKBufferWithOffset buffer_with_offset();
};
static inline VKIndexBuffer *unwrap(IndexBuf *index_buffer)

View File

@ -96,8 +96,6 @@ void VKVertexAttributeObject::update_bindings(const VKContext &context, VKBatch
}
is_valid = true;
BLI_assert(interface.enabled_attr_mask_ == occupied_attributes);
}
void VKVertexAttributeObject::update_bindings(VKImmediate &immediate)

View File

@ -22,7 +22,8 @@ class VKImmediate;
using AttributeMask = uint16_t;
struct VKVertexAttributeObject {
class VKVertexAttributeObject {
public:
bool is_valid = false;
VkPipelineVertexInputStateCreateInfo info = {
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, NULL};

View File

@ -35,11 +35,20 @@ void VKVertexBuffer::bind_as_ssbo(uint binding)
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, *location);
}
void VKVertexBuffer::bind_as_texture(uint /*binding*/) {}
void VKVertexBuffer::bind_as_texture(uint /*binding*/)
{
NOT_YET_IMPLEMENTED
}
void VKVertexBuffer::wrap_handle(uint64_t /*handle*/) {}
void VKVertexBuffer::wrap_handle(uint64_t /*handle*/)
{
NOT_YET_IMPLEMENTED
}
void VKVertexBuffer::update_sub(uint /*start*/, uint /*len*/, const void * /*data*/) {}
void VKVertexBuffer::update_sub(uint /*start*/, uint /*len*/, const void * /*data*/)
{
NOT_YET_IMPLEMENTED
}
void VKVertexBuffer::read(void *data) const
{
@ -61,7 +70,14 @@ void VKVertexBuffer::acquire_data()
data = (uchar *)MEM_mallocN(sizeof(uchar) * this->size_alloc_get(), __func__);
}
void VKVertexBuffer::resize_data() {}
void VKVertexBuffer::resize_data()
{
if (usage_ == GPU_USAGE_DEVICE_ONLY) {
return;
}
data = (uchar *)MEM_reallocN(data, sizeof(uchar) * this->size_alloc_get());
}
void VKVertexBuffer::release_data()
{
@ -90,7 +106,7 @@ void VKVertexBuffer::upload_data()
allocate();
}
if (flag &= GPU_VERTBUF_DATA_DIRTY) {
if (flag & GPU_VERTBUF_DATA_DIRTY) {
void *data_to_upload = data;
if (conversion_needed(format)) {
data_to_upload = convert();
@ -108,7 +124,10 @@ void VKVertexBuffer::upload_data()
}
}
void VKVertexBuffer::duplicate_data(VertBuf * /*dst*/) {}
void VKVertexBuffer::duplicate_data(VertBuf * /*dst*/)
{
NOT_YET_IMPLEMENTED
}
void VKVertexBuffer::allocate()
{

View File

@ -615,6 +615,20 @@ static void rna_float_print(FILE *f, float num)
}
}
static const char *rna_ui_scale_type_string(const PropertyScaleType type)
{
switch (type) {
case PROP_SCALE_LINEAR:
return "PROP_SCALE_LINEAR";
case PROP_SCALE_LOG:
return "PROP_SCALE_LOG";
case PROP_SCALE_CUBIC:
return "PROP_SCALE_CUBIC";
}
BLI_assert_unreachable();
return "";
}
static void rna_int_print(FILE *f, int64_t num)
{
if (num == INT_MIN) {
@ -4164,8 +4178,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
rna_function_string(fprop->getarray_ex),
rna_function_string(fprop->setarray_ex),
rna_function_string(fprop->range_ex));
rna_float_print(f, fprop->ui_scale_type);
fprintf(f, ", ");
fprintf(f, "%s, ", rna_ui_scale_type_string(fprop->ui_scale_type));
rna_float_print(f, fprop->softmin);
fprintf(f, ", ");
rna_float_print(f, fprop->softmax);

View File

@ -109,9 +109,17 @@ static void rna_Operator_enum_search_invoke(bContext *C, wmOperator *op)
WM_enum_search_invoke(C, op, NULL);
}
static bool rna_event_modal_handler_add(struct bContext *C, struct wmOperator *operator)
static bool rna_event_modal_handler_add(
struct bContext *C, ReportList *reports, struct wmOperator *operator)
{
return WM_event_add_modal_handler(C, operator) != NULL;
wmWindow *win = CTX_wm_window(C);
if (win == NULL) {
BKE_report(reports, RPT_ERROR, "No active window in context!");
return false;
}
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
return WM_event_add_modal_handler_ex(win, area, region, operator) != NULL;
}
/* XXX, need a way for python to know event types, 0x0110 is hard coded */
@ -776,7 +784,7 @@ void RNA_api_wm(StructRNA *srna)
func,
"Add a modal handler to the window manager, for the given modal operator "
"(called by invoke() with self, just before returning {'RUNNING_MODAL'})");
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "operator", "Operator", "", "Operator to call");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_function_return(

View File

@ -349,6 +349,7 @@ DefNode(GeometryNode, GEO_NODE_INPUT_RADIUS, 0, "INPUT_RADIUS", InputRadius, "Ra
DefNode(GeometryNode, GEO_NODE_INPUT_SCENE_TIME, 0, "INPUT_SCENE_TIME", InputSceneTime, "Scene Time", "Retrieve the current time in the scene's animation in units of seconds or frames")
DefNode(GeometryNode, GEO_NODE_INPUT_SHADE_SMOOTH, 0, "INPUT_SHADE_SMOOTH", InputShadeSmooth, "Is Shade Smooth", "Retrieve whether each face is marked for smooth shading")
DefNode(GeometryNode, GEO_NODE_INPUT_SHORTEST_EDGE_PATHS, 0, "SHORTEST_EDGE_PATHS", InputShortestEdgePaths, "Shortest Edge Paths", "")
DefNode(GeometryNode, GEO_NODE_INPUT_SIGNED_DISTANCE, 0, "SIGNED_DISTANCE", InputSignedDistance, "Signed Distance", "Retrieve the signed distance field grid called 'distance' from a volume")
DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_CYCLIC, 0, "INPUT_SPLINE_CYCLIC",InputSplineCyclic, "Is Spline Cyclic", "Retrieve whether each spline endpoint connects to the beginning")
DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_LENGTH, 0, "SPLINE_LENGTH", SplineLength, "Spline Length", "Retrieve the total length of each spline, as a distance or as a number of points")
DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_RESOLUTION, 0, "INPUT_SPLINE_RESOLUTION", InputSplineResolution, "Spline Resolution", "Retrieve the number of evaluated points that will be generated for every control point on curves")

View File

@ -102,6 +102,7 @@ set(SRC
nodes/node_geo_input_scene_time.cc
nodes/node_geo_input_shade_smooth.cc
nodes/node_geo_input_shortest_edge_paths.cc
nodes/node_geo_input_signed_distance.cc
nodes/node_geo_input_spline_cyclic.cc
nodes/node_geo_input_spline_length.cc
nodes/node_geo_input_spline_resolution.cc

View File

@ -86,6 +86,7 @@ void register_geometry_nodes()
register_node_type_geo_input_scene_time();
register_node_type_geo_input_shade_smooth();
register_node_type_geo_input_shortest_edge_paths();
register_node_type_geo_input_signed_distance();
register_node_type_geo_input_spline_cyclic();
register_node_type_geo_input_spline_length();
register_node_type_geo_input_spline_resolution();

View File

@ -83,6 +83,7 @@ void register_node_type_geo_input_radius();
void register_node_type_geo_input_scene_time();
void register_node_type_geo_input_shade_smooth();
void register_node_type_geo_input_shortest_edge_paths();
void register_node_type_geo_input_signed_distance();
void register_node_type_geo_input_spline_cyclic();
void register_node_type_geo_input_spline_length();
void register_node_type_geo_input_spline_resolution();

View File

@ -1093,14 +1093,6 @@ static void extrude_mesh_face_regions(Mesh &mesh,
BKE_mesh_runtime_clear_cache(&mesh);
}
/* Get the range into an array of extruded corners, edges, or vertices for a particular polygon. */
static IndexRange selected_corner_range(Span<int> offsets, const int index)
{
const int offset = offsets[index];
const int next_offset = offsets[index + 1];
return IndexRange(offset, next_offset - offset);
}
static void extrude_individual_mesh_faces(
Mesh &mesh,
const Field<bool> &selection_field,
@ -1131,12 +1123,13 @@ static void extrude_individual_mesh_faces(
* parallelism later on by avoiding the need to keep track of an offset when iterating through
* all polygons. */
int extrude_corner_size = 0;
Array<int> index_offsets(poly_selection.size() + 1);
Array<int> group_per_face_data(poly_selection.size() + 1);
for (const int i_selection : poly_selection.index_range()) {
index_offsets[i_selection] = extrude_corner_size;
group_per_face_data[i_selection] = extrude_corner_size;
extrude_corner_size += orig_polys[poly_selection[i_selection]].size();
}
index_offsets.last() = extrude_corner_size;
group_per_face_data.last() = extrude_corner_size;
const OffsetIndices<int> group_per_face(group_per_face_data);
const IndexRange new_vert_range{orig_vert_size, extrude_corner_size};
/* One edge connects each selected vertex to a new vertex on the extruded polygons. */
@ -1177,7 +1170,7 @@ static void extrude_individual_mesh_faces(
Array<int> duplicate_edge_indices(extrude_corner_size);
threading::parallel_for(poly_selection.index_range(), 256, [&](const IndexRange range) {
for (const int i_selection : range) {
const IndexRange extrude_range = selected_corner_range(index_offsets, i_selection);
const IndexRange extrude_range = group_per_face[i_selection];
const IndexRange poly = polys[poly_selection[i_selection]];
MutableSpan<int> poly_verts = corner_verts.slice(poly);
@ -1254,7 +1247,7 @@ static void extrude_individual_mesh_faces(
threading::parallel_for(poly_selection.index_range(), 512, [&](const IndexRange range) {
for (const int i_selection : range) {
const IndexRange poly = polys[poly_selection[i_selection]];
const IndexRange extrude_range = selected_corner_range(index_offsets, i_selection);
const IndexRange extrude_range = group_per_face[i_selection];
/* For the extruded edges, mix the data from the two neighboring original edges of
* the extruded polygon. */
@ -1288,7 +1281,7 @@ static void extrude_individual_mesh_faces(
threading::parallel_for(poly_selection.index_range(), 1024, [&](const IndexRange range) {
for (const int i_selection : range) {
const int poly_index = poly_selection[i_selection];
const IndexRange extrude_range = selected_corner_range(index_offsets, i_selection);
const IndexRange extrude_range = group_per_face[i_selection];
new_data.slice(extrude_range).fill(data[poly_index]);
}
});
@ -1306,7 +1299,7 @@ static void extrude_individual_mesh_faces(
for (const int i_selection : range) {
const IndexRange poly = polys[poly_selection[i_selection]];
const Span<T> poly_loop_data = data.slice(poly);
const IndexRange extrude_range = selected_corner_range(index_offsets, i_selection);
const IndexRange extrude_range = group_per_face[i_selection];
for (const int i : IndexRange(poly.size())) {
const int i_next = (i == poly.size() - 1) ? 0 : i + 1;
@ -1338,7 +1331,7 @@ static void extrude_individual_mesh_faces(
/* Offset the new vertices. */
threading::parallel_for(poly_selection.index_range(), 1024, [&](const IndexRange range) {
for (const int i_selection : range) {
const IndexRange extrude_range = selected_corner_range(index_offsets, i_selection);
const IndexRange extrude_range = group_per_face[i_selection];
for (float3 &position : new_positions.slice(extrude_range)) {
position += poly_offset[poly_selection[i_selection]];
}
@ -1366,7 +1359,7 @@ static void extrude_individual_mesh_faces(
threading::parallel_for(poly_selection.index_range(), 1024, [&](const IndexRange range) {
for (const int selection_i : range) {
const int poly_i = poly_selection[selection_i];
const IndexRange extrude_range = selected_corner_range(index_offsets, selection_i);
const IndexRange extrude_range = group_per_face[selection_i];
new_poly_orig_indices.slice(extrude_range).fill(poly_orig_indices[poly_i]);
}
});

View File

@ -0,0 +1,49 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "NOD_add_node_search.hh"
#include "NOD_socket_search_link.hh"
#include "node_geometry_util.hh"
namespace blender::nodes::node_geo_input_signed_distance_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Float>(N_("Signed Distance")).field_source();
}
static void search_node_add_ops(GatherAddNodeSearchParams &params)
{
if (U.experimental.use_new_volume_nodes) {
blender::nodes::search_node_add_ops_for_basic_node(params);
}
}
static void search_link_ops(GatherLinkSearchOpParams &params)
{
if (U.experimental.use_new_volume_nodes) {
blender::nodes::search_link_ops_for_basic_node(params);
}
}
static void node_geo_exec(GeoNodeExecParams params)
{
Field<float> signed_distance_field{AttributeFieldInput::Create<float>("distance")};
params.set_output("Signed Distance", std::move(signed_distance_field));
}
} // namespace blender::nodes::node_geo_input_signed_distance_cc
void register_node_type_geo_input_signed_distance()
{
namespace file_ns = blender::nodes::node_geo_input_signed_distance_cc;
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_SIGNED_DISTANCE, "Signed Distance", NODE_CLASS_INPUT);
ntype.geometry_node_execute = file_ns::node_geo_exec;
ntype.declare = file_ns::node_declare;
ntype.gather_add_node_search_ops = file_ns::search_node_add_ops;
ntype.gather_link_search_ops = file_ns::search_link_ops;
nodeRegisterType(&ntype);
}

View File

@ -8,7 +8,7 @@ namespace blender::nodes::node_shader_displacement_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Float>(N_("Height")).default_value(0.0f).min(0.0f).max(1000.0f);
b.add_input<decl::Float>(N_("Midlevel")).default_value(0.0f).min(0.0f).max(1000.0f);
b.add_input<decl::Float>(N_("Midlevel")).default_value(0.5f).min(0.0f).max(1000.0f);
b.add_input<decl::Float>(N_("Scale")).default_value(1.0f).min(0.0f).max(1000.0f);
b.add_input<decl::Vector>(N_("Normal")).hide_value();
b.add_output<decl::Vector>(N_("Displacement"));
@ -17,13 +17,6 @@ static void node_declare(NodeDeclarationBuilder &b)
static void node_shader_init_displacement(bNodeTree * /*ntree*/, bNode *node)
{
node->custom1 = SHD_SPACE_OBJECT; /* space */
/* Set default value here for backwards compatibility. */
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
if (STREQ(sock->name, "Midlevel")) {
((bNodeSocketValueFloat *)sock->default_value)->value = 0.5f;
}
}
}
static int gpu_shader_displacement(GPUMaterial *mat,

View File

@ -30,7 +30,11 @@ static void sh_node_tex_brick_declare(NodeDeclarationBuilder &b)
.max(0.125f)
.default_value(0.02f)
.no_muted_links();
b.add_input<decl::Float>(N_("Mortar Smooth")).min(0.0f).max(1.0f).no_muted_links();
b.add_input<decl::Float>(N_("Mortar Smooth"))
.min(0.0f)
.max(1.0f)
.default_value(0.1f)
.no_muted_links();
b.add_input<decl::Float>(N_("Bias")).min(-1.0f).max(1.0f).no_muted_links();
b.add_input<decl::Float>(N_("Brick Width"))
.min(0.01f)
@ -78,12 +82,6 @@ static void node_shader_init_tex_brick(bNodeTree * /*ntree*/, bNode *node)
tex->squash_freq = 2;
node->storage = tex;
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
if (STREQ(sock->name, "Mortar Smooth")) {
((bNodeSocketValueFloat *)sock->default_value)->value = 0.1f;
}
}
}
static int node_shader_gpu_tex_brick(GPUMaterial *mat,

View File

@ -519,7 +519,15 @@ void WM_event_free_ui_handler_all(struct bContext *C,
wmUIHandlerFunc handle_fn,
wmUIHandlerRemoveFunc remove_fn);
struct wmEventHandler_Op *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op);
/**
* Add a modal handler to `win`, `area` and `region` may optionally be NULL.
*/
struct wmEventHandler_Op *WM_event_add_modal_handler_ex(struct wmWindow *win,
struct ScrArea *area,
struct ARegion *region,
wmOperator *op) ATTR_NONNULL(1, 4);
struct wmEventHandler_Op *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op)
ATTR_NONNULL(1, 2);
/**
* Modal handlers store a pointer to an area which might be freed while the handler runs.
* Use this function to NULL all handler pointers to \a old_area.
@ -1518,6 +1526,7 @@ typedef enum eWM_JobType {
WM_JOB_TYPE_SEQ_DRAG_DROP_PREVIEW,
WM_JOB_TYPE_CALCULATE_SIMULATION_NODES,
WM_JOB_TYPE_BAKE_SIMULATION_NODES,
WM_JOB_TYPE_UV_PACK,
/* add as needed, bake, seq proxy build
* if having hard coded values is a problem */
} eWM_JobType;

View File

@ -4408,11 +4408,13 @@ static void WM_event_set_handler_flag(wmEventHandler *handler, const int flag)
}
#endif
wmEventHandler_Op *WM_event_add_modal_handler(bContext *C, wmOperator *op)
wmEventHandler_Op *WM_event_add_modal_handler_ex(wmWindow *win,
ScrArea *area,
ARegion *region,
wmOperator *op)
{
wmEventHandler_Op *handler = MEM_cnew<wmEventHandler_Op>(__func__);
handler->head.type = WM_HANDLER_TYPE_OP;
wmWindow *win = CTX_wm_window(C);
/* Operator was part of macro. */
if (op->opm) {
@ -4425,8 +4427,8 @@ wmEventHandler_Op *WM_event_add_modal_handler(bContext *C, wmOperator *op)
handler->op = op;
}
handler->context.area = CTX_wm_area(C); /* Means frozen screen context for modal handlers! */
handler->context.region = CTX_wm_region(C);
handler->context.area = area; /* Means frozen screen context for modal handlers! */
handler->context.region = region;
handler->context.region_type = handler->context.region ? handler->context.region->regiontype :
-1;
@ -4439,6 +4441,14 @@ wmEventHandler_Op *WM_event_add_modal_handler(bContext *C, wmOperator *op)
return handler;
}
wmEventHandler_Op *WM_event_add_modal_handler(bContext *C, wmOperator *op)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
return WM_event_add_modal_handler_ex(win, area, region, op);
}
void WM_event_modal_handler_area_replace(wmWindow *win, const ScrArea *old_area, ScrArea *new_area)
{
LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) {

View File

@ -1070,12 +1070,20 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
WM_cursor_wait(false);
{
Main *bmain = CTX_data_main(C);
/* Temporarily set the window context as this was once supported, see: #107759. */
wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
wmWindow *win = static_cast<wmWindow *>(wm->windows.first);
BLI_assert(!CTX_wm_window(C));
Main *bmain = CTX_data_main(C);
BKE_callback_exec_string(
bmain, success ? BKE_CB_EVT_LOAD_POST : BKE_CB_EVT_LOAD_POST_FAIL, filepath);
CTX_wm_window_set(C, win);
BKE_callback_exec_string(
bmain, success ? BKE_CB_EVT_LOAD_POST : BKE_CB_EVT_LOAD_POST_FAIL, filepath);
CTX_wm_window_set(C, nullptr);
BLI_assert(BKE_main_namemap_validate(bmain));
BLI_assert(BKE_main_namemap_validate(bmain));
}
return success;
}
@ -1457,10 +1465,20 @@ void wm_homefile_read_post(struct bContext *C,
wm_file_read_post(C, params_file_read_post);
if (params_file_read_post->use_data) {
BKE_callback_exec_string(CTX_data_main(C),
Main *bmain = CTX_data_main(C);
/* Temporarily set the window context as this was once supported, see: #107759. */
wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
wmWindow *win = static_cast<wmWindow *>(wm->windows.first);
BLI_assert(!CTX_wm_window(C));
CTX_wm_window_set(C, win);
BKE_callback_exec_string(bmain,
params_file_read_post->success ? BKE_CB_EVT_LOAD_POST :
BKE_CB_EVT_LOAD_POST_FAIL,
/* `filpath` (empty for home-file reading). */
"");
CTX_wm_window_set(C, nullptr);
}
if (params_file_read_post->is_alloc) {