52using geo_eval_log::GeoTreeLog;
131 const bNodeSocket &socket = *this->gizmo_node.input_by_identifier(identifier);
132 const std::optional<T> value_opt = this->tree_log.find_primitive_socket_value<
T>(socket);
136 r_value = *value_opt;
181 bool any_interacting =
false;
185 return any_interacting;
195 float factor_from_transform = 1.0f;
196 float current_value = 0.0f;
202 gizmo_ =
WM_gizmo_new(
"GIZMO_GT_arrow_3d", &gzgroup,
nullptr);
217 if (is_interacting) {
250 if (!
params.get_input_value(
"Position", position) ||
251 !
params.get_input_value(
"Direction", direction))
253 params.r_report.missing_socket_logs =
true;
258 params.r_report.invalid_transform =
true;
265 float4x4 gizmo_transform =
params.parent_transform * gizmo_base_transform;
275 edit_data_.current_value = 0.0f;
282 const float new_gizmo_value = *
static_cast<const float *
>(value_ptr);
283 self.edit_data_.current_value = new_gizmo_value;
284 const float offset = new_gizmo_value *
self.edit_data_.factor_from_transform;
286 value_variant.
set(value_variant.
get<
float>() + offset);
292 *
static_cast<float *
>(value_ptr) =
self.edit_data_.current_value;
303 bool is_negative_transform =
false;
304 float current_value = 0.0f;
310 gizmo_ =
WM_gizmo_new(
"GIZMO_GT_dial_3d", &gzgroup,
nullptr);
325 if (is_interacting) {
340 int draw_options =
RNA_enum_get(gizmo_->ptr,
"draw_options");
342 RNA_enum_set(gizmo_->ptr,
"draw_options", draw_options);
356 if (!
params.get_input_value(
"Position", position) || !
params.get_input_value(
"Up", up) ||
357 !
params.get_input_value(
"Screen Space", screen_space) ||
358 !
params.get_input_value(
"Radius", radius))
360 params.r_report.missing_socket_logs =
true;
366 params.r_report.invalid_transform =
true;
372 float4x4 gizmo_transform =
params.parent_transform * gizmo_base_transform;
392 edit_data_.current_value = 0.0f;
399 const float new_gizmo_value = *
static_cast<const float *
>(value_ptr);
400 self.edit_data_.current_value = new_gizmo_value;
401 float offset = new_gizmo_value;
402 if (
self.edit_data_.is_negative_transform) {
406 value_variant.
set(value_variant.
get<
float>() + offset);
411 *
static_cast<float *
>(value_ptr) =
self.edit_data_.current_value;
419 std::array<wmGizmo *, 3> translation_gizmos_ = {};
420 std::array<wmGizmo *, 3> rotation_gizmos_ = {};
421 std::array<wmGizmo *, 3> scale_gizmos_ = {};
423 bool any_translation_visible_ =
false;
424 bool any_rotation_visible_ =
false;
425 bool any_scale_visible_ =
false;
436 float3 current_translation;
446 translation_gizmos_[axis] =
WM_gizmo_new(
"GIZMO_GT_arrow_3d", &gzgroup,
nullptr);
451 rotation_gizmos_[axis] =
WM_gizmo_new(
"GIZMO_GT_dial_3d", &gzgroup,
nullptr);
456 scale_gizmos_[axis] =
WM_gizmo_new(
"GIZMO_GT_arrow_3d", &gzgroup,
nullptr);
463 gizmos.
extend(translation_gizmos_);
464 gizmos.
extend(rotation_gizmos_);
465 gizmos.
extend(scale_gizmos_);
472 params.gizmo_node.storage);
481 if (!
params.get_input_value(
"Position", position) ||
482 !
params.get_input_value(
"Rotation", rotation))
484 params.r_report.missing_socket_logs =
true;
489 base_transform_from_socket.
location() = position;
493 transform_orientation_ = orientation_slot.
type;
495 parent_transform_ =
params.parent_transform;
504 any_translation_visible_ =
false;
505 any_rotation_visible_ =
false;
506 any_scale_visible_ =
false;
508 const auto &elem = std::get<nodes::inverse_eval::MatrixElem>(
params.elem.elem);
511 const bool translation_used = (storage.
flag &
514 const bool rotation_used = (storage.
flag &
524 any_translation_visible_ |= translation_used;
525 any_rotation_visible_ |= rotation_used;
526 any_scale_visible_ |= scale_used;
533 wmGizmo *gizmo = translation_gizmos_[axis];
539 if (any_rotation_visible_) {
543 else if (any_scale_visible_) {
558 wmGizmo *gizmo = rotation_gizmos_[axis];
578 wmGizmo *gizmo = scale_gizmos_[axis];
582 const float length = (any_translation_visible_ || any_rotation_visible_) ? 0.775f : 1.0f;
590 const float4x4 &base_transform_from_socket)
594 wmGizmo *gizmo = translation_gizmos_[axis_i];
600 axis, base_transform_from_socket,
params);
603 edit_data_.current_translation[axis_i] = 0.0f;
609 const void *value_ptr) {
612 const float new_gizmo_value = *
static_cast<const float *
>(value_ptr);
613 self.edit_data_.current_translation[axis_i] = new_gizmo_value;
615 translation[axis_i] = new_gizmo_value;
625 1.0f,
math::length((
self.parent_transform_.view<3, 3>() * orientation)[axis_i]));
629 value_variant.
set(value);
635 *
static_cast<float *
>(value_ptr) =
self.edit_data_.current_translation[axis_i];
642 const float4x4 &base_transform_from_socket)
646 wmGizmo *gizmo = rotation_gizmos_[axis_i];
652 axis, base_transform_from_socket,
params);
655 edit_data_.current_rotation[axis_i] = 0.0f;
661 const void *value_ptr) {
665 const float new_gizmo_value = *
static_cast<const float *
>(value_ptr);
666 self.edit_data_.current_rotation[axis_i] = new_gizmo_value;
669 float3 local_rotation_axis;
680 value.
view<3, 3>() = rotation_matrix * value.
view<3, 3>();
681 value_variant.
set(value);
687 *
static_cast<float *
>(value_ptr) =
self.edit_data_.current_rotation[axis_i];
694 const float4x4 &base_transform_from_socket)
698 wmGizmo *gizmo = scale_gizmos_[axis_i];
704 axis, base_transform_from_socket,
params);
707 edit_data_.current_scale[axis_i] = 0.0f;
713 const void *value_ptr) {
717 const float new_gizmo_value = *
static_cast<const float *
>(value_ptr);
718 self.edit_data_.current_scale[axis_i] = new_gizmo_value;
719 float3 scale{1.0f, 1.0f, 1.0f};
720 scale[axis_i] += new_gizmo_value;
735 value.
view<3, 3>() = scale_matrix * value.
view<3, 3>();
736 value_variant.
set(value);
742 *
static_cast<float *
>(value_ptr) =
self.edit_data_.current_scale[axis_i];
749 const float4x4 &base_transform_from_socket,
753 const float3 global_location =
754 (
params.parent_transform * base_transform_from_socket).location();
756 float3 global_direction{};
758 global_direction = axis_direction;
762 base_transform_from_socket.
view<3, 3>(),
766 gizmo_transform.
location() = global_location;
794 return std::make_unique<LinearGizmo>();
796 return std::make_unique<DialGizmo>();
798 return std::make_unique<TransformGizmos>();
808 if (edit_data_component->gizmo_edit_hints_) {
809 if (
const float4x4 *m = edit_data_component->gizmo_edit_hints_->gizmo_transforms.lookup_ptr(
857 for (
const int reference_i : references.
index_range()) {
864 const int index =
handles.first_index_try(reference_i);
868 reference_geometry, gizmo_id, sub_transform))
888 if (
const geo_eval_log::ViewerNodeLog *viewer_log =
891 if (
const bke::GeometrySet *viewer_geometry = viewer_log->main_geometry()) {
892 return *viewer_geometry;
925 MEM_delete(gzgroup_data);
950 auto compute_context_cache = std::make_shared<bke::ComputeContextCache>();
954 *compute_context_cache,
955 [&](
const Object &object_orig,
958 const bNode &gizmo_node,
962 if (new_gizmos_by_node.
contains(gizmo_id)) {
966 if (!nmd_orig.
runtime->eval_log) {
979 compute_context, gizmo_node, gizmo_socket);
982 ntree.ensure_topology_cache();
985 if (std::optional<std::unique_ptr<NodeGizmos>> old_gizmos =
986 gzgroup_data.gizmos_by_node.pop_try(gizmo_id))
989 node_gizmos = old_gizmos->get();
990 new_gizmos_by_node.
add(gizmo_id, std::move(*old_gizmos));
995 new_node_gizmos->create_gizmos(*gzgroup);
997 for (
wmGizmo *gizmo : new_node_gizmos->get_all_gizmos()) {
1000 node_gizmos = new_node_gizmos.get();
1001 new_gizmos_by_node.
add(gizmo_id, std::move(new_node_gizmos));
1007 GeoTreeLog &tree_log = nmd_orig.
runtime->eval_log->get_tree_log(compute_context.
hash());
1008 tree_log.ensure_socket_values();
1009 tree_log.ensure_evaluated_gizmo_nodes();
1011 const std::optional<float4x4> crazy_space_geometry_transform =
1014 const bool missing_logged_data = !tree_log.evaluated_gizmo_nodes.contains(
1016 if (missing_logged_data) {
1024 const bool missing_used_transform = gizmo_node.output_socket(0).is_logically_linked() &&
1025 !crazy_space_geometry_transform.has_value();
1026 if (missing_used_transform) {
1031 const float4x4 object_to_world{object_eval->object_to_world()};
1032 const float4x4 geometry_transform = crazy_space_geometry_transform.value_or(
1037 *
C, object_to_world * geometry_transform, gizmo_node, tree_log, report, elem};
1038 node_gizmos->
update(update_params);
1042 if (!any_interacting) {
1051 compute_context_cache,
1052 compute_context = &compute_context,
1053 gizmo_node_tree = &gizmo_node.owner_tree(),
1054 gizmo_node = &gizmo_node,
1055 object_orig = &object_orig,
1057 eval_log = nmd_orig.
runtime->eval_log](
1060 gizmo_node_tree->ensure_topology_cache();
1061 const bNodeSocket &socket = *gizmo_node->input_by_identifier(socket_identifier);
1064 const_cast<Object &
>(*object_orig),
1079 bool any_gizmo_interactive =
false;
1080 for (
const std::unique_ptr<NodeGizmos> &node_gizmos : new_gizmos_by_node.
values()) {
1081 any_gizmo_interactive |= node_gizmos->is_any_interacting();
1083 if (any_gizmo_interactive) {
1084 for (std::unique_ptr<NodeGizmos> &node_gizmos : new_gizmos_by_node.
values()) {
1085 for (
wmGizmo *gizmo : node_gizmos->get_all_gizmos()) {
1094 for (std::unique_ptr<NodeGizmos> &node_gizmos : gzgroup_data.gizmos_by_node.values()) {
1096 for (
wmGizmo *gizmo : gizmos) {
1101 gzgroup_data.gizmos_by_node = std::move(new_gizmos_by_node);
1115 gzgt->
name =
"Geometry Nodes Widgets";
1116 gzgt->
idname =
"VIEW3D_GGT_geometry_nodes";
ScrArea * CTX_wm_area(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
void BKE_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
#define GEO_NODE_GIZMO_LINEAR
#define GEO_NODE_GIZMO_DIAL
#define GEO_NODE_GIZMO_TRANSFORM
General operations, lookup, etc. for blender objects.
MINLINE float safe_divide(float a, float b)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void unit_m4(float m[4][4])
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
#define BLI_STRUCT_EQUALITY_OPERATORS_2(Type, m1, m2)
#define SET_FLAG_FROM_TEST(value, test, flag)
void DEG_id_tag_update_for_side_effect_request(Depsgraph *depsgraph, ID *id, unsigned int flags)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ GEO_NODE_GIZMO_COLOR_PRIMARY
@ GEO_NODE_GIZMO_COLOR_SECONDARY
@ GEO_NODE_LINEAR_GIZMO_DRAW_STYLE_CROSS
@ GEO_NODE_LINEAR_GIZMO_DRAW_STYLE_BOX
@ GEO_NODE_LINEAR_GIZMO_DRAW_STYLE_ARROW
@ GEO_NODE_TRANSFORM_GIZMO_USE_ROTATION_X
@ GEO_NODE_TRANSFORM_GIZMO_USE_SCALE_X
@ GEO_NODE_TRANSFORM_GIZMO_USE_TRANSLATION_X
@ V3D_GIZMO_HIDE_MODIFIER
@ ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE
@ ED_GIZMO_DIAL_DRAW_FLAG_CLIP
@ ED_GIZMO_ARROW_STYLE_CROSS
@ ED_GIZMO_ARROW_STYLE_BOX
@ ED_GIZMO_ARROW_STYLE_NORMAL
void UI_GetThemeColor3fv(int colorid, float col[3])
@ WM_GIZMO_DRAW_OFFSET_SCALE
@ WM_GIZMOGROUPTYPE_PERSISTENT
BMesh const char void * data
BPy_StructRNA * depsgraph
unsigned long long int uint64_t
const ComputeContextHash & hash() const
ValueIterator values() const &
bool add(const Key &key, const Value &value)
bool contains(const Key &key) const
constexpr int64_t first_index(const T &search_value) const
constexpr IndexRange index_range() const
void extend(Span< T > array)
GeometrySet & geometry_set()
Span< int > reference_handles() const
Span< float4x4 > transforms() const
Span< InstanceReference > references() const
void update_style(const NodeGeometryDialGizmo &storage, const bool is_interacting)
bool update_transform(GizmosUpdateParams ¶ms)
Vector< wmGizmo * > get_all_gizmos() override
void create_gizmos(wmGizmoGroup &gzgroup) override
void update_target_property()
void update(GizmosUpdateParams ¶ms) override
void create_gizmos(wmGizmoGroup &gzgroup) override
Vector< wmGizmo * > get_all_gizmos() override
bool update_transform(GizmosUpdateParams ¶ms)
void update_target_property()
void update_style(const NodeGeometryLinearGizmo &storage)
void update(GizmosUpdateParams ¶ms) override
bool is_any_interacting()
virtual ~NodeGizmos()=default
ApplyChangeFn apply_change
virtual void create_gizmos(wmGizmoGroup &gzgroup)=0
virtual void update(GizmosUpdateParams &)
virtual Vector< wmGizmo * > get_all_gizmos()=0
static constexpr Value Z_POS
static constexpr Value Z_NEG
static constexpr Axis from_int(const int axis_int)
float length(VecOp< float, D >) RET
GeometrySet object_get_evaluated_geometry_set(const Object &object, bool apply_subdiv=true)
static ThemeColorID get_axis_theme_color_id(const int axis)
static float4x4 matrix_from_position_and_up_direction(const float3 &position, const float3 &direction, const math::AxisSigned direction_axis)
static void WIDGETGROUP_geometry_nodes_refresh(const bContext *C, wmGizmoGroup *gzgroup)
static const float4x4 * find_direct_gizmo_transform(const bke::GeometrySet &geometry, const bke::NodeGizmoID &gizmo_id)
static void WIDGETGROUP_geometry_nodes_setup(const bContext *, wmGizmoGroup *gzgroup)
static std::optional< float4x4 > find_gizmo_geometry_transform(const bke::GeometrySet &geometry, const bke::NodeGizmoID &gizmo_id)
static std::unique_ptr< NodeGizmos > create_gizmo_node_gizmos(const bNode &gizmo_node)
static void WIDGETGROUP_geometry_nodes_draw_prepare(const bContext *, wmGizmoGroup *)
static bool WIDGETGROUP_geometry_nodes_poll(const bContext *C, wmGizmoGroupType *)
static void make_matrix_orthonormal_but_keep_z_axis(float4x4 &m)
std::function< void( StringRef socket_identifier, FunctionRef< void(bke::SocketValueVariant &value)> modify_value)> ApplyChangeFn
static ThemeColorID get_gizmo_theme_color_id(const GeometryNodeGizmoColor color_id)
static bool gizmo_is_interacting(const wmGizmo &gizmo)
static bool has_nested_gizmo_transform(const bke::GeometrySet &geometry, const bke::NodeGizmoID &gizmo_id)
static void get_axis_gizmo_colors(const int axis, float *r_color, float *r_color_hi)
static bke::GeometrySet find_geometry_for_gizmo(const Object &object_eval, const NodesModifierData &nmd_orig, const View3D &v3d)
static std::optional< float4x4 > find_gizmo_geometry_transform_recursive(const bke::GeometrySet &geometry, const bke::NodeGizmoID &gizmo_id, const float4x4 &transform)
QuaternionBase< float > Quaternion
bool is_orthonormal(const MatT &mat)
T to_vector(const Axis axis)
T length(const VecBase< T, Size > &a)
AxisAngleBase< float, AngleRadianBase< float > > AxisAngle
bool is_unit_scale(const MatBase< T, NumCol, NumRow > &m)
T average(const VecBase< T, Size > &a)
CartesianBasis invert(const CartesianBasis &basis)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
MatT from_scale(const VecBase< typename MatT::base_type, ScaleDim > &scale)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > to_scale(const MatBase< T, NumCol, NumRow > &mat)
VecBase< T, 3 > transform_direction(const MatBase< T, 3, 3 > &mat, const VecBase< T, 3 > &direction)
MatT from_rotation(const RotationT &rotation)
T determinant(const MatBase< T, Size, Size > &mat)
ie::ElemVariant get_editable_gizmo_elem(const ComputeContext &gizmo_context, const bNode &gizmo_node, const bNodeSocket &gizmo_socket)
void apply_gizmo_change(bContext &C, Object &object, NodesModifierData &nmd, geo_eval_log::GeoNodesLog &eval_log, const ComputeContext &gizmo_context, const bNodeSocket &gizmo_socket, const FunctionRef< void(bke::SocketValueVariant &value)> apply_on_gizmo_value_fn)
void foreach_active_gizmo(const bContext &C, bke::ComputeContextCache &compute_context_cache, const ForeachGizmoFn fn)
MatBase< float, 4, 4 > float4x4
uint64_t get_default_hash(const T &v, const Args &...args)
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
int RNA_enum_get(PointerRNA *ptr, const char *name)
struct bNodeTree * node_group
NodesModifierRuntimeHandle * runtime
TransformOrientationSlot orientation_slots[4]
const c_style_mat & ptr() const
const MatView< T, ViewNumCol, ViewNumRow, NumCol, NumRow, SrcStartCol, SrcStartRow, Alignment > view() const
static MatBase identity()
bke::NodeGizmoID gizmo_id
const Object * object_orig
Map< GeoNodesObjectGizmoID, std::unique_ptr< NodeGizmos > > gizmos_by_node
bool get_input_value(const StringRef identifier, T &r_value)
nodes::inverse_eval::ElemVariant elem
float4x4 parent_transform
wmGizmoGroupFnSetupKeymap setup_keymap
wmGizmoGroupFnRefresh refresh
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupFnDrawPrepare draw_prepare
wmGizmoMap * parent_gzmap
void(* customdata_free)(void *)
wmGizmoPropertyFnGet value_get_fn
wmGizmoPropertyFnSet value_set_fn
float matrix_offset[4][4]
void VIEW3D_GGT_geometry_nodes(wmGizmoGroupType *gzgt)
void WM_main_add_notifier(uint type, void *reference)
void WM_gizmo_set_line_width(wmGizmo *gz, const float line_width)
void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
wmGizmo * WM_gizmo_new(const StringRef idname, wmGizmoGroup *gzgroup, PointerRNA *properties)
void WM_gizmo_unlink(ListBase *gizmolist, wmGizmoMap *gzmap, wmGizmo *gz, bContext *C)
wmKeyMap * WM_gizmogroup_setup_keymap_generic_maybe_drag(const wmGizmoGroupType *, wmKeyConfig *kc)
void WM_gizmo_target_property_def_func(wmGizmo *gz, const char *idname, const wmGizmoPropertyFnParams *params)