Cleanup: Reduce binary size by deduplicating attribute processing #107823
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, ¶ms);
|
||||
scene, objects_changed, object_changed_len, nullptr, nullptr, false, true, ¶ms);
|
||||
|
||||
/* #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, ¶ms);
|
||||
uvedit_pack_islands_multi(scene, &ob, 1, &bm, nullptr, false, true, ¶ms);
|
||||
|
||||
/* Write back from BMesh to Mesh. */
|
||||
BMeshToMeshParams bm_to_me_params{};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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 ¶ms)
|
||||
{
|
||||
if (U.experimental.use_new_volume_nodes) {
|
||||
blender::nodes::search_node_add_ops_for_basic_node(params);
|
||||
}
|
||||
}
|
||||
|
||||
static void search_link_ops(GatherLinkSearchOpParams ¶ms)
|
||||
{
|
||||
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);
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue