Compare commits
18 Commits
temp-enum-
...
temp-inter
Author | SHA1 | Date | |
---|---|---|---|
2935fd5f4d | |||
abf62d06d1 | |||
35ae7ab933 | |||
cc17ed26ce | |||
20224369d9 | |||
e9b7e5e0b9 | |||
67e5edbaa3 | |||
f565620435 | |||
a6e4cb092e | |||
![]() |
bc0c06ecbe | ||
53468c2b13 | |||
47b8baa5c4 | |||
03e22da665 | |||
aa2f6e5977 | |||
ff0c42acfc | |||
a49d6a5350 | |||
bec72a43ae | |||
7b530c6096 |
@@ -62,15 +62,15 @@ bool BlenderSync::BKE_object_is_modified(BL::Object &b_ob)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BlenderSync::object_is_geometry(BL::Object &b_ob)
|
||||
bool BlenderSync::object_is_geometry(BObjectInfo &b_ob_info)
|
||||
{
|
||||
BL::ID b_ob_data = b_ob.data();
|
||||
BL::ID b_ob_data = b_ob_info.object_data;
|
||||
|
||||
if (!b_ob_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BL::Object::type_enum type = b_ob.type();
|
||||
BL::Object::type_enum type = b_ob_info.iter_object.type();
|
||||
|
||||
if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR) {
|
||||
/* Will be exported attached to mesh. */
|
||||
@@ -87,6 +87,24 @@ bool BlenderSync::object_is_geometry(BL::Object &b_ob)
|
||||
return b_ob_data.is_a(&RNA_Mesh);
|
||||
}
|
||||
|
||||
bool BlenderSync::object_can_have_geometry(BL::Object &b_ob)
|
||||
{
|
||||
BL::Object::type_enum type = b_ob.type();
|
||||
switch (type) {
|
||||
case BL::Object::type_MESH:
|
||||
case BL::Object::type_CURVE:
|
||||
case BL::Object::type_SURFACE:
|
||||
case BL::Object::type_META:
|
||||
case BL::Object::type_FONT:
|
||||
case BL::Object::type_HAIR:
|
||||
case BL::Object::type_POINTCLOUD:
|
||||
case BL::Object::type_VOLUME:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool BlenderSync::object_is_light(BL::Object &b_ob)
|
||||
{
|
||||
BL::ID b_ob_data = b_ob.data();
|
||||
@@ -189,7 +207,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
||||
}
|
||||
|
||||
/* only interested in object that we can create meshes from */
|
||||
if (!object_is_geometry(b_ob)) {
|
||||
if (!object_is_geometry(b_ob_info)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@@ -162,19 +162,19 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
/* Object */
|
||||
else if (b_id.is_a(&RNA_Object)) {
|
||||
BL::Object b_ob(b_id);
|
||||
const bool is_geometry = object_is_geometry(b_ob);
|
||||
const bool is_light = !is_geometry && object_is_light(b_ob);
|
||||
const bool can_have_geometry = object_can_have_geometry(b_ob);
|
||||
const bool is_light = !can_have_geometry && object_is_light(b_ob);
|
||||
|
||||
if (b_ob.is_instancer() && b_update.is_updated_shading()) {
|
||||
/* Needed for e.g. object color updates on instancer. */
|
||||
object_map.set_recalc(b_ob);
|
||||
}
|
||||
|
||||
if (is_geometry || is_light) {
|
||||
if (can_have_geometry || is_light) {
|
||||
const bool updated_geometry = b_update.is_updated_geometry();
|
||||
|
||||
/* Geometry (mesh, hair, volume). */
|
||||
if (is_geometry) {
|
||||
if (can_have_geometry) {
|
||||
if (b_update.is_updated_transform() || b_update.is_updated_shading()) {
|
||||
object_map.set_recalc(b_ob);
|
||||
}
|
||||
|
@@ -208,7 +208,8 @@ class BlenderSync {
|
||||
/* util */
|
||||
void find_shader(BL::ID &id, array<Node *> &used_shaders, Shader *default_shader);
|
||||
bool BKE_object_is_modified(BL::Object &b_ob);
|
||||
bool object_is_geometry(BL::Object &b_ob);
|
||||
bool object_is_geometry(BObjectInfo &b_ob_info);
|
||||
bool object_can_have_geometry(BL::Object &b_ob);
|
||||
bool object_is_light(BL::Object &b_ob);
|
||||
|
||||
/* variables */
|
||||
|
@@ -379,7 +379,6 @@ if(WITH_CYCLES_CUDA_BINARIES)
|
||||
${SRC_KERNEL_HEADERS}
|
||||
${SRC_KERNEL_DEVICE_GPU_HEADERS}
|
||||
${SRC_KERNEL_DEVICE_CUDA_HEADERS}
|
||||
${SRC_KERNEL_DEVICE_METAL_HEADERS}
|
||||
${SRC_UTIL_HEADERS}
|
||||
)
|
||||
set(cuda_cubins)
|
||||
|
@@ -92,25 +92,19 @@
|
||||
|
||||
/* Compute number of threads per block and minimum blocks per multiprocessor
|
||||
* given the maximum number of registers per thread. */
|
||||
|
||||
#define ccl_gpu_kernel_threads(block_num_threads) \
|
||||
extern "C" __global__ void __launch_bounds__(block_num_threads)
|
||||
|
||||
#define ccl_gpu_kernel_threads_registers(block_num_threads, thread_num_registers) \
|
||||
#define ccl_gpu_kernel(block_num_threads, thread_num_registers) \
|
||||
extern "C" __global__ void __launch_bounds__(block_num_threads, \
|
||||
GPU_MULTIPRESSOR_MAX_REGISTERS / \
|
||||
(block_num_threads * thread_num_registers))
|
||||
|
||||
/* allow ccl_gpu_kernel to accept 1 or 2 parameters */
|
||||
#define SELECT_MACRO(_1, _2, NAME, ...) NAME
|
||||
#define ccl_gpu_kernel(...) \
|
||||
SELECT_MACRO(__VA_ARGS__, ccl_gpu_kernel_threads_registers, ccl_gpu_kernel_threads)(__VA_ARGS__)
|
||||
#define ccl_gpu_kernel_threads(block_num_threads) \
|
||||
extern "C" __global__ void __launch_bounds__(block_num_threads)
|
||||
|
||||
#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
|
||||
|
||||
#define ccl_gpu_kernel_call(x) x
|
||||
|
||||
/* define a function object where "func" is the lambda body, and additional parameters are used to
|
||||
/* Define a function object where "func" is the lambda body, and additional parameters are used to
|
||||
* specify captured state */
|
||||
#define ccl_gpu_kernel_lambda(func, ...) \
|
||||
struct KernelLambda { \
|
||||
@@ -119,8 +113,7 @@
|
||||
{ \
|
||||
return (func); \
|
||||
} \
|
||||
} ccl_gpu_kernel_lambda_pass; \
|
||||
ccl_gpu_kernel_lambda_pass
|
||||
} ccl_gpu_kernel_lambda_pass
|
||||
|
||||
/* sanity checks */
|
||||
|
||||
|
@@ -56,8 +56,7 @@
|
||||
*/
|
||||
|
||||
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
||||
ccl_gpu_kernel_signature(integrator_reset,
|
||||
int num_states)
|
||||
ccl_gpu_kernel_signature(integrator_reset, int num_states)
|
||||
{
|
||||
const int state = ccl_gpu_global_id_x();
|
||||
|
||||
@@ -265,7 +264,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
||||
}
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_queued_paths_array,
|
||||
int num_states,
|
||||
ccl_global int *indices,
|
||||
@@ -273,14 +272,14 @@ ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
int kernel_index)
|
||||
{
|
||||
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) == kernel_index,
|
||||
int kernel_index)
|
||||
.kernel_index = kernel_index;
|
||||
int kernel_index);
|
||||
ccl_gpu_kernel_lambda_pass.kernel_index = kernel_index;
|
||||
|
||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||
num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_queued_shadow_paths_array,
|
||||
int num_states,
|
||||
ccl_global int *indices,
|
||||
@@ -288,25 +287,26 @@ ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
int kernel_index)
|
||||
{
|
||||
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, shadow_path, queued_kernel) == kernel_index,
|
||||
int kernel_index)
|
||||
.kernel_index = kernel_index;
|
||||
int kernel_index);
|
||||
ccl_gpu_kernel_lambda_pass.kernel_index = kernel_index;
|
||||
|
||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||
num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_active_paths_array,
|
||||
int num_states,
|
||||
ccl_global int *indices,
|
||||
ccl_global int *num_indices)
|
||||
{
|
||||
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) != 0);
|
||||
|
||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||
num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_terminated_paths_array,
|
||||
int num_states,
|
||||
ccl_global int *indices,
|
||||
@@ -314,11 +314,12 @@ ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
int indices_offset)
|
||||
{
|
||||
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) == 0);
|
||||
|
||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||
num_states, indices + indices_offset, num_indices, ccl_gpu_kernel_lambda_pass);
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_terminated_shadow_paths_array,
|
||||
int num_states,
|
||||
ccl_global int *indices,
|
||||
@@ -326,11 +327,12 @@ ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
int indices_offset)
|
||||
{
|
||||
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, shadow_path, queued_kernel) == 0);
|
||||
|
||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||
num_states, indices + indices_offset, num_indices, ccl_gpu_kernel_lambda_pass);
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_sorted_paths_array,
|
||||
int num_states,
|
||||
int num_states_limit,
|
||||
@@ -343,37 +345,37 @@ ccl_gpu_kernel(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_lambda((INTEGRATOR_STATE(state, path, queued_kernel) == kernel_index) ?
|
||||
INTEGRATOR_STATE(state, path, shader_sort_key) :
|
||||
GPU_PARALLEL_SORTED_INDEX_INACTIVE_KEY,
|
||||
int kernel_index)
|
||||
.kernel_index = kernel_index;
|
||||
|
||||
int kernel_index);
|
||||
ccl_gpu_kernel_lambda_pass.kernel_index = kernel_index;
|
||||
|
||||
const uint state_index = ccl_gpu_global_id_x();
|
||||
gpu_parallel_sorted_index_array(
|
||||
state_index,
|
||||
num_states,
|
||||
num_states_limit,
|
||||
indices,
|
||||
gpu_parallel_sorted_index_array(state_index,
|
||||
num_states,
|
||||
num_states_limit,
|
||||
indices,
|
||||
num_indices,
|
||||
key_counter,
|
||||
key_prefix_sum,
|
||||
ccl_gpu_kernel_lambda_pass);
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_compact_paths_array,
|
||||
int num_states,
|
||||
ccl_global int *indices,
|
||||
ccl_global int *num_indices,
|
||||
int num_active_paths)
|
||||
ccl_global int *num_indices,
|
||||
int num_active_paths)
|
||||
{
|
||||
ccl_gpu_kernel_lambda((state >= num_active_paths) && (INTEGRATOR_STATE(state, path, queued_kernel) != 0),
|
||||
int num_active_paths)
|
||||
.num_active_paths = num_active_paths;
|
||||
|
||||
ccl_gpu_kernel_lambda((state >= num_active_paths) &&
|
||||
(INTEGRATOR_STATE(state, path, queued_kernel) != 0),
|
||||
int num_active_paths);
|
||||
ccl_gpu_kernel_lambda_pass.num_active_paths = num_active_paths;
|
||||
|
||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||
num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_compact_states,
|
||||
ccl_global const int *active_terminated_states,
|
||||
const int active_states_offset,
|
||||
@@ -390,22 +392,23 @@ ccl_gpu_kernel(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
}
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_compact_shadow_paths_array,
|
||||
int num_states,
|
||||
ccl_global int *indices,
|
||||
ccl_global int *num_indices,
|
||||
int num_active_paths)
|
||||
ccl_global int *num_indices,
|
||||
int num_active_paths)
|
||||
{
|
||||
ccl_gpu_kernel_lambda((state >= num_active_paths) && (INTEGRATOR_STATE(state, shadow_path, queued_kernel) != 0),
|
||||
int num_active_paths)
|
||||
.num_active_paths = num_active_paths;
|
||||
ccl_gpu_kernel_lambda((state >= num_active_paths) &&
|
||||
(INTEGRATOR_STATE(state, shadow_path, queued_kernel) != 0),
|
||||
int num_active_paths);
|
||||
ccl_gpu_kernel_lambda_pass.num_active_paths = num_active_paths;
|
||||
|
||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||
num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
ccl_gpu_kernel_signature(integrator_compact_shadow_states,
|
||||
ccl_global const int *active_terminated_states,
|
||||
const int active_states_offset,
|
||||
@@ -422,7 +425,7 @@ ccl_gpu_kernel(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
||||
}
|
||||
}
|
||||
|
||||
ccl_gpu_kernel(GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(
|
||||
ccl_gpu_kernel_threads(GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(
|
||||
prefix_sum, ccl_global int *counter, ccl_global int *prefix_sum, int num_values)
|
||||
{
|
||||
gpu_parallel_prefix_sum(ccl_gpu_global_id_x(), counter, prefix_sum, num_values);
|
||||
@@ -524,7 +527,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
||||
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) \
|
||||
ccl_gpu_kernel_signature(film_convert_##variant, \
|
||||
const KernelFilmConvert kfilm_convert, \
|
||||
ccl_global uchar4 *rgba, \
|
||||
ccl_global float *pixels, \
|
||||
ccl_global float *render_buffer, \
|
||||
int num_pixels, \
|
||||
int width, \
|
||||
@@ -544,20 +547,10 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
||||
ccl_global const float *buffer = render_buffer + offset + x * kfilm_convert.pass_stride + \
|
||||
y * stride * kfilm_convert.pass_stride; \
|
||||
\
|
||||
float pixel[4]; \
|
||||
ccl_global float *pixel = pixels + \
|
||||
(render_pixel_index + rgba_offset) * kfilm_convert.pixel_stride; \
|
||||
\
|
||||
film_get_pass_pixel_##variant(&kfilm_convert, buffer, pixel); \
|
||||
\
|
||||
film_apply_pass_pixel_overlays_rgba(&kfilm_convert, buffer, pixel); \
|
||||
\
|
||||
if (input_channel_count == 1) { \
|
||||
pixel[1] = pixel[2] = pixel[0]; \
|
||||
} \
|
||||
if (input_channel_count <= 3) { \
|
||||
pixel[3] = 1.0f; \
|
||||
} \
|
||||
\
|
||||
ccl_global float *out = ((ccl_global float *)rgba) + rgba_offset + y * rgba_stride + x; \
|
||||
*(ccl_global float4 *)out = make_float4(pixel[0], pixel[1], pixel[2], pixel[3]); \
|
||||
} \
|
||||
\
|
||||
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) \
|
||||
@@ -585,8 +578,6 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
||||
\
|
||||
float pixel[4]; \
|
||||
film_get_pass_pixel_##variant(&kfilm_convert, buffer, pixel); \
|
||||
\
|
||||
film_apply_pass_pixel_overlays_rgba(&kfilm_convert, buffer, pixel); \
|
||||
\
|
||||
if (input_channel_count == 1) { \
|
||||
pixel[1] = pixel[2] = pixel[0]; \
|
||||
@@ -595,7 +586,9 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
||||
pixel[3] = 1.0f; \
|
||||
} \
|
||||
\
|
||||
ccl_global half4 *out = ((ccl_global half4 *)rgba) + (rgba_offset + y * rgba_stride + x); \
|
||||
film_apply_pass_pixel_overlays_rgba(&kfilm_convert, buffer, pixel); \
|
||||
\
|
||||
ccl_global half4 *out = ((ccl_global half4 *)rgba) + rgba_offset + y * rgba_stride + x; \
|
||||
*out = float4_to_half4_display(make_float4(pixel[0], pixel[1], pixel[2], pixel[3])); \
|
||||
}
|
||||
|
||||
@@ -617,6 +610,8 @@ KERNEL_FILM_CONVERT_VARIANT(shadow_catcher_matte_with_shadow, 4)
|
||||
KERNEL_FILM_CONVERT_VARIANT(combined, 4)
|
||||
KERNEL_FILM_CONVERT_VARIANT(float4, 4)
|
||||
|
||||
#undef KERNEL_FILM_CONVERT_VARIANT
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Shader evaluation.
|
||||
*/
|
||||
|
@@ -35,25 +35,19 @@
|
||||
|
||||
/* Compute number of threads per block and minimum blocks per multiprocessor
|
||||
* given the maximum number of registers per thread. */
|
||||
|
||||
#define ccl_gpu_kernel_threads(block_num_threads) \
|
||||
extern "C" __global__ void __launch_bounds__(block_num_threads)
|
||||
|
||||
#define ccl_gpu_kernel_threads_registers(block_num_threads, thread_num_registers) \
|
||||
#define ccl_gpu_kernel(block_num_threads, thread_num_registers) \
|
||||
extern "C" __global__ void __launch_bounds__(block_num_threads, \
|
||||
GPU_MULTIPRESSOR_MAX_REGISTERS / \
|
||||
(block_num_threads * thread_num_registers))
|
||||
|
||||
/* allow ccl_gpu_kernel to accept 1 or 2 parameters */
|
||||
#define SELECT_MACRO(_1, _2, NAME, ...) NAME
|
||||
#define ccl_gpu_kernel(...) \
|
||||
SELECT_MACRO(__VA_ARGS__, ccl_gpu_kernel_threads_registers, ccl_gpu_kernel_threads)(__VA_ARGS__)
|
||||
#define ccl_gpu_kernel_threads(block_num_threads) \
|
||||
extern "C" __global__ void __launch_bounds__(block_num_threads)
|
||||
|
||||
#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
|
||||
|
||||
#define ccl_gpu_kernel_call(x) x
|
||||
|
||||
/* define a function object where "func" is the lambda body, and additional parameters are used to
|
||||
/* Define a function object where "func" is the lambda body, and additional parameters are used to
|
||||
* specify captured state */
|
||||
#define ccl_gpu_kernel_lambda(func, ...) \
|
||||
struct KernelLambda { \
|
||||
@@ -62,8 +56,7 @@
|
||||
{ \
|
||||
return (func); \
|
||||
} \
|
||||
} ccl_gpu_kernel_lambda_pass; \
|
||||
ccl_gpu_kernel_lambda_pass
|
||||
} ccl_gpu_kernel_lambda_pass
|
||||
|
||||
/* sanity checks */
|
||||
|
||||
|
@@ -70,7 +70,8 @@ using namespace metal;
|
||||
|
||||
/* kernel.h adapters */
|
||||
|
||||
#define ccl_gpu_kernel(...)
|
||||
#define ccl_gpu_kernel(block_num_threads, thread_num_registers)
|
||||
#define ccl_gpu_kernel_threads(block_num_threads)
|
||||
|
||||
/* convert a comma-separated list into a semicolon-separated list (so that we can generate a struct based on kernel entrypoint parameters) */
|
||||
#define FN0()
|
||||
@@ -143,7 +144,7 @@ void kernel_gpu_##name::run(thread MetalKernelContext& context, \
|
||||
ccl_private MetalKernelContext &context; \
|
||||
__VA_ARGS__; \
|
||||
int operator()(const int state) const { return (func); } \
|
||||
}ccl_gpu_kernel_lambda_pass(context); ccl_gpu_kernel_lambda_pass
|
||||
} ccl_gpu_kernel_lambda_pass(context)
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -247,4 +248,4 @@ constant constexpr array<sampler, SamplerCount> metal_samplers = {
|
||||
sampler(address::repeat, filter::linear),
|
||||
sampler(address::clamp_to_edge, filter::linear),
|
||||
sampler(address::clamp_to_zero, filter::linear),
|
||||
};
|
||||
};
|
||||
|
@@ -264,7 +264,7 @@ PYGETTEXT_KEYWORDS = (() +
|
||||
for it in ("BMO_error_raise",)) +
|
||||
|
||||
tuple(("{}\\((?:[^\"',]+,)\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
|
||||
for it in ("modifier_setError",)) +
|
||||
for it in ("BKE_modifier_set_error",)) +
|
||||
|
||||
tuple((r"{}\(\s*" + _msg_re + r"\s*,\s*(?:" +
|
||||
r"\s*,\s*)?(?:".join(_ctxt_re_gen(i) for i in range(PYGETTEXT_MAX_MULTI_CTXT)) + r")?\s*\)").format(it)
|
||||
|
@@ -306,31 +306,6 @@ class NODE_OT_tree_path_parent(Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class NODE_OT_enum_item_add(Operator):
|
||||
'''Add enum item'''
|
||||
bl_idname = "node.enum_item_add"
|
||||
bl_label = "Add Enum Item"
|
||||
bl_options = {'UNDO'}
|
||||
|
||||
node_name: StringProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
space = context.space_data
|
||||
return space is not None and space.type == 'NODE_EDITOR' and space.edit_tree is not None
|
||||
|
||||
def execute(self, context):
|
||||
import random
|
||||
|
||||
space = context.space_data
|
||||
node = space.edit_tree.nodes.get(self.node_name)
|
||||
if node is None:
|
||||
return {'CANCELLED'}
|
||||
item = node.enum_items.new()
|
||||
item.value = random.randint(0, 1e7)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
classes = (
|
||||
NodeSetting,
|
||||
|
||||
@@ -339,5 +314,4 @@ classes = (
|
||||
NODE_OT_add_search,
|
||||
NODE_OT_collapse_hide_unused_toggle,
|
||||
NODE_OT_tree_path_parent,
|
||||
NODE_OT_enum_item_add,
|
||||
)
|
||||
|
@@ -754,7 +754,6 @@ geometry_node_categories = [
|
||||
NodeItem("GeometryNodeSwitch"),
|
||||
NodeItem("FunctionNodeRandomValue"),
|
||||
NodeItem("FunctionNodeAlignEulerToVector"),
|
||||
NodeItem("FunctionNodeEnum"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_VECTOR", "Vector", items=[
|
||||
NodeItem("ShaderNodeVectorCurve"),
|
||||
|
@@ -41,7 +41,8 @@ struct Mesh;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
|
||||
void BKE_mesh_runtime_reset(struct Mesh *mesh);
|
||||
void BKE_mesh_runtime_init_data(struct Mesh *mesh);
|
||||
void BKE_mesh_runtime_free_data(struct Mesh *mesh);
|
||||
void BKE_mesh_runtime_reset_on_copy(struct Mesh *mesh, const int flag);
|
||||
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh);
|
||||
void BKE_mesh_runtime_looptri_recalc(struct Mesh *mesh);
|
||||
|
@@ -264,12 +264,6 @@ typedef struct bNodeType {
|
||||
/* Additional parameters in the side panel */
|
||||
void (*draw_buttons_ex)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
|
||||
|
||||
bool (*draw_socket)(struct uiLayout *layout,
|
||||
const struct bContext *C,
|
||||
struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
struct bNodeSocket *socket);
|
||||
|
||||
/* Additional drawing on backdrop */
|
||||
void (*draw_backdrop)(
|
||||
struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y);
|
||||
@@ -741,7 +735,6 @@ void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available);
|
||||
|
||||
int nodeSocketLinkLimit(const struct bNodeSocket *sock);
|
||||
|
||||
void nodeUpdateFromDeclaration(struct bNodeTree *ntree, struct bNode *node);
|
||||
bool nodeDeclarationEnsure(struct bNodeTree *ntree, struct bNode *node);
|
||||
bool nodeDeclarationEnsureOnOutdatedNode(struct bNodeTree *ntree, struct bNode *node);
|
||||
void nodeSocketDeclarationsUpdate(struct bNode *node);
|
||||
@@ -1584,7 +1577,6 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
|
||||
#define FN_NODE_REPLACE_STRING 1218
|
||||
#define FN_NODE_INPUT_BOOL 1219
|
||||
#define FN_NODE_INPUT_INT 1220
|
||||
#define FN_NODE_ENUM 1221
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@@ -88,7 +88,7 @@ static void mesh_init_data(ID *id)
|
||||
CustomData_reset(&mesh->pdata);
|
||||
CustomData_reset(&mesh->ldata);
|
||||
|
||||
BKE_mesh_runtime_reset(mesh);
|
||||
BKE_mesh_runtime_init_data(mesh);
|
||||
|
||||
mesh->face_sets_color_seed = BLI_hash_int(PIL_check_seconds_timer_i() & UINT_MAX);
|
||||
}
|
||||
@@ -168,7 +168,7 @@ static void mesh_free_data(ID *id)
|
||||
mesh->edit_mesh = nullptr;
|
||||
}
|
||||
|
||||
BKE_mesh_runtime_clear_cache(mesh);
|
||||
BKE_mesh_runtime_free_data(mesh);
|
||||
mesh_clear_geometry(mesh);
|
||||
MEM_SAFE_FREE(mesh->mat);
|
||||
}
|
||||
@@ -308,7 +308,9 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
|
||||
mesh->texflag &= ~ME_AUTOSPACE_EVALUATED;
|
||||
mesh->edit_mesh = nullptr;
|
||||
BKE_mesh_runtime_reset(mesh);
|
||||
|
||||
memset(&mesh->runtime, 0, sizeof(mesh->runtime));
|
||||
BKE_mesh_runtime_init_data(mesh);
|
||||
|
||||
/* happens with old files */
|
||||
if (mesh->mselect == nullptr) {
|
||||
|
@@ -45,17 +45,54 @@
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Default values defined at read time.
|
||||
* \brief Initialize the runtime mutexes of the given mesh.
|
||||
*
|
||||
* Any existing mutexes will be overridden.
|
||||
*/
|
||||
void BKE_mesh_runtime_reset(Mesh *mesh)
|
||||
static void mesh_runtime_init_mutexes(Mesh *mesh)
|
||||
{
|
||||
memset(&mesh->runtime, 0, sizeof(mesh->runtime));
|
||||
mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex");
|
||||
BLI_mutex_init(mesh->runtime.eval_mutex);
|
||||
mesh->runtime.render_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime render_mutex");
|
||||
BLI_mutex_init(mesh->runtime.render_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief free the mutexes of the given mesh runtime.
|
||||
*/
|
||||
static void mesh_runtime_free_mutexes(Mesh *mesh)
|
||||
{
|
||||
if (mesh->runtime.eval_mutex != NULL) {
|
||||
BLI_mutex_end(mesh->runtime.eval_mutex);
|
||||
MEM_freeN(mesh->runtime.eval_mutex);
|
||||
mesh->runtime.eval_mutex = NULL;
|
||||
}
|
||||
if (mesh->runtime.render_mutex != NULL) {
|
||||
BLI_mutex_end(mesh->runtime.render_mutex);
|
||||
MEM_freeN(mesh->runtime.render_mutex);
|
||||
mesh->runtime.render_mutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialize the runtime of the given mesh.
|
||||
*
|
||||
* Function expects that the runtime is already cleared.
|
||||
*/
|
||||
void BKE_mesh_runtime_init_data(Mesh *mesh)
|
||||
{
|
||||
mesh_runtime_init_mutexes(mesh);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Free all data (and mutexes) inside the runtime of the given mesh.
|
||||
*/
|
||||
void BKE_mesh_runtime_free_data(Mesh *mesh)
|
||||
{
|
||||
BKE_mesh_runtime_clear_cache(mesh);
|
||||
mesh_runtime_free_mutexes(mesh);
|
||||
}
|
||||
|
||||
/* Clear all pointers which we don't want to be shared on copying the datablock.
|
||||
* However, keep all the flags which defines what the mesh is (for example, that
|
||||
* it's deformed only, or that its custom data layers are out of date.) */
|
||||
@@ -71,25 +108,16 @@ void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int UNUSED(flag))
|
||||
runtime->bvh_cache = NULL;
|
||||
runtime->shrinkwrap_data = NULL;
|
||||
|
||||
mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex");
|
||||
BLI_mutex_init(mesh->runtime.eval_mutex);
|
||||
|
||||
mesh->runtime.render_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime render_mutex");
|
||||
BLI_mutex_init(mesh->runtime.render_mutex);
|
||||
mesh_runtime_init_mutexes(mesh);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief This function clears runtime cache of the given mesh.
|
||||
*
|
||||
* Call this function to recalculate runtime data when used.
|
||||
*/
|
||||
void BKE_mesh_runtime_clear_cache(Mesh *mesh)
|
||||
{
|
||||
if (mesh->runtime.eval_mutex != NULL) {
|
||||
BLI_mutex_end(mesh->runtime.eval_mutex);
|
||||
MEM_freeN(mesh->runtime.eval_mutex);
|
||||
mesh->runtime.eval_mutex = NULL;
|
||||
}
|
||||
if (mesh->runtime.render_mutex != NULL) {
|
||||
BLI_mutex_end(mesh->runtime.render_mutex);
|
||||
MEM_freeN(mesh->runtime.render_mutex);
|
||||
mesh->runtime.render_mutex = NULL;
|
||||
}
|
||||
if (mesh->runtime.mesh_eval != NULL) {
|
||||
mesh->runtime.mesh_eval->edit_mesh = NULL;
|
||||
BKE_id_free(NULL, mesh->runtime.mesh_eval);
|
||||
|
@@ -87,7 +87,6 @@
|
||||
#include "NOD_node_tree_ref.hh"
|
||||
#include "NOD_shader.h"
|
||||
#include "NOD_socket.h"
|
||||
#include "NOD_socket_declarations.hh"
|
||||
#include "NOD_texture.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
@@ -131,6 +130,10 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
|
||||
static void nodeMuteRerouteOutputLinks(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
const bool mute);
|
||||
static FieldInferencingInterface *node_field_inferencing_interface_copy(
|
||||
const FieldInferencingInterface &field_inferencing_interface);
|
||||
static void node_field_inferencing_interface_free(
|
||||
const FieldInferencingInterface *field_inferencing_interface);
|
||||
|
||||
static void ntree_init_data(ID *id)
|
||||
{
|
||||
@@ -243,13 +246,9 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
|
||||
ntree_dst->interface_type = nullptr;
|
||||
|
||||
if (ntree_src->field_inferencing_interface) {
|
||||
ntree_dst->field_inferencing_interface = new blender::nodes::FieldInferencingInterface(
|
||||
ntree_dst->field_inferencing_interface = node_field_inferencing_interface_copy(
|
||||
*ntree_src->field_inferencing_interface);
|
||||
}
|
||||
if (ntree_src->enum_inferencing_interface) {
|
||||
ntree_dst->enum_inferencing_interface = new blender::nodes::EnumInferencingInterface(
|
||||
*ntree_src->enum_inferencing_interface);
|
||||
}
|
||||
|
||||
if (flag & LIB_ID_COPY_NO_PREVIEW) {
|
||||
ntree_dst->preview = nullptr;
|
||||
@@ -302,8 +301,7 @@ static void ntree_free_data(ID *id)
|
||||
MEM_freeN(sock);
|
||||
}
|
||||
|
||||
delete ntree->field_inferencing_interface;
|
||||
delete ntree->enum_inferencing_interface;
|
||||
node_field_inferencing_interface_free(ntree->field_inferencing_interface);
|
||||
|
||||
/* free preview hash */
|
||||
if (ntree->previews) {
|
||||
@@ -361,7 +359,6 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_ENUM:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -493,9 +490,6 @@ static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *so
|
||||
case SOCK_MATERIAL:
|
||||
BLO_write_struct(writer, bNodeSocketValueMaterial, sock->default_value);
|
||||
break;
|
||||
case SOCK_ENUM:
|
||||
BLO_write_struct(writer, bNodeSocketValueEnum, sock->default_value);
|
||||
break;
|
||||
case __SOCK_MESH:
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
@@ -626,15 +620,6 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
|
||||
}
|
||||
BLO_write_struct_by_name(writer, node->typeinfo->storagename, storage);
|
||||
}
|
||||
else if (node->type == FN_NODE_ENUM) {
|
||||
NodeFunctionEnum *storage = (NodeFunctionEnum *)node->storage;
|
||||
BLO_write_struct(writer, NodeFunctionEnum, storage);
|
||||
BLO_write_struct_list(writer, NodeFunctionEnumItem, &storage->items);
|
||||
LISTBASE_FOREACH (NodeFunctionEnumItem *, item, &storage->items) {
|
||||
BLO_write_string(writer, item->name);
|
||||
BLO_write_string(writer, item->description);
|
||||
}
|
||||
}
|
||||
else if (node->typeinfo != &NodeTypeUndefined) {
|
||||
BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
|
||||
}
|
||||
@@ -697,10 +682,6 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
|
||||
sock->total_inputs = 0; /* Clear runtime data set before drawing. */
|
||||
sock->cache = nullptr;
|
||||
sock->declaration = nullptr;
|
||||
if (sock->type == SOCK_ENUM) {
|
||||
bNodeSocketValueEnum *socket_value = (bNodeSocketValueEnum *)sock->default_value;
|
||||
socket_value->items = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* ntree itself has been read! */
|
||||
@@ -716,7 +697,6 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
|
||||
ntree->execdata = nullptr;
|
||||
|
||||
ntree->field_inferencing_interface = nullptr;
|
||||
ntree->enum_inferencing_interface = nullptr;
|
||||
|
||||
BLO_read_data_address(reader, &ntree->adt);
|
||||
BKE_animdata_blend_read_data(reader, ntree->adt);
|
||||
@@ -821,17 +801,6 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
|
||||
BLO_read_data_address(reader, &storage->string);
|
||||
break;
|
||||
}
|
||||
case FN_NODE_ENUM: {
|
||||
NodeFunctionEnum *storage = (NodeFunctionEnum *)node->storage;
|
||||
BLO_read_data_address(reader, &storage->owner_node);
|
||||
BLO_read_list(reader, &storage->items);
|
||||
LISTBASE_FOREACH (NodeFunctionEnumItem *, item, &storage->items) {
|
||||
BLO_read_data_address(reader, &item->owner_node);
|
||||
BLO_read_data_address(reader, &item->name);
|
||||
BLO_read_data_address(reader, &item->description);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -936,7 +905,6 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_ENUM:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1032,7 +1000,6 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock)
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_ENUM:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1160,6 +1127,8 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
|
||||
BLI_strncpy(node->name, DATA_(ntype->ui_name), NODE_MAXSTR);
|
||||
nodeUniqueName(ntree, node);
|
||||
|
||||
node_add_sockets_from_type(ntree, node, ntype);
|
||||
|
||||
if (ntype->initfunc != nullptr) {
|
||||
ntype->initfunc(ntree, node);
|
||||
}
|
||||
@@ -1168,8 +1137,6 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
|
||||
ntree->typeinfo->node_add_init(ntree, node);
|
||||
}
|
||||
|
||||
node_add_sockets_from_type(ntree, node, ntype);
|
||||
|
||||
if (node->id) {
|
||||
id_us_plus(node->id);
|
||||
}
|
||||
@@ -1447,7 +1414,7 @@ void nodeRegisterType(bNodeType *nt)
|
||||
if (nt->declare && !nt->declaration_is_dynamic) {
|
||||
if (nt->fixed_declaration == nullptr) {
|
||||
nt->fixed_declaration = new blender::nodes::NodeDeclaration();
|
||||
blender::nodes::NodeDeclarationBuilder builder{*nt->fixed_declaration, nullptr};
|
||||
blender::nodes::NodeDeclarationBuilder builder{*nt->fixed_declaration};
|
||||
nt->declare(builder);
|
||||
}
|
||||
}
|
||||
@@ -1633,7 +1600,6 @@ static void socket_id_user_increment(bNodeSocket *sock)
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_ENUM:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1687,7 +1653,6 @@ static void socket_id_user_decrement(bNodeSocket *sock)
|
||||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_ENUM:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1850,8 +1815,6 @@ const char *nodeStaticSocketType(int type, int subtype)
|
||||
return "NodeSocketTexture";
|
||||
case SOCK_MATERIAL:
|
||||
return "NodeSocketMaterial";
|
||||
case SOCK_ENUM:
|
||||
return "NodeSocketEnum";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1929,8 +1892,6 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype)
|
||||
return "NodeSocketInterfaceTexture";
|
||||
case SOCK_MATERIAL:
|
||||
return "NodeSocketInterfaceMaterial";
|
||||
case SOCK_ENUM:
|
||||
return "NodeSocketInterfaceEnum";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1964,8 +1925,6 @@ const char *nodeStaticSocketLabel(int type, int UNUSED(subtype))
|
||||
return "Texture";
|
||||
case SOCK_MATERIAL:
|
||||
return "Material";
|
||||
case SOCK_ENUM:
|
||||
return "Enum";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -4094,7 +4053,7 @@ bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
}
|
||||
if (node->typeinfo->declaration_is_dynamic) {
|
||||
node->declaration = new blender::nodes::NodeDeclaration();
|
||||
blender::nodes::NodeDeclarationBuilder builder{*node->declaration, node};
|
||||
blender::nodes::NodeDeclarationBuilder builder{*node->declaration};
|
||||
node->typeinfo->declare(builder);
|
||||
}
|
||||
else {
|
||||
@@ -4118,16 +4077,6 @@ bool nodeDeclarationEnsure(bNodeTree *ntree, bNode *node)
|
||||
return false;
|
||||
}
|
||||
|
||||
void nodeUpdateFromDeclaration(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
if (!node->typeinfo->declaration_is_dynamic) {
|
||||
return;
|
||||
}
|
||||
delete node->declaration;
|
||||
node->declaration = nullptr;
|
||||
node_verify_sockets(ntree, node, true);
|
||||
}
|
||||
|
||||
/* ************** Node Clipboard *********** */
|
||||
|
||||
#define USE_NODE_CB_VALIDATE
|
||||
@@ -4591,14 +4540,24 @@ void ntreeUpdateAllNew(Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
/* Ideally this would first sort the trees based on their dependencies and then update every
|
||||
* tree just once. */
|
||||
ntreeUpdateTree(main, ntree);
|
||||
ntreeUpdateTree(nullptr, ntree);
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
static FieldInferencingInterface *node_field_inferencing_interface_copy(
|
||||
const FieldInferencingInterface &field_inferencing_interface)
|
||||
{
|
||||
return new FieldInferencingInterface(field_inferencing_interface);
|
||||
}
|
||||
|
||||
static void node_field_inferencing_interface_free(
|
||||
const FieldInferencingInterface *field_inferencing_interface)
|
||||
{
|
||||
delete field_inferencing_interface;
|
||||
}
|
||||
|
||||
namespace blender::bke::node_field_inferencing {
|
||||
|
||||
static bool is_field_socket_type(eNodeSocketDatatype type)
|
||||
@@ -4611,7 +4570,7 @@ static bool is_field_socket_type(const SocketRef &socket)
|
||||
return is_field_socket_type((eNodeSocketDatatype)socket.typeinfo()->type);
|
||||
}
|
||||
|
||||
static bool update_field_inferencing(const NodeTreeRef &tree);
|
||||
static bool update_field_inferencing(bNodeTree &btree);
|
||||
|
||||
static InputSocketFieldType get_interface_input_field_type(const NodeRef &node,
|
||||
const InputSocketRef &socket)
|
||||
@@ -4710,8 +4669,7 @@ static FieldInferencingInterface get_node_field_inferencing_interface(const Node
|
||||
}
|
||||
if (group->field_inferencing_interface == nullptr) {
|
||||
/* Update group recursively. */
|
||||
const NodeTreeRef group_tree{group};
|
||||
update_field_inferencing(group_tree);
|
||||
update_field_inferencing(*group);
|
||||
}
|
||||
return *group->field_inferencing_interface;
|
||||
}
|
||||
@@ -5069,10 +5027,12 @@ static void update_socket_shapes(const NodeTreeRef &tree,
|
||||
}
|
||||
}
|
||||
|
||||
static bool update_field_inferencing(const NodeTreeRef &tree)
|
||||
static bool update_field_inferencing(bNodeTree &btree)
|
||||
{
|
||||
using namespace blender::nodes;
|
||||
bNodeTree &btree = *tree.btree();
|
||||
if (btree.type != NTREE_GEOMETRY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create new inferencing interface for this node group. */
|
||||
FieldInferencingInterface *new_inferencing_interface = new FieldInferencingInterface();
|
||||
@@ -5081,6 +5041,9 @@ static bool update_field_inferencing(const NodeTreeRef &tree)
|
||||
new_inferencing_interface->outputs.resize(BLI_listbase_count(&btree.outputs),
|
||||
OutputFieldDependency::ForDataSource());
|
||||
|
||||
/* Create #NodeTreeRef to accelerate various queries on the node tree (e.g. linked sockets). */
|
||||
const NodeTreeRef tree{&btree};
|
||||
|
||||
/* Keep track of the state of all sockets. The index into this array is #SocketRef::id(). */
|
||||
Array<SocketFieldState> field_state_by_socket_id(tree.sockets().size());
|
||||
|
||||
@@ -5102,185 +5065,6 @@ static bool update_field_inferencing(const NodeTreeRef &tree)
|
||||
|
||||
} // namespace blender::bke::node_field_inferencing
|
||||
|
||||
namespace blender::bke::enum_inferencing {
|
||||
|
||||
using namespace blender::nodes;
|
||||
|
||||
static bool update_enum_inferencing(const NodeTreeRef &tree);
|
||||
|
||||
static EnumInputInferencingInfo get_input_enum_socket_inferencing_info(
|
||||
const InputSocketRef &socket)
|
||||
{
|
||||
BLI_assert(socket.typeinfo()->type == SOCK_ENUM);
|
||||
const NodeRef &node = socket.node();
|
||||
if (node.is_group_node()) {
|
||||
bNodeTree *group = (bNodeTree *)node.bnode()->id;
|
||||
if (group == nullptr) {
|
||||
return {};
|
||||
}
|
||||
if (!ntreeIsRegistered(group)) {
|
||||
return {};
|
||||
}
|
||||
if (group->enum_inferencing_interface == nullptr) {
|
||||
/* Update group recursively. */
|
||||
const NodeTreeRef group_tree{group};
|
||||
update_enum_inferencing(group_tree);
|
||||
}
|
||||
return group->enum_inferencing_interface->inputs[socket.index()];
|
||||
}
|
||||
if (node.is_reroute_node()) {
|
||||
return {};
|
||||
}
|
||||
const decl::Enum &socket_decl = static_cast<const decl::Enum &>(*socket.bsocket()->declaration);
|
||||
return socket_decl.inferencing_info();
|
||||
}
|
||||
|
||||
struct EnumState {
|
||||
std::shared_ptr<EnumItems> items;
|
||||
int group_output_index = -1;
|
||||
bool targets_are_invalid = false;
|
||||
};
|
||||
|
||||
static bool enum_states_are_compatible(const EnumState &a, const EnumState &b)
|
||||
{
|
||||
if (a.items && b.items) {
|
||||
return a.items->items() == b.items->items();
|
||||
}
|
||||
if (a.group_output_index == -1 || b.group_output_index == -1) {
|
||||
return true;
|
||||
}
|
||||
if (a.group_output_index == b.group_output_index) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool update_enum_inferencing(const NodeTreeRef &tree)
|
||||
{
|
||||
using namespace blender::nodes;
|
||||
|
||||
bNodeTree &btree = *tree.btree();
|
||||
|
||||
/* TODO: handle cyclic trees */
|
||||
const NodeTreeRef::ToposortResult toposort_result = tree.toposort(
|
||||
NodeTreeRef::ToposortDirection::RightToLeft);
|
||||
|
||||
Map<const SocketRef *, EnumState> state_by_socket;
|
||||
|
||||
for (const NodeRef *node : toposort_result.sorted_nodes) {
|
||||
bNode &bnode = *node->bnode();
|
||||
nodeDeclarationEnsure(&btree, &bnode);
|
||||
|
||||
if (node->is_group_output_node()) {
|
||||
for (const InputSocketRef *input_socket : node->inputs()) {
|
||||
if (input_socket->typeinfo()->type == SOCK_ENUM) {
|
||||
state_by_socket.add(input_socket, EnumState{nullptr, input_socket->index()});
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const OutputSocketRef *socket : node->outputs()) {
|
||||
if (socket->typeinfo()->type != SOCK_ENUM) {
|
||||
continue;
|
||||
}
|
||||
EnumState enum_state;
|
||||
for (const InputSocketRef *target_socket : socket->directly_linked_sockets()) {
|
||||
if (target_socket->is_available()) {
|
||||
EnumState new_state = state_by_socket.lookup_default(target_socket, {});
|
||||
if (enum_states_are_compatible(enum_state, new_state)) {
|
||||
enum_state = new_state;
|
||||
enum_state.targets_are_invalid = false;
|
||||
}
|
||||
else {
|
||||
enum_state = {};
|
||||
enum_state.targets_are_invalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
state_by_socket.add_new(socket, enum_state);
|
||||
}
|
||||
|
||||
for (const InputSocketRef *socket : node->inputs()) {
|
||||
if (socket->typeinfo()->type != SOCK_ENUM) {
|
||||
continue;
|
||||
}
|
||||
EnumInputInferencingInfo inferencing_info = get_input_enum_socket_inferencing_info(*socket);
|
||||
EnumState input_state;
|
||||
if (inferencing_info.items) {
|
||||
input_state.items = inferencing_info.items;
|
||||
}
|
||||
else {
|
||||
int inference_index = inferencing_info.inference_index;
|
||||
if (inference_index == -1) {
|
||||
for (const OutputSocketRef *output_socket : node->outputs()) {
|
||||
if (output_socket->typeinfo()->type == SOCK_ENUM) {
|
||||
inference_index = output_socket->index();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
BLI_assert(inference_index >= 0);
|
||||
const OutputSocketRef &output_socket = node->output(inference_index);
|
||||
input_state = state_by_socket.lookup(&output_socket);
|
||||
input_state.targets_are_invalid = false;
|
||||
}
|
||||
state_by_socket.add_new(socket, input_state);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto item : state_by_socket.items()) {
|
||||
const SocketRef *socket = item.key;
|
||||
const EnumState &state = item.value;
|
||||
bNodeSocketValueEnum *socket_value = (bNodeSocketValueEnum *)socket->bsocket()->default_value;
|
||||
if (state.items) {
|
||||
socket_value->items = state.items->items();
|
||||
}
|
||||
else {
|
||||
socket_value->items = nullptr;
|
||||
}
|
||||
socket_value->targets_are_invalid = state.targets_are_invalid;
|
||||
}
|
||||
|
||||
EnumInferencingInterface *new_inferencing_interface = new EnumInferencingInterface();
|
||||
new_inferencing_interface->inputs.resize(BLI_listbase_count(&btree.inputs));
|
||||
|
||||
for (const NodeRef *node : tree.nodes_by_type("NodeGroupInput")) {
|
||||
for (const OutputSocketRef *output_socket : node->outputs().drop_back(1)) {
|
||||
if (output_socket->typeinfo()->type != SOCK_ENUM) {
|
||||
continue;
|
||||
}
|
||||
const EnumState &state = state_by_socket.lookup(output_socket);
|
||||
EnumInputInferencingInfo &group_input_info =
|
||||
new_inferencing_interface->inputs[output_socket->index()];
|
||||
if (state.items) {
|
||||
group_input_info.items = state.items;
|
||||
}
|
||||
else if (state.group_output_index >= 0) {
|
||||
group_input_info.inference_index = state.group_output_index;
|
||||
}
|
||||
else {
|
||||
group_input_info.items = std::make_shared<EnumItems>();
|
||||
}
|
||||
bNodeSocket *interface_socket = (bNodeSocket *)BLI_findlink(&btree.inputs,
|
||||
output_socket->index());
|
||||
BLI_assert(interface_socket->type == SOCK_ENUM);
|
||||
bNodeSocketValueEnum *interface_value = (bNodeSocketValueEnum *)
|
||||
interface_socket->default_value;
|
||||
interface_value->items = group_input_info.items ? group_input_info.items->items() : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
delete btree.enum_inferencing_interface;
|
||||
btree.enum_inferencing_interface = new_inferencing_interface;
|
||||
|
||||
/* TODO: Only return true when the interface changed. */
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace blender::bke::enum_inferencing
|
||||
|
||||
/**
|
||||
* \param tree_update_flag: #eNodeTreeUpdate enum.
|
||||
*/
|
||||
@@ -5349,7 +5133,6 @@ void ntreeUpdateTree(Main *bmain, bNodeTree *ntree)
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
/* node tree update tags override individual node update flags */
|
||||
if ((node->update & NODE_UPDATE) || (ntree->update & NTREE_UPDATE)) {
|
||||
nodeUpdateFromDeclaration(ntree, node);
|
||||
if (node->typeinfo->updatefunc) {
|
||||
node->typeinfo->updatefunc(ntree, node);
|
||||
}
|
||||
@@ -5372,19 +5155,10 @@ void ntreeUpdateTree(Main *bmain, bNodeTree *ntree)
|
||||
int tree_user_update_flag = 0;
|
||||
|
||||
if (ntree->update & NTREE_UPDATE) {
|
||||
if (ntree->type == NTREE_GEOMETRY) {
|
||||
/* Create #NodeTreeRef to accelerate various queries on the node tree (e.g. linked
|
||||
* sockets). */
|
||||
const NodeTreeRef tree{ntree};
|
||||
/* If the field interface of this node tree has changed, all node trees using
|
||||
* this group will need to recalculate their interface as well. */
|
||||
if (blender::bke::node_field_inferencing::update_field_inferencing(tree)) {
|
||||
tree_user_update_flag |= NTREE_UPDATE_FIELD_INFERENCING;
|
||||
}
|
||||
if (blender::bke::enum_inferencing::update_enum_inferencing(tree)) {
|
||||
/* TODO: Fix flag handling. */
|
||||
tree_user_update_flag |= NTREE_UPDATE_FIELD_INFERENCING;
|
||||
}
|
||||
/* If the field interface of this node tree has changed, all node trees using
|
||||
* this group will need to recalculate their interface as well. */
|
||||
if (blender::bke::node_field_inferencing::update_field_inferencing(*ntree)) {
|
||||
tree_user_update_flag |= NTREE_UPDATE_FIELD_INFERENCING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5420,7 +5194,6 @@ void nodeUpdate(bNodeTree *ntree, bNode *node)
|
||||
}
|
||||
ntree->is_updating = true;
|
||||
|
||||
nodeUpdateFromDeclaration(ntree, node);
|
||||
if (node->typeinfo->updatefunc) {
|
||||
node->typeinfo->updatefunc(ntree, node);
|
||||
}
|
||||
@@ -5451,7 +5224,6 @@ bool nodeUpdateID(bNodeTree *ntree, ID *id)
|
||||
if (node->id == id) {
|
||||
changed = true;
|
||||
node->update |= NODE_UPDATE_ID;
|
||||
nodeUpdateFromDeclaration(ntree, node);
|
||||
if (node->typeinfo->updatefunc) {
|
||||
node->typeinfo->updatefunc(ntree, node);
|
||||
}
|
||||
@@ -6184,7 +5956,6 @@ static void registerFunctionNodes()
|
||||
|
||||
register_node_type_fn_align_euler_to_vector();
|
||||
register_node_type_fn_boolean_math();
|
||||
register_node_type_fn_enum();
|
||||
register_node_type_fn_float_compare();
|
||||
register_node_type_fn_float_to_int();
|
||||
register_node_type_fn_input_bool();
|
||||
|
@@ -645,6 +645,10 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports))
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 25)) {
|
||||
version_node_socket_index_animdata(bmain, NTREE_SHADER, SH_NODE_BSDF_PRINCIPLED, 4, 2, 25);
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 26)) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
ToolSettings *tool_settings = scene->toolsettings;
|
||||
@@ -780,7 +784,6 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports))
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
|
||||
version_node_socket_index_animdata(bmain, NTREE_SHADER, SH_NODE_BSDF_PRINCIPLED, 4, 2, 25);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -404,16 +404,13 @@ void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges)
|
||||
*/
|
||||
static void bm_mesh_edges_sharp_tag(BMesh *bm,
|
||||
const float (*fnos)[3],
|
||||
const float split_angle,
|
||||
float split_angle_cos,
|
||||
const bool do_sharp_edges_tag)
|
||||
{
|
||||
BMIter eiter;
|
||||
BMEdge *e;
|
||||
int i;
|
||||
|
||||
const bool check_angle = (split_angle < (float)M_PI);
|
||||
const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
|
||||
|
||||
if (fnos) {
|
||||
BM_mesh_elem_index_ensure(bm, BM_FACE);
|
||||
}
|
||||
@@ -451,7 +448,7 @@ void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
|
||||
return;
|
||||
}
|
||||
|
||||
bm_mesh_edges_sharp_tag(bm, NULL, split_angle, true);
|
||||
bm_mesh_edges_sharp_tag(bm, NULL, cosf(split_angle), true);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -1110,11 +1107,13 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm,
|
||||
const short (*clnors_data)[2],
|
||||
const int cd_loop_clnors_offset,
|
||||
const bool do_rebuild,
|
||||
const float split_angle)
|
||||
const float split_angle_cos)
|
||||
{
|
||||
BMIter fiter;
|
||||
BMFace *f_curr;
|
||||
const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
|
||||
/* When false the caller must have already tagged the edges. */
|
||||
const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS);
|
||||
|
||||
MLoopNorSpaceArray _lnors_spacearr = {NULL};
|
||||
|
||||
@@ -1155,7 +1154,9 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm,
|
||||
|
||||
/* Always tag edges based on winding & sharp edge flag
|
||||
* (even when the auto-smooth angle doesn't need to be calculated). */
|
||||
bm_mesh_edges_sharp_tag(bm, fnos, has_clnors ? (float)M_PI : split_angle, false);
|
||||
if (do_edge_tag) {
|
||||
bm_mesh_edges_sharp_tag(bm, fnos, has_clnors ? -1.0f : split_angle_cos, false);
|
||||
}
|
||||
|
||||
/* We now know edges that can be smoothed (they are tagged),
|
||||
* and edges that will be hard (they aren't).
|
||||
@@ -1308,12 +1309,9 @@ static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm,
|
||||
const short (*clnors_data)[2],
|
||||
const int cd_loop_clnors_offset,
|
||||
const bool do_rebuild,
|
||||
const float split_angle)
|
||||
const float split_angle_cos)
|
||||
{
|
||||
const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
|
||||
const bool check_angle = (split_angle < (float)M_PI);
|
||||
const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
|
||||
|
||||
MLoopNorSpaceArray _lnors_spacearr = {NULL};
|
||||
|
||||
{
|
||||
@@ -1387,7 +1385,7 @@ static void bm_mesh_loops_calc_normals(BMesh *bm,
|
||||
const short (*clnors_data)[2],
|
||||
const int cd_loop_clnors_offset,
|
||||
const bool do_rebuild,
|
||||
const float split_angle)
|
||||
const float split_angle_cos)
|
||||
{
|
||||
if (bm->totloop < BM_OMP_LIMIT) {
|
||||
bm_mesh_loops_calc_normals__single_threaded(bm,
|
||||
@@ -1398,7 +1396,7 @@ static void bm_mesh_loops_calc_normals(BMesh *bm,
|
||||
clnors_data,
|
||||
cd_loop_clnors_offset,
|
||||
do_rebuild,
|
||||
split_angle);
|
||||
split_angle_cos);
|
||||
}
|
||||
else {
|
||||
bm_mesh_loops_calc_normals__multi_threaded(bm,
|
||||
@@ -1409,7 +1407,7 @@ static void bm_mesh_loops_calc_normals(BMesh *bm,
|
||||
clnors_data,
|
||||
cd_loop_clnors_offset,
|
||||
do_rebuild,
|
||||
split_angle);
|
||||
split_angle_cos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1620,7 +1618,7 @@ static void bm_mesh_loops_custom_normals_set(BMesh *bm,
|
||||
|
||||
/* Tag smooth edges and set lnos from vnos when they might be completely smooth...
|
||||
* When using custom loop normals, disable the angle feature! */
|
||||
bm_mesh_edges_sharp_tag(bm, fnos, (float)M_PI, false);
|
||||
bm_mesh_edges_sharp_tag(bm, fnos, -1.0f, false);
|
||||
|
||||
/* Finish computing lnos by accumulating face normals
|
||||
* in each fan of faces defined by sharp edges. */
|
||||
@@ -1751,7 +1749,7 @@ void BM_loops_calc_normal_vcos(BMesh *bm,
|
||||
clnors_data,
|
||||
cd_loop_clnors_offset,
|
||||
do_rebuild,
|
||||
has_clnors ? (float)M_PI : split_angle);
|
||||
has_clnors ? -1.0f : cosf(split_angle));
|
||||
}
|
||||
else {
|
||||
BLI_assert(!r_lnors_spacearr);
|
||||
|
@@ -66,7 +66,7 @@ set(SRC
|
||||
interface_region_menu_popup.c
|
||||
interface_region_popover.c
|
||||
interface_region_popup.c
|
||||
interface_region_search.c
|
||||
interface_region_search.cc
|
||||
interface_region_tooltip.c
|
||||
interface_regions.c
|
||||
interface_style.c
|
||||
|
@@ -397,8 +397,8 @@ typedef struct uiHandleButtonData {
|
||||
float vec[3], origvec[3];
|
||||
ColorBand *coba;
|
||||
|
||||
/* Tool-tip. */
|
||||
uint tooltip_force : 1;
|
||||
/* True when alt is held and the preference for displaying tooltips should be ignored. */
|
||||
bool tooltip_force;
|
||||
|
||||
/* auto open */
|
||||
bool used_mouse;
|
||||
|
@@ -23,9 +23,9 @@
|
||||
* Search Box Region & Interaction
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
@@ -84,7 +84,7 @@ struct uiSearchItems {
|
||||
void *active;
|
||||
};
|
||||
|
||||
typedef struct uiSearchboxData {
|
||||
struct uiSearchboxData {
|
||||
rcti bbox;
|
||||
uiFontStyle fstyle;
|
||||
uiSearchItems items;
|
||||
@@ -102,7 +102,7 @@ typedef struct uiSearchboxData {
|
||||
* Used so we can show leading text to menu items less prominently (not related to 'use_sep').
|
||||
*/
|
||||
const char *sep_string;
|
||||
} uiSearchboxData;
|
||||
};
|
||||
|
||||
#define SEARCH_ITEMS 10
|
||||
|
||||
@@ -166,9 +166,9 @@ bool UI_search_item_add(uiSearchItems *items,
|
||||
|
||||
if (name_prefix_offset != 0) {
|
||||
/* Lazy initialize, as this isn't used often. */
|
||||
if (items->name_prefix_offsets == NULL) {
|
||||
items->name_prefix_offsets = MEM_callocN(
|
||||
items->maxitem * sizeof(*items->name_prefix_offsets), "search name prefix offsets");
|
||||
if (items->name_prefix_offsets == nullptr) {
|
||||
items->name_prefix_offsets = (uint8_t *)MEM_callocN(
|
||||
items->maxitem * sizeof(*items->name_prefix_offsets), __func__);
|
||||
}
|
||||
items->name_prefix_offsets[items->totitem] = name_prefix_offset;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ int UI_searchbox_size_x(void)
|
||||
|
||||
int UI_search_items_find_index(uiSearchItems *items, const char *name)
|
||||
{
|
||||
if (items->name_prefix_offsets != NULL) {
|
||||
if (items->name_prefix_offsets != nullptr) {
|
||||
for (int i = 0; i < items->totitem; i++) {
|
||||
if (STREQ(name, items->names[i] + items->name_prefix_offsets[i])) {
|
||||
return i;
|
||||
@@ -218,7 +218,7 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name)
|
||||
/* region is the search box itself */
|
||||
static void ui_searchbox_select(bContext *C, ARegion *region, uiBut *but, int step)
|
||||
{
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||
|
||||
/* apply step */
|
||||
data->active += step;
|
||||
@@ -285,14 +285,14 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr
|
||||
|
||||
int ui_searchbox_find_index(ARegion *region, const char *name)
|
||||
{
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||
return UI_search_items_find_index(&data->items, name);
|
||||
}
|
||||
|
||||
/* x and y in screen-coords. */
|
||||
bool ui_searchbox_inside(ARegion *region, const int xy[2])
|
||||
{
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||
|
||||
return BLI_rcti_isect_pt(&data->bbox, xy[0] - region->winrct.xmin, xy[1] - region->winrct.ymin);
|
||||
}
|
||||
@@ -300,12 +300,12 @@ bool ui_searchbox_inside(ARegion *region, const int xy[2])
|
||||
/* string validated to be of correct length (but->hardmax) */
|
||||
bool ui_searchbox_apply(uiBut *but, ARegion *region)
|
||||
{
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
|
||||
search_but->item_active = NULL;
|
||||
search_but->item_active = nullptr;
|
||||
|
||||
if (data->active != -1) {
|
||||
const char *name = data->items.names[data->active] +
|
||||
@@ -314,7 +314,7 @@ bool ui_searchbox_apply(uiBut *but, ARegion *region)
|
||||
data->items.name_prefix_offsets[data->active] :
|
||||
0);
|
||||
|
||||
const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : NULL;
|
||||
const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : nullptr;
|
||||
|
||||
/* Search button with dynamic string properties may have their own method of applying
|
||||
* the search results, so only copy the result if there is a proper space for it. */
|
||||
@@ -356,7 +356,7 @@ static struct ARegion *wm_searchbox_tooltip_init(struct bContext *C,
|
||||
}
|
||||
|
||||
ARegion *searchbox_region = UI_region_searchbox_region_get(region);
|
||||
uiSearchboxData *data = searchbox_region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(searchbox_region->regiondata);
|
||||
|
||||
BLI_assert(data->items.pointers[data->active] == search_but->item_active);
|
||||
|
||||
@@ -367,13 +367,13 @@ static struct ARegion *wm_searchbox_tooltip_init(struct bContext *C,
|
||||
C, region, &rect, search_but->arg, search_but->item_active);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ui_searchbox_event(
|
||||
bContext *C, ARegion *region, uiBut *but, ARegion *butregion, const wmEvent *event)
|
||||
{
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
int type = event->type, val = event->val;
|
||||
bool handled = false;
|
||||
@@ -481,7 +481,7 @@ static void ui_searchbox_update_fn(bContext *C,
|
||||
void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool reset)
|
||||
{
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
|
||||
@@ -499,7 +499,7 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re
|
||||
if (search_but->items_update_fn && search_but->item_active) {
|
||||
data->items.active = search_but->item_active;
|
||||
ui_searchbox_update_fn(C, search_but, but->editstr, &data->items);
|
||||
data->items.active = NULL;
|
||||
data->items.active = nullptr;
|
||||
|
||||
/* found active item, calculate real offset by centering it */
|
||||
if (data->items.totitem) {
|
||||
@@ -538,7 +538,7 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re
|
||||
/* Never include the prefix in the button. */
|
||||
(data->items.name_prefix_offsets ? data->items.name_prefix_offsets[a] :
|
||||
0);
|
||||
const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : NULL;
|
||||
const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : nullptr;
|
||||
if (STREQLEN(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen)) {
|
||||
data->active = a;
|
||||
break;
|
||||
@@ -558,7 +558,7 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re
|
||||
int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *str)
|
||||
{
|
||||
uiButSearch *search_but = (uiButSearch *)but;
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||
int match = AUTOCOMPLETE_NO_MATCH;
|
||||
|
||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||
@@ -569,7 +569,7 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *st
|
||||
ui_searchbox_update_fn(C, search_but, but->editstr, &data->items);
|
||||
|
||||
match = UI_autocomplete_end(data->items.autocpl, str);
|
||||
data->items.autocpl = NULL;
|
||||
data->items.autocpl = nullptr;
|
||||
}
|
||||
|
||||
return match;
|
||||
@@ -577,7 +577,7 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *st
|
||||
|
||||
static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
|
||||
{
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||
|
||||
/* pixel space */
|
||||
wmOrtho2_region_pixelspace(region);
|
||||
@@ -630,7 +630,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
|
||||
const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
|
||||
char *name = data->items.names[a];
|
||||
int icon = data->items.icons[a];
|
||||
char *name_sep_test = NULL;
|
||||
char *name_sep_test = nullptr;
|
||||
|
||||
uiMenuItemSeparatorType separator_type = UI_MENU_ITEM_SEPARATOR_NONE;
|
||||
if (data->use_shortcut_sep) {
|
||||
@@ -652,15 +652,15 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
|
||||
}
|
||||
|
||||
/* Simple menu item. */
|
||||
ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, separator_type, NULL);
|
||||
ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, separator_type, nullptr);
|
||||
}
|
||||
else {
|
||||
/* Split menu item, faded text before the separator. */
|
||||
char *name_sep = NULL;
|
||||
char *name_sep = nullptr;
|
||||
do {
|
||||
name_sep = name_sep_test;
|
||||
name_sep_test = strstr(name_sep + search_sep_len, data->sep_string);
|
||||
} while (name_sep_test != NULL);
|
||||
} while (name_sep_test != nullptr);
|
||||
|
||||
name_sep += search_sep_len;
|
||||
const char name_sep_prev = *name_sep;
|
||||
@@ -683,7 +683,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
|
||||
}
|
||||
|
||||
/* The previous menu item draws the active selection. */
|
||||
ui_draw_menu_item(&data->fstyle, &rect, name_sep, icon, state, separator_type, NULL);
|
||||
ui_draw_menu_item(&data->fstyle, &rect, name_sep, icon, state, separator_type, nullptr);
|
||||
}
|
||||
}
|
||||
/* indicate more */
|
||||
@@ -705,7 +705,7 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
|
||||
|
||||
static void ui_searchbox_region_free_fn(ARegion *region)
|
||||
{
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||
|
||||
/* free search data */
|
||||
for (int a = 0; a < data->items.maxitem; a++) {
|
||||
@@ -716,12 +716,12 @@ static void ui_searchbox_region_free_fn(ARegion *region)
|
||||
MEM_freeN(data->items.icons);
|
||||
MEM_freeN(data->items.states);
|
||||
|
||||
if (data->items.name_prefix_offsets != NULL) {
|
||||
if (data->items.name_prefix_offsets != nullptr) {
|
||||
MEM_freeN(data->items.name_prefix_offsets);
|
||||
}
|
||||
|
||||
MEM_freeN(data);
|
||||
region->regiondata = NULL;
|
||||
region->regiondata = nullptr;
|
||||
}
|
||||
|
||||
static ARegion *ui_searchbox_create_generic_ex(bContext *C,
|
||||
@@ -746,7 +746,7 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C,
|
||||
region->type = &type;
|
||||
|
||||
/* create searchbox data */
|
||||
uiSearchboxData *data = MEM_callocN(sizeof(uiSearchboxData), "uiSearchboxData");
|
||||
uiSearchboxData *data = (uiSearchboxData *)MEM_callocN(sizeof(uiSearchboxData), __func__);
|
||||
|
||||
/* set font, get bb */
|
||||
data->fstyle = style->widget; /* copy struct */
|
||||
@@ -767,7 +767,7 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C,
|
||||
data->prv_cols = but->a2;
|
||||
}
|
||||
|
||||
if (but->optype != NULL || use_shortcut_sep) {
|
||||
if (but->optype != nullptr || use_shortcut_sep) {
|
||||
data->use_shortcut_sep = true;
|
||||
}
|
||||
data->sep_string = search_but->item_sep_string;
|
||||
@@ -881,13 +881,13 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C,
|
||||
/* In case the button's string is dynamic, make sure there are buffers available. */
|
||||
data->items.maxstrlen = but->hardmax == 0 ? UI_MAX_NAME_STR : but->hardmax;
|
||||
data->items.totitem = 0;
|
||||
data->items.names = MEM_callocN(data->items.maxitem * sizeof(void *), "search names");
|
||||
data->items.pointers = MEM_callocN(data->items.maxitem * sizeof(void *), "search pointers");
|
||||
data->items.icons = MEM_callocN(data->items.maxitem * sizeof(int), "search icons");
|
||||
data->items.states = MEM_callocN(data->items.maxitem * sizeof(int), "search flags");
|
||||
data->items.name_prefix_offsets = NULL; /* Lazy initialized as needed. */
|
||||
data->items.names = (char **)MEM_callocN(data->items.maxitem * sizeof(void *), __func__);
|
||||
data->items.pointers = (void **)MEM_callocN(data->items.maxitem * sizeof(void *), __func__);
|
||||
data->items.icons = (int *)MEM_callocN(data->items.maxitem * sizeof(int), __func__);
|
||||
data->items.states = (int *)MEM_callocN(data->items.maxitem * sizeof(int), __func__);
|
||||
data->items.name_prefix_offsets = nullptr; /* Lazy initialized as needed. */
|
||||
for (int i = 0; i < data->items.maxitem; i++) {
|
||||
data->items.names[i] = MEM_callocN(data->items.maxstrlen + 1, "search pointers");
|
||||
data->items.names[i] = (char *)MEM_callocN(data->items.maxstrlen + 1, __func__);
|
||||
}
|
||||
|
||||
return region;
|
||||
@@ -924,7 +924,7 @@ static void str_tolower_titlecaps_ascii(char *str, const size_t len)
|
||||
|
||||
static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARegion *region)
|
||||
{
|
||||
uiSearchboxData *data = region->regiondata;
|
||||
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||
|
||||
/* pixel space */
|
||||
wmOrtho2_region_pixelspace(region);
|
||||
@@ -952,10 +952,10 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
|
||||
{
|
||||
const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
|
||||
|
||||
wmOperatorType *ot = data->items.pointers[a];
|
||||
wmOperatorType *ot = static_cast<wmOperatorType *>(data->items.pointers[a]);
|
||||
char text_pre[128];
|
||||
char *text_pre_p = strstr(ot->idname, "_OT_");
|
||||
if (text_pre_p == NULL) {
|
||||
const char *text_pre_p = strstr(ot->idname, "_OT_");
|
||||
if (text_pre_p == nullptr) {
|
||||
text_pre[0] = '\0';
|
||||
}
|
||||
else {
|
||||
@@ -975,7 +975,7 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
|
||||
data->items.icons[a],
|
||||
state,
|
||||
UI_MENU_ITEM_SEPARATOR_NONE,
|
||||
NULL);
|
||||
nullptr);
|
||||
ui_draw_menu_item(&data->fstyle,
|
||||
&rect_post,
|
||||
data->items.names[a],
|
||||
@@ -983,7 +983,7 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
|
||||
state,
|
||||
data->use_shortcut_sep ? UI_MENU_ITEM_SEPARATOR_SHORTCUT :
|
||||
UI_MENU_ITEM_SEPARATOR_NONE,
|
||||
NULL);
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
/* indicate more */
|
||||
@@ -1044,17 +1044,17 @@ void ui_but_search_refresh(uiButSearch *search_but)
|
||||
return;
|
||||
}
|
||||
|
||||
uiSearchItems *items = MEM_callocN(sizeof(uiSearchItems), "search items");
|
||||
uiSearchItems *items = (uiSearchItems *)MEM_callocN(sizeof(uiSearchItems), __func__);
|
||||
|
||||
/* setup search struct */
|
||||
items->maxitem = 10;
|
||||
items->maxstrlen = 256;
|
||||
items->names = MEM_callocN(items->maxitem * sizeof(void *), "search names");
|
||||
items->names = (char **)MEM_callocN(items->maxitem * sizeof(void *), __func__);
|
||||
for (int i = 0; i < items->maxitem; i++) {
|
||||
items->names[i] = MEM_callocN(but->hardmax + 1, "search names");
|
||||
items->names[i] = (char *)MEM_callocN(but->hardmax + 1, __func__);
|
||||
}
|
||||
|
||||
ui_searchbox_update_fn(but->block->evil_C, search_but, but->drawstr, items);
|
||||
ui_searchbox_update_fn((bContext *)but->block->evil_C, search_but, but->drawstr, items);
|
||||
|
||||
if (!search_but->results_are_suggestions) {
|
||||
/* Only red-alert when we are sure of it, this can miss cases when >10 matches. */
|
@@ -22,9 +22,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* interface_region_menu_popup.c */
|
||||
uint ui_popup_menu_hash(const char *str);
|
||||
|
||||
/* interface_regions_intern.h */
|
||||
ARegion *ui_region_temp_add(bScreen *screen);
|
||||
void ui_region_temp_remove(struct bContext *C, bScreen *screen, ARegion *region);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -1348,7 +1348,7 @@ void UI_view2d_dot_grid_draw(const View2D *v2d,
|
||||
const float min_step,
|
||||
const int grid_levels)
|
||||
{
|
||||
BLI_assert(grid_levels > 0 && grid_levels < 10);
|
||||
BLI_assert(grid_levels >= 0 && grid_levels < 10);
|
||||
const float zoom_x = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
|
||||
const float zoom_normalized = (zoom_x - v2d->minzoom) / (v2d->maxzoom - v2d->minzoom);
|
||||
|
||||
|
@@ -3472,7 +3472,6 @@ static const float std_node_socket_colors[][4] = {
|
||||
{0.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */
|
||||
{0.62, 0.31, 0.64, 1.0}, /* SOCK_TEXTURE */
|
||||
{0.92, 0.46, 0.51, 1.0}, /* SOCK_MATERIAL */
|
||||
{0.00, 0.00, 0.00, 1.0}, /* SOCK_ENUM */
|
||||
};
|
||||
|
||||
/* common color callbacks for standard types */
|
||||
@@ -3691,10 +3690,6 @@ static void std_node_socket_draw(
|
||||
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
|
||||
break;
|
||||
}
|
||||
case SOCK_ENUM: {
|
||||
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
node_socket_button_label(C, layout, ptr, node_ptr, text);
|
||||
break;
|
||||
@@ -3732,8 +3727,7 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout
|
||||
}
|
||||
case SOCK_BOOLEAN:
|
||||
case SOCK_RGBA:
|
||||
case SOCK_STRING:
|
||||
case SOCK_ENUM: {
|
||||
case SOCK_STRING: {
|
||||
uiItemR(col, ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), 0);
|
||||
break;
|
||||
}
|
||||
@@ -4450,12 +4444,6 @@ void node_draw_link(const bContext *C, View2D *v2d, SpaceNode *snode, bNodeLink
|
||||
th_col1 = th_col2 = th_col3 = TH_REDALERT;
|
||||
}
|
||||
}
|
||||
if (link->fromsock && link->fromsock->type == SOCK_ENUM) {
|
||||
bNodeSocketValueEnum *socket_value = (bNodeSocketValueEnum *)link->fromsock->default_value;
|
||||
if (socket_value->targets_are_invalid) {
|
||||
th_col1 = th_col2 = th_col3 = TH_REDALERT;
|
||||
}
|
||||
}
|
||||
|
||||
node_draw_link_bezier(C, v2d, snode, link, th_col1, th_col2, th_col3);
|
||||
}
|
||||
|
@@ -419,10 +419,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
|
||||
uiLayout *row = uiLayoutRow(layout, true);
|
||||
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
|
||||
const char *socket_label = nodeSocketLabel(nsock);
|
||||
if (node->typeinfo->draw_socket == NULL ||
|
||||
!node->typeinfo->draw_socket(row, C, ntree, node, nsock)) {
|
||||
nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
|
||||
}
|
||||
nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
|
||||
|
||||
UI_block_align_end(node->block);
|
||||
UI_block_layout_resolve(node->block, nullptr, &buty);
|
||||
@@ -557,11 +554,8 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
|
||||
|
||||
uiLayout *row = uiLayoutRow(layout, true);
|
||||
|
||||
if (node->typeinfo->draw_socket == NULL ||
|
||||
!node->typeinfo->draw_socket(row, C, ntree, node, nsock)) {
|
||||
const char *socket_label = nodeSocketLabel(nsock);
|
||||
nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
|
||||
}
|
||||
const char *socket_label = nodeSocketLabel(nsock);
|
||||
nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
|
||||
|
||||
UI_block_align_end(node->block);
|
||||
UI_block_layout_resolve(node->block, nullptr, &buty);
|
||||
|
@@ -1335,8 +1335,6 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
/* add modal handler */
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
ntreeUpdateTree(bmain, snode->edittree);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
|
||||
@@ -2180,7 +2178,6 @@ static int get_main_socket_priority(const bNodeSocket *socket)
|
||||
case SOCK_COLLECTION:
|
||||
case SOCK_TEXTURE:
|
||||
case SOCK_MATERIAL:
|
||||
case SOCK_ENUM:
|
||||
return 5;
|
||||
}
|
||||
return -1;
|
||||
|
@@ -377,7 +377,7 @@ static Vector<NodeLinkItem> ui_node_link_items(NodeLinkArg *arg,
|
||||
using namespace blender::nodes;
|
||||
|
||||
r_node_decl.emplace(NodeDeclaration());
|
||||
NodeDeclarationBuilder node_decl_builder{*r_node_decl, nullptr};
|
||||
NodeDeclarationBuilder node_decl_builder{*r_node_decl};
|
||||
arg->node_type->declare(node_decl_builder);
|
||||
Span<SocketDeclarationPtr> socket_decls = (in_out == SOCK_IN) ? r_node_decl->inputs() :
|
||||
r_node_decl->outputs();
|
||||
|
@@ -191,7 +191,6 @@ typedef enum eNodeSocketDatatype {
|
||||
SOCK_COLLECTION = 11,
|
||||
SOCK_TEXTURE = 12,
|
||||
SOCK_MATERIAL = 13,
|
||||
SOCK_ENUM = 14,
|
||||
} eNodeSocketDatatype;
|
||||
|
||||
/* Socket shape. */
|
||||
@@ -478,13 +477,10 @@ typedef struct bNodeLink {
|
||||
#ifdef __cplusplus
|
||||
namespace blender::nodes {
|
||||
struct FieldInferencingInterface;
|
||||
struct EnumInferencingInterface;
|
||||
} // namespace blender::nodes
|
||||
}
|
||||
using FieldInferencingInterfaceHandle = blender::nodes::FieldInferencingInterface;
|
||||
using EnumInferencingInterfaceHandle = blender::nodes::EnumInferencingInterface;
|
||||
#else
|
||||
typedef struct FieldInferencingInterfaceHandle FieldInferencingInterfaceHandle;
|
||||
typedef struct EnumInferencingInterfaceHandle EnumInferencingInterfaceHandle;
|
||||
#endif
|
||||
|
||||
/* the basis for a Node tree, all links and nodes reside internal here */
|
||||
@@ -511,7 +507,6 @@ typedef struct bNodeTree {
|
||||
ListBase nodes, links;
|
||||
/** Information about how inputs and outputs of the node group interact with fields. */
|
||||
FieldInferencingInterfaceHandle *field_inferencing_interface;
|
||||
EnumInferencingInterfaceHandle *enum_inferencing_interface;
|
||||
|
||||
/** Set init on fileread. */
|
||||
int type, init;
|
||||
@@ -684,17 +679,6 @@ typedef struct bNodeSocketValueMaterial {
|
||||
struct Material *value;
|
||||
} bNodeSocketValueMaterial;
|
||||
|
||||
/* TODO: Add something to help with versioning for built-in enums. */
|
||||
typedef struct bNodeSocketValueEnum {
|
||||
int value;
|
||||
char targets_are_invalid;
|
||||
char _pad[3];
|
||||
/**
|
||||
* Possible items for the enum. This is only runtime data and is not owned by the socket.
|
||||
*/
|
||||
const struct EnumPropertyItem *items;
|
||||
} bNodeSocketValueEnum;
|
||||
|
||||
/* Data structs, for node->storage. */
|
||||
enum {
|
||||
CMP_NODE_MASKTYPE_ADD = 0,
|
||||
@@ -1622,21 +1606,6 @@ typedef struct NodeGeometryViewer {
|
||||
int8_t data_type;
|
||||
} NodeGeometryViewer;
|
||||
|
||||
typedef struct NodeFunctionEnumItem {
|
||||
struct NodeFunctionEnumItem *next, *prev;
|
||||
bNode *owner_node;
|
||||
int value;
|
||||
char _pad[4];
|
||||
char *name;
|
||||
char *description;
|
||||
} NodeFunctionEnumItem;
|
||||
|
||||
typedef struct NodeFunctionEnum {
|
||||
bNode *owner_node;
|
||||
/** NodeFunctionEnumItem. */
|
||||
ListBase items;
|
||||
} NodeFunctionEnum;
|
||||
|
||||
/* script node mode */
|
||||
#define NODE_SCRIPT_INTERNAL 0
|
||||
#define NODE_SCRIPT_EXTERNAL 1
|
||||
|
@@ -449,8 +449,6 @@ extern StructRNA RNA_MusgraveTexture;
|
||||
extern StructRNA RNA_NlaStrip;
|
||||
extern StructRNA RNA_NlaTrack;
|
||||
extern StructRNA RNA_Node;
|
||||
extern StructRNA RNA_NodeFunctionEnum;
|
||||
extern StructRNA RNA_NodeFunctionEnumItem;
|
||||
extern StructRNA RNA_NodeInstanceHash;
|
||||
extern StructRNA RNA_NodeLink;
|
||||
extern StructRNA RNA_NodeOutputFileSlotFile;
|
||||
|
@@ -78,7 +78,6 @@ static const EnumPropertyItem node_socket_data_type_items[] = {
|
||||
{SOCK_COLLECTION, "COLLECTION", 0, "Collection", ""},
|
||||
{SOCK_TEXTURE, "TEXTURE", 0, "Texture", ""},
|
||||
{SOCK_MATERIAL, "MATERIAL", 0, "Material", ""},
|
||||
{SOCK_ENUM, "ENUM", 0, "Enum", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -107,7 +106,6 @@ static const EnumPropertyItem node_socket_type_items[] = {
|
||||
{SOCK_COLLECTION, "COLLECTION", 0, "Collection", ""},
|
||||
{SOCK_TEXTURE, "TEXTURE", 0, "Texture", ""},
|
||||
{SOCK_MATERIAL, "MATERIAL", 0, "Material", ""},
|
||||
{SOCK_ENUM, "ENUM", 0, "Enum", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -1237,8 +1235,8 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree,
|
||||
ntreeTexCheckCyclics(ntree);
|
||||
}
|
||||
|
||||
nodeUpdate(ntree, node);
|
||||
ntreeUpdateTree(CTX_data_main(C), ntree);
|
||||
nodeUpdate(ntree, node);
|
||||
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
|
||||
|
||||
return node;
|
||||
@@ -2059,8 +2057,7 @@ static bool switch_type_supported(const EnumPropertyItem *item)
|
||||
SOCK_COLLECTION,
|
||||
SOCK_TEXTURE,
|
||||
SOCK_MATERIAL,
|
||||
SOCK_IMAGE,
|
||||
SOCK_ENUM);
|
||||
SOCK_IMAGE);
|
||||
}
|
||||
|
||||
static const EnumPropertyItem *rna_GeometryNodeSwitch_type_itemf(bContext *UNUSED(C),
|
||||
@@ -3441,7 +3438,6 @@ static bool rna_NodeInternal_poll_instance(bNode *node, bNodeTree *ntree)
|
||||
static void rna_NodeInternal_update(ID *id, bNode *node)
|
||||
{
|
||||
bNodeTree *ntree = (bNodeTree *)id;
|
||||
nodeUpdateFromDeclaration(ntree, node);
|
||||
if (node->typeinfo->updatefunc) {
|
||||
node->typeinfo->updatefunc(ntree, node);
|
||||
}
|
||||
@@ -4573,58 +4569,6 @@ bool rna_NodeSocketMaterial_default_value_poll(PointerRNA *UNUSED(ptr), PointerR
|
||||
return ma->gp_style == NULL;
|
||||
}
|
||||
|
||||
static void rna_nodeFunctionEnum_update_enum(Main *bmain, bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
ntree->update |= NTREE_UPDATE_FIELD_INFERENCING;
|
||||
nodeUpdate(ntree, node);
|
||||
ED_node_tag_update_nodetree(bmain, ntree, node);
|
||||
ntreeUpdateTree(bmain, ntree);
|
||||
}
|
||||
|
||||
static void rna_NodeFunctionEnumItem_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
{
|
||||
NodeFunctionEnumItem *item = (NodeFunctionEnumItem *)ptr->data;
|
||||
bNode *node = item->owner_node;
|
||||
rna_nodeFunctionEnum_update_enum(bmain, (bNodeTree *)ptr->owner_id, node);
|
||||
}
|
||||
|
||||
static NodeFunctionEnumItem *rna_NodeFunctionEnumItems_items_new(ID *id, bNode *node, bContext *C)
|
||||
{
|
||||
NodeFunctionEnum *storage = node->storage;
|
||||
NodeFunctionEnumItem *item = MEM_callocN(sizeof(NodeFunctionEnumItem), __func__);
|
||||
item->owner_node = node;
|
||||
BLI_addtail(&storage->items, item);
|
||||
|
||||
PointerRNA node_ptr;
|
||||
RNA_pointer_create(id, &RNA_Node, node, &node_ptr);
|
||||
|
||||
Main *bmain = CTX_data_main(C);
|
||||
bNodeTree *ntree = (bNodeTree *)id;
|
||||
rna_nodeFunctionEnum_update_enum(bmain, ntree, node);
|
||||
return item;
|
||||
}
|
||||
|
||||
static const EnumPropertyItem *rna_NodeSocketEnum_items(bContext *UNUSED(C),
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *UNUSED(prop),
|
||||
bool *r_free)
|
||||
{
|
||||
*r_free = false;
|
||||
bNodeSocket *socket = ptr->data;
|
||||
bNodeSocketValueEnum *storage = (bNodeSocketValueEnum *)socket->default_value;
|
||||
if (storage->items == NULL) {
|
||||
return DummyRNA_NULL_items;
|
||||
}
|
||||
return storage->items;
|
||||
}
|
||||
|
||||
static void rna_NodeSocketEnum_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
bNodeSocket *socket = ptr->data;
|
||||
bNodeSocketValueEnum *storage = (bNodeSocketValueEnum *)socket->default_value;
|
||||
storage->value = value;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static const EnumPropertyItem prop_image_layer_items[] = {
|
||||
@@ -5120,60 +5064,6 @@ static void def_fn_input_string(StructRNA *srna)
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void rna_def_fn_enum_item(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "NodeFunctionEnumItem", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Node Function Enum Item", "");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Value", "Internal identifier if the enum item");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeFunctionEnumItem_update");
|
||||
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Name", "Display name of the enum item");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeFunctionEnumItem_update");
|
||||
|
||||
prop = RNA_def_property(srna, "description", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Description", "Tooltip for the enum item");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeFunctionEnumItem_update");
|
||||
}
|
||||
|
||||
static void rna_def_fn_enum_items_api(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
RNA_def_property_srna(cprop, "NodeFunctionEnumItems");
|
||||
srna = RNA_def_struct(brna, "NodeFunctionEnumItems", NULL);
|
||||
RNA_def_struct_sdna(srna, "bNode");
|
||||
RNA_def_struct_ui_text(srna, "Enum Items", "");
|
||||
|
||||
func = RNA_def_function(srna, "new", "rna_NodeFunctionEnumItems_items_new");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_SELF_ID);
|
||||
RNA_def_function_ui_description(func, "Add a new enum item");
|
||||
parm = RNA_def_pointer(func, "item", "NodeFunctionEnumItem", "", "New enum item");
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
static void def_fn_enum(BlenderRNA *brna, StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
rna_def_fn_enum_item(brna);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeFunctionEnum", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "enum_items", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "items", NULL);
|
||||
RNA_def_property_struct_type(prop, "NodeFunctionEnumItem");
|
||||
RNA_def_property_ui_text(prop, "Items", "");
|
||||
rna_def_fn_enum_items_api(brna, prop);
|
||||
}
|
||||
|
||||
/* -- Shader Nodes ---------------------------------------------------------- */
|
||||
|
||||
static void def_sh_output(StructRNA *srna)
|
||||
@@ -12070,47 +11960,6 @@ static void rna_def_node_socket_material(BlenderRNA *brna,
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
|
||||
}
|
||||
|
||||
static void rna_def_node_socket_enum(BlenderRNA *brna,
|
||||
const char *identifier,
|
||||
const char *interface_idname)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
|
||||
RNA_def_struct_ui_text(srna, "Enum Node Socket", "Enum socket of a node");
|
||||
RNA_def_struct_sdna(srna, "bNodeSocket");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocketValueEnum", "default_value");
|
||||
|
||||
prop = RNA_def_property(srna, "default_value", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "value");
|
||||
RNA_def_property_enum_funcs(prop, NULL, "rna_NodeSocketEnum_set", "rna_NodeSocketEnum_items");
|
||||
RNA_def_property_enum_items(prop, DummyRNA_DEFAULT_items);
|
||||
RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
|
||||
|
||||
/* socket interface */
|
||||
srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
|
||||
RNA_def_struct_ui_text(srna, "Enum Node Socket Interface", "Enum socket of a node");
|
||||
RNA_def_struct_sdna(srna, "bNodeSocket");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocketValueEnum", "default_value");
|
||||
|
||||
prop = RNA_def_property(srna, "default_value", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "value");
|
||||
RNA_def_property_enum_funcs(prop, NULL, "rna_NodeSocketEnum_set", "rna_NodeSocketEnum_items");
|
||||
RNA_def_property_enum_items(prop, DummyRNA_DEFAULT_items);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
|
||||
}
|
||||
|
||||
static void rna_def_node_socket_standard_types(BlenderRNA *brna)
|
||||
{
|
||||
/* XXX Workaround: Registered functions are not exposed in python by bpy,
|
||||
@@ -12263,8 +12112,6 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna)
|
||||
rna_def_node_socket_texture(brna, "NodeSocketTexture", "NodeSocketInterfaceTexture");
|
||||
|
||||
rna_def_node_socket_material(brna, "NodeSocketMaterial", "NodeSocketInterfaceMaterial");
|
||||
|
||||
rna_def_node_socket_enum(brna, "NodeSocketEnum", "NodeSocketInterfaceEnum");
|
||||
}
|
||||
|
||||
static void rna_def_internal_node(BlenderRNA *brna)
|
||||
@@ -13274,9 +13121,6 @@ void RNA_def_nodetree(BlenderRNA *brna)
|
||||
/* needs brna argument, can't use NOD_static_types.h */ \
|
||||
def_cmp_output_file(brna, srna); \
|
||||
} \
|
||||
if (ID == FN_NODE_ENUM) { \
|
||||
def_fn_enum(brna, srna); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* hack, don't want to add include path to RNA just for this, since in the future RNA types
|
||||
|
@@ -1049,17 +1049,6 @@ static void check_property_socket_sync(const Object *ob, ModifierData *md)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool has_geometry_output = false;
|
||||
LISTBASE_FOREACH (const bNodeSocket *, socket, &nmd->node_group->outputs) {
|
||||
if (socket->type == SOCK_GEOMETRY) {
|
||||
has_geometry_output = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_geometry_output) {
|
||||
BKE_modifier_set_error(ob, md, "Node group must have a geometry output");
|
||||
}
|
||||
}
|
||||
|
||||
static void modifyGeometry(ModifierData *md,
|
||||
@@ -1078,6 +1067,7 @@ static void modifyGeometry(ModifierData *md,
|
||||
|
||||
if (tree.has_link_cycles()) {
|
||||
BKE_modifier_set_error(ctx->object, md, "Node group has cycles");
|
||||
geometry_set.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1085,17 +1075,23 @@ static void modifyGeometry(ModifierData *md,
|
||||
Span<const NodeRef *> input_nodes = root_tree_ref.nodes_by_type("NodeGroupInput");
|
||||
Span<const NodeRef *> output_nodes = root_tree_ref.nodes_by_type("NodeGroupOutput");
|
||||
if (output_nodes.size() != 1) {
|
||||
BKE_modifier_set_error(ctx->object, md, "Node group must have a single output node");
|
||||
geometry_set.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
const NodeRef &output_node = *output_nodes[0];
|
||||
Span<const InputSocketRef *> group_outputs = output_node.inputs().drop_back(1);
|
||||
if (group_outputs.is_empty()) {
|
||||
BKE_modifier_set_error(ctx->object, md, "Node group must have an output socket");
|
||||
geometry_set.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
const InputSocketRef *first_output_socket = group_outputs[0];
|
||||
if (first_output_socket->idname() != "NodeSocketGeometry") {
|
||||
BKE_modifier_set_error(ctx->object, md, "Node group's first output must be a geometry");
|
||||
geometry_set.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -139,7 +139,6 @@ set(SRC
|
||||
|
||||
function/nodes/node_fn_align_euler_to_vector.cc
|
||||
function/nodes/node_fn_boolean_math.cc
|
||||
function/nodes/node_fn_enum.cc
|
||||
function/nodes/node_fn_float_compare.cc
|
||||
function/nodes/node_fn_float_to_int.cc
|
||||
function/nodes/node_fn_input_bool.cc
|
||||
|
@@ -24,7 +24,6 @@ void register_node_type_fn_legacy_random_float(void);
|
||||
|
||||
void register_node_type_fn_align_euler_to_vector(void);
|
||||
void register_node_type_fn_boolean_math(void);
|
||||
void register_node_type_fn_enum(void);
|
||||
void register_node_type_fn_float_compare(void);
|
||||
void register_node_type_fn_float_to_int(void);
|
||||
void register_node_type_fn_input_bool(void);
|
||||
|
@@ -66,27 +66,6 @@ using fn::GVMutableArray_Typed;
|
||||
using fn::GVMutableArrayPtr;
|
||||
using geometry_nodes_eval_log::NodeWarningType;
|
||||
|
||||
/** Wrapper for an integer so that one can not perform various operations like addition on it. */
|
||||
struct EnumValue {
|
||||
int value;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const EnumValue &value)
|
||||
{
|
||||
stream << value.value;
|
||||
return stream;
|
||||
}
|
||||
|
||||
friend bool operator==(const EnumValue &a, const EnumValue &b)
|
||||
{
|
||||
return a.value == b.value;
|
||||
}
|
||||
|
||||
uint64_t hash() const
|
||||
{
|
||||
return this->value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This class exists to separate the memory management details of the geometry nodes evaluator
|
||||
* from the node execution functions and related utilities.
|
||||
@@ -160,8 +139,7 @@ class GeoNodeExecParams {
|
||||
std::is_same_v<T, bool> ||
|
||||
std::is_same_v<T, ColorGeometry4f> ||
|
||||
std::is_same_v<T, float3> ||
|
||||
std::is_same_v<T, std::string> ||
|
||||
std::is_same_v<T, EnumValue>;
|
||||
std::is_same_v<T, std::string>;
|
||||
|
||||
/**
|
||||
* Get the input value for the input socket with the given identifier.
|
||||
@@ -233,10 +211,6 @@ class GeoNodeExecParams {
|
||||
const Field<T> &field = this->get_input<Field<T>>(identifier);
|
||||
return fn::evaluate_constant_field(field);
|
||||
}
|
||||
else if constexpr (std::is_enum_v<T>) {
|
||||
const int value = this->get_input<EnumValue>(identifier).value;
|
||||
return (T)this->validate_enum_value(identifier, value);
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG
|
||||
this->check_input_access(identifier, &CPPType::get<T>());
|
||||
@@ -380,8 +354,6 @@ class GeoNodeExecParams {
|
||||
|
||||
/* Find the active socket with the input name (not the identifier). */
|
||||
const bNodeSocket *find_available_socket(const StringRef name) const;
|
||||
|
||||
const int validate_enum_value(StringRef identifier, const int value) const;
|
||||
};
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
@@ -243,13 +243,11 @@ class NodeDeclaration {
|
||||
|
||||
class NodeDeclarationBuilder {
|
||||
private:
|
||||
/** The node may be null. */
|
||||
NodeDeclaration &declaration_;
|
||||
const bNode *node_;
|
||||
Vector<std::unique_ptr<BaseSocketDeclarationBuilder>> builders_;
|
||||
|
||||
public:
|
||||
NodeDeclarationBuilder(NodeDeclaration &declaration, const bNode *node);
|
||||
NodeDeclarationBuilder(NodeDeclaration &declaration);
|
||||
|
||||
/**
|
||||
* All inputs support fields, and all outputs are fields if any of the inputs is a field.
|
||||
@@ -260,12 +258,6 @@ class NodeDeclarationBuilder {
|
||||
declaration_.is_function_node_ = value;
|
||||
}
|
||||
|
||||
/** Return the node this declaration is build for. It may be null. */
|
||||
const bNode *node() const
|
||||
{
|
||||
return node_;
|
||||
}
|
||||
|
||||
template<typename DeclType>
|
||||
typename DeclType::Builder &add_input(StringRef name, StringRef identifier = "");
|
||||
template<typename DeclType>
|
||||
@@ -399,9 +391,8 @@ inline const OutputFieldDependency &SocketDeclaration::output_field_dependency()
|
||||
/** \name #NodeDeclarationBuilder Inline Methods
|
||||
* \{ */
|
||||
|
||||
inline NodeDeclarationBuilder::NodeDeclarationBuilder(NodeDeclaration &declaration,
|
||||
const bNode *node)
|
||||
: declaration_(declaration), node_(node)
|
||||
inline NodeDeclarationBuilder::NodeDeclarationBuilder(NodeDeclaration &declaration)
|
||||
: declaration_(declaration)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -16,41 +16,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "NOD_node_declaration.hh"
|
||||
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_float3.hh"
|
||||
#include "BLI_utility_mixins.hh"
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
class EnumItems : NonCopyable, NonMovable {
|
||||
private:
|
||||
const EnumPropertyItem *items_;
|
||||
std::function<void()> free_fn_;
|
||||
|
||||
public:
|
||||
EnumItems();
|
||||
EnumItems(const EnumPropertyItem *items, std::function<void()> free_fn);
|
||||
~EnumItems();
|
||||
|
||||
const EnumPropertyItem *items() const;
|
||||
};
|
||||
|
||||
struct EnumInputInferencingInfo {
|
||||
std::shared_ptr<EnumItems> items;
|
||||
int inference_index = -1;
|
||||
};
|
||||
|
||||
struct EnumInferencingInterface {
|
||||
Vector<EnumInputInferencingInfo> inputs;
|
||||
};
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
||||
namespace blender::nodes::decl {
|
||||
|
||||
@@ -194,32 +165,6 @@ class StringBuilder : public SocketDeclarationBuilder<String> {
|
||||
StringBuilder &default_value(const std::string value);
|
||||
};
|
||||
|
||||
class EnumBuilder;
|
||||
|
||||
class Enum : public SocketDeclaration {
|
||||
private:
|
||||
int default_value_ = 0;
|
||||
EnumInputInferencingInfo inferencing_info_;
|
||||
friend EnumBuilder;
|
||||
|
||||
public:
|
||||
using Builder = EnumBuilder;
|
||||
|
||||
const EnumInputInferencingInfo &inferencing_info() const;
|
||||
|
||||
bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const override;
|
||||
bool matches(const bNodeSocket &socket) const override;
|
||||
};
|
||||
|
||||
class EnumBuilder : public SocketDeclarationBuilder<Enum> {
|
||||
public:
|
||||
EnumBuilder &default_value(const int value);
|
||||
|
||||
EnumBuilder &static_items(const EnumPropertyItem *items);
|
||||
EnumBuilder &dynamic_items(std::shared_ptr<EnumItems> items);
|
||||
EnumBuilder &inference_items(const int output_index = -1);
|
||||
};
|
||||
|
||||
class IDSocketDeclaration : public SocketDeclaration {
|
||||
private:
|
||||
const char *idname_;
|
||||
@@ -393,18 +338,6 @@ inline StringBuilder &StringBuilder::default_value(std::string value)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #EnumBuilder Inline Methods
|
||||
* \{ */
|
||||
|
||||
inline EnumBuilder &EnumBuilder::default_value(const int value)
|
||||
{
|
||||
decl_->default_value_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #IDSocketDeclaration and Children Inline Methods
|
||||
* \{ */
|
||||
|
@@ -268,7 +268,6 @@ DefNode(FunctionNode, FN_NODE_LEGACY_RANDOM_FLOAT, 0, "LEGACY_RANDOM_FLOAT", Leg
|
||||
DefNode(FunctionNode, FN_NODE_ALIGN_EULER_TO_VECTOR, def_fn_align_euler_to_vector, "ALIGN_EULER_TO_VECTOR", AlignEulerToVector, "Align Euler To Vector", "")
|
||||
DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "")
|
||||
DefNode(FunctionNode, FN_NODE_COMPARE_FLOATS, def_float_compare, "COMPARE_FLOATS", CompareFloats, "Compare Floats", "")
|
||||
DefNode(FunctionNode, FN_NODE_ENUM, 0, "ENUM", Enum, "Enum", "")
|
||||
DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_BOOL, def_fn_input_bool, "INPUT_BOOL", InputBool, "Boolean", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_COLOR, def_fn_input_color, "INPUT_COLOR", InputColor, "Color", "")
|
||||
|
@@ -1,206 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "NOD_geometry_exec.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void fn_node_enum_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
const bNode *node = b.node();
|
||||
if (node == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
b.add_output<decl::Int>("Index");
|
||||
|
||||
EnumPropertyItem *items = nullptr;
|
||||
int tot_items = 0;
|
||||
|
||||
const NodeFunctionEnum *storage = (const NodeFunctionEnum *)node->storage;
|
||||
LISTBASE_FOREACH (const NodeFunctionEnumItem *, item, &storage->items) {
|
||||
b.add_output<decl::Bool>(item->name ? item->name : "Bool",
|
||||
"item_" + std::to_string(item->value));
|
||||
EnumPropertyItem enum_item = {0};
|
||||
enum_item.identifier = BLI_strdup(item->name ? item->name : "");
|
||||
enum_item.name = enum_item.identifier;
|
||||
enum_item.description = BLI_strdup(item->description ? item->description : "");
|
||||
enum_item.value = item->value;
|
||||
RNA_enum_item_add(&items, &tot_items, &enum_item);
|
||||
}
|
||||
RNA_enum_item_end(&items, &tot_items);
|
||||
|
||||
std::shared_ptr<EnumItems> socket_items = std::make_shared<EnumItems>(
|
||||
items, [tot_items, items]() {
|
||||
for (const int i : IndexRange(tot_items - 1)) {
|
||||
EnumPropertyItem &enum_item = items[i];
|
||||
MEM_freeN((void *)enum_item.identifier);
|
||||
MEM_freeN((void *)enum_item.description);
|
||||
}
|
||||
MEM_freeN(items);
|
||||
});
|
||||
|
||||
b.add_input<decl::Enum>("Enum").dynamic_items(std::move(socket_items)).hide_label();
|
||||
};
|
||||
|
||||
static bool fn_node_enum_draw_socket(uiLayout *layout,
|
||||
const bContext *UNUSED(C),
|
||||
bNodeTree *ntree,
|
||||
bNode *node,
|
||||
bNodeSocket *socket)
|
||||
{
|
||||
const int socket_index = BLI_findindex(&node->outputs, socket);
|
||||
if (socket_index <= 0) {
|
||||
return false;
|
||||
}
|
||||
NodeFunctionEnum *storage = (NodeFunctionEnum *)node->storage;
|
||||
NodeFunctionEnumItem *item = (NodeFunctionEnumItem *)BLI_findlink(&storage->items,
|
||||
socket_index - 1);
|
||||
PointerRNA item_ptr;
|
||||
RNA_pointer_create(&ntree->id, &RNA_NodeFunctionEnumItem, item, &item_ptr);
|
||||
uiItemR(layout, &item_ptr, "name", 0, "", ICON_NONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fn_node_enum_init(bNodeTree *UNUSED(tree), bNode *node)
|
||||
{
|
||||
NodeFunctionEnum *data = (NodeFunctionEnum *)MEM_callocN(sizeof(NodeFunctionEnum), __func__);
|
||||
data->owner_node = node;
|
||||
node->storage = data;
|
||||
}
|
||||
|
||||
static void fn_node_enum_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
bNode *node = (bNode *)ptr->data;
|
||||
uiItemStringO(layout, "Add", ICON_PLUS, "node.enum_item_add", "node_name", node->name);
|
||||
}
|
||||
|
||||
class EnumFunction : public fn::MultiFunction {
|
||||
private:
|
||||
Vector<int> enum_values_;
|
||||
fn::MFSignature signature_;
|
||||
|
||||
public:
|
||||
EnumFunction(const bNode &node)
|
||||
{
|
||||
fn::MFSignatureBuilder signature{"Enum Function"};
|
||||
signature.single_input<EnumValue>("Enum");
|
||||
signature.single_output<int>("Index");
|
||||
|
||||
const NodeFunctionEnum *storage = (NodeFunctionEnum *)node.storage;
|
||||
LISTBASE_FOREACH (const NodeFunctionEnumItem *, item, &storage->items) {
|
||||
signature.single_output<bool>(item->name);
|
||||
enum_values_.append(item->value);
|
||||
}
|
||||
|
||||
signature_ = signature.build();
|
||||
this->set_signature(&signature_);
|
||||
}
|
||||
|
||||
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
|
||||
{
|
||||
const VArray<EnumValue> &enum_in = params.readonly_single_input<EnumValue>(0, "Enum");
|
||||
MutableSpan<int> r_indices = params.uninitialized_single_output_if_required<int>(1, "Index");
|
||||
|
||||
if (!r_indices.is_empty()) {
|
||||
for (const int i : mask) {
|
||||
const int in_value = enum_in[i].value;
|
||||
r_indices[i] = enum_values_.first_index_of_try(in_value);
|
||||
}
|
||||
}
|
||||
|
||||
for (const int enum_index : enum_values_.index_range()) {
|
||||
MutableSpan<bool> r_bools = params.uninitialized_single_output_if_required<bool>(2 +
|
||||
enum_index);
|
||||
if (r_bools.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
const int enum_value = enum_values_[enum_index];
|
||||
for (const int i : mask) {
|
||||
const int in_value = enum_in[i].value;
|
||||
r_bools[i] = in_value == enum_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void fn_node_enum_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
builder.construct_and_set_matching_fn<EnumFunction>(builder.node());
|
||||
}
|
||||
|
||||
static void fn_node_enum_copy_storage(bNodeTree *UNUSED(dest_ntree),
|
||||
bNode *dst_node,
|
||||
const bNode *src_node)
|
||||
{
|
||||
const NodeFunctionEnum *src_storage = (const NodeFunctionEnum *)src_node->storage;
|
||||
NodeFunctionEnum *dst_storage = (NodeFunctionEnum *)MEM_dupallocN(src_storage);
|
||||
dst_storage->owner_node = dst_node;
|
||||
BLI_listbase_clear(&dst_storage->items);
|
||||
LISTBASE_FOREACH (const NodeFunctionEnumItem *, src_item, &src_storage->items) {
|
||||
NodeFunctionEnumItem *dst_item = (NodeFunctionEnumItem *)MEM_dupallocN(src_item);
|
||||
dst_item->owner_node = dst_node;
|
||||
dst_item->name = (char *)MEM_dupallocN(src_item->name);
|
||||
dst_item->description = (char *)MEM_dupallocN(src_item->description);
|
||||
BLI_addtail(&dst_storage->items, dst_item);
|
||||
}
|
||||
dst_node->storage = dst_storage;
|
||||
}
|
||||
|
||||
static void fn_node_enum_free_storage(bNode *node)
|
||||
{
|
||||
NodeFunctionEnum *storage = (NodeFunctionEnum *)node->storage;
|
||||
LISTBASE_FOREACH_MUTABLE (NodeFunctionEnumItem *, item, &storage->items) {
|
||||
if (item->name) {
|
||||
MEM_freeN(item->name);
|
||||
}
|
||||
if (item->description) {
|
||||
MEM_freeN(item->description);
|
||||
}
|
||||
MEM_freeN(item);
|
||||
}
|
||||
MEM_freeN(storage);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
||||
void register_node_type_fn_enum()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
fn_node_type_base(&ntype, FN_NODE_ENUM, "Enum", NODE_CLASS_SCRIPT, 0);
|
||||
node_type_storage(&ntype,
|
||||
"NodeFunctionEnum",
|
||||
blender::nodes::fn_node_enum_free_storage,
|
||||
blender::nodes::fn_node_enum_copy_storage);
|
||||
node_type_init(&ntype, blender::nodes::fn_node_enum_init);
|
||||
ntype.declare = blender::nodes::fn_node_enum_declare;
|
||||
ntype.declaration_is_dynamic = true;
|
||||
ntype.build_multi_function = blender::nodes::fn_node_enum_build_multi_function;
|
||||
ntype.draw_buttons = blender::nodes::fn_node_enum_layout;
|
||||
ntype.draw_socket = blender::nodes::fn_node_enum_draw_socket;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
@@ -110,8 +110,7 @@ static bool geometry_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype
|
||||
SOCK_COLLECTION,
|
||||
SOCK_TEXTURE,
|
||||
SOCK_IMAGE,
|
||||
SOCK_MATERIAL,
|
||||
SOCK_ENUM);
|
||||
SOCK_MATERIAL);
|
||||
}
|
||||
|
||||
void register_node_tree_type_geo(void)
|
||||
|
@@ -31,25 +31,7 @@ namespace blender::nodes {
|
||||
|
||||
static void geo_node_collection_info_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
static const EnumPropertyItem rna_node_geometry_collection_info_transform_space_items[] = {
|
||||
{GEO_NODE_TRANSFORM_SPACE_ORIGINAL,
|
||||
"ORIGINAL",
|
||||
0,
|
||||
"Original",
|
||||
"Output the geometry relative to the collection offset"},
|
||||
{GEO_NODE_TRANSFORM_SPACE_RELATIVE,
|
||||
"RELATIVE",
|
||||
0,
|
||||
"Relative",
|
||||
"Bring the input collection geometry into the modified object, maintaining the relative "
|
||||
"position between the objects in the scene"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
b.add_input<decl::Collection>(N_("Collection")).hide_label();
|
||||
b.add_input<decl::Enum>(N_("Transform Space"))
|
||||
.static_items(rna_node_geometry_collection_info_transform_space_items)
|
||||
.hide_label();
|
||||
b.add_input<decl::Bool>(N_("Separate Children"))
|
||||
.description(
|
||||
N_("Output each child of the collection as a separate instance, sorted alphabetically"));
|
||||
@@ -60,6 +42,11 @@ static void geo_node_collection_info_declare(NodeDeclarationBuilder &b)
|
||||
b.add_output<decl::Geometry>(N_("Geometry"));
|
||||
}
|
||||
|
||||
static void geo_node_collection_info_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "transform_space", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
static void geo_node_collection_info_node_init(bNodeTree *UNUSED(tree), bNode *node)
|
||||
{
|
||||
NodeGeometryCollectionInfo *data = (NodeGeometryCollectionInfo *)MEM_callocN(
|
||||
@@ -93,8 +80,10 @@ static void geo_node_collection_info_exec(GeoNodeExecParams params)
|
||||
return;
|
||||
}
|
||||
|
||||
const bool use_relative_transform = params.get_input<GeometryNodeTransformSpace>(
|
||||
"Transform Space") == GEO_NODE_TRANSFORM_SPACE_RELATIVE;
|
||||
const bNode &bnode = params.node();
|
||||
NodeGeometryCollectionInfo *node_storage = (NodeGeometryCollectionInfo *)bnode.storage;
|
||||
const bool use_relative_transform = (node_storage->transform_space ==
|
||||
GEO_NODE_TRANSFORM_SPACE_RELATIVE);
|
||||
|
||||
InstancesComponent &instances = geometry_set_out.get_component_for_write<InstancesComponent>();
|
||||
|
||||
@@ -180,5 +169,6 @@ void register_node_type_geo_collection_info()
|
||||
node_free_standard_storage,
|
||||
node_copy_standard_storage);
|
||||
ntype.geometry_node_execute = blender::nodes::geo_node_collection_info_exec;
|
||||
ntype.draw_buttons = blender::nodes::geo_node_collection_info_layout;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
@@ -35,17 +35,15 @@ namespace blender::nodes {
|
||||
|
||||
static void geo_node_curve_fill_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
static const EnumPropertyItem mode_items[] = {
|
||||
{GEO_NODE_CURVE_FILL_MODE_TRIANGULATED, "TRIANGLES", 0, "Triangles", ""},
|
||||
{GEO_NODE_CURVE_FILL_MODE_NGONS, "NGONS", 0, "N-gons", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
|
||||
b.add_input<decl::Enum>(N_("Mode")).static_items(mode_items);
|
||||
b.add_output<decl::Geometry>(N_("Mesh"));
|
||||
}
|
||||
|
||||
static void geo_node_curve_fill_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
static void geo_node_curve_fill_init(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
NodeGeometryCurveFill *data = (NodeGeometryCurveFill *)MEM_callocN(sizeof(NodeGeometryCurveFill),
|
||||
@@ -153,7 +151,8 @@ static void geo_node_curve_fill_exec(GeoNodeExecParams params)
|
||||
{
|
||||
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
|
||||
|
||||
const GeometryNodeCurveFillMode mode = params.get_input<GeometryNodeCurveFillMode>("Mode");
|
||||
const NodeGeometryCurveFill &storage = *(const NodeGeometryCurveFill *)params.node().storage;
|
||||
const GeometryNodeCurveFillMode mode = (GeometryNodeCurveFillMode)storage.mode;
|
||||
|
||||
geometry_set.modify_geometry_sets(
|
||||
[&](GeometrySet &geometry_set) { curve_fill_calculate(geometry_set, mode); });
|
||||
@@ -174,5 +173,6 @@ void register_node_type_geo_curve_fill()
|
||||
&ntype, "NodeGeometryCurveFill", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.declare = blender::nodes::geo_node_curve_fill_declare;
|
||||
ntype.geometry_node_execute = blender::nodes::geo_node_curve_fill_exec;
|
||||
ntype.draw_buttons = blender::nodes::geo_node_curve_fill_layout;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
@@ -68,8 +68,6 @@ static void geo_node_switch_declare(NodeDeclarationBuilder &b)
|
||||
b.add_input<decl::Material>(N_("True"), "True_010");
|
||||
b.add_input<decl::Image>(N_("False"), "False_011");
|
||||
b.add_input<decl::Image>(N_("True"), "True_011");
|
||||
b.add_input<decl::Enum>(N_("False"), "False_012");
|
||||
b.add_input<decl::Enum>(N_("True"), "True_012");
|
||||
|
||||
b.add_output<decl::Float>(N_("Output")).dependent_field();
|
||||
b.add_output<decl::Int>(N_("Output"), "Output_001").dependent_field();
|
||||
@@ -83,7 +81,6 @@ static void geo_node_switch_declare(NodeDeclarationBuilder &b)
|
||||
b.add_output<decl::Texture>(N_("Output"), "Output_009");
|
||||
b.add_output<decl::Material>(N_("Output"), "Output_010");
|
||||
b.add_output<decl::Image>(N_("Output"), "Output_011");
|
||||
b.add_output<decl::Enum>(N_("Output"), "Output_012").inference_items();
|
||||
}
|
||||
|
||||
static void geo_node_switch_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
@@ -290,10 +287,6 @@ static void geo_node_switch_exec(GeoNodeExecParams params)
|
||||
switch_no_fields<Image *>(params, "_011");
|
||||
break;
|
||||
}
|
||||
case SOCK_ENUM: {
|
||||
switch_no_fields<EnumValue>(params, "_012");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
|
@@ -254,29 +254,6 @@ std::string GeoNodeExecParams::attribute_producer_name() const
|
||||
return provider_->dnode->label_or_name() + TIP_(" node");
|
||||
}
|
||||
|
||||
const int GeoNodeExecParams::validate_enum_value(StringRef identifier, const int value) const
|
||||
{
|
||||
const bNodeSocket &socket = *provider_->dnode->input_by_identifier(identifier).bsocket();
|
||||
BLI_assert(socket.type == SOCK_ENUM);
|
||||
const bNodeSocketValueEnum *socket_value = (const bNodeSocketValueEnum *)socket.default_value;
|
||||
BLI_assert(socket_value->items != nullptr);
|
||||
for (const EnumPropertyItem *item = socket_value->items; item->identifier != nullptr; item++) {
|
||||
if (item->identifier[0]) {
|
||||
if (item->value == value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Use the first value as default if the passed in value is invalid. */
|
||||
for (const EnumPropertyItem *item = socket_value->items; item->identifier != nullptr; item++) {
|
||||
if (item->identifier[0]) {
|
||||
return item->value;
|
||||
}
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GeoNodeExecParams::check_input_access(StringRef identifier,
|
||||
const CPPType *requested_type) const
|
||||
{
|
||||
|
@@ -44,13 +44,11 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "NOD_geometry_exec.hh"
|
||||
#include "NOD_node_declaration.hh"
|
||||
#include "NOD_socket.h"
|
||||
|
||||
#include "FN_cpp_type_make.hh"
|
||||
#include "FN_field.hh"
|
||||
#include "FN_field_cpp_type.hh"
|
||||
|
||||
using namespace blender;
|
||||
using blender::nodes::SocketDeclarationPtr;
|
||||
@@ -400,14 +398,6 @@ void node_socket_init_default_value(bNodeSocket *sock)
|
||||
sizeof(bNodeSocketValueMaterial), "node socket value material");
|
||||
dval->value = nullptr;
|
||||
|
||||
sock->default_value = dval;
|
||||
break;
|
||||
}
|
||||
case SOCK_ENUM: {
|
||||
bNodeSocketValueEnum *dval = (bNodeSocketValueEnum *)MEM_callocN(
|
||||
sizeof(bNodeSocketValueEnum), "node socket value enum");
|
||||
dval->value = 0;
|
||||
|
||||
sock->default_value = dval;
|
||||
break;
|
||||
}
|
||||
@@ -504,12 +494,6 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from)
|
||||
id_us_plus(&toval->value->id);
|
||||
break;
|
||||
}
|
||||
case SOCK_ENUM: {
|
||||
bNodeSocketValueEnum *toval = (bNodeSocketValueEnum *)to->default_value;
|
||||
bNodeSocketValueEnum *fromval = (bNodeSocketValueEnum *)from->default_value;
|
||||
*toval = *fromval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
to->flag |= (from->flag & SOCK_HIDE_VALUE);
|
||||
@@ -827,8 +811,6 @@ MAKE_CPP_TYPE(Collection, Collection *, CPPTypeFlags::BasicType)
|
||||
MAKE_CPP_TYPE(Texture, Tex *, CPPTypeFlags::BasicType)
|
||||
MAKE_CPP_TYPE(Image, Image *, CPPTypeFlags::BasicType)
|
||||
MAKE_CPP_TYPE(Material, Material *, CPPTypeFlags::BasicType)
|
||||
MAKE_CPP_TYPE(EnumValue, blender::nodes::EnumValue, CPPTypeFlags::None)
|
||||
MAKE_FIELD_CPP_TYPE(EnumValueField, blender::nodes::EnumValue);
|
||||
|
||||
static bNodeSocketType *make_socket_type_object()
|
||||
{
|
||||
@@ -902,26 +884,6 @@ static bNodeSocketType *make_socket_type_material()
|
||||
return socktype;
|
||||
}
|
||||
|
||||
static bNodeSocketType *make_socket_type_enum()
|
||||
{
|
||||
using blender::nodes::EnumValue;
|
||||
bNodeSocketType *socktype = make_standard_socket_type(SOCK_ENUM, PROP_NONE);
|
||||
socktype->get_base_cpp_type = []() { return &blender::fn::CPPType::get<EnumValue>(); };
|
||||
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
|
||||
((EnumValue *)r_value)->value = ((bNodeSocketValueEnum *)socket.default_value)->value;
|
||||
};
|
||||
|
||||
socktype->get_geometry_nodes_cpp_type = []() {
|
||||
return &blender::fn::CPPType::get<blender::fn::Field<EnumValue>>();
|
||||
};
|
||||
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
|
||||
EnumValue value;
|
||||
socket.typeinfo->get_base_cpp_value(socket, &value);
|
||||
new (r_value) blender::fn::Field<EnumValue>(blender::fn::make_constant_field(value));
|
||||
};
|
||||
return socktype;
|
||||
}
|
||||
|
||||
void register_standard_node_socket_types(void)
|
||||
{
|
||||
/* Draw callbacks are set in `drawnode.c` to avoid bad-level calls. */
|
||||
@@ -968,7 +930,5 @@ void register_standard_node_socket_types(void)
|
||||
|
||||
nodeRegisterSocketType(make_socket_type_material());
|
||||
|
||||
nodeRegisterSocketType(make_socket_type_enum());
|
||||
|
||||
nodeRegisterSocketType(make_socket_type_virtual());
|
||||
}
|
||||
|
@@ -19,36 +19,8 @@
|
||||
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
EnumItems::EnumItems() : items_(DummyRNA_NULL_items)
|
||||
{
|
||||
}
|
||||
|
||||
EnumItems::EnumItems(const EnumPropertyItem *items, std::function<void()> free_fn)
|
||||
: items_(items), free_fn_(std::move(free_fn))
|
||||
{
|
||||
BLI_assert(items != nullptr);
|
||||
}
|
||||
|
||||
EnumItems::~EnumItems()
|
||||
{
|
||||
if (free_fn_) {
|
||||
free_fn_();
|
||||
}
|
||||
}
|
||||
|
||||
const EnumPropertyItem *EnumItems::items() const
|
||||
{
|
||||
return items_;
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
||||
namespace blender::nodes::decl {
|
||||
|
||||
static void modify_subtype_except_for_storage(bNodeSocket &socket, int new_subtype)
|
||||
@@ -301,56 +273,6 @@ bool String::matches(const bNodeSocket &socket) const
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #Enum
|
||||
* \{ */
|
||||
|
||||
const EnumInputInferencingInfo &Enum::inferencing_info() const
|
||||
{
|
||||
return inferencing_info_;
|
||||
}
|
||||
|
||||
bNodeSocket &Enum::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const
|
||||
{
|
||||
bNodeSocket &socket = *nodeAddStaticSocket(
|
||||
&ntree, &node, in_out, SOCK_ENUM, PROP_NONE, identifier_.c_str(), name_.c_str());
|
||||
((bNodeSocketValueEnum *)socket.default_value)->value = default_value_;
|
||||
this->set_common_flags(socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
bool Enum::matches(const bNodeSocket &socket) const
|
||||
{
|
||||
if (!this->matches_common_data(socket)) {
|
||||
return false;
|
||||
}
|
||||
if (socket.type != SOCK_ENUM) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
EnumBuilder &EnumBuilder::static_items(const EnumPropertyItem *items)
|
||||
{
|
||||
BLI_assert(items != nullptr);
|
||||
decl_->inferencing_info_.items = std::make_shared<EnumItems>(items, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
EnumBuilder &EnumBuilder::dynamic_items(std::shared_ptr<EnumItems> items)
|
||||
{
|
||||
decl_->inferencing_info_.items = std::move(items);
|
||||
return *this;
|
||||
}
|
||||
|
||||
EnumBuilder &EnumBuilder::inference_items(const int output_index)
|
||||
{
|
||||
decl_->inferencing_info_.inference_index = output_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #IDSocketDeclaration
|
||||
* \{ */
|
||||
|
@@ -483,14 +483,6 @@ static int node_datatype_priority(eNodeSocketDatatype from, eNodeSocketDatatype
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
case SOCK_ENUM: {
|
||||
switch (from) {
|
||||
case SOCK_ENUM:
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user