Attributes: Add 2D integer vector attribute type
This type will be used to store mesh edges in #106638, but it could be used for anything else too. This commit adds support for: - The new type in the Python API - Editing the type in the edit mode "Attribute Set" operator - Rendering the type in EEVEE and Cycles for all geometry types - Geometry nodes attribute interpolation and mixing - Viewing the type in the spreadsheet and using row filters The attribute uses the `blender::int2` type in most code, and the `vec2i` DNA type in C code when necessary. The enum names are based on `INT32_2D` for consistency with `INT8` and `INT32`. Pull Request: https://projects.blender.org/blender/blender/pulls/106677
This commit is contained in:
@@ -803,6 +803,16 @@ static void attr_create_generic(Scene *scene,
|
||||
num_curves, num_keys, data, element, [&](int i) { return float(src[i]); });
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT32_2D: {
|
||||
BL::Int2Attribute b_int2_attribute{b_attribute};
|
||||
const int2 *src = static_cast<const int2 *>(b_int2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float2(float(src[i][0]), float(src[i][1]));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_VECTOR: {
|
||||
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
|
||||
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
|
||||
|
||||
@@ -528,6 +528,19 @@ static void attr_create_generic(Scene *scene,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT32_2D: {
|
||||
BL::Int2Attribute b_int2_attribute{b_attribute};
|
||||
if (b_int2_attribute.data.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
const int2 *src = static_cast<const int2 *>(b_int2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) {
|
||||
return make_float2(float(src[i][0]), float(src[i][1]));
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Not supported. */
|
||||
break;
|
||||
|
||||
@@ -102,6 +102,16 @@ static void copy_attributes(PointCloud *pointcloud,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT32_2D: {
|
||||
BL::Int2Attribute b_int2_attribute{b_attribute};
|
||||
const int2 *src = static_cast<const int2 *>(b_int2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float2(float(src[i][0]), float(src[i][1]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_VECTOR: {
|
||||
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
|
||||
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
|
||||
|
||||
@@ -23,6 +23,7 @@ inline void convert_to_static_type(const CPPType &cpp_type, const Func &func)
|
||||
float2,
|
||||
float3,
|
||||
int,
|
||||
int2,
|
||||
bool,
|
||||
int8_t,
|
||||
ColorGeometry4f,
|
||||
@@ -68,6 +69,11 @@ template<> inline int mix2(const float factor, const int &a, const int &b)
|
||||
return int(std::round((1.0f - factor) * a + factor * b));
|
||||
}
|
||||
|
||||
template<> inline int2 mix2(const float factor, const int2 &a, const int2 &b)
|
||||
{
|
||||
return math::interpolate(a, b, factor);
|
||||
}
|
||||
|
||||
template<> inline float mix2(const float factor, const float &a, const float &b)
|
||||
{
|
||||
return (1.0f - factor) * a + factor * b;
|
||||
@@ -121,6 +127,11 @@ template<> inline int mix3(const float3 &weights, const int &v0, const int &v1,
|
||||
return int(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2));
|
||||
}
|
||||
|
||||
template<> inline int2 mix3(const float3 &weights, const int2 &v0, const int2 &v1, const int2 &v2)
|
||||
{
|
||||
return int2(weights.x * float2(v0) + weights.y * float2(v1) + weights.z * float2(v2));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float mix3(const float3 &weights, const float &v0, const float &v1, const float &v2)
|
||||
{
|
||||
@@ -194,6 +205,14 @@ inline int mix4(const float4 &weights, const int &v0, const int &v1, const int &
|
||||
return int(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2 + weights.w * v3));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int2 mix4(
|
||||
const float4 &weights, const int2 &v0, const int2 &v1, const int2 &v2, const int2 &v3)
|
||||
{
|
||||
return int2(weights.x * float2(v0) + weights.y * float2(v1) + weights.z * float2(v2) +
|
||||
weights.w * float2(v3));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float mix4(
|
||||
const float4 &weights, const float &v0, const float &v1, const float &v2, const float &v3)
|
||||
@@ -382,7 +401,7 @@ class SimpleMixerWithAccumulationType {
|
||||
private:
|
||||
struct Item {
|
||||
/* Store both values together, because they are accessed together. */
|
||||
AccumulationT value = {0};
|
||||
AccumulationT value = AccumulationT(0);
|
||||
float weight = 0.0f;
|
||||
};
|
||||
|
||||
@@ -517,6 +536,15 @@ template<> struct DefaultMixerStruct<int> {
|
||||
* uses double instead of float so that it is accurate for all 32 bit integers. */
|
||||
using type = SimpleMixerWithAccumulationType<int, double, double_to_int>;
|
||||
};
|
||||
template<> struct DefaultMixerStruct<int2> {
|
||||
static int2 double_to_int(const double2 &value)
|
||||
{
|
||||
return int2(math::round(value));
|
||||
}
|
||||
/* Store interpolated ints in a double temporarily, so that weights are handled correctly. It
|
||||
* uses double instead of float so that it is accurate for all 32 bit integers. */
|
||||
using type = SimpleMixerWithAccumulationType<int2, double2, double_to_int>;
|
||||
};
|
||||
template<> struct DefaultMixerStruct<bool> {
|
||||
static bool float_to_bool(const float &value)
|
||||
{
|
||||
|
||||
@@ -92,17 +92,19 @@ static int attribute_data_type_complexity(const eCustomDataType data_type)
|
||||
return 2;
|
||||
case CD_PROP_FLOAT:
|
||||
return 3;
|
||||
case CD_PROP_FLOAT2:
|
||||
case CD_PROP_INT32_2D:
|
||||
return 4;
|
||||
case CD_PROP_FLOAT3:
|
||||
case CD_PROP_FLOAT2:
|
||||
return 5;
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
case CD_PROP_FLOAT3:
|
||||
return 6;
|
||||
case CD_PROP_COLOR:
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
return 7;
|
||||
case CD_PROP_COLOR:
|
||||
return 8;
|
||||
#if 0 /* These attribute types are not supported yet. */
|
||||
case CD_PROP_STRING:
|
||||
return 6;
|
||||
return 9;
|
||||
#endif
|
||||
default:
|
||||
/* Only accept "generic" custom data types used by the attribute system. */
|
||||
|
||||
@@ -1892,8 +1892,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||
{sizeof(float), "MFloatProperty", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 45: CD_PROP_INT8 */
|
||||
{sizeof(int8_t), "MInt8Property", 1, N_("Int8"), nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 46: CD_HAIRMAPPING */ /* UNUSED */
|
||||
{-1, "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 46: CD_PROP_INT32_2D */
|
||||
{sizeof(vec2i), "vec2i", 1, N_("Int 2D"), nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||
/* 47: CD_PROP_COLOR */
|
||||
{sizeof(MPropCol),
|
||||
"MPropCol",
|
||||
@@ -5360,6 +5360,8 @@ const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type)
|
||||
return &CPPType::get<float3>();
|
||||
case CD_PROP_INT32:
|
||||
return &CPPType::get<int>();
|
||||
case CD_PROP_INT32_2D:
|
||||
return &CPPType::get<int2>();
|
||||
case CD_PROP_COLOR:
|
||||
return &CPPType::get<ColorGeometry4f>();
|
||||
case CD_PROP_BOOL:
|
||||
@@ -5389,6 +5391,9 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
|
||||
if (type.is<int>()) {
|
||||
return CD_PROP_INT32;
|
||||
}
|
||||
if (type.is<int2>()) {
|
||||
return CD_PROP_INT32_2D;
|
||||
}
|
||||
if (type.is<ColorGeometry4f>()) {
|
||||
return CD_PROP_COLOR;
|
||||
}
|
||||
|
||||
@@ -616,6 +616,16 @@ static int customdata_compare(
|
||||
BLI_edgehash_free(eh, nullptr);
|
||||
break;
|
||||
}
|
||||
case CD_PROP_INT32_2D: {
|
||||
const blender::int2 *l1_data = static_cast<const blender::int2 *>(l1->data);
|
||||
const blender::int2 *l2_data = static_cast<const blender::int2 *>(l2->data);
|
||||
for (int i = 0; i < total_length; i++) {
|
||||
if (l1_data[i] != l2_data[i]) {
|
||||
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CD_PROP_BYTE_COLOR: {
|
||||
MLoopCol *lp1 = (MLoopCol *)l1->data;
|
||||
MLoopCol *lp2 = (MLoopCol *)l2->data;
|
||||
|
||||
@@ -51,6 +51,10 @@ static int32_t float_to_int(const float &a)
|
||||
{
|
||||
return int32_t(a);
|
||||
}
|
||||
static int2 float_to_int2(const float &a)
|
||||
{
|
||||
return int2(a);
|
||||
}
|
||||
static bool float_to_bool(const float &a)
|
||||
{
|
||||
return a > 0.0f;
|
||||
@@ -81,6 +85,10 @@ static int float2_to_int(const float2 &a)
|
||||
{
|
||||
return int32_t((a.x + a.y) / 2.0f);
|
||||
}
|
||||
static int2 float2_to_int2(const float2 &a)
|
||||
{
|
||||
return int2(a.x, a.y);
|
||||
}
|
||||
static bool float2_to_bool(const float2 &a)
|
||||
{
|
||||
return !math::is_zero(a);
|
||||
@@ -114,6 +122,10 @@ static int float3_to_int(const float3 &a)
|
||||
{
|
||||
return int((a.x + a.y + a.z) / 3.0f);
|
||||
}
|
||||
static int2 float3_to_int2(const float3 &a)
|
||||
{
|
||||
return int2(a.x, a.y);
|
||||
}
|
||||
static float2 float3_to_float2(const float3 &a)
|
||||
{
|
||||
return float2(a);
|
||||
@@ -136,6 +148,10 @@ static int8_t int_to_int8(const int32_t &a)
|
||||
return std::clamp(
|
||||
a, int(std::numeric_limits<int8_t>::min()), int(std::numeric_limits<int8_t>::max()));
|
||||
}
|
||||
static int2 int_to_int2(const int32_t &a)
|
||||
{
|
||||
return int2(a);
|
||||
}
|
||||
static float int_to_float(const int32_t &a)
|
||||
{
|
||||
return float(a);
|
||||
@@ -157,6 +173,39 @@ static ColorGeometry4b int_to_byte_color(const int32_t &a)
|
||||
return int_to_color(a).encode();
|
||||
}
|
||||
|
||||
static bool int2_to_bool(const int2 &a)
|
||||
{
|
||||
return !math::is_zero(a);
|
||||
}
|
||||
static float2 int2_to_float2(const int2 &a)
|
||||
{
|
||||
return float2(a);
|
||||
}
|
||||
static int int2_to_int(const int2 &a)
|
||||
{
|
||||
return math::midpoint(a.x, a.y);
|
||||
}
|
||||
static int8_t int2_to_int8(const int2 &a)
|
||||
{
|
||||
return int_to_int8(int2_to_int(a));
|
||||
}
|
||||
static float int2_to_float(const int2 &a)
|
||||
{
|
||||
return float2_to_float(float2(a));
|
||||
}
|
||||
static float3 int2_to_float3(const int2 &a)
|
||||
{
|
||||
return float3(float(a.x), float(a.y), 0.0f);
|
||||
}
|
||||
static ColorGeometry4f int2_to_color(const int2 &a)
|
||||
{
|
||||
return ColorGeometry4f(float(a.x), float(a.y), 0.0f, 1.0f);
|
||||
}
|
||||
static ColorGeometry4b int2_to_byte_color(const int2 &a)
|
||||
{
|
||||
return int2_to_color(a).encode();
|
||||
}
|
||||
|
||||
static bool int8_to_bool(const int8_t &a)
|
||||
{
|
||||
return a > 0;
|
||||
@@ -165,6 +214,10 @@ static int int8_to_int(const int8_t &a)
|
||||
{
|
||||
return int(a);
|
||||
}
|
||||
static int2 int8_to_int2(const int8_t &a)
|
||||
{
|
||||
return int2(a);
|
||||
}
|
||||
static float int8_to_float(const int8_t &a)
|
||||
{
|
||||
return float(a);
|
||||
@@ -198,6 +251,10 @@ static int32_t bool_to_int(const bool &a)
|
||||
{
|
||||
return int32_t(a);
|
||||
}
|
||||
static int2 bool_to_int2(const bool &a)
|
||||
{
|
||||
return int2(a);
|
||||
}
|
||||
static float2 bool_to_float2(const bool &a)
|
||||
{
|
||||
return (a) ? float2(1.0f) : float2(0.0f);
|
||||
@@ -227,6 +284,10 @@ static int32_t color_to_int(const ColorGeometry4f &a)
|
||||
{
|
||||
return int(rgb_to_grayscale(a));
|
||||
}
|
||||
static int2 color_to_int2(const ColorGeometry4f &a)
|
||||
{
|
||||
return int2(a.r, a.g);
|
||||
}
|
||||
static int8_t color_to_int8(const ColorGeometry4f &a)
|
||||
{
|
||||
return int_to_int8(color_to_int(a));
|
||||
@@ -256,6 +317,10 @@ static int32_t byte_color_to_int(const ColorGeometry4b &a)
|
||||
{
|
||||
return color_to_int(a.decode());
|
||||
}
|
||||
static int2 byte_color_to_int2(const ColorGeometry4b &a)
|
||||
{
|
||||
return int2(a.r, a.g);
|
||||
}
|
||||
static int8_t byte_color_to_int8(const ColorGeometry4b &a)
|
||||
{
|
||||
return color_to_int8(a.decode());
|
||||
@@ -280,6 +345,7 @@ static DataTypeConversions create_implicit_conversions()
|
||||
add_implicit_conversion<float, float2, float_to_float2>(conversions);
|
||||
add_implicit_conversion<float, float3, float_to_float3>(conversions);
|
||||
add_implicit_conversion<float, int32_t, float_to_int>(conversions);
|
||||
add_implicit_conversion<float, int2, float_to_int2>(conversions);
|
||||
add_implicit_conversion<float, bool, float_to_bool>(conversions);
|
||||
add_implicit_conversion<float, int8_t, float_to_int8>(conversions);
|
||||
add_implicit_conversion<float, ColorGeometry4f, float_to_color>(conversions);
|
||||
@@ -288,6 +354,7 @@ static DataTypeConversions create_implicit_conversions()
|
||||
add_implicit_conversion<float2, float3, float2_to_float3>(conversions);
|
||||
add_implicit_conversion<float2, float, float2_to_float>(conversions);
|
||||
add_implicit_conversion<float2, int32_t, float2_to_int>(conversions);
|
||||
add_implicit_conversion<float2, int2, float2_to_int2>(conversions);
|
||||
add_implicit_conversion<float2, bool, float2_to_bool>(conversions);
|
||||
add_implicit_conversion<float2, int8_t, float2_to_int8>(conversions);
|
||||
add_implicit_conversion<float2, ColorGeometry4f, float2_to_color>(conversions);
|
||||
@@ -297,20 +364,32 @@ static DataTypeConversions create_implicit_conversions()
|
||||
add_implicit_conversion<float3, int8_t, float3_to_int8>(conversions);
|
||||
add_implicit_conversion<float3, float, float3_to_float>(conversions);
|
||||
add_implicit_conversion<float3, int32_t, float3_to_int>(conversions);
|
||||
add_implicit_conversion<float3, int2, float3_to_int2>(conversions);
|
||||
add_implicit_conversion<float3, float2, float3_to_float2>(conversions);
|
||||
add_implicit_conversion<float3, ColorGeometry4f, float3_to_color>(conversions);
|
||||
add_implicit_conversion<float3, ColorGeometry4b, float3_to_byte_color>(conversions);
|
||||
|
||||
add_implicit_conversion<int32_t, bool, int_to_bool>(conversions);
|
||||
add_implicit_conversion<int32_t, int8_t, int_to_int8>(conversions);
|
||||
add_implicit_conversion<int32_t, int2, int_to_int2>(conversions);
|
||||
add_implicit_conversion<int32_t, float, int_to_float>(conversions);
|
||||
add_implicit_conversion<int32_t, float2, int_to_float2>(conversions);
|
||||
add_implicit_conversion<int32_t, float3, int_to_float3>(conversions);
|
||||
add_implicit_conversion<int32_t, ColorGeometry4f, int_to_color>(conversions);
|
||||
add_implicit_conversion<int32_t, ColorGeometry4b, int_to_byte_color>(conversions);
|
||||
|
||||
add_implicit_conversion<int2, bool, int2_to_bool>(conversions);
|
||||
add_implicit_conversion<int2, int8_t, int2_to_int8>(conversions);
|
||||
add_implicit_conversion<int2, int, int2_to_int>(conversions);
|
||||
add_implicit_conversion<int2, float, int2_to_float>(conversions);
|
||||
add_implicit_conversion<int2, float2, int2_to_float2>(conversions);
|
||||
add_implicit_conversion<int2, float3, int2_to_float3>(conversions);
|
||||
add_implicit_conversion<int2, ColorGeometry4f, int2_to_color>(conversions);
|
||||
add_implicit_conversion<int2, ColorGeometry4b, int2_to_byte_color>(conversions);
|
||||
|
||||
add_implicit_conversion<int8_t, bool, int8_to_bool>(conversions);
|
||||
add_implicit_conversion<int8_t, int32_t, int8_to_int>(conversions);
|
||||
add_implicit_conversion<int8_t, int2, int8_to_int2>(conversions);
|
||||
add_implicit_conversion<int8_t, float, int8_to_float>(conversions);
|
||||
add_implicit_conversion<int8_t, float2, int8_to_float2>(conversions);
|
||||
add_implicit_conversion<int8_t, float3, int8_to_float3>(conversions);
|
||||
@@ -320,6 +399,7 @@ static DataTypeConversions create_implicit_conversions()
|
||||
add_implicit_conversion<bool, float, bool_to_float>(conversions);
|
||||
add_implicit_conversion<bool, int8_t, bool_to_int8>(conversions);
|
||||
add_implicit_conversion<bool, int32_t, bool_to_int>(conversions);
|
||||
add_implicit_conversion<bool, int2, bool_to_int2>(conversions);
|
||||
add_implicit_conversion<bool, float2, bool_to_float2>(conversions);
|
||||
add_implicit_conversion<bool, float3, bool_to_float3>(conversions);
|
||||
add_implicit_conversion<bool, ColorGeometry4f, bool_to_color>(conversions);
|
||||
@@ -329,6 +409,7 @@ static DataTypeConversions create_implicit_conversions()
|
||||
add_implicit_conversion<ColorGeometry4f, int8_t, color_to_int8>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, float, color_to_float>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, int32_t, color_to_int>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, int2, color_to_int2>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, float2, color_to_float2>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, float3, color_to_float3>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4f, ColorGeometry4b, color_to_byte_color>(conversions);
|
||||
@@ -337,6 +418,7 @@ static DataTypeConversions create_implicit_conversions()
|
||||
add_implicit_conversion<ColorGeometry4b, int8_t, byte_color_to_int8>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, float, byte_color_to_float>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, int32_t, byte_color_to_int>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, int2, byte_color_to_int2>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, float2, byte_color_to_float2>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, float3, byte_color_to_float3>(conversions);
|
||||
add_implicit_conversion<ColorGeometry4b, ColorGeometry4f, byte_color_to_color>(conversions);
|
||||
|
||||
@@ -194,11 +194,22 @@ inline T interpolate(const T &a, const T &b, const FactorT &t)
|
||||
|
||||
template<typename T> inline T midpoint(const T &a, const T &b)
|
||||
{
|
||||
auto result = (a + b) * T(0.5);
|
||||
if constexpr (std::is_integral_v<T>) {
|
||||
result = std::round(result);
|
||||
/** See std::midpoint from C++20. */
|
||||
using Unsigned = std::make_unsigned_t<T>;
|
||||
int sign = 1;
|
||||
Unsigned smaller = a;
|
||||
Unsigned larger = b;
|
||||
if (a > b) {
|
||||
sign = -1;
|
||||
smaller = b;
|
||||
larger = a;
|
||||
}
|
||||
return a + sign * T(Unsigned(larger - smaller) / 2);
|
||||
}
|
||||
else {
|
||||
return (a + b) * T(0.5);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace blender::math
|
||||
|
||||
@@ -52,6 +52,7 @@ BLI_CPP_TYPE_MAKE(blender::float4x4, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(int8_t, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(int16_t, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(int32_t, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(blender::int2, CPPTypeFlags::BasicType)
|
||||
BLI_CPP_TYPE_MAKE(int64_t, CPPTypeFlags::BasicType)
|
||||
|
||||
BLI_CPP_TYPE_MAKE(uint8_t, CPPTypeFlags::BasicType)
|
||||
@@ -80,6 +81,7 @@ void register_cpp_types()
|
||||
BLI_CPP_TYPE_REGISTER(int8_t);
|
||||
BLI_CPP_TYPE_REGISTER(int16_t);
|
||||
BLI_CPP_TYPE_REGISTER(int32_t);
|
||||
BLI_CPP_TYPE_REGISTER(blender::int2);
|
||||
BLI_CPP_TYPE_REGISTER(int64_t);
|
||||
|
||||
BLI_CPP_TYPE_REGISTER(uint8_t);
|
||||
|
||||
@@ -80,9 +80,10 @@ bool drw_custom_data_match_attribute(const CustomData *custom_data,
|
||||
int *r_layer_index,
|
||||
eCustomDataType *r_type)
|
||||
{
|
||||
const eCustomDataType possible_attribute_types[8] = {
|
||||
const eCustomDataType possible_attribute_types[9] = {
|
||||
CD_PROP_BOOL,
|
||||
CD_PROP_INT8,
|
||||
CD_PROP_INT32_2D,
|
||||
CD_PROP_INT32,
|
||||
CD_PROP_FLOAT,
|
||||
CD_PROP_FLOAT2,
|
||||
|
||||
@@ -395,6 +395,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
|
||||
case CD_PROP_BOOL:
|
||||
case CD_PROP_INT8:
|
||||
case CD_PROP_INT32:
|
||||
case CD_PROP_INT32_2D:
|
||||
case CD_PROP_FLOAT:
|
||||
case CD_PROP_FLOAT2: {
|
||||
if (layer != -1 && domain.has_value()) {
|
||||
|
||||
@@ -100,6 +100,7 @@ static uint gpu_component_size_for_attribute_type(eCustomDataType type)
|
||||
* comment #extract_attr_init. */
|
||||
return 3;
|
||||
case CD_PROP_FLOAT2:
|
||||
case CD_PROP_INT32_2D:
|
||||
return 2;
|
||||
case CD_PROP_FLOAT3:
|
||||
return 3;
|
||||
@@ -116,6 +117,7 @@ static GPUVertFetchMode get_fetch_mode_for_type(eCustomDataType type)
|
||||
switch (type) {
|
||||
case CD_PROP_INT8:
|
||||
case CD_PROP_INT32:
|
||||
case CD_PROP_INT32_2D:
|
||||
return GPU_FETCH_INT_TO_FLOAT;
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
return GPU_FETCH_INT_TO_FLOAT_UNIT;
|
||||
@@ -128,6 +130,7 @@ static GPUVertCompType get_comp_type_for_type(eCustomDataType type)
|
||||
{
|
||||
switch (type) {
|
||||
case CD_PROP_INT8:
|
||||
case CD_PROP_INT32_2D:
|
||||
case CD_PROP_INT32:
|
||||
return GPU_COMP_I32;
|
||||
case CD_PROP_BYTE_COLOR:
|
||||
@@ -299,6 +302,9 @@ static void extract_attr(const MeshRenderData *mr,
|
||||
case CD_PROP_INT32:
|
||||
extract_attr_generic<int32_t, int3>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_INT32_2D:
|
||||
extract_attr_generic<int2>(mr, vbo, request);
|
||||
break;
|
||||
case CD_PROP_FLOAT:
|
||||
extract_attr_generic<float, float3>(mr, vbo, request);
|
||||
break;
|
||||
|
||||
@@ -102,6 +102,8 @@ static StringRefNull rna_property_name_for_type(const eCustomDataType type)
|
||||
case CD_PROP_INT8:
|
||||
case CD_PROP_INT32:
|
||||
return "value_int";
|
||||
case CD_PROP_INT32_2D:
|
||||
return "value_int_vector_2d";
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
return "";
|
||||
@@ -208,6 +210,9 @@ static int mesh_set_attribute_exec(bContext *C, wmOperator *op)
|
||||
case CD_PROP_INT32:
|
||||
*static_cast<int32_t *>(buffer) = RNA_int_get(op->ptr, prop_name.c_str());
|
||||
break;
|
||||
case CD_PROP_INT32_2D:
|
||||
RNA_int_get_array(op->ptr, prop_name.c_str(), static_cast<int *>(buffer));
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
@@ -320,6 +325,9 @@ static int mesh_set_attribute_invoke(bContext *C, wmOperator *op, const wmEvent
|
||||
case CD_PROP_INT32:
|
||||
RNA_property_int_set(op->ptr, prop, *active_value.get<int32_t>());
|
||||
break;
|
||||
case CD_PROP_INT32_2D:
|
||||
RNA_property_int_set_array(op->ptr, prop, *active_value.get<int2>());
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
@@ -385,6 +393,16 @@ void MESH_OT_attribute_set(wmOperatorType *ot)
|
||||
-FLT_MAX,
|
||||
FLT_MAX);
|
||||
RNA_def_int(ot->srna, "value_int", 0, INT_MIN, INT_MAX, "Value", "", INT_MIN, INT_MAX);
|
||||
RNA_def_int_array(ot->srna,
|
||||
"value_int_vector_2d",
|
||||
2,
|
||||
nullptr,
|
||||
INT_MIN,
|
||||
INT_MAX,
|
||||
"Value",
|
||||
"",
|
||||
INT_MIN,
|
||||
INT_MAX);
|
||||
RNA_def_float_color(
|
||||
ot->srna, "value_color", 4, color_default, -FLT_MAX, FLT_MAX, "Value", "", 0.0f, 1.0f);
|
||||
RNA_def_boolean(ot->srna, "value_bool", false, "Value", "");
|
||||
|
||||
@@ -144,6 +144,7 @@ static eCustomDataType data_type_in_attribute_input_node(const eCustomDataType t
|
||||
/* Unsupported currently. */
|
||||
return CD_PROP_FLOAT;
|
||||
case CD_PROP_FLOAT2:
|
||||
case CD_PROP_INT32_2D:
|
||||
/* No 2D vector sockets currently. */
|
||||
return CD_PROP_FLOAT3;
|
||||
case CD_PROP_INT8:
|
||||
|
||||
@@ -335,6 +335,7 @@ static float get_default_column_width(const ColumnValues &values)
|
||||
return float_width;
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT:
|
||||
return float_width;
|
||||
case SPREADSHEET_VALUE_TYPE_INT32_2D:
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT2:
|
||||
return 2.0f * float_width;
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT3:
|
||||
|
||||
@@ -30,6 +30,9 @@ eSpreadsheetColumnValueType cpp_type_to_column_type(const CPPType &type)
|
||||
if (type.is<int>()) {
|
||||
return SPREADSHEET_VALUE_TYPE_INT32;
|
||||
}
|
||||
if (type.is<int2>()) {
|
||||
return SPREADSHEET_VALUE_TYPE_INT32_2D;
|
||||
}
|
||||
if (type.is<float>()) {
|
||||
return SPREADSHEET_VALUE_TYPE_FLOAT;
|
||||
}
|
||||
|
||||
@@ -138,6 +138,10 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
|
||||
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
|
||||
UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
|
||||
}
|
||||
else if (data.type().is<int2>()) {
|
||||
const int2 value = data.get<int2>(real_index);
|
||||
this->draw_int_vector(params, Span(&value.x, 2));
|
||||
}
|
||||
else if (data.type().is<float>()) {
|
||||
const float value = data.get<float>(real_index);
|
||||
std::stringstream ss;
|
||||
@@ -311,6 +315,36 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
|
||||
}
|
||||
}
|
||||
|
||||
void draw_int_vector(const CellDrawParams ¶ms, const Span<int> values) const
|
||||
{
|
||||
BLI_assert(!values.is_empty());
|
||||
const float segment_width = float(params.width) / values.size();
|
||||
for (const int i : values.index_range()) {
|
||||
std::stringstream ss;
|
||||
const int value = values[i];
|
||||
ss << " " << value;
|
||||
const std::string value_str = ss.str();
|
||||
uiBut *but = uiDefIconTextBut(params.block,
|
||||
UI_BTYPE_LABEL,
|
||||
0,
|
||||
ICON_NONE,
|
||||
value_str.c_str(),
|
||||
params.xmin + i * segment_width,
|
||||
params.ymin,
|
||||
segment_width,
|
||||
params.height,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr);
|
||||
/* Right-align Floats. */
|
||||
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
|
||||
UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_byte_color(const CellDrawParams ¶ms, const ColorGeometry4b color) const
|
||||
{
|
||||
const ColorGeometry4f float_color = color.decode();
|
||||
|
||||
@@ -140,6 +140,36 @@ static void apply_row_filter(const SpreadsheetRowFilter &row_filter,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (column_data.type().is<int2>()) {
|
||||
const int2 value = row_filter.value_int2;
|
||||
switch (row_filter.operation) {
|
||||
case SPREADSHEET_ROW_FILTER_EQUAL: {
|
||||
const float threshold_sq = pow2f(row_filter.threshold);
|
||||
apply_filter_operation(
|
||||
column_data.typed<int2>(),
|
||||
[&](const int2 cell) { return math::distance_squared(cell, value) <= threshold_sq; },
|
||||
prev_mask,
|
||||
new_indices);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_GREATER: {
|
||||
apply_filter_operation(
|
||||
column_data.typed<int2>(),
|
||||
[&](const int2 cell) { return cell.x > value.x && cell.y > value.y; },
|
||||
prev_mask,
|
||||
new_indices);
|
||||
break;
|
||||
}
|
||||
case SPREADSHEET_ROW_FILTER_LESS: {
|
||||
apply_filter_operation(
|
||||
column_data.typed<int2>(),
|
||||
[&](const int2 cell) { return cell.x < value.x && cell.y < value.y; },
|
||||
prev_mask,
|
||||
new_indices);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (column_data.type().is<float2>()) {
|
||||
const float2 value = row_filter.value_float2;
|
||||
switch (row_filter.operation) {
|
||||
|
||||
@@ -68,6 +68,11 @@ static std::string value_string(const SpreadsheetRowFilter &row_filter,
|
||||
result << std::fixed << row_filter.value_float;
|
||||
return result.str();
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_INT32_2D: {
|
||||
std::ostringstream result;
|
||||
result << "(" << row_filter.value_int2[0] << ", " << row_filter.value_int2[1] << ")";
|
||||
return result.str();
|
||||
}
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT2: {
|
||||
std::ostringstream result;
|
||||
result.precision(3);
|
||||
@@ -198,6 +203,10 @@ static void spreadsheet_filter_panel_draw(const bContext *C, Panel *panel)
|
||||
uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, filter_ptr, "value_int", 0, IFACE_("Value"), ICON_NONE);
|
||||
break;
|
||||
case SPREADSHEET_VALUE_TYPE_INT32_2D:
|
||||
uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, filter_ptr, "value_int2", 0, IFACE_("Value"), ICON_NONE);
|
||||
break;
|
||||
case SPREADSHEET_VALUE_TYPE_FLOAT:
|
||||
uiItemR(layout, filter_ptr, "operation", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, filter_ptr, "value_float", 0, IFACE_("Value"), ICON_NONE);
|
||||
|
||||
@@ -17,6 +17,7 @@ FN_FIELD_CPP_TYPE_MAKE(blender::ColorGeometry4b);
|
||||
FN_FIELD_CPP_TYPE_MAKE(bool);
|
||||
FN_FIELD_CPP_TYPE_MAKE(int8_t);
|
||||
FN_FIELD_CPP_TYPE_MAKE(int32_t);
|
||||
FN_FIELD_CPP_TYPE_MAKE(blender::int2);
|
||||
FN_FIELD_CPP_TYPE_MAKE(std::string);
|
||||
|
||||
BLI_VECTOR_CPP_TYPE_MAKE(blender::fn::ValueOrField<std::string>);
|
||||
@@ -31,6 +32,7 @@ void FN_register_cpp_types()
|
||||
FN_FIELD_CPP_TYPE_REGISTER(bool);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(int8_t);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(int32_t);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(blender::int2);
|
||||
FN_FIELD_CPP_TYPE_REGISTER(std::string);
|
||||
|
||||
BLI_VECTOR_CPP_TYPE_REGISTER(blender::fn::ValueOrField<std::string>);
|
||||
|
||||
@@ -165,7 +165,8 @@ typedef enum eCustomDataType {
|
||||
/* CD_LOCATION = 43, */ /* UNUSED */
|
||||
/* CD_RADIUS = 44, */ /* UNUSED */
|
||||
CD_PROP_INT8 = 45,
|
||||
/* CD_HAIRMAPPING = 46, */ /* UNUSED, can be reused. */
|
||||
/* Two 32-bit signed integers. */
|
||||
CD_PROP_INT32_2D = 46,
|
||||
|
||||
CD_PROP_COLOR = 47,
|
||||
CD_PROP_FLOAT3 = 48,
|
||||
@@ -218,6 +219,7 @@ typedef enum eCustomDataType {
|
||||
#define CD_MASK_PROP_FLOAT2 (1ULL << CD_PROP_FLOAT2)
|
||||
#define CD_MASK_PROP_BOOL (1ULL << CD_PROP_BOOL)
|
||||
#define CD_MASK_PROP_INT8 (1ULL << CD_PROP_INT8)
|
||||
#define CD_MASK_PROP_INT32_2D (1ULL << CD_PROP_INT32_2D)
|
||||
|
||||
#define CD_MASK_HAIRLENGTH (1ULL << CD_HAIRLENGTH)
|
||||
|
||||
@@ -231,7 +233,7 @@ typedef enum eCustomDataType {
|
||||
#define CD_MASK_PROP_ALL \
|
||||
(CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 | \
|
||||
CD_MASK_PROP_COLOR | CD_MASK_PROP_STRING | CD_MASK_PROP_BYTE_COLOR | CD_MASK_PROP_BOOL | \
|
||||
CD_MASK_PROP_INT8)
|
||||
CD_MASK_PROP_INT8 | CD_MASK_PROP_INT32_2D)
|
||||
|
||||
/* All color attributes */
|
||||
#define CD_MASK_COLOR_ALL (CD_MASK_PROP_COLOR | CD_MASK_PROP_BYTE_COLOR)
|
||||
|
||||
@@ -1980,6 +1980,7 @@ typedef struct SpreadsheetRowFilter {
|
||||
char _pad0[2];
|
||||
|
||||
int value_int;
|
||||
int value_int2[2];
|
||||
char *value_string;
|
||||
float value_float;
|
||||
float threshold;
|
||||
@@ -2025,6 +2026,7 @@ typedef enum eSpreadsheetColumnValueType {
|
||||
SPREADSHEET_VALUE_TYPE_STRING = 7,
|
||||
SPREADSHEET_VALUE_TYPE_BYTE_COLOR = 8,
|
||||
SPREADSHEET_VALUE_TYPE_INT8 = 9,
|
||||
SPREADSHEET_VALUE_TYPE_INT32_2D = 10,
|
||||
} eSpreadsheetColumnValueType;
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,12 +23,12 @@ typedef struct vec2f {
|
||||
float x, y;
|
||||
} vec2f;
|
||||
|
||||
/* not used at the moment */
|
||||
/*
|
||||
typedef struct vec2i {
|
||||
int x, y;
|
||||
} vec2i;
|
||||
|
||||
/* not used at the moment */
|
||||
/*
|
||||
typedef struct vec2d {
|
||||
double x, y;
|
||||
} vec2d;
|
||||
|
||||
@@ -39,6 +39,7 @@ const EnumPropertyItem rna_enum_attribute_type_items[] = {
|
||||
{CD_PROP_BOOL, "BOOLEAN", 0, "Boolean", "True or false"},
|
||||
{CD_PROP_FLOAT2, "FLOAT2", 0, "2D Vector", "2D vector with floating-point values"},
|
||||
{CD_PROP_INT8, "INT8", 0, "8-Bit Integer", "Smaller integer with a range from -128 to 127"},
|
||||
{CD_PROP_INT32_2D, "INT32_2D", 0, "2D Integer Vector", "32-bit signed integer vector"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -65,7 +66,8 @@ const EnumPropertyItem rna_enum_attribute_type_with_auto_items[] = {
|
||||
{CD_PROP_STRING, "STRING", 0, "String", "Text string"},
|
||||
{CD_PROP_BOOL, "BOOLEAN", 0, "Boolean", "True or false"},
|
||||
{CD_PROP_FLOAT2, "FLOAT2", 0, "2D Vector", "2D vector with floating-point values"},
|
||||
{CD_PROP_INT8, "INT8", 0, "8-Bit Integer", "Smaller integer with a range from -128 to 127"},
|
||||
{CD_PROP_FLOAT2, "FLOAT2", 0, "2D Vector", "2D vector with floating-point values"},
|
||||
{CD_PROP_INT32_2D, "INT32_2D", 0, "2D Integer Vector", "32-bit signed integer vector"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -162,6 +164,8 @@ static StructRNA *srna_by_custom_data_layer_type(const eCustomDataType type)
|
||||
return &RNA_Float2Attribute;
|
||||
case CD_PROP_INT8:
|
||||
return &RNA_ByteIntAttribute;
|
||||
case CD_PROP_INT32_2D:
|
||||
return &RNA_Int2Attribute;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@@ -292,6 +296,9 @@ static void rna_Attribute_data_begin(CollectionPropertyIterator *iter, PointerRN
|
||||
case CD_PROP_INT8:
|
||||
struct_size = sizeof(int8_t);
|
||||
break;
|
||||
case CD_PROP_INT32_2D:
|
||||
struct_size = sizeof(int[2]);
|
||||
break;
|
||||
default:
|
||||
struct_size = 0;
|
||||
length = 0;
|
||||
@@ -1017,6 +1024,40 @@ static void rna_def_attribute_int8(BlenderRNA *brna)
|
||||
prop, "rna_ByteIntAttributeValue_get", "rna_ByteIntAttributeValue_set", NULL);
|
||||
}
|
||||
|
||||
static void rna_def_attribute_int2(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "Int2Attribute", "Attribute");
|
||||
RNA_def_struct_sdna(srna, "CustomDataLayer");
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "2D Integer Vector Attribute", "Geometry attribute that stores 2D integer vectors");
|
||||
|
||||
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "Int2AttributeValue");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_Attribute_data_begin",
|
||||
"rna_iterator_array_next",
|
||||
"rna_iterator_array_end",
|
||||
"rna_iterator_array_get",
|
||||
"rna_Attribute_data_length",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
srna = RNA_def_struct(brna, "Int2AttributeValue", NULL);
|
||||
RNA_def_struct_sdna(srna, "vec2i");
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "2D Integer Vector Attribute Value", "2D value in geometry attribute");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Vector", "2D vector");
|
||||
RNA_def_property_int_sdna(prop, NULL, "x");
|
||||
RNA_def_property_array(prop, 2);
|
||||
RNA_def_property_update(prop, 0, "rna_Attribute_update_data");
|
||||
}
|
||||
|
||||
static void rna_def_attribute_float2(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -1095,6 +1136,7 @@ static void rna_def_attribute(BlenderRNA *brna)
|
||||
rna_def_attribute_float_color(brna);
|
||||
rna_def_attribute_byte_color(brna);
|
||||
rna_def_attribute_int(brna);
|
||||
rna_def_attribute_int2(brna);
|
||||
rna_def_attribute_string(brna);
|
||||
rna_def_attribute_bool(brna);
|
||||
rna_def_attribute_float2(brna);
|
||||
|
||||
@@ -8004,6 +8004,11 @@ static void rna_def_spreadsheet_row_filter(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "8-Bit Integer Value", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "value_int2", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_array(prop, 2);
|
||||
RNA_def_property_ui_text(prop, "2D Vector Value", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "value_boolean", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SPREADSHEET_ROW_FILTER_BOOL_VALUE);
|
||||
RNA_def_property_ui_text(prop, "Boolean Value", "");
|
||||
|
||||
Reference in New Issue
Block a user