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;
|
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) {
|
if (!b_ob_data) {
|
||||||
return false;
|
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) {
|
if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR) {
|
||||||
/* Will be exported attached to mesh. */
|
/* 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);
|
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)
|
bool BlenderSync::object_is_light(BL::Object &b_ob)
|
||||||
{
|
{
|
||||||
BL::ID b_ob_data = b_ob.data();
|
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 */
|
/* 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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -162,19 +162,19 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
|||||||
/* Object */
|
/* Object */
|
||||||
else if (b_id.is_a(&RNA_Object)) {
|
else if (b_id.is_a(&RNA_Object)) {
|
||||||
BL::Object b_ob(b_id);
|
BL::Object b_ob(b_id);
|
||||||
const bool is_geometry = object_is_geometry(b_ob);
|
const bool can_have_geometry = object_can_have_geometry(b_ob);
|
||||||
const bool is_light = !is_geometry && object_is_light(b_ob);
|
const bool is_light = !can_have_geometry && object_is_light(b_ob);
|
||||||
|
|
||||||
if (b_ob.is_instancer() && b_update.is_updated_shading()) {
|
if (b_ob.is_instancer() && b_update.is_updated_shading()) {
|
||||||
/* Needed for e.g. object color updates on instancer. */
|
/* Needed for e.g. object color updates on instancer. */
|
||||||
object_map.set_recalc(b_ob);
|
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();
|
const bool updated_geometry = b_update.is_updated_geometry();
|
||||||
|
|
||||||
/* Geometry (mesh, hair, volume). */
|
/* Geometry (mesh, hair, volume). */
|
||||||
if (is_geometry) {
|
if (can_have_geometry) {
|
||||||
if (b_update.is_updated_transform() || b_update.is_updated_shading()) {
|
if (b_update.is_updated_transform() || b_update.is_updated_shading()) {
|
||||||
object_map.set_recalc(b_ob);
|
object_map.set_recalc(b_ob);
|
||||||
}
|
}
|
||||||
|
@@ -208,7 +208,8 @@ class BlenderSync {
|
|||||||
/* util */
|
/* util */
|
||||||
void find_shader(BL::ID &id, array<Node *> &used_shaders, Shader *default_shader);
|
void find_shader(BL::ID &id, array<Node *> &used_shaders, Shader *default_shader);
|
||||||
bool BKE_object_is_modified(BL::Object &b_ob);
|
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);
|
bool object_is_light(BL::Object &b_ob);
|
||||||
|
|
||||||
/* variables */
|
/* variables */
|
||||||
|
@@ -379,7 +379,6 @@ if(WITH_CYCLES_CUDA_BINARIES)
|
|||||||
${SRC_KERNEL_HEADERS}
|
${SRC_KERNEL_HEADERS}
|
||||||
${SRC_KERNEL_DEVICE_GPU_HEADERS}
|
${SRC_KERNEL_DEVICE_GPU_HEADERS}
|
||||||
${SRC_KERNEL_DEVICE_CUDA_HEADERS}
|
${SRC_KERNEL_DEVICE_CUDA_HEADERS}
|
||||||
${SRC_KERNEL_DEVICE_METAL_HEADERS}
|
|
||||||
${SRC_UTIL_HEADERS}
|
${SRC_UTIL_HEADERS}
|
||||||
)
|
)
|
||||||
set(cuda_cubins)
|
set(cuda_cubins)
|
||||||
|
@@ -92,25 +92,19 @@
|
|||||||
|
|
||||||
/* Compute number of threads per block and minimum blocks per multiprocessor
|
/* Compute number of threads per block and minimum blocks per multiprocessor
|
||||||
* given the maximum number of registers per thread. */
|
* given the maximum number of registers per thread. */
|
||||||
|
#define ccl_gpu_kernel(block_num_threads, thread_num_registers) \
|
||||||
#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) \
|
|
||||||
extern "C" __global__ void __launch_bounds__(block_num_threads, \
|
extern "C" __global__ void __launch_bounds__(block_num_threads, \
|
||||||
GPU_MULTIPRESSOR_MAX_REGISTERS / \
|
GPU_MULTIPRESSOR_MAX_REGISTERS / \
|
||||||
(block_num_threads * thread_num_registers))
|
(block_num_threads * thread_num_registers))
|
||||||
|
|
||||||
/* allow ccl_gpu_kernel to accept 1 or 2 parameters */
|
#define ccl_gpu_kernel_threads(block_num_threads) \
|
||||||
#define SELECT_MACRO(_1, _2, NAME, ...) NAME
|
extern "C" __global__ void __launch_bounds__(block_num_threads)
|
||||||
#define ccl_gpu_kernel(...) \
|
|
||||||
SELECT_MACRO(__VA_ARGS__, ccl_gpu_kernel_threads_registers, ccl_gpu_kernel_threads)(__VA_ARGS__)
|
|
||||||
|
|
||||||
#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
|
#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
|
||||||
|
|
||||||
#define ccl_gpu_kernel_call(x) x
|
#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 */
|
* specify captured state */
|
||||||
#define ccl_gpu_kernel_lambda(func, ...) \
|
#define ccl_gpu_kernel_lambda(func, ...) \
|
||||||
struct KernelLambda { \
|
struct KernelLambda { \
|
||||||
@@ -119,8 +113,7 @@
|
|||||||
{ \
|
{ \
|
||||||
return (func); \
|
return (func); \
|
||||||
} \
|
} \
|
||||||
} ccl_gpu_kernel_lambda_pass; \
|
} ccl_gpu_kernel_lambda_pass
|
||||||
ccl_gpu_kernel_lambda_pass
|
|
||||||
|
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
|
|
||||||
|
@@ -56,8 +56,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(integrator_reset,
|
ccl_gpu_kernel_signature(integrator_reset, int num_states)
|
||||||
int num_states)
|
|
||||||
{
|
{
|
||||||
const int state = ccl_gpu_global_id_x();
|
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,
|
ccl_gpu_kernel_signature(integrator_queued_paths_array,
|
||||||
int num_states,
|
int num_states,
|
||||||
ccl_global int *indices,
|
ccl_global int *indices,
|
||||||
@@ -273,14 +272,14 @@ ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
|||||||
int kernel_index)
|
int kernel_index)
|
||||||
{
|
{
|
||||||
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) == kernel_index,
|
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) == kernel_index,
|
||||||
int kernel_index)
|
int kernel_index);
|
||||||
.kernel_index = kernel_index;
|
ccl_gpu_kernel_lambda_pass.kernel_index = kernel_index;
|
||||||
|
|
||||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||||
num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
|
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,
|
ccl_gpu_kernel_signature(integrator_queued_shadow_paths_array,
|
||||||
int num_states,
|
int num_states,
|
||||||
ccl_global int *indices,
|
ccl_global int *indices,
|
||||||
@@ -288,25 +287,26 @@ ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
|||||||
int kernel_index)
|
int kernel_index)
|
||||||
{
|
{
|
||||||
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, shadow_path, queued_kernel) == kernel_index,
|
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, shadow_path, queued_kernel) == kernel_index,
|
||||||
int kernel_index)
|
int kernel_index);
|
||||||
.kernel_index = kernel_index;
|
ccl_gpu_kernel_lambda_pass.kernel_index = kernel_index;
|
||||||
|
|
||||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||||
num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
|
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,
|
ccl_gpu_kernel_signature(integrator_active_paths_array,
|
||||||
int num_states,
|
int num_states,
|
||||||
ccl_global int *indices,
|
ccl_global int *indices,
|
||||||
ccl_global int *num_indices)
|
ccl_global int *num_indices)
|
||||||
{
|
{
|
||||||
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) != 0);
|
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) != 0);
|
||||||
|
|
||||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||||
num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
|
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,
|
ccl_gpu_kernel_signature(integrator_terminated_paths_array,
|
||||||
int num_states,
|
int num_states,
|
||||||
ccl_global int *indices,
|
ccl_global int *indices,
|
||||||
@@ -314,11 +314,12 @@ ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
|||||||
int indices_offset)
|
int indices_offset)
|
||||||
{
|
{
|
||||||
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) == 0);
|
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, path, queued_kernel) == 0);
|
||||||
|
|
||||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||||
num_states, indices + indices_offset, num_indices, ccl_gpu_kernel_lambda_pass);
|
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,
|
ccl_gpu_kernel_signature(integrator_terminated_shadow_paths_array,
|
||||||
int num_states,
|
int num_states,
|
||||||
ccl_global int *indices,
|
ccl_global int *indices,
|
||||||
@@ -326,11 +327,12 @@ ccl_gpu_kernel(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
|
|||||||
int indices_offset)
|
int indices_offset)
|
||||||
{
|
{
|
||||||
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, shadow_path, queued_kernel) == 0);
|
ccl_gpu_kernel_lambda(INTEGRATOR_STATE(state, shadow_path, queued_kernel) == 0);
|
||||||
|
|
||||||
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||||
num_states, indices + indices_offset, num_indices, ccl_gpu_kernel_lambda_pass);
|
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,
|
ccl_gpu_kernel_signature(integrator_sorted_paths_array,
|
||||||
int num_states,
|
int num_states,
|
||||||
int num_states_limit,
|
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) ?
|
ccl_gpu_kernel_lambda((INTEGRATOR_STATE(state, path, queued_kernel) == kernel_index) ?
|
||||||
INTEGRATOR_STATE(state, path, shader_sort_key) :
|
INTEGRATOR_STATE(state, path, shader_sort_key) :
|
||||||
GPU_PARALLEL_SORTED_INDEX_INACTIVE_KEY,
|
GPU_PARALLEL_SORTED_INDEX_INACTIVE_KEY,
|
||||||
int kernel_index)
|
int kernel_index);
|
||||||
.kernel_index = kernel_index;
|
ccl_gpu_kernel_lambda_pass.kernel_index = kernel_index;
|
||||||
|
|
||||||
const uint state_index = ccl_gpu_global_id_x();
|
const uint state_index = ccl_gpu_global_id_x();
|
||||||
gpu_parallel_sorted_index_array(
|
gpu_parallel_sorted_index_array(state_index,
|
||||||
state_index,
|
num_states,
|
||||||
num_states,
|
num_states_limit,
|
||||||
num_states_limit,
|
indices,
|
||||||
indices,
|
|
||||||
num_indices,
|
num_indices,
|
||||||
key_counter,
|
key_counter,
|
||||||
key_prefix_sum,
|
key_prefix_sum,
|
||||||
ccl_gpu_kernel_lambda_pass);
|
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,
|
ccl_gpu_kernel_signature(integrator_compact_paths_array,
|
||||||
int num_states,
|
int num_states,
|
||||||
ccl_global int *indices,
|
ccl_global int *indices,
|
||||||
ccl_global int *num_indices,
|
ccl_global int *num_indices,
|
||||||
int num_active_paths)
|
int num_active_paths)
|
||||||
{
|
{
|
||||||
ccl_gpu_kernel_lambda((state >= num_active_paths) && (INTEGRATOR_STATE(state, path, queued_kernel) != 0),
|
ccl_gpu_kernel_lambda((state >= num_active_paths) &&
|
||||||
int num_active_paths)
|
(INTEGRATOR_STATE(state, path, queued_kernel) != 0),
|
||||||
.num_active_paths = num_active_paths;
|
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>(
|
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||||
num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
|
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_gpu_kernel_signature(integrator_compact_states,
|
||||||
ccl_global const int *active_terminated_states,
|
ccl_global const int *active_terminated_states,
|
||||||
const int active_states_offset,
|
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,
|
ccl_gpu_kernel_signature(integrator_compact_shadow_paths_array,
|
||||||
int num_states,
|
int num_states,
|
||||||
ccl_global int *indices,
|
ccl_global int *indices,
|
||||||
ccl_global int *num_indices,
|
ccl_global int *num_indices,
|
||||||
int num_active_paths)
|
int num_active_paths)
|
||||||
{
|
{
|
||||||
ccl_gpu_kernel_lambda((state >= num_active_paths) && (INTEGRATOR_STATE(state, shadow_path, queued_kernel) != 0),
|
ccl_gpu_kernel_lambda((state >= num_active_paths) &&
|
||||||
int num_active_paths)
|
(INTEGRATOR_STATE(state, shadow_path, queued_kernel) != 0),
|
||||||
.num_active_paths = num_active_paths;
|
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>(
|
gpu_parallel_active_index_array<GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE>(
|
||||||
num_states, indices, num_indices, ccl_gpu_kernel_lambda_pass);
|
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_gpu_kernel_signature(integrator_compact_shadow_states,
|
||||||
ccl_global const int *active_terminated_states,
|
ccl_global const int *active_terminated_states,
|
||||||
const int active_states_offset,
|
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)
|
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);
|
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(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) \
|
||||||
ccl_gpu_kernel_signature(film_convert_##variant, \
|
ccl_gpu_kernel_signature(film_convert_##variant, \
|
||||||
const KernelFilmConvert kfilm_convert, \
|
const KernelFilmConvert kfilm_convert, \
|
||||||
ccl_global uchar4 *rgba, \
|
ccl_global float *pixels, \
|
||||||
ccl_global float *render_buffer, \
|
ccl_global float *render_buffer, \
|
||||||
int num_pixels, \
|
int num_pixels, \
|
||||||
int width, \
|
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 + \
|
ccl_global const float *buffer = render_buffer + offset + x * kfilm_convert.pass_stride + \
|
||||||
y * stride * 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_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) \
|
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]; \
|
float pixel[4]; \
|
||||||
film_get_pass_pixel_##variant(&kfilm_convert, buffer, pixel); \
|
film_get_pass_pixel_##variant(&kfilm_convert, buffer, pixel); \
|
||||||
\
|
|
||||||
film_apply_pass_pixel_overlays_rgba(&kfilm_convert, buffer, pixel); \
|
|
||||||
\
|
\
|
||||||
if (input_channel_count == 1) { \
|
if (input_channel_count == 1) { \
|
||||||
pixel[1] = pixel[2] = pixel[0]; \
|
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; \
|
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])); \
|
*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(combined, 4)
|
||||||
KERNEL_FILM_CONVERT_VARIANT(float4, 4)
|
KERNEL_FILM_CONVERT_VARIANT(float4, 4)
|
||||||
|
|
||||||
|
#undef KERNEL_FILM_CONVERT_VARIANT
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* Shader evaluation.
|
* Shader evaluation.
|
||||||
*/
|
*/
|
||||||
|
@@ -35,25 +35,19 @@
|
|||||||
|
|
||||||
/* Compute number of threads per block and minimum blocks per multiprocessor
|
/* Compute number of threads per block and minimum blocks per multiprocessor
|
||||||
* given the maximum number of registers per thread. */
|
* given the maximum number of registers per thread. */
|
||||||
|
#define ccl_gpu_kernel(block_num_threads, thread_num_registers) \
|
||||||
#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) \
|
|
||||||
extern "C" __global__ void __launch_bounds__(block_num_threads, \
|
extern "C" __global__ void __launch_bounds__(block_num_threads, \
|
||||||
GPU_MULTIPRESSOR_MAX_REGISTERS / \
|
GPU_MULTIPRESSOR_MAX_REGISTERS / \
|
||||||
(block_num_threads * thread_num_registers))
|
(block_num_threads * thread_num_registers))
|
||||||
|
|
||||||
/* allow ccl_gpu_kernel to accept 1 or 2 parameters */
|
#define ccl_gpu_kernel_threads(block_num_threads) \
|
||||||
#define SELECT_MACRO(_1, _2, NAME, ...) NAME
|
extern "C" __global__ void __launch_bounds__(block_num_threads)
|
||||||
#define ccl_gpu_kernel(...) \
|
|
||||||
SELECT_MACRO(__VA_ARGS__, ccl_gpu_kernel_threads_registers, ccl_gpu_kernel_threads)(__VA_ARGS__)
|
|
||||||
|
|
||||||
#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
|
#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
|
||||||
|
|
||||||
#define ccl_gpu_kernel_call(x) x
|
#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 */
|
* specify captured state */
|
||||||
#define ccl_gpu_kernel_lambda(func, ...) \
|
#define ccl_gpu_kernel_lambda(func, ...) \
|
||||||
struct KernelLambda { \
|
struct KernelLambda { \
|
||||||
@@ -62,8 +56,7 @@
|
|||||||
{ \
|
{ \
|
||||||
return (func); \
|
return (func); \
|
||||||
} \
|
} \
|
||||||
} ccl_gpu_kernel_lambda_pass; \
|
} ccl_gpu_kernel_lambda_pass
|
||||||
ccl_gpu_kernel_lambda_pass
|
|
||||||
|
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
|
|
||||||
|
@@ -70,7 +70,8 @@ using namespace metal;
|
|||||||
|
|
||||||
/* kernel.h adapters */
|
/* 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) */
|
/* convert a comma-separated list into a semicolon-separated list (so that we can generate a struct based on kernel entrypoint parameters) */
|
||||||
#define FN0()
|
#define FN0()
|
||||||
@@ -143,7 +144,7 @@ void kernel_gpu_##name::run(thread MetalKernelContext& context, \
|
|||||||
ccl_private MetalKernelContext &context; \
|
ccl_private MetalKernelContext &context; \
|
||||||
__VA_ARGS__; \
|
__VA_ARGS__; \
|
||||||
int operator()(const int state) const { return (func); } \
|
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
|
// clang-format on
|
||||||
|
|
||||||
@@ -247,4 +248,4 @@ constant constexpr array<sampler, SamplerCount> metal_samplers = {
|
|||||||
sampler(address::repeat, filter::linear),
|
sampler(address::repeat, filter::linear),
|
||||||
sampler(address::clamp_to_edge, filter::linear),
|
sampler(address::clamp_to_edge, filter::linear),
|
||||||
sampler(address::clamp_to_zero, filter::linear),
|
sampler(address::clamp_to_zero, filter::linear),
|
||||||
};
|
};
|
||||||
|
@@ -264,7 +264,7 @@ PYGETTEXT_KEYWORDS = (() +
|
|||||||
for it in ("BMO_error_raise",)) +
|
for it in ("BMO_error_raise",)) +
|
||||||
|
|
||||||
tuple(("{}\\((?:[^\"',]+,)\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
|
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*(?:" +
|
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)
|
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'}
|
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 = (
|
classes = (
|
||||||
NodeSetting,
|
NodeSetting,
|
||||||
|
|
||||||
@@ -339,5 +314,4 @@ classes = (
|
|||||||
NODE_OT_add_search,
|
NODE_OT_add_search,
|
||||||
NODE_OT_collapse_hide_unused_toggle,
|
NODE_OT_collapse_hide_unused_toggle,
|
||||||
NODE_OT_tree_path_parent,
|
NODE_OT_tree_path_parent,
|
||||||
NODE_OT_enum_item_add,
|
|
||||||
)
|
)
|
||||||
|
@@ -754,7 +754,6 @@ geometry_node_categories = [
|
|||||||
NodeItem("GeometryNodeSwitch"),
|
NodeItem("GeometryNodeSwitch"),
|
||||||
NodeItem("FunctionNodeRandomValue"),
|
NodeItem("FunctionNodeRandomValue"),
|
||||||
NodeItem("FunctionNodeAlignEulerToVector"),
|
NodeItem("FunctionNodeAlignEulerToVector"),
|
||||||
NodeItem("FunctionNodeEnum"),
|
|
||||||
]),
|
]),
|
||||||
GeometryNodeCategory("GEO_VECTOR", "Vector", items=[
|
GeometryNodeCategory("GEO_VECTOR", "Vector", items=[
|
||||||
NodeItem("ShaderNodeVectorCurve"),
|
NodeItem("ShaderNodeVectorCurve"),
|
||||||
|
@@ -41,7 +41,8 @@ struct Mesh;
|
|||||||
struct Object;
|
struct Object;
|
||||||
struct Scene;
|
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);
|
void BKE_mesh_runtime_reset_on_copy(struct Mesh *mesh, const int flag);
|
||||||
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh);
|
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh);
|
||||||
void BKE_mesh_runtime_looptri_recalc(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 */
|
/* Additional parameters in the side panel */
|
||||||
void (*draw_buttons_ex)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
|
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 */
|
/* Additional drawing on backdrop */
|
||||||
void (*draw_backdrop)(
|
void (*draw_backdrop)(
|
||||||
struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y);
|
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);
|
int nodeSocketLinkLimit(const struct bNodeSocket *sock);
|
||||||
|
|
||||||
void nodeUpdateFromDeclaration(struct bNodeTree *ntree, struct bNode *node);
|
|
||||||
bool nodeDeclarationEnsure(struct bNodeTree *ntree, struct bNode *node);
|
bool nodeDeclarationEnsure(struct bNodeTree *ntree, struct bNode *node);
|
||||||
bool nodeDeclarationEnsureOnOutdatedNode(struct bNodeTree *ntree, struct bNode *node);
|
bool nodeDeclarationEnsureOnOutdatedNode(struct bNodeTree *ntree, struct bNode *node);
|
||||||
void nodeSocketDeclarationsUpdate(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_REPLACE_STRING 1218
|
||||||
#define FN_NODE_INPUT_BOOL 1219
|
#define FN_NODE_INPUT_BOOL 1219
|
||||||
#define FN_NODE_INPUT_INT 1220
|
#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->pdata);
|
||||||
CustomData_reset(&mesh->ldata);
|
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);
|
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;
|
mesh->edit_mesh = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BKE_mesh_runtime_clear_cache(mesh);
|
BKE_mesh_runtime_free_data(mesh);
|
||||||
mesh_clear_geometry(mesh);
|
mesh_clear_geometry(mesh);
|
||||||
MEM_SAFE_FREE(mesh->mat);
|
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->texflag &= ~ME_AUTOSPACE_EVALUATED;
|
||||||
mesh->edit_mesh = nullptr;
|
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 */
|
/* happens with old files */
|
||||||
if (mesh->mselect == nullptr) {
|
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");
|
mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex");
|
||||||
BLI_mutex_init(mesh->runtime.eval_mutex);
|
BLI_mutex_init(mesh->runtime.eval_mutex);
|
||||||
mesh->runtime.render_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime render_mutex");
|
mesh->runtime.render_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime render_mutex");
|
||||||
BLI_mutex_init(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.
|
/* 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
|
* 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.) */
|
* 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->bvh_cache = NULL;
|
||||||
runtime->shrinkwrap_data = NULL;
|
runtime->shrinkwrap_data = NULL;
|
||||||
|
|
||||||
mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex");
|
mesh_runtime_init_mutexes(mesh);
|
||||||
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 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)
|
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) {
|
if (mesh->runtime.mesh_eval != NULL) {
|
||||||
mesh->runtime.mesh_eval->edit_mesh = NULL;
|
mesh->runtime.mesh_eval->edit_mesh = NULL;
|
||||||
BKE_id_free(NULL, mesh->runtime.mesh_eval);
|
BKE_id_free(NULL, mesh->runtime.mesh_eval);
|
||||||
|
@@ -87,7 +87,6 @@
|
|||||||
#include "NOD_node_tree_ref.hh"
|
#include "NOD_node_tree_ref.hh"
|
||||||
#include "NOD_shader.h"
|
#include "NOD_shader.h"
|
||||||
#include "NOD_socket.h"
|
#include "NOD_socket.h"
|
||||||
#include "NOD_socket_declarations.hh"
|
|
||||||
#include "NOD_texture.h"
|
#include "NOD_texture.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
@@ -131,6 +130,10 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
|
|||||||
static void nodeMuteRerouteOutputLinks(struct bNodeTree *ntree,
|
static void nodeMuteRerouteOutputLinks(struct bNodeTree *ntree,
|
||||||
struct bNode *node,
|
struct bNode *node,
|
||||||
const bool mute);
|
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)
|
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;
|
ntree_dst->interface_type = nullptr;
|
||||||
|
|
||||||
if (ntree_src->field_inferencing_interface) {
|
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);
|
*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) {
|
if (flag & LIB_ID_COPY_NO_PREVIEW) {
|
||||||
ntree_dst->preview = nullptr;
|
ntree_dst->preview = nullptr;
|
||||||
@@ -302,8 +301,7 @@ static void ntree_free_data(ID *id)
|
|||||||
MEM_freeN(sock);
|
MEM_freeN(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete ntree->field_inferencing_interface;
|
node_field_inferencing_interface_free(ntree->field_inferencing_interface);
|
||||||
delete ntree->enum_inferencing_interface;
|
|
||||||
|
|
||||||
/* free preview hash */
|
/* free preview hash */
|
||||||
if (ntree->previews) {
|
if (ntree->previews) {
|
||||||
@@ -361,7 +359,6 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket
|
|||||||
case SOCK_CUSTOM:
|
case SOCK_CUSTOM:
|
||||||
case SOCK_SHADER:
|
case SOCK_SHADER:
|
||||||
case SOCK_GEOMETRY:
|
case SOCK_GEOMETRY:
|
||||||
case SOCK_ENUM:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,9 +490,6 @@ static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *so
|
|||||||
case SOCK_MATERIAL:
|
case SOCK_MATERIAL:
|
||||||
BLO_write_struct(writer, bNodeSocketValueMaterial, sock->default_value);
|
BLO_write_struct(writer, bNodeSocketValueMaterial, sock->default_value);
|
||||||
break;
|
break;
|
||||||
case SOCK_ENUM:
|
|
||||||
BLO_write_struct(writer, bNodeSocketValueEnum, sock->default_value);
|
|
||||||
break;
|
|
||||||
case __SOCK_MESH:
|
case __SOCK_MESH:
|
||||||
case SOCK_CUSTOM:
|
case SOCK_CUSTOM:
|
||||||
case SOCK_SHADER:
|
case SOCK_SHADER:
|
||||||
@@ -626,15 +620,6 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
|
|||||||
}
|
}
|
||||||
BLO_write_struct_by_name(writer, node->typeinfo->storagename, storage);
|
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) {
|
else if (node->typeinfo != &NodeTypeUndefined) {
|
||||||
BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
|
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->total_inputs = 0; /* Clear runtime data set before drawing. */
|
||||||
sock->cache = nullptr;
|
sock->cache = nullptr;
|
||||||
sock->declaration = 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! */
|
/* ntree itself has been read! */
|
||||||
@@ -716,7 +697,6 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
|
|||||||
ntree->execdata = nullptr;
|
ntree->execdata = nullptr;
|
||||||
|
|
||||||
ntree->field_inferencing_interface = nullptr;
|
ntree->field_inferencing_interface = nullptr;
|
||||||
ntree->enum_inferencing_interface = nullptr;
|
|
||||||
|
|
||||||
BLO_read_data_address(reader, &ntree->adt);
|
BLO_read_data_address(reader, &ntree->adt);
|
||||||
BKE_animdata_blend_read_data(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);
|
BLO_read_data_address(reader, &storage->string);
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -936,7 +905,6 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock
|
|||||||
case SOCK_CUSTOM:
|
case SOCK_CUSTOM:
|
||||||
case SOCK_SHADER:
|
case SOCK_SHADER:
|
||||||
case SOCK_GEOMETRY:
|
case SOCK_GEOMETRY:
|
||||||
case SOCK_ENUM:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1032,7 +1000,6 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock)
|
|||||||
case SOCK_CUSTOM:
|
case SOCK_CUSTOM:
|
||||||
case SOCK_SHADER:
|
case SOCK_SHADER:
|
||||||
case SOCK_GEOMETRY:
|
case SOCK_GEOMETRY:
|
||||||
case SOCK_ENUM:
|
|
||||||
break;
|
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);
|
BLI_strncpy(node->name, DATA_(ntype->ui_name), NODE_MAXSTR);
|
||||||
nodeUniqueName(ntree, node);
|
nodeUniqueName(ntree, node);
|
||||||
|
|
||||||
|
node_add_sockets_from_type(ntree, node, ntype);
|
||||||
|
|
||||||
if (ntype->initfunc != nullptr) {
|
if (ntype->initfunc != nullptr) {
|
||||||
ntype->initfunc(ntree, node);
|
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);
|
ntree->typeinfo->node_add_init(ntree, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
node_add_sockets_from_type(ntree, node, ntype);
|
|
||||||
|
|
||||||
if (node->id) {
|
if (node->id) {
|
||||||
id_us_plus(node->id);
|
id_us_plus(node->id);
|
||||||
}
|
}
|
||||||
@@ -1447,7 +1414,7 @@ void nodeRegisterType(bNodeType *nt)
|
|||||||
if (nt->declare && !nt->declaration_is_dynamic) {
|
if (nt->declare && !nt->declaration_is_dynamic) {
|
||||||
if (nt->fixed_declaration == nullptr) {
|
if (nt->fixed_declaration == nullptr) {
|
||||||
nt->fixed_declaration = new blender::nodes::NodeDeclaration();
|
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);
|
nt->declare(builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1633,7 +1600,6 @@ static void socket_id_user_increment(bNodeSocket *sock)
|
|||||||
case SOCK_CUSTOM:
|
case SOCK_CUSTOM:
|
||||||
case SOCK_SHADER:
|
case SOCK_SHADER:
|
||||||
case SOCK_GEOMETRY:
|
case SOCK_GEOMETRY:
|
||||||
case SOCK_ENUM:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1687,7 +1653,6 @@ static void socket_id_user_decrement(bNodeSocket *sock)
|
|||||||
case SOCK_CUSTOM:
|
case SOCK_CUSTOM:
|
||||||
case SOCK_SHADER:
|
case SOCK_SHADER:
|
||||||
case SOCK_GEOMETRY:
|
case SOCK_GEOMETRY:
|
||||||
case SOCK_ENUM:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1850,8 +1815,6 @@ const char *nodeStaticSocketType(int type, int subtype)
|
|||||||
return "NodeSocketTexture";
|
return "NodeSocketTexture";
|
||||||
case SOCK_MATERIAL:
|
case SOCK_MATERIAL:
|
||||||
return "NodeSocketMaterial";
|
return "NodeSocketMaterial";
|
||||||
case SOCK_ENUM:
|
|
||||||
return "NodeSocketEnum";
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1929,8 +1892,6 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype)
|
|||||||
return "NodeSocketInterfaceTexture";
|
return "NodeSocketInterfaceTexture";
|
||||||
case SOCK_MATERIAL:
|
case SOCK_MATERIAL:
|
||||||
return "NodeSocketInterfaceMaterial";
|
return "NodeSocketInterfaceMaterial";
|
||||||
case SOCK_ENUM:
|
|
||||||
return "NodeSocketInterfaceEnum";
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1964,8 +1925,6 @@ const char *nodeStaticSocketLabel(int type, int UNUSED(subtype))
|
|||||||
return "Texture";
|
return "Texture";
|
||||||
case SOCK_MATERIAL:
|
case SOCK_MATERIAL:
|
||||||
return "Material";
|
return "Material";
|
||||||
case SOCK_ENUM:
|
|
||||||
return "Enum";
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -4094,7 +4053,7 @@ bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *UNUSED(ntree), bNode *node)
|
|||||||
}
|
}
|
||||||
if (node->typeinfo->declaration_is_dynamic) {
|
if (node->typeinfo->declaration_is_dynamic) {
|
||||||
node->declaration = new blender::nodes::NodeDeclaration();
|
node->declaration = new blender::nodes::NodeDeclaration();
|
||||||
blender::nodes::NodeDeclarationBuilder builder{*node->declaration, node};
|
blender::nodes::NodeDeclarationBuilder builder{*node->declaration};
|
||||||
node->typeinfo->declare(builder);
|
node->typeinfo->declare(builder);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -4118,16 +4077,6 @@ bool nodeDeclarationEnsure(bNodeTree *ntree, bNode *node)
|
|||||||
return false;
|
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 *********** */
|
/* ************** Node Clipboard *********** */
|
||||||
|
|
||||||
#define USE_NODE_CB_VALIDATE
|
#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
|
ntreeUpdateTree(nullptr, ntree);
|
||||||
* tree just once. */
|
|
||||||
ntreeUpdateTree(main, ntree);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FOREACH_NODETREE_END;
|
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 {
|
namespace blender::bke::node_field_inferencing {
|
||||||
|
|
||||||
static bool is_field_socket_type(eNodeSocketDatatype type)
|
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);
|
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,
|
static InputSocketFieldType get_interface_input_field_type(const NodeRef &node,
|
||||||
const InputSocketRef &socket)
|
const InputSocketRef &socket)
|
||||||
@@ -4710,8 +4669,7 @@ static FieldInferencingInterface get_node_field_inferencing_interface(const Node
|
|||||||
}
|
}
|
||||||
if (group->field_inferencing_interface == nullptr) {
|
if (group->field_inferencing_interface == nullptr) {
|
||||||
/* Update group recursively. */
|
/* Update group recursively. */
|
||||||
const NodeTreeRef group_tree{group};
|
update_field_inferencing(*group);
|
||||||
update_field_inferencing(group_tree);
|
|
||||||
}
|
}
|
||||||
return *group->field_inferencing_interface;
|
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;
|
using namespace blender::nodes;
|
||||||
bNodeTree &btree = *tree.btree();
|
if (btree.type != NTREE_GEOMETRY) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create new inferencing interface for this node group. */
|
/* Create new inferencing interface for this node group. */
|
||||||
FieldInferencingInterface *new_inferencing_interface = new FieldInferencingInterface();
|
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),
|
new_inferencing_interface->outputs.resize(BLI_listbase_count(&btree.outputs),
|
||||||
OutputFieldDependency::ForDataSource());
|
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(). */
|
/* 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());
|
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::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.
|
* \param tree_update_flag: #eNodeTreeUpdate enum.
|
||||||
*/
|
*/
|
||||||
@@ -5349,7 +5133,6 @@ void ntreeUpdateTree(Main *bmain, bNodeTree *ntree)
|
|||||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||||
/* node tree update tags override individual node update flags */
|
/* node tree update tags override individual node update flags */
|
||||||
if ((node->update & NODE_UPDATE) || (ntree->update & NTREE_UPDATE)) {
|
if ((node->update & NODE_UPDATE) || (ntree->update & NTREE_UPDATE)) {
|
||||||
nodeUpdateFromDeclaration(ntree, node);
|
|
||||||
if (node->typeinfo->updatefunc) {
|
if (node->typeinfo->updatefunc) {
|
||||||
node->typeinfo->updatefunc(ntree, node);
|
node->typeinfo->updatefunc(ntree, node);
|
||||||
}
|
}
|
||||||
@@ -5372,19 +5155,10 @@ void ntreeUpdateTree(Main *bmain, bNodeTree *ntree)
|
|||||||
int tree_user_update_flag = 0;
|
int tree_user_update_flag = 0;
|
||||||
|
|
||||||
if (ntree->update & NTREE_UPDATE) {
|
if (ntree->update & NTREE_UPDATE) {
|
||||||
if (ntree->type == NTREE_GEOMETRY) {
|
/* If the field interface of this node tree has changed, all node trees using
|
||||||
/* Create #NodeTreeRef to accelerate various queries on the node tree (e.g. linked
|
* this group will need to recalculate their interface as well. */
|
||||||
* sockets). */
|
if (blender::bke::node_field_inferencing::update_field_inferencing(*ntree)) {
|
||||||
const NodeTreeRef tree{ntree};
|
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(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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5420,7 +5194,6 @@ void nodeUpdate(bNodeTree *ntree, bNode *node)
|
|||||||
}
|
}
|
||||||
ntree->is_updating = true;
|
ntree->is_updating = true;
|
||||||
|
|
||||||
nodeUpdateFromDeclaration(ntree, node);
|
|
||||||
if (node->typeinfo->updatefunc) {
|
if (node->typeinfo->updatefunc) {
|
||||||
node->typeinfo->updatefunc(ntree, node);
|
node->typeinfo->updatefunc(ntree, node);
|
||||||
}
|
}
|
||||||
@@ -5451,7 +5224,6 @@ bool nodeUpdateID(bNodeTree *ntree, ID *id)
|
|||||||
if (node->id == id) {
|
if (node->id == id) {
|
||||||
changed = true;
|
changed = true;
|
||||||
node->update |= NODE_UPDATE_ID;
|
node->update |= NODE_UPDATE_ID;
|
||||||
nodeUpdateFromDeclaration(ntree, node);
|
|
||||||
if (node->typeinfo->updatefunc) {
|
if (node->typeinfo->updatefunc) {
|
||||||
node->typeinfo->updatefunc(ntree, node);
|
node->typeinfo->updatefunc(ntree, node);
|
||||||
}
|
}
|
||||||
@@ -6184,7 +5956,6 @@ static void registerFunctionNodes()
|
|||||||
|
|
||||||
register_node_type_fn_align_euler_to_vector();
|
register_node_type_fn_align_euler_to_vector();
|
||||||
register_node_type_fn_boolean_math();
|
register_node_type_fn_boolean_math();
|
||||||
register_node_type_fn_enum();
|
|
||||||
register_node_type_fn_float_compare();
|
register_node_type_fn_float_compare();
|
||||||
register_node_type_fn_float_to_int();
|
register_node_type_fn_float_to_int();
|
||||||
register_node_type_fn_input_bool();
|
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)) {
|
if (!MAIN_VERSION_ATLEAST(bmain, 300, 26)) {
|
||||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||||
ToolSettings *tool_settings = scene->toolsettings;
|
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. */
|
/* 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,
|
static void bm_mesh_edges_sharp_tag(BMesh *bm,
|
||||||
const float (*fnos)[3],
|
const float (*fnos)[3],
|
||||||
const float split_angle,
|
float split_angle_cos,
|
||||||
const bool do_sharp_edges_tag)
|
const bool do_sharp_edges_tag)
|
||||||
{
|
{
|
||||||
BMIter eiter;
|
BMIter eiter;
|
||||||
BMEdge *e;
|
BMEdge *e;
|
||||||
int i;
|
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) {
|
if (fnos) {
|
||||||
BM_mesh_elem_index_ensure(bm, BM_FACE);
|
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;
|
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 short (*clnors_data)[2],
|
||||||
const int cd_loop_clnors_offset,
|
const int cd_loop_clnors_offset,
|
||||||
const bool do_rebuild,
|
const bool do_rebuild,
|
||||||
const float split_angle)
|
const float split_angle_cos)
|
||||||
{
|
{
|
||||||
BMIter fiter;
|
BMIter fiter;
|
||||||
BMFace *f_curr;
|
BMFace *f_curr;
|
||||||
const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
|
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};
|
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
|
/* Always tag edges based on winding & sharp edge flag
|
||||||
* (even when the auto-smooth angle doesn't need to be calculated). */
|
* (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),
|
/* We now know edges that can be smoothed (they are tagged),
|
||||||
* and edges that will be hard (they aren't).
|
* 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 short (*clnors_data)[2],
|
||||||
const int cd_loop_clnors_offset,
|
const int cd_loop_clnors_offset,
|
||||||
const bool do_rebuild,
|
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 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};
|
MLoopNorSpaceArray _lnors_spacearr = {NULL};
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -1387,7 +1385,7 @@ static void bm_mesh_loops_calc_normals(BMesh *bm,
|
|||||||
const short (*clnors_data)[2],
|
const short (*clnors_data)[2],
|
||||||
const int cd_loop_clnors_offset,
|
const int cd_loop_clnors_offset,
|
||||||
const bool do_rebuild,
|
const bool do_rebuild,
|
||||||
const float split_angle)
|
const float split_angle_cos)
|
||||||
{
|
{
|
||||||
if (bm->totloop < BM_OMP_LIMIT) {
|
if (bm->totloop < BM_OMP_LIMIT) {
|
||||||
bm_mesh_loops_calc_normals__single_threaded(bm,
|
bm_mesh_loops_calc_normals__single_threaded(bm,
|
||||||
@@ -1398,7 +1396,7 @@ static void bm_mesh_loops_calc_normals(BMesh *bm,
|
|||||||
clnors_data,
|
clnors_data,
|
||||||
cd_loop_clnors_offset,
|
cd_loop_clnors_offset,
|
||||||
do_rebuild,
|
do_rebuild,
|
||||||
split_angle);
|
split_angle_cos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bm_mesh_loops_calc_normals__multi_threaded(bm,
|
bm_mesh_loops_calc_normals__multi_threaded(bm,
|
||||||
@@ -1409,7 +1407,7 @@ static void bm_mesh_loops_calc_normals(BMesh *bm,
|
|||||||
clnors_data,
|
clnors_data,
|
||||||
cd_loop_clnors_offset,
|
cd_loop_clnors_offset,
|
||||||
do_rebuild,
|
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...
|
/* Tag smooth edges and set lnos from vnos when they might be completely smooth...
|
||||||
* When using custom loop normals, disable the angle feature! */
|
* 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
|
/* Finish computing lnos by accumulating face normals
|
||||||
* in each fan of faces defined by sharp edges. */
|
* in each fan of faces defined by sharp edges. */
|
||||||
@@ -1751,7 +1749,7 @@ void BM_loops_calc_normal_vcos(BMesh *bm,
|
|||||||
clnors_data,
|
clnors_data,
|
||||||
cd_loop_clnors_offset,
|
cd_loop_clnors_offset,
|
||||||
do_rebuild,
|
do_rebuild,
|
||||||
has_clnors ? (float)M_PI : split_angle);
|
has_clnors ? -1.0f : cosf(split_angle));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BLI_assert(!r_lnors_spacearr);
|
BLI_assert(!r_lnors_spacearr);
|
||||||
|
@@ -66,7 +66,7 @@ set(SRC
|
|||||||
interface_region_menu_popup.c
|
interface_region_menu_popup.c
|
||||||
interface_region_popover.c
|
interface_region_popover.c
|
||||||
interface_region_popup.c
|
interface_region_popup.c
|
||||||
interface_region_search.c
|
interface_region_search.cc
|
||||||
interface_region_tooltip.c
|
interface_region_tooltip.c
|
||||||
interface_regions.c
|
interface_regions.c
|
||||||
interface_style.c
|
interface_style.c
|
||||||
|
@@ -397,8 +397,8 @@ typedef struct uiHandleButtonData {
|
|||||||
float vec[3], origvec[3];
|
float vec[3], origvec[3];
|
||||||
ColorBand *coba;
|
ColorBand *coba;
|
||||||
|
|
||||||
/* Tool-tip. */
|
/* True when alt is held and the preference for displaying tooltips should be ignored. */
|
||||||
uint tooltip_force : 1;
|
bool tooltip_force;
|
||||||
|
|
||||||
/* auto open */
|
/* auto open */
|
||||||
bool used_mouse;
|
bool used_mouse;
|
||||||
|
@@ -23,9 +23,9 @@
|
|||||||
* Search Box Region & Interaction
|
* Search Box Region & Interaction
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
|
|
||||||
#include "DNA_ID.h"
|
#include "DNA_ID.h"
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
@@ -84,7 +84,7 @@ struct uiSearchItems {
|
|||||||
void *active;
|
void *active;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct uiSearchboxData {
|
struct uiSearchboxData {
|
||||||
rcti bbox;
|
rcti bbox;
|
||||||
uiFontStyle fstyle;
|
uiFontStyle fstyle;
|
||||||
uiSearchItems items;
|
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').
|
* Used so we can show leading text to menu items less prominently (not related to 'use_sep').
|
||||||
*/
|
*/
|
||||||
const char *sep_string;
|
const char *sep_string;
|
||||||
} uiSearchboxData;
|
};
|
||||||
|
|
||||||
#define SEARCH_ITEMS 10
|
#define SEARCH_ITEMS 10
|
||||||
|
|
||||||
@@ -166,9 +166,9 @@ bool UI_search_item_add(uiSearchItems *items,
|
|||||||
|
|
||||||
if (name_prefix_offset != 0) {
|
if (name_prefix_offset != 0) {
|
||||||
/* Lazy initialize, as this isn't used often. */
|
/* Lazy initialize, as this isn't used often. */
|
||||||
if (items->name_prefix_offsets == NULL) {
|
if (items->name_prefix_offsets == nullptr) {
|
||||||
items->name_prefix_offsets = MEM_callocN(
|
items->name_prefix_offsets = (uint8_t *)MEM_callocN(
|
||||||
items->maxitem * sizeof(*items->name_prefix_offsets), "search name prefix offsets");
|
items->maxitem * sizeof(*items->name_prefix_offsets), __func__);
|
||||||
}
|
}
|
||||||
items->name_prefix_offsets[items->totitem] = name_prefix_offset;
|
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)
|
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++) {
|
for (int i = 0; i < items->totitem; i++) {
|
||||||
if (STREQ(name, items->names[i] + items->name_prefix_offsets[i])) {
|
if (STREQ(name, items->names[i] + items->name_prefix_offsets[i])) {
|
||||||
return i;
|
return i;
|
||||||
@@ -218,7 +218,7 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name)
|
|||||||
/* region is the search box itself */
|
/* region is the search box itself */
|
||||||
static void ui_searchbox_select(bContext *C, ARegion *region, uiBut *but, int step)
|
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 */
|
/* apply step */
|
||||||
data->active += 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)
|
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);
|
return UI_search_items_find_index(&data->items, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* x and y in screen-coords. */
|
/* x and y in screen-coords. */
|
||||||
bool ui_searchbox_inside(ARegion *region, const int xy[2])
|
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);
|
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) */
|
/* string validated to be of correct length (but->hardmax) */
|
||||||
bool ui_searchbox_apply(uiBut *but, ARegion *region)
|
bool ui_searchbox_apply(uiBut *but, ARegion *region)
|
||||||
{
|
{
|
||||||
uiSearchboxData *data = region->regiondata;
|
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||||
uiButSearch *search_but = (uiButSearch *)but;
|
uiButSearch *search_but = (uiButSearch *)but;
|
||||||
|
|
||||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
||||||
|
|
||||||
search_but->item_active = NULL;
|
search_but->item_active = nullptr;
|
||||||
|
|
||||||
if (data->active != -1) {
|
if (data->active != -1) {
|
||||||
const char *name = data->items.names[data->active] +
|
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] :
|
data->items.name_prefix_offsets[data->active] :
|
||||||
0);
|
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
|
/* 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. */
|
* 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);
|
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);
|
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);
|
C, region, &rect, search_but->arg, search_but->item_active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ui_searchbox_event(
|
bool ui_searchbox_event(
|
||||||
bContext *C, ARegion *region, uiBut *but, ARegion *butregion, const wmEvent *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;
|
uiButSearch *search_but = (uiButSearch *)but;
|
||||||
int type = event->type, val = event->val;
|
int type = event->type, val = event->val;
|
||||||
bool handled = false;
|
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)
|
void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool reset)
|
||||||
{
|
{
|
||||||
uiButSearch *search_but = (uiButSearch *)but;
|
uiButSearch *search_but = (uiButSearch *)but;
|
||||||
uiSearchboxData *data = region->regiondata;
|
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||||
|
|
||||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
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) {
|
if (search_but->items_update_fn && search_but->item_active) {
|
||||||
data->items.active = search_but->item_active;
|
data->items.active = search_but->item_active;
|
||||||
ui_searchbox_update_fn(C, search_but, but->editstr, &data->items);
|
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 */
|
/* found active item, calculate real offset by centering it */
|
||||||
if (data->items.totitem) {
|
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. */
|
/* Never include the prefix in the button. */
|
||||||
(data->items.name_prefix_offsets ? data->items.name_prefix_offsets[a] :
|
(data->items.name_prefix_offsets ? data->items.name_prefix_offsets[a] :
|
||||||
0);
|
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)) {
|
if (STREQLEN(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen)) {
|
||||||
data->active = a;
|
data->active = a;
|
||||||
break;
|
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)
|
int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *str)
|
||||||
{
|
{
|
||||||
uiButSearch *search_but = (uiButSearch *)but;
|
uiButSearch *search_but = (uiButSearch *)but;
|
||||||
uiSearchboxData *data = region->regiondata;
|
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||||
int match = AUTOCOMPLETE_NO_MATCH;
|
int match = AUTOCOMPLETE_NO_MATCH;
|
||||||
|
|
||||||
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
|
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);
|
ui_searchbox_update_fn(C, search_but, but->editstr, &data->items);
|
||||||
|
|
||||||
match = UI_autocomplete_end(data->items.autocpl, str);
|
match = UI_autocomplete_end(data->items.autocpl, str);
|
||||||
data->items.autocpl = NULL;
|
data->items.autocpl = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return match;
|
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)
|
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 */
|
/* pixel space */
|
||||||
wmOrtho2_region_pixelspace(region);
|
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];
|
const int state = ((a == data->active) ? UI_ACTIVE : 0) | data->items.states[a];
|
||||||
char *name = data->items.names[a];
|
char *name = data->items.names[a];
|
||||||
int icon = data->items.icons[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;
|
uiMenuItemSeparatorType separator_type = UI_MENU_ITEM_SEPARATOR_NONE;
|
||||||
if (data->use_shortcut_sep) {
|
if (data->use_shortcut_sep) {
|
||||||
@@ -652,15 +652,15 @@ static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Simple menu item. */
|
/* 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 {
|
else {
|
||||||
/* Split menu item, faded text before the separator. */
|
/* Split menu item, faded text before the separator. */
|
||||||
char *name_sep = NULL;
|
char *name_sep = nullptr;
|
||||||
do {
|
do {
|
||||||
name_sep = name_sep_test;
|
name_sep = name_sep_test;
|
||||||
name_sep_test = strstr(name_sep + search_sep_len, data->sep_string);
|
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;
|
name_sep += search_sep_len;
|
||||||
const char name_sep_prev = *name_sep;
|
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. */
|
/* 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 */
|
/* 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)
|
static void ui_searchbox_region_free_fn(ARegion *region)
|
||||||
{
|
{
|
||||||
uiSearchboxData *data = region->regiondata;
|
uiSearchboxData *data = static_cast<uiSearchboxData *>(region->regiondata);
|
||||||
|
|
||||||
/* free search data */
|
/* free search data */
|
||||||
for (int a = 0; a < data->items.maxitem; a++) {
|
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.icons);
|
||||||
MEM_freeN(data->items.states);
|
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->items.name_prefix_offsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_freeN(data);
|
MEM_freeN(data);
|
||||||
region->regiondata = NULL;
|
region->regiondata = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ARegion *ui_searchbox_create_generic_ex(bContext *C,
|
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;
|
region->type = &type;
|
||||||
|
|
||||||
/* create searchbox data */
|
/* create searchbox data */
|
||||||
uiSearchboxData *data = MEM_callocN(sizeof(uiSearchboxData), "uiSearchboxData");
|
uiSearchboxData *data = (uiSearchboxData *)MEM_callocN(sizeof(uiSearchboxData), __func__);
|
||||||
|
|
||||||
/* set font, get bb */
|
/* set font, get bb */
|
||||||
data->fstyle = style->widget; /* copy struct */
|
data->fstyle = style->widget; /* copy struct */
|
||||||
@@ -767,7 +767,7 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C,
|
|||||||
data->prv_cols = but->a2;
|
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->use_shortcut_sep = true;
|
||||||
}
|
}
|
||||||
data->sep_string = search_but->item_sep_string;
|
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. */
|
/* 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.maxstrlen = but->hardmax == 0 ? UI_MAX_NAME_STR : but->hardmax;
|
||||||
data->items.totitem = 0;
|
data->items.totitem = 0;
|
||||||
data->items.names = MEM_callocN(data->items.maxitem * sizeof(void *), "search names");
|
data->items.names = (char **)MEM_callocN(data->items.maxitem * sizeof(void *), __func__);
|
||||||
data->items.pointers = MEM_callocN(data->items.maxitem * sizeof(void *), "search pointers");
|
data->items.pointers = (void **)MEM_callocN(data->items.maxitem * sizeof(void *), __func__);
|
||||||
data->items.icons = MEM_callocN(data->items.maxitem * sizeof(int), "search icons");
|
data->items.icons = (int *)MEM_callocN(data->items.maxitem * sizeof(int), __func__);
|
||||||
data->items.states = MEM_callocN(data->items.maxitem * sizeof(int), "search flags");
|
data->items.states = (int *)MEM_callocN(data->items.maxitem * sizeof(int), __func__);
|
||||||
data->items.name_prefix_offsets = NULL; /* Lazy initialized as needed. */
|
data->items.name_prefix_offsets = nullptr; /* Lazy initialized as needed. */
|
||||||
for (int i = 0; i < data->items.maxitem; i++) {
|
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;
|
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)
|
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 */
|
/* pixel space */
|
||||||
wmOrtho2_region_pixelspace(region);
|
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];
|
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[128];
|
||||||
char *text_pre_p = strstr(ot->idname, "_OT_");
|
const char *text_pre_p = strstr(ot->idname, "_OT_");
|
||||||
if (text_pre_p == NULL) {
|
if (text_pre_p == nullptr) {
|
||||||
text_pre[0] = '\0';
|
text_pre[0] = '\0';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -975,7 +975,7 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
|
|||||||
data->items.icons[a],
|
data->items.icons[a],
|
||||||
state,
|
state,
|
||||||
UI_MENU_ITEM_SEPARATOR_NONE,
|
UI_MENU_ITEM_SEPARATOR_NONE,
|
||||||
NULL);
|
nullptr);
|
||||||
ui_draw_menu_item(&data->fstyle,
|
ui_draw_menu_item(&data->fstyle,
|
||||||
&rect_post,
|
&rect_post,
|
||||||
data->items.names[a],
|
data->items.names[a],
|
||||||
@@ -983,7 +983,7 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
|
|||||||
state,
|
state,
|
||||||
data->use_shortcut_sep ? UI_MENU_ITEM_SEPARATOR_SHORTCUT :
|
data->use_shortcut_sep ? UI_MENU_ITEM_SEPARATOR_SHORTCUT :
|
||||||
UI_MENU_ITEM_SEPARATOR_NONE,
|
UI_MENU_ITEM_SEPARATOR_NONE,
|
||||||
NULL);
|
nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* indicate more */
|
/* indicate more */
|
||||||
@@ -1044,17 +1044,17 @@ void ui_but_search_refresh(uiButSearch *search_but)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uiSearchItems *items = MEM_callocN(sizeof(uiSearchItems), "search items");
|
uiSearchItems *items = (uiSearchItems *)MEM_callocN(sizeof(uiSearchItems), __func__);
|
||||||
|
|
||||||
/* setup search struct */
|
/* setup search struct */
|
||||||
items->maxitem = 10;
|
items->maxitem = 10;
|
||||||
items->maxstrlen = 256;
|
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++) {
|
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) {
|
if (!search_but->results_are_suggestions) {
|
||||||
/* Only red-alert when we are sure of it, this can miss cases when >10 matches. */
|
/* Only red-alert when we are sure of it, this can miss cases when >10 matches. */
|
@@ -22,9 +22,17 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/* interface_region_menu_popup.c */
|
/* interface_region_menu_popup.c */
|
||||||
uint ui_popup_menu_hash(const char *str);
|
uint ui_popup_menu_hash(const char *str);
|
||||||
|
|
||||||
/* interface_regions_intern.h */
|
/* interface_regions_intern.h */
|
||||||
ARegion *ui_region_temp_add(bScreen *screen);
|
ARegion *ui_region_temp_add(bScreen *screen);
|
||||||
void ui_region_temp_remove(struct bContext *C, bScreen *screen, ARegion *region);
|
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 float min_step,
|
||||||
const int grid_levels)
|
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_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);
|
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.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */
|
||||||
{0.62, 0.31, 0.64, 1.0}, /* SOCK_TEXTURE */
|
{0.62, 0.31, 0.64, 1.0}, /* SOCK_TEXTURE */
|
||||||
{0.92, 0.46, 0.51, 1.0}, /* SOCK_MATERIAL */
|
{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 */
|
/* 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);
|
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SOCK_ENUM: {
|
|
||||||
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
node_socket_button_label(C, layout, ptr, node_ptr, text);
|
node_socket_button_label(C, layout, ptr, node_ptr, text);
|
||||||
break;
|
break;
|
||||||
@@ -3732,8 +3727,7 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout
|
|||||||
}
|
}
|
||||||
case SOCK_BOOLEAN:
|
case SOCK_BOOLEAN:
|
||||||
case SOCK_RGBA:
|
case SOCK_RGBA:
|
||||||
case SOCK_STRING:
|
case SOCK_STRING: {
|
||||||
case SOCK_ENUM: {
|
|
||||||
uiItemR(col, ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), 0);
|
uiItemR(col, ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), 0);
|
||||||
break;
|
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;
|
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);
|
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);
|
uiLayout *row = uiLayoutRow(layout, true);
|
||||||
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
|
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
|
||||||
const char *socket_label = nodeSocketLabel(nsock);
|
const char *socket_label = nodeSocketLabel(nsock);
|
||||||
if (node->typeinfo->draw_socket == NULL ||
|
nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
|
||||||
!node->typeinfo->draw_socket(row, C, ntree, node, nsock)) {
|
|
||||||
nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(socket_label));
|
|
||||||
}
|
|
||||||
|
|
||||||
UI_block_align_end(node->block);
|
UI_block_align_end(node->block);
|
||||||
UI_block_layout_resolve(node->block, nullptr, &buty);
|
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);
|
uiLayout *row = uiLayoutRow(layout, true);
|
||||||
|
|
||||||
if (node->typeinfo->draw_socket == NULL ||
|
const char *socket_label = nodeSocketLabel(nsock);
|
||||||
!node->typeinfo->draw_socket(row, C, ntree, node, 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_align_end(node->block);
|
||||||
UI_block_layout_resolve(node->block, nullptr, &buty);
|
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 */
|
/* add modal handler */
|
||||||
WM_event_add_modal_handler(C, op);
|
WM_event_add_modal_handler(C, op);
|
||||||
|
|
||||||
ntreeUpdateTree(bmain, snode->edittree);
|
|
||||||
|
|
||||||
return OPERATOR_RUNNING_MODAL;
|
return OPERATOR_RUNNING_MODAL;
|
||||||
}
|
}
|
||||||
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
|
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
|
||||||
@@ -2180,7 +2178,6 @@ static int get_main_socket_priority(const bNodeSocket *socket)
|
|||||||
case SOCK_COLLECTION:
|
case SOCK_COLLECTION:
|
||||||
case SOCK_TEXTURE:
|
case SOCK_TEXTURE:
|
||||||
case SOCK_MATERIAL:
|
case SOCK_MATERIAL:
|
||||||
case SOCK_ENUM:
|
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@@ -377,7 +377,7 @@ static Vector<NodeLinkItem> ui_node_link_items(NodeLinkArg *arg,
|
|||||||
using namespace blender::nodes;
|
using namespace blender::nodes;
|
||||||
|
|
||||||
r_node_decl.emplace(NodeDeclaration());
|
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);
|
arg->node_type->declare(node_decl_builder);
|
||||||
Span<SocketDeclarationPtr> socket_decls = (in_out == SOCK_IN) ? r_node_decl->inputs() :
|
Span<SocketDeclarationPtr> socket_decls = (in_out == SOCK_IN) ? r_node_decl->inputs() :
|
||||||
r_node_decl->outputs();
|
r_node_decl->outputs();
|
||||||
|
@@ -191,7 +191,6 @@ typedef enum eNodeSocketDatatype {
|
|||||||
SOCK_COLLECTION = 11,
|
SOCK_COLLECTION = 11,
|
||||||
SOCK_TEXTURE = 12,
|
SOCK_TEXTURE = 12,
|
||||||
SOCK_MATERIAL = 13,
|
SOCK_MATERIAL = 13,
|
||||||
SOCK_ENUM = 14,
|
|
||||||
} eNodeSocketDatatype;
|
} eNodeSocketDatatype;
|
||||||
|
|
||||||
/* Socket shape. */
|
/* Socket shape. */
|
||||||
@@ -478,13 +477,10 @@ typedef struct bNodeLink {
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
namespace blender::nodes {
|
namespace blender::nodes {
|
||||||
struct FieldInferencingInterface;
|
struct FieldInferencingInterface;
|
||||||
struct EnumInferencingInterface;
|
}
|
||||||
} // namespace blender::nodes
|
|
||||||
using FieldInferencingInterfaceHandle = blender::nodes::FieldInferencingInterface;
|
using FieldInferencingInterfaceHandle = blender::nodes::FieldInferencingInterface;
|
||||||
using EnumInferencingInterfaceHandle = blender::nodes::EnumInferencingInterface;
|
|
||||||
#else
|
#else
|
||||||
typedef struct FieldInferencingInterfaceHandle FieldInferencingInterfaceHandle;
|
typedef struct FieldInferencingInterfaceHandle FieldInferencingInterfaceHandle;
|
||||||
typedef struct EnumInferencingInterfaceHandle EnumInferencingInterfaceHandle;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* the basis for a Node tree, all links and nodes reside internal here */
|
/* the basis for a Node tree, all links and nodes reside internal here */
|
||||||
@@ -511,7 +507,6 @@ typedef struct bNodeTree {
|
|||||||
ListBase nodes, links;
|
ListBase nodes, links;
|
||||||
/** Information about how inputs and outputs of the node group interact with fields. */
|
/** Information about how inputs and outputs of the node group interact with fields. */
|
||||||
FieldInferencingInterfaceHandle *field_inferencing_interface;
|
FieldInferencingInterfaceHandle *field_inferencing_interface;
|
||||||
EnumInferencingInterfaceHandle *enum_inferencing_interface;
|
|
||||||
|
|
||||||
/** Set init on fileread. */
|
/** Set init on fileread. */
|
||||||
int type, init;
|
int type, init;
|
||||||
@@ -684,17 +679,6 @@ typedef struct bNodeSocketValueMaterial {
|
|||||||
struct Material *value;
|
struct Material *value;
|
||||||
} bNodeSocketValueMaterial;
|
} 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. */
|
/* Data structs, for node->storage. */
|
||||||
enum {
|
enum {
|
||||||
CMP_NODE_MASKTYPE_ADD = 0,
|
CMP_NODE_MASKTYPE_ADD = 0,
|
||||||
@@ -1622,21 +1606,6 @@ typedef struct NodeGeometryViewer {
|
|||||||
int8_t data_type;
|
int8_t data_type;
|
||||||
} NodeGeometryViewer;
|
} 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 */
|
/* script node mode */
|
||||||
#define NODE_SCRIPT_INTERNAL 0
|
#define NODE_SCRIPT_INTERNAL 0
|
||||||
#define NODE_SCRIPT_EXTERNAL 1
|
#define NODE_SCRIPT_EXTERNAL 1
|
||||||
|
@@ -449,8 +449,6 @@ extern StructRNA RNA_MusgraveTexture;
|
|||||||
extern StructRNA RNA_NlaStrip;
|
extern StructRNA RNA_NlaStrip;
|
||||||
extern StructRNA RNA_NlaTrack;
|
extern StructRNA RNA_NlaTrack;
|
||||||
extern StructRNA RNA_Node;
|
extern StructRNA RNA_Node;
|
||||||
extern StructRNA RNA_NodeFunctionEnum;
|
|
||||||
extern StructRNA RNA_NodeFunctionEnumItem;
|
|
||||||
extern StructRNA RNA_NodeInstanceHash;
|
extern StructRNA RNA_NodeInstanceHash;
|
||||||
extern StructRNA RNA_NodeLink;
|
extern StructRNA RNA_NodeLink;
|
||||||
extern StructRNA RNA_NodeOutputFileSlotFile;
|
extern StructRNA RNA_NodeOutputFileSlotFile;
|
||||||
|
@@ -78,7 +78,6 @@ static const EnumPropertyItem node_socket_data_type_items[] = {
|
|||||||
{SOCK_COLLECTION, "COLLECTION", 0, "Collection", ""},
|
{SOCK_COLLECTION, "COLLECTION", 0, "Collection", ""},
|
||||||
{SOCK_TEXTURE, "TEXTURE", 0, "Texture", ""},
|
{SOCK_TEXTURE, "TEXTURE", 0, "Texture", ""},
|
||||||
{SOCK_MATERIAL, "MATERIAL", 0, "Material", ""},
|
{SOCK_MATERIAL, "MATERIAL", 0, "Material", ""},
|
||||||
{SOCK_ENUM, "ENUM", 0, "Enum", ""},
|
|
||||||
{0, NULL, 0, NULL, NULL},
|
{0, NULL, 0, NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -107,7 +106,6 @@ static const EnumPropertyItem node_socket_type_items[] = {
|
|||||||
{SOCK_COLLECTION, "COLLECTION", 0, "Collection", ""},
|
{SOCK_COLLECTION, "COLLECTION", 0, "Collection", ""},
|
||||||
{SOCK_TEXTURE, "TEXTURE", 0, "Texture", ""},
|
{SOCK_TEXTURE, "TEXTURE", 0, "Texture", ""},
|
||||||
{SOCK_MATERIAL, "MATERIAL", 0, "Material", ""},
|
{SOCK_MATERIAL, "MATERIAL", 0, "Material", ""},
|
||||||
{SOCK_ENUM, "ENUM", 0, "Enum", ""},
|
|
||||||
{0, NULL, 0, NULL, NULL},
|
{0, NULL, 0, NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1237,8 +1235,8 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree,
|
|||||||
ntreeTexCheckCyclics(ntree);
|
ntreeTexCheckCyclics(ntree);
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeUpdate(ntree, node);
|
|
||||||
ntreeUpdateTree(CTX_data_main(C), ntree);
|
ntreeUpdateTree(CTX_data_main(C), ntree);
|
||||||
|
nodeUpdate(ntree, node);
|
||||||
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
|
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@@ -2059,8 +2057,7 @@ static bool switch_type_supported(const EnumPropertyItem *item)
|
|||||||
SOCK_COLLECTION,
|
SOCK_COLLECTION,
|
||||||
SOCK_TEXTURE,
|
SOCK_TEXTURE,
|
||||||
SOCK_MATERIAL,
|
SOCK_MATERIAL,
|
||||||
SOCK_IMAGE,
|
SOCK_IMAGE);
|
||||||
SOCK_ENUM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const EnumPropertyItem *rna_GeometryNodeSwitch_type_itemf(bContext *UNUSED(C),
|
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)
|
static void rna_NodeInternal_update(ID *id, bNode *node)
|
||||||
{
|
{
|
||||||
bNodeTree *ntree = (bNodeTree *)id;
|
bNodeTree *ntree = (bNodeTree *)id;
|
||||||
nodeUpdateFromDeclaration(ntree, node);
|
|
||||||
if (node->typeinfo->updatefunc) {
|
if (node->typeinfo->updatefunc) {
|
||||||
node->typeinfo->updatefunc(ntree, node);
|
node->typeinfo->updatefunc(ntree, node);
|
||||||
}
|
}
|
||||||
@@ -4573,58 +4569,6 @@ bool rna_NodeSocketMaterial_default_value_poll(PointerRNA *UNUSED(ptr), PointerR
|
|||||||
return ma->gp_style == NULL;
|
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
|
#else
|
||||||
|
|
||||||
static const EnumPropertyItem prop_image_layer_items[] = {
|
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");
|
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 ---------------------------------------------------------- */
|
/* -- Shader Nodes ---------------------------------------------------------- */
|
||||||
|
|
||||||
static void def_sh_output(StructRNA *srna)
|
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");
|
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)
|
static void rna_def_node_socket_standard_types(BlenderRNA *brna)
|
||||||
{
|
{
|
||||||
/* XXX Workaround: Registered functions are not exposed in python by bpy,
|
/* 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_texture(brna, "NodeSocketTexture", "NodeSocketInterfaceTexture");
|
||||||
|
|
||||||
rna_def_node_socket_material(brna, "NodeSocketMaterial", "NodeSocketInterfaceMaterial");
|
rna_def_node_socket_material(brna, "NodeSocketMaterial", "NodeSocketInterfaceMaterial");
|
||||||
|
|
||||||
rna_def_node_socket_enum(brna, "NodeSocketEnum", "NodeSocketInterfaceEnum");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_internal_node(BlenderRNA *brna)
|
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 */ \
|
/* needs brna argument, can't use NOD_static_types.h */ \
|
||||||
def_cmp_output_file(brna, srna); \
|
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
|
/* 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;
|
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,
|
static void modifyGeometry(ModifierData *md,
|
||||||
@@ -1078,6 +1067,7 @@ static void modifyGeometry(ModifierData *md,
|
|||||||
|
|
||||||
if (tree.has_link_cycles()) {
|
if (tree.has_link_cycles()) {
|
||||||
BKE_modifier_set_error(ctx->object, md, "Node group has cycles");
|
BKE_modifier_set_error(ctx->object, md, "Node group has cycles");
|
||||||
|
geometry_set.clear();
|
||||||
return;
|
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 *> input_nodes = root_tree_ref.nodes_by_type("NodeGroupInput");
|
||||||
Span<const NodeRef *> output_nodes = root_tree_ref.nodes_by_type("NodeGroupOutput");
|
Span<const NodeRef *> output_nodes = root_tree_ref.nodes_by_type("NodeGroupOutput");
|
||||||
if (output_nodes.size() != 1) {
|
if (output_nodes.size() != 1) {
|
||||||
|
BKE_modifier_set_error(ctx->object, md, "Node group must have a single output node");
|
||||||
|
geometry_set.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NodeRef &output_node = *output_nodes[0];
|
const NodeRef &output_node = *output_nodes[0];
|
||||||
Span<const InputSocketRef *> group_outputs = output_node.inputs().drop_back(1);
|
Span<const InputSocketRef *> group_outputs = output_node.inputs().drop_back(1);
|
||||||
if (group_outputs.is_empty()) {
|
if (group_outputs.is_empty()) {
|
||||||
|
BKE_modifier_set_error(ctx->object, md, "Node group must have an output socket");
|
||||||
|
geometry_set.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputSocketRef *first_output_socket = group_outputs[0];
|
const InputSocketRef *first_output_socket = group_outputs[0];
|
||||||
if (first_output_socket->idname() != "NodeSocketGeometry") {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -139,7 +139,6 @@ set(SRC
|
|||||||
|
|
||||||
function/nodes/node_fn_align_euler_to_vector.cc
|
function/nodes/node_fn_align_euler_to_vector.cc
|
||||||
function/nodes/node_fn_boolean_math.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_compare.cc
|
||||||
function/nodes/node_fn_float_to_int.cc
|
function/nodes/node_fn_float_to_int.cc
|
||||||
function/nodes/node_fn_input_bool.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_align_euler_to_vector(void);
|
||||||
void register_node_type_fn_boolean_math(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_compare(void);
|
||||||
void register_node_type_fn_float_to_int(void);
|
void register_node_type_fn_float_to_int(void);
|
||||||
void register_node_type_fn_input_bool(void);
|
void register_node_type_fn_input_bool(void);
|
||||||
|
@@ -66,27 +66,6 @@ using fn::GVMutableArray_Typed;
|
|||||||
using fn::GVMutableArrayPtr;
|
using fn::GVMutableArrayPtr;
|
||||||
using geometry_nodes_eval_log::NodeWarningType;
|
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
|
* This class exists to separate the memory management details of the geometry nodes evaluator
|
||||||
* from the node execution functions and related utilities.
|
* 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, bool> ||
|
||||||
std::is_same_v<T, ColorGeometry4f> ||
|
std::is_same_v<T, ColorGeometry4f> ||
|
||||||
std::is_same_v<T, float3> ||
|
std::is_same_v<T, float3> ||
|
||||||
std::is_same_v<T, std::string> ||
|
std::is_same_v<T, std::string>;
|
||||||
std::is_same_v<T, EnumValue>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the input value for the input socket with the given identifier.
|
* 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);
|
const Field<T> &field = this->get_input<Field<T>>(identifier);
|
||||||
return fn::evaluate_constant_field(field);
|
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 {
|
else {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
this->check_input_access(identifier, &CPPType::get<T>());
|
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). */
|
/* Find the active socket with the input name (not the identifier). */
|
||||||
const bNodeSocket *find_available_socket(const StringRef name) const;
|
const bNodeSocket *find_available_socket(const StringRef name) const;
|
||||||
|
|
||||||
const int validate_enum_value(StringRef identifier, const int value) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::nodes
|
} // namespace blender::nodes
|
||||||
|
@@ -243,13 +243,11 @@ class NodeDeclaration {
|
|||||||
|
|
||||||
class NodeDeclarationBuilder {
|
class NodeDeclarationBuilder {
|
||||||
private:
|
private:
|
||||||
/** The node may be null. */
|
|
||||||
NodeDeclaration &declaration_;
|
NodeDeclaration &declaration_;
|
||||||
const bNode *node_;
|
|
||||||
Vector<std::unique_ptr<BaseSocketDeclarationBuilder>> builders_;
|
Vector<std::unique_ptr<BaseSocketDeclarationBuilder>> builders_;
|
||||||
|
|
||||||
public:
|
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.
|
* 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;
|
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>
|
template<typename DeclType>
|
||||||
typename DeclType::Builder &add_input(StringRef name, StringRef identifier = "");
|
typename DeclType::Builder &add_input(StringRef name, StringRef identifier = "");
|
||||||
template<typename DeclType>
|
template<typename DeclType>
|
||||||
@@ -399,9 +391,8 @@ inline const OutputFieldDependency &SocketDeclaration::output_field_dependency()
|
|||||||
/** \name #NodeDeclarationBuilder Inline Methods
|
/** \name #NodeDeclarationBuilder Inline Methods
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
inline NodeDeclarationBuilder::NodeDeclarationBuilder(NodeDeclaration &declaration,
|
inline NodeDeclarationBuilder::NodeDeclarationBuilder(NodeDeclaration &declaration)
|
||||||
const bNode *node)
|
: declaration_(declaration)
|
||||||
: declaration_(declaration), node_(node)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,41 +16,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "NOD_node_declaration.hh"
|
#include "NOD_node_declaration.hh"
|
||||||
|
|
||||||
#include "RNA_types.h"
|
#include "RNA_types.h"
|
||||||
|
|
||||||
#include "BLI_color.hh"
|
#include "BLI_color.hh"
|
||||||
#include "BLI_float3.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 {
|
namespace blender::nodes::decl {
|
||||||
|
|
||||||
@@ -194,32 +165,6 @@ class StringBuilder : public SocketDeclarationBuilder<String> {
|
|||||||
StringBuilder &default_value(const std::string value);
|
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 {
|
class IDSocketDeclaration : public SocketDeclaration {
|
||||||
private:
|
private:
|
||||||
const char *idname_;
|
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
|
/** \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_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_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_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_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_BOOL, def_fn_input_bool, "INPUT_BOOL", InputBool, "Boolean", "")
|
||||||
DefNode(FunctionNode, FN_NODE_INPUT_COLOR, def_fn_input_color, "INPUT_COLOR", InputColor, "Color", "")
|
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_COLLECTION,
|
||||||
SOCK_TEXTURE,
|
SOCK_TEXTURE,
|
||||||
SOCK_IMAGE,
|
SOCK_IMAGE,
|
||||||
SOCK_MATERIAL,
|
SOCK_MATERIAL);
|
||||||
SOCK_ENUM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_node_tree_type_geo(void)
|
void register_node_tree_type_geo(void)
|
||||||
|
@@ -31,25 +31,7 @@ namespace blender::nodes {
|
|||||||
|
|
||||||
static void geo_node_collection_info_declare(NodeDeclarationBuilder &b)
|
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::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"))
|
b.add_input<decl::Bool>(N_("Separate Children"))
|
||||||
.description(
|
.description(
|
||||||
N_("Output each child of the collection as a separate instance, sorted alphabetically"));
|
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"));
|
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)
|
static void geo_node_collection_info_node_init(bNodeTree *UNUSED(tree), bNode *node)
|
||||||
{
|
{
|
||||||
NodeGeometryCollectionInfo *data = (NodeGeometryCollectionInfo *)MEM_callocN(
|
NodeGeometryCollectionInfo *data = (NodeGeometryCollectionInfo *)MEM_callocN(
|
||||||
@@ -93,8 +80,10 @@ static void geo_node_collection_info_exec(GeoNodeExecParams params)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool use_relative_transform = params.get_input<GeometryNodeTransformSpace>(
|
const bNode &bnode = params.node();
|
||||||
"Transform Space") == GEO_NODE_TRANSFORM_SPACE_RELATIVE;
|
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>();
|
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_free_standard_storage,
|
||||||
node_copy_standard_storage);
|
node_copy_standard_storage);
|
||||||
ntype.geometry_node_execute = blender::nodes::geo_node_collection_info_exec;
|
ntype.geometry_node_execute = blender::nodes::geo_node_collection_info_exec;
|
||||||
|
ntype.draw_buttons = blender::nodes::geo_node_collection_info_layout;
|
||||||
nodeRegisterType(&ntype);
|
nodeRegisterType(&ntype);
|
||||||
}
|
}
|
||||||
|
@@ -35,17 +35,15 @@ namespace blender::nodes {
|
|||||||
|
|
||||||
static void geo_node_curve_fill_declare(NodeDeclarationBuilder &b)
|
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::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"));
|
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)
|
static void geo_node_curve_fill_init(bNodeTree *UNUSED(ntree), bNode *node)
|
||||||
{
|
{
|
||||||
NodeGeometryCurveFill *data = (NodeGeometryCurveFill *)MEM_callocN(sizeof(NodeGeometryCurveFill),
|
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");
|
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(
|
geometry_set.modify_geometry_sets(
|
||||||
[&](GeometrySet &geometry_set) { curve_fill_calculate(geometry_set, mode); });
|
[&](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, "NodeGeometryCurveFill", node_free_standard_storage, node_copy_standard_storage);
|
||||||
ntype.declare = blender::nodes::geo_node_curve_fill_declare;
|
ntype.declare = blender::nodes::geo_node_curve_fill_declare;
|
||||||
ntype.geometry_node_execute = blender::nodes::geo_node_curve_fill_exec;
|
ntype.geometry_node_execute = blender::nodes::geo_node_curve_fill_exec;
|
||||||
|
ntype.draw_buttons = blender::nodes::geo_node_curve_fill_layout;
|
||||||
nodeRegisterType(&ntype);
|
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::Material>(N_("True"), "True_010");
|
||||||
b.add_input<decl::Image>(N_("False"), "False_011");
|
b.add_input<decl::Image>(N_("False"), "False_011");
|
||||||
b.add_input<decl::Image>(N_("True"), "True_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::Float>(N_("Output")).dependent_field();
|
||||||
b.add_output<decl::Int>(N_("Output"), "Output_001").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::Texture>(N_("Output"), "Output_009");
|
||||||
b.add_output<decl::Material>(N_("Output"), "Output_010");
|
b.add_output<decl::Material>(N_("Output"), "Output_010");
|
||||||
b.add_output<decl::Image>(N_("Output"), "Output_011");
|
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)
|
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");
|
switch_no_fields<Image *>(params, "_011");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SOCK_ENUM: {
|
|
||||||
switch_no_fields<EnumValue>(params, "_012");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
BLI_assert_unreachable();
|
BLI_assert_unreachable();
|
||||||
break;
|
break;
|
||||||
|
@@ -254,29 +254,6 @@ std::string GeoNodeExecParams::attribute_producer_name() const
|
|||||||
return provider_->dnode->label_or_name() + TIP_(" node");
|
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,
|
void GeoNodeExecParams::check_input_access(StringRef identifier,
|
||||||
const CPPType *requested_type) const
|
const CPPType *requested_type) const
|
||||||
{
|
{
|
||||||
|
@@ -44,13 +44,11 @@
|
|||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "NOD_geometry_exec.hh"
|
|
||||||
#include "NOD_node_declaration.hh"
|
#include "NOD_node_declaration.hh"
|
||||||
#include "NOD_socket.h"
|
#include "NOD_socket.h"
|
||||||
|
|
||||||
#include "FN_cpp_type_make.hh"
|
#include "FN_cpp_type_make.hh"
|
||||||
#include "FN_field.hh"
|
#include "FN_field.hh"
|
||||||
#include "FN_field_cpp_type.hh"
|
|
||||||
|
|
||||||
using namespace blender;
|
using namespace blender;
|
||||||
using blender::nodes::SocketDeclarationPtr;
|
using blender::nodes::SocketDeclarationPtr;
|
||||||
@@ -400,14 +398,6 @@ void node_socket_init_default_value(bNodeSocket *sock)
|
|||||||
sizeof(bNodeSocketValueMaterial), "node socket value material");
|
sizeof(bNodeSocketValueMaterial), "node socket value material");
|
||||||
dval->value = nullptr;
|
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;
|
sock->default_value = dval;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -504,12 +494,6 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from)
|
|||||||
id_us_plus(&toval->value->id);
|
id_us_plus(&toval->value->id);
|
||||||
break;
|
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);
|
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(Texture, Tex *, CPPTypeFlags::BasicType)
|
||||||
MAKE_CPP_TYPE(Image, Image *, CPPTypeFlags::BasicType)
|
MAKE_CPP_TYPE(Image, Image *, CPPTypeFlags::BasicType)
|
||||||
MAKE_CPP_TYPE(Material, Material *, 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()
|
static bNodeSocketType *make_socket_type_object()
|
||||||
{
|
{
|
||||||
@@ -902,26 +884,6 @@ static bNodeSocketType *make_socket_type_material()
|
|||||||
return socktype;
|
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)
|
void register_standard_node_socket_types(void)
|
||||||
{
|
{
|
||||||
/* Draw callbacks are set in `drawnode.c` to avoid bad-level calls. */
|
/* 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_material());
|
||||||
|
|
||||||
nodeRegisterSocketType(make_socket_type_enum());
|
|
||||||
|
|
||||||
nodeRegisterSocketType(make_socket_type_virtual());
|
nodeRegisterSocketType(make_socket_type_virtual());
|
||||||
}
|
}
|
||||||
|
@@ -19,36 +19,8 @@
|
|||||||
|
|
||||||
#include "BKE_node.h"
|
#include "BKE_node.h"
|
||||||
|
|
||||||
#include "RNA_enum_types.h"
|
|
||||||
|
|
||||||
#include "BLI_math_vector.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 {
|
namespace blender::nodes::decl {
|
||||||
|
|
||||||
static void modify_subtype_except_for_storage(bNodeSocket &socket, int new_subtype)
|
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
|
/** \name #IDSocketDeclaration
|
||||||
* \{ */
|
* \{ */
|
||||||
|
@@ -483,14 +483,6 @@ static int node_datatype_priority(eNodeSocketDatatype from, eNodeSocketDatatype
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case SOCK_ENUM: {
|
|
||||||
switch (from) {
|
|
||||||
case SOCK_ENUM:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user