Curves: Add edit mode operator to set attribute values #105076
|
@ -5823,6 +5823,7 @@ class VIEW3D_MT_edit_curves(Menu):
|
||||||
|
|
||||||
layout.menu("VIEW3D_MT_transform")
|
layout.menu("VIEW3D_MT_transform")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
layout.operator("curves.attribute_set")
|
||||||
layout.operator("curves.delete")
|
layout.operator("curves.delete")
|
||||||
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ set(INC_SYS
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SRC
|
set(SRC
|
||||||
|
intern/attribute_set.cc
|
||||||
intern/curves_add.cc
|
intern/curves_add.cc
|
||||||
intern/curves_data.cc
|
intern/curves_data.cc
|
||||||
intern/curves_edit.cc
|
intern/curves_edit.cc
|
||||||
|
|
|
@ -0,0 +1,227 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup edmesh
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BLI_generic_pointer.hh"
|
||||||
|
|
||||||
|
#include "BKE_attribute.h"
|
||||||
|
#include "BKE_attribute_math.hh"
|
||||||
|
#include "BKE_context.h"
|
||||||
|
#include "BKE_report.h"
|
||||||
|
#include "BKE_type_conversions.hh"
|
||||||
|
|
||||||
|
#include "WM_api.hh"
|
||||||
|
#include "WM_types.hh"
|
||||||
|
|
||||||
|
#include "ED_curves.hh"
|
||||||
|
#include "ED_geometry.hh"
|
||||||
|
#include "ED_object.hh"
|
||||||
|
#include "ED_screen.hh"
|
||||||
|
#include "ED_transform.hh"
|
||||||
|
#include "ED_view3d.hh"
|
||||||
|
|
||||||
|
#include "RNA_access.hh"
|
||||||
|
|
||||||
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
|
#include "UI_interface.hh"
|
||||||
|
#include "UI_resources.hh"
|
||||||
|
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "DEG_depsgraph.hh"
|
||||||
|
#include "DEG_depsgraph_query.hh"
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Delete Operator
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
namespace blender::ed::curves {
|
||||||
|
|
||||||
|
static bool active_attribute_poll(bContext *C)
|
||||||
|
{
|
||||||
|
if (!editable_curves_in_edit_mode_poll(C)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Object *object = CTX_data_active_object(C);
|
||||||
|
Curves &curves_id = *static_cast<Curves *>(object->data);
|
||||||
|
const CustomDataLayer *layer = BKE_id_attributes_active_get(&const_cast<ID &>(curves_id.id));
|
||||||
|
if (!layer) {
|
||||||
|
CTX_wm_operator_poll_msg_set(C, "No active attribute");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (layer->type == CD_PROP_STRING) {
|
||||||
|
CTX_wm_operator_poll_msg_set(C, "Active string attribute not supported");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IndexMask retrieve_selected_elements(const Curves &curves_id,
|
||||||
|
const eAttrDomain domain,
|
||||||
|
IndexMaskMemory &memory)
|
||||||
|
{
|
||||||
|
switch (domain) {
|
||||||
|
case ATTR_DOMAIN_POINT:
|
||||||
|
return retrieve_selected_points(curves_id, memory);
|
||||||
|
case ATTR_DOMAIN_CURVE:
|
||||||
|
return retrieve_selected_curves(curves_id, memory);
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void validate_value(const bke::AttributeAccessor attributes,
|
||||||
|
const StringRef name,
|
||||||
|
const CPPType &type,
|
||||||
|
void *buffer)
|
||||||
|
{
|
||||||
|
const bke::AttributeValidator validator = attributes.lookup_validator(name);
|
||||||
|
if (!validator) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BUFFER_FOR_CPP_TYPE_VALUE(type, validated_buffer);
|
||||||
|
BLI_SCOPED_DEFER([&]() { type.destruct(validated_buffer); });
|
||||||
|
|
||||||
|
const IndexMask single_mask(1);
|
||||||
|
mf::ParamsBuilder params(*validator.function, &single_mask);
|
||||||
|
params.add_readonly_single_input(GPointer(type, buffer));
|
||||||
|
params.add_uninitialized_single_output({type, validated_buffer, 1});
|
||||||
|
mf::ContextBuilder context;
|
||||||
|
validator.function->call(single_mask, params, context);
|
||||||
|
|
||||||
|
type.copy_assign(validated_buffer, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_attribute_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
Object *active_object = CTX_data_active_object(C);
|
||||||
|
Curves &active_curves_id = *static_cast<Curves *>(active_object->data);
|
||||||
|
|
||||||
|
CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&active_curves_id.id);
|
||||||
|
const eCustomDataType active_type = eCustomDataType(active_attribute->type);
|
||||||
|
const CPPType &type = *bke::custom_data_type_to_cpp_type(active_type);
|
||||||
|
|
||||||
|
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
||||||
|
BLI_SCOPED_DEFER([&]() { type.destruct(buffer); });
|
||||||
|
const GPointer value = geometry::rna_property_for_attribute_type_retrieve_value(
|
||||||
|
*op->ptr, active_type, buffer);
|
||||||
|
|
||||||
|
const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions();
|
||||||
|
|
||||||
|
for (Curves *curves_id : get_unique_editable_curves(*C)) {
|
||||||
|
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||||
|
CustomDataLayer *layer = BKE_id_attributes_active_get(&curves_id->id);
|
||||||
|
if (!layer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||||
|
bke::GSpanAttributeWriter attribute = attributes.lookup_for_write_span(layer->name);
|
||||||
|
|
||||||
|
/* Use implicit conversions to try to handle the case where the active attribute has a
|
||||||
|
* different type on multiple objects. */
|
||||||
|
const CPPType &dst_type = attribute.span.type();
|
||||||
|
if (&type != &dst_type && !conversions.is_convertible(type, dst_type)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
BUFFER_FOR_CPP_TYPE_VALUE(dst_type, dst_buffer);
|
||||||
|
BLI_SCOPED_DEFER([&]() { dst_type.destruct(dst_buffer); });
|
||||||
|
conversions.convert_to_uninitialized(type, dst_type, value.get(), dst_buffer);
|
||||||
|
|
||||||
|
validate_value(attributes, layer->name, dst_type, dst_buffer);
|
||||||
|
const GPointer dst_value(type, dst_buffer);
|
||||||
|
|
||||||
|
IndexMaskMemory memory;
|
||||||
|
const IndexMask selection = retrieve_selected_elements(*curves_id, attribute.domain, memory);
|
||||||
|
if (selection.is_empty()) {
|
||||||
|
attribute.finish();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dst_type.fill_assign_indices(dst_value.get(), attribute.span.data(), selection);
|
||||||
|
attribute.finish();
|
||||||
|
|
||||||
|
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_attribute_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
{
|
||||||
|
Object *active_object = CTX_data_active_object(C);
|
||||||
|
Curves &active_curves_id = *static_cast<Curves *>(active_object->data);
|
||||||
|
|
||||||
|
CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&active_curves_id.id);
|
||||||
|
const bke::CurvesGeometry &curves = active_curves_id.geometry.wrap();
|
||||||
|
const bke::AttributeAccessor attributes = curves.attributes();
|
||||||
|
const bke::GAttributeReader attribute = attributes.lookup(active_attribute->name);
|
||||||
|
const eAttrDomain domain = attribute.domain;
|
||||||
|
|
||||||
|
IndexMaskMemory memory;
|
||||||
|
const IndexMask selection = retrieve_selected_elements(active_curves_id, domain, memory);
|
||||||
|
|
||||||
|
const CPPType &type = attribute.varray.type();
|
||||||
|
|
||||||
|
PropertyRNA *prop = geometry::rna_property_for_type(*op->ptr,
|
||||||
|
bke::cpp_type_to_custom_data_type(type));
|
||||||
|
if (RNA_property_is_set(op->ptr, prop)) {
|
||||||
|
return WM_operator_props_popup(C, op, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
||||||
|
BLI_SCOPED_DEFER([&]() { type.destruct(buffer); });
|
||||||
|
|
||||||
|
bke::attribute_math::convert_to_static_type(type, [&](auto dummy) {
|
||||||
|
using T = decltype(dummy);
|
||||||
|
const VArray<T> values_typed = attribute.varray.typed<T>();
|
||||||
|
bke::attribute_math::DefaultMixer<T> mixer{MutableSpan(static_cast<T *>(buffer), 1)};
|
||||||
|
selection.foreach_index([&](const int i) { mixer.mix_in(0, values_typed[i]); });
|
||||||
|
mixer.finalize();
|
||||||
|
});
|
||||||
|
|
||||||
|
geometry::rna_property_for_attribute_type_set_value(*op->ptr, *prop, GPointer(type, buffer));
|
||||||
|
|
||||||
|
return WM_operator_props_popup(C, op, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_attribute_ui(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
uiLayout *layout = uiLayoutColumn(op->layout, true);
|
||||||
|
uiLayoutSetPropSep(layout, true);
|
||||||
|
uiLayoutSetPropDecorate(layout, false);
|
||||||
|
|
||||||
|
Object *object = CTX_data_active_object(C);
|
||||||
|
Curves &curves_id = *static_cast<Curves *>(object->data);
|
||||||
|
|
||||||
|
CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&curves_id.id);
|
||||||
|
const eCustomDataType active_type = eCustomDataType(active_attribute->type);
|
||||||
|
const StringRefNull prop_name = geometry::rna_property_name_for_type(active_type);
|
||||||
|
const char *name = active_attribute->name;
|
||||||
|
uiItemR(layout, op->ptr, prop_name.c_str(), UI_ITEM_NONE, name, ICON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CURVES_OT_attribute_set(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
using namespace blender::ed;
|
||||||
|
using namespace blender::ed::curves;
|
||||||
|
ot->name = "Set Attribute";
|
||||||
|
ot->description = "Set values of the active attribute for selected elements";
|
||||||
|
ot->idname = "CURVES_OT_attribute_set";
|
||||||
|
|
||||||
|
ot->exec = set_attribute_exec;
|
||||||
|
ot->invoke = set_attribute_invoke;
|
||||||
|
ot->poll = active_attribute_poll;
|
||||||
|
ot->ui = set_attribute_ui;
|
||||||
|
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
|
||||||
|
geometry::register_rna_properties_for_attribute_types(*ot->srna);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::ed::curves
|
||||||
|
|
||||||
|
/** \} */
|
|
@ -1236,6 +1236,7 @@ static void CURVES_OT_delete(wmOperatorType *ot)
|
||||||
void ED_operatortypes_curves()
|
void ED_operatortypes_curves()
|
||||||
{
|
{
|
||||||
using namespace blender::ed::curves;
|
using namespace blender::ed::curves;
|
||||||
|
WM_operatortype_append(CURVES_OT_attribute_set);
|
||||||
WM_operatortype_append(CURVES_OT_convert_to_particle_system);
|
WM_operatortype_append(CURVES_OT_convert_to_particle_system);
|
||||||
WM_operatortype_append(CURVES_OT_convert_from_particle_system);
|
WM_operatortype_append(CURVES_OT_convert_from_particle_system);
|
||||||
WM_operatortype_append(CURVES_OT_snap_curves_to_surface);
|
WM_operatortype_append(CURVES_OT_snap_curves_to_surface);
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include "DNA_meshdata_types.h"
|
#include "DNA_meshdata_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
|
|
||||||
|
#include "BLI_color.hh"
|
||||||
|
|
||||||
#include "BKE_attribute.h"
|
#include "BKE_attribute.h"
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
#include "BKE_deform.h"
|
#include "BKE_deform.h"
|
||||||
|
@ -42,6 +44,137 @@
|
||||||
|
|
||||||
namespace blender::ed::geometry {
|
namespace blender::ed::geometry {
|
||||||
|
|
||||||
|
StringRefNull rna_property_name_for_type(const eCustomDataType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case CD_PROP_FLOAT:
|
||||||
|
return "value_float";
|
||||||
|
case CD_PROP_FLOAT2:
|
||||||
|
return "value_float_vector_2d";
|
||||||
|
case CD_PROP_FLOAT3:
|
||||||
|
return "value_float_vector_3d";
|
||||||
|
case CD_PROP_COLOR:
|
||||||
|
case CD_PROP_BYTE_COLOR:
|
||||||
|
return "value_color";
|
||||||
|
case CD_PROP_BOOL:
|
||||||
|
return "value_bool";
|
||||||
|
case CD_PROP_INT8:
|
||||||
|
case CD_PROP_INT32:
|
||||||
|
return "value_int";
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyRNA *rna_property_for_type(PointerRNA &ptr, const eCustomDataType type)
|
||||||
|
{
|
||||||
|
return RNA_struct_find_property(&ptr, rna_property_name_for_type(type).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_rna_properties_for_attribute_types(StructRNA &srna)
|
||||||
|
{
|
||||||
|
static blender::float4 color_default(1);
|
||||||
|
|
||||||
|
RNA_def_float(&srna, "value_float", 0.0f, -FLT_MAX, FLT_MAX, "Value", "", -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_float_array(&srna,
|
||||||
|
"value_float_vector_2d",
|
||||||
|
2,
|
||||||
|
nullptr,
|
||||||
|
-FLT_MAX,
|
||||||
|
FLT_MAX,
|
||||||
|
"Value",
|
||||||
|
"",
|
||||||
|
-FLT_MAX,
|
||||||
|
FLT_MAX);
|
||||||
|
RNA_def_float_array(&srna,
|
||||||
|
"value_float_vector_3d",
|
||||||
|
3,
|
||||||
|
nullptr,
|
||||||
|
-FLT_MAX,
|
||||||
|
FLT_MAX,
|
||||||
|
"Value",
|
||||||
|
"",
|
||||||
|
-FLT_MAX,
|
||||||
|
FLT_MAX);
|
||||||
|
RNA_def_int(&srna, "value_int", 0, INT_MIN, INT_MAX, "Value", "", INT_MIN, INT_MAX);
|
||||||
|
RNA_def_float_color(
|
||||||
|
&srna, "value_color", 4, color_default, -FLT_MAX, FLT_MAX, "Value", "", 0.0f, 1.0f);
|
||||||
|
RNA_def_boolean(&srna, "value_bool", false, "Value", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
GPointer rna_property_for_attribute_type_retrieve_value(PointerRNA &ptr,
|
||||||
|
const eCustomDataType type,
|
||||||
|
void *buffer)
|
||||||
|
{
|
||||||
|
const StringRefNull prop_name = rna_property_name_for_type(type);
|
||||||
|
switch (type) {
|
||||||
|
case CD_PROP_FLOAT:
|
||||||
|
*static_cast<float *>(buffer) = RNA_float_get(&ptr, prop_name.c_str());
|
||||||
|
break;
|
||||||
|
case CD_PROP_FLOAT2:
|
||||||
|
RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
|
||||||
|
break;
|
||||||
|
case CD_PROP_FLOAT3:
|
||||||
|
RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
|
||||||
|
break;
|
||||||
|
case CD_PROP_COLOR:
|
||||||
|
RNA_float_get_array(&ptr, prop_name.c_str(), static_cast<float *>(buffer));
|
||||||
|
break;
|
||||||
|
case CD_PROP_BYTE_COLOR:
|
||||||
|
ColorGeometry4f value;
|
||||||
|
RNA_float_get_array(&ptr, prop_name.c_str(), value);
|
||||||
|
*static_cast<ColorGeometry4b *>(buffer) = value.encode();
|
||||||
|
break;
|
||||||
|
case CD_PROP_BOOL:
|
||||||
|
*static_cast<bool *>(buffer) = RNA_boolean_get(&ptr, prop_name.c_str());
|
||||||
|
break;
|
||||||
|
case CD_PROP_INT8:
|
||||||
|
*static_cast<int8_t *>(buffer) = RNA_int_get(&ptr, prop_name.c_str());
|
||||||
|
break;
|
||||||
|
case CD_PROP_INT32:
|
||||||
|
*static_cast<int32_t *>(buffer) = RNA_int_get(&ptr, prop_name.c_str());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
return GPointer(bke::custom_data_type_to_cpp_type(type), buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rna_property_for_attribute_type_set_value(PointerRNA &ptr,
|
||||||
|
PropertyRNA &prop,
|
||||||
|
const GPointer value)
|
||||||
|
{
|
||||||
|
switch (bke::cpp_type_to_custom_data_type(*value.type())) {
|
||||||
|
case CD_PROP_FLOAT:
|
||||||
|
RNA_property_float_set(&ptr, &prop, *value.get<float>());
|
||||||
|
break;
|
||||||
|
case CD_PROP_FLOAT2:
|
||||||
|
RNA_property_float_set_array(&ptr, &prop, *value.get<float2>());
|
||||||
|
break;
|
||||||
|
case CD_PROP_FLOAT3:
|
||||||
|
RNA_property_float_set_array(&ptr, &prop, *value.get<float3>());
|
||||||
|
break;
|
||||||
|
case CD_PROP_BYTE_COLOR:
|
||||||
|
RNA_property_float_set_array(&ptr, &prop, value.get<ColorGeometry4b>()->decode());
|
||||||
|
break;
|
||||||
|
case CD_PROP_COLOR:
|
||||||
|
RNA_property_float_set_array(&ptr, &prop, *value.get<ColorGeometry4f>());
|
||||||
|
break;
|
||||||
|
case CD_PROP_BOOL:
|
||||||
|
RNA_property_boolean_set(&ptr, &prop, *value.get<bool>());
|
||||||
|
break;
|
||||||
|
case CD_PROP_INT8:
|
||||||
|
RNA_property_int_set(&ptr, &prop, *value.get<int8_t>());
|
||||||
|
break;
|
||||||
|
case CD_PROP_INT32:
|
||||||
|
RNA_property_int_set(&ptr, &prop, *value.get<int32_t>());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*********************** Attribute Operators ************************/
|
/*********************** Attribute Operators ************************/
|
||||||
|
|
||||||
static bool geometry_attributes_poll(bContext *C)
|
static bool geometry_attributes_poll(bContext *C)
|
||||||
|
|
|
@ -70,6 +70,14 @@ bool curves_poll(bContext *C);
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Operators
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
void CURVES_OT_attribute_set(wmOperatorType *ot);
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Mask Functions
|
/** \name Mask Functions
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
|
@ -18,6 +18,33 @@
|
||||||
struct Mesh;
|
struct Mesh;
|
||||||
struct ReportList;
|
struct ReportList;
|
||||||
|
|
||||||
|
#include "BLI_generic_pointer.hh"
|
||||||
|
#include "BLI_string_ref.hh"
|
||||||
|
|
||||||
|
struct PointerRNA;
|
||||||
|
struct PropertyRNA;
|
||||||
|
|
||||||
|
namespace blender::ed::geometry {
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Attribute Value RNA Property Helpers
|
||||||
|
*
|
||||||
|
* Functions to make it easier to register RNA properties for the various attribute types and
|
||||||
|
* retrieve/set their values.
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
StringRefNull rna_property_name_for_type(eCustomDataType type);
|
||||||
|
PropertyRNA *rna_property_for_type(PointerRNA &ptr, const eCustomDataType type);
|
||||||
|
void register_rna_properties_for_attribute_types(StructRNA &srna);
|
||||||
|
GPointer rna_property_for_attribute_type_retrieve_value(PointerRNA &ptr,
|
||||||
|
const eCustomDataType type,
|
||||||
|
void *buffer);
|
||||||
|
void rna_property_for_attribute_type_set_value(PointerRNA &ptr, PropertyRNA &prop, GPointer value);
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
} // namespace blender::ed::geometry
|
||||||
|
|
||||||
void ED_operatortypes_geometry();
|
void ED_operatortypes_geometry();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "RNA_define.hh"
|
#include "RNA_define.hh"
|
||||||
#include "RNA_enum_types.hh"
|
#include "RNA_enum_types.hh"
|
||||||
|
|
||||||
|
#include "ED_geometry.hh"
|
||||||
#include "ED_mesh.hh"
|
#include "ED_mesh.hh"
|
||||||
#include "ED_object.hh"
|
#include "ED_object.hh"
|
||||||
#include "ED_screen.hh"
|
#include "ED_screen.hh"
|
||||||
|
@ -88,33 +89,6 @@ static bool mesh_active_attribute_poll(bContext *C)
|
||||||
|
|
||||||
namespace set_attribute {
|
namespace set_attribute {
|
||||||
|
|
||||||
static StringRefNull rna_property_name_for_type(const eCustomDataType type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case CD_PROP_FLOAT:
|
|
||||||
return "value_float";
|
|
||||||
case CD_PROP_FLOAT2:
|
|
||||||
return "value_float_vector_2d";
|
|
||||||
case CD_PROP_FLOAT3:
|
|
||||||
return "value_float_vector_3d";
|
|
||||||
case CD_PROP_COLOR:
|
|
||||||
case CD_PROP_BYTE_COLOR:
|
|
||||||
return "value_color";
|
|
||||||
case CD_PROP_BOOL:
|
|
||||||
return "value_bool";
|
|
||||||
case CD_PROP_INT8:
|
|
||||||
case CD_PROP_INT32:
|
|
||||||
return "value_int";
|
|
||||||
case CD_PROP_INT32_2D:
|
|
||||||
return "value_int_vector_2d";
|
|
||||||
case CD_PROP_QUATERNION:
|
|
||||||
return "value_quat";
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bmesh_vert_edge_face_layer_selected_values_set(BMesh &bm,
|
static void bmesh_vert_edge_face_layer_selected_values_set(BMesh &bm,
|
||||||
const BMIterType iter_type,
|
const BMIterType iter_type,
|
||||||
const GPointer value,
|
const GPointer value,
|
||||||
|
@ -186,48 +160,9 @@ static int mesh_set_attribute_exec(bContext *C, wmOperator *op)
|
||||||
|
|
||||||
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
||||||
BLI_SCOPED_DEFER([&]() { type.destruct(buffer); });
|
BLI_SCOPED_DEFER([&]() { type.destruct(buffer); });
|
||||||
|
const GPointer value = geometry::rna_property_for_attribute_type_retrieve_value(
|
||||||
|
*op->ptr, active_type, buffer);
|
||||||
|
|
||||||
const StringRefNull prop_name = rna_property_name_for_type(active_type);
|
|
||||||
switch (active_type) {
|
|
||||||
case CD_PROP_FLOAT:
|
|
||||||
*static_cast<float *>(buffer) = RNA_float_get(op->ptr, prop_name.c_str());
|
|
||||||
break;
|
|
||||||
case CD_PROP_FLOAT2:
|
|
||||||
RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast<float *>(buffer));
|
|
||||||
break;
|
|
||||||
case CD_PROP_FLOAT3:
|
|
||||||
RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast<float *>(buffer));
|
|
||||||
break;
|
|
||||||
case CD_PROP_COLOR:
|
|
||||||
RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast<float *>(buffer));
|
|
||||||
break;
|
|
||||||
case CD_PROP_QUATERNION: {
|
|
||||||
float4 value;
|
|
||||||
RNA_float_get_array(op->ptr, prop_name.c_str(), value);
|
|
||||||
*static_cast<math::Quaternion *>(buffer) = math::normalize(math::Quaternion(value));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CD_PROP_BYTE_COLOR:
|
|
||||||
ColorGeometry4f value;
|
|
||||||
RNA_float_get_array(op->ptr, prop_name.c_str(), value);
|
|
||||||
*static_cast<ColorGeometry4b *>(buffer) = value.encode();
|
|
||||||
break;
|
|
||||||
case CD_PROP_BOOL:
|
|
||||||
*static_cast<bool *>(buffer) = RNA_boolean_get(op->ptr, prop_name.c_str());
|
|
||||||
break;
|
|
||||||
case CD_PROP_INT8:
|
|
||||||
*static_cast<int8_t *>(buffer) = RNA_int_get(op->ptr, prop_name.c_str());
|
|
||||||
break;
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
const GPointer value(type, buffer);
|
|
||||||
const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions();
|
const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions();
|
||||||
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -305,48 +240,12 @@ static int mesh_set_attribute_invoke(bContext *C, wmOperator *op, const wmEvent
|
||||||
return WM_operator_props_popup(C, op, event);
|
return WM_operator_props_popup(C, op, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
const StringRefNull prop_name = rna_property_name_for_type(data_type);
|
|
||||||
const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
|
const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
|
||||||
const GPointer active_value(type, POINTER_OFFSET(active_elem->head.data, layer->offset));
|
const GPointer active_value(type, POINTER_OFFSET(active_elem->head.data, layer->offset));
|
||||||
|
|
||||||
PropertyRNA *prop = RNA_struct_find_property(op->ptr, prop_name.c_str());
|
PropertyRNA *prop = geometry::rna_property_for_type(*op->ptr, data_type);
|
||||||
if (!RNA_property_is_set(op->ptr, prop)) {
|
if (!RNA_property_is_set(op->ptr, prop)) {
|
||||||
switch (data_type) {
|
geometry::rna_property_for_attribute_type_set_value(*op->ptr, *prop, active_value);
|
||||||
case CD_PROP_FLOAT:
|
|
||||||
RNA_property_float_set(op->ptr, prop, *active_value.get<float>());
|
|
||||||
break;
|
|
||||||
case CD_PROP_FLOAT2:
|
|
||||||
RNA_property_float_set_array(op->ptr, prop, *active_value.get<float2>());
|
|
||||||
break;
|
|
||||||
case CD_PROP_FLOAT3:
|
|
||||||
RNA_property_float_set_array(op->ptr, prop, *active_value.get<float3>());
|
|
||||||
break;
|
|
||||||
case CD_PROP_BYTE_COLOR:
|
|
||||||
RNA_property_float_set_array(op->ptr, prop, active_value.get<ColorGeometry4b>()->decode());
|
|
||||||
break;
|
|
||||||
case CD_PROP_COLOR:
|
|
||||||
RNA_property_float_set_array(op->ptr, prop, *active_value.get<ColorGeometry4f>());
|
|
||||||
break;
|
|
||||||
case CD_PROP_BOOL:
|
|
||||||
RNA_property_boolean_set(op->ptr, prop, *active_value.get<bool>());
|
|
||||||
break;
|
|
||||||
case CD_PROP_INT8:
|
|
||||||
RNA_property_int_set(op->ptr, prop, *active_value.get<int8_t>());
|
|
||||||
break;
|
|
||||||
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;
|
|
||||||
case CD_PROP_QUATERNION: {
|
|
||||||
const math::Quaternion value = math::normalize(*active_value.get<math::Quaternion>());
|
|
||||||
RNA_property_float_set_array(op->ptr, prop, float4(value));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return WM_operator_props_popup(C, op, event);
|
return WM_operator_props_popup(C, op, event);
|
||||||
|
@ -361,7 +260,7 @@ static void mesh_set_attribute_ui(bContext *C, wmOperator *op)
|
||||||
Mesh *mesh = ED_mesh_context(C);
|
Mesh *mesh = ED_mesh_context(C);
|
||||||
CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&mesh->id);
|
CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&mesh->id);
|
||||||
const eCustomDataType active_type = eCustomDataType(active_attribute->type);
|
const eCustomDataType active_type = eCustomDataType(active_attribute->type);
|
||||||
const StringRefNull prop_name = rna_property_name_for_type(active_type);
|
const StringRefNull prop_name = geometry::rna_property_name_for_type(active_type);
|
||||||
const char *name = active_attribute->name;
|
const char *name = active_attribute->name;
|
||||||
uiItemR(layout, op->ptr, prop_name.c_str(), UI_ITEM_NONE, name, ICON_NONE);
|
uiItemR(layout, op->ptr, prop_name.c_str(), UI_ITEM_NONE, name, ICON_NONE);
|
||||||
}
|
}
|
||||||
|
@ -385,53 +284,7 @@ void MESH_OT_attribute_set(wmOperatorType *ot)
|
||||||
|
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
|
||||||
static blender::float4 color_default(1);
|
blender::ed::geometry::register_rna_properties_for_attribute_types(*ot->srna);
|
||||||
|
|
||||||
RNA_def_float(ot->srna, "value_float", 0.0f, -FLT_MAX, FLT_MAX, "Value", "", -FLT_MAX, FLT_MAX);
|
|
||||||
RNA_def_float_array(ot->srna,
|
|
||||||
"value_float_vector_2d",
|
|
||||||
2,
|
|
||||||
nullptr,
|
|
||||||
-FLT_MAX,
|
|
||||||
FLT_MAX,
|
|
||||||
"Value",
|
|
||||||
"",
|
|
||||||
-FLT_MAX,
|
|
||||||
FLT_MAX);
|
|
||||||
RNA_def_float_array(ot->srna,
|
|
||||||
"value_float_vector_3d",
|
|
||||||
3,
|
|
||||||
nullptr,
|
|
||||||
-FLT_MAX,
|
|
||||||
FLT_MAX,
|
|
||||||
"Value",
|
|
||||||
"",
|
|
||||||
-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", "");
|
|
||||||
RNA_def_float_array(ot->srna,
|
|
||||||
"value_quat",
|
|
||||||
4,
|
|
||||||
rna_default_quaternion,
|
|
||||||
-FLT_MAX,
|
|
||||||
FLT_MAX,
|
|
||||||
"Value",
|
|
||||||
"",
|
|
||||||
FLT_MAX,
|
|
||||||
FLT_MAX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
Loading…
Reference in New Issue