Blender V4.3
overlay_next_relation.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#pragma once
10
11#include "BKE_constraint.h"
12
15#include "DNA_modifier_types.h"
16
18
19namespace blender::draw::overlay {
20
21class Relations {
22
23 private:
24 PassSimple ps_ = {"Relations"};
25
26 LinePrimitiveBuf relations_buf_;
27 PointPrimitiveBuf points_buf_;
28
29 bool enabled_ = false;
30
31 public:
32 Relations(SelectionType selection_type)
33 : relations_buf_(selection_type, "relations_buf_"),
34 points_buf_(selection_type, "points_buf_")
35 {
36 }
37
38 void begin_sync(Resources & /*res*/, const State &state)
39 {
40 enabled_ = state.space_type == SPACE_VIEW3D;
41
42 points_buf_.clear();
43 relations_buf_.clear();
44 }
45
46 void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
47 {
48 if (!enabled_) {
49 return;
50 }
51
52 Object *ob = ob_ref.object;
53 const float4 &relation_color = res.theme_settings.color_wire;
54 const float4 &constraint_color = res.theme_settings.color_grid_axis_z; /* ? */
55
57 const float3 &parent_pos = ob->runtime->parent_display_origin;
58 relations_buf_.append(parent_pos, ob->object_to_world().location(), relation_color);
59 }
60
61 /* Drawing the hook lines. */
63 if (md->type == eModifierType_Hook) {
64 HookModifierData *hmd = reinterpret_cast<HookModifierData *>(md);
65 const float3 center = math::transform_point(ob->object_to_world(), float3(hmd->cent));
66 if (hmd->object) {
67 relations_buf_.append(hmd->object->object_to_world().location(), center, relation_color);
68 }
69 points_buf_.append(center, relation_color);
70 }
71 }
72
73 for (GpencilModifierData *md :
75 {
76 if (md->type == eGpencilModifierType_Hook) {
77 HookGpencilModifierData *hmd = reinterpret_cast<HookGpencilModifierData *>(md);
78 const float3 center = math::transform_point(ob->object_to_world(), float3(hmd->cent));
79 if (hmd->object) {
80 relations_buf_.append(hmd->object->object_to_world().location(), center, relation_color);
81 }
82 points_buf_.append(center, relation_color);
83 }
84 }
85
86 if (ob->rigidbody_constraint) {
87 Object *rbc_ob1 = ob->rigidbody_constraint->ob1;
88 Object *rbc_ob2 = ob->rigidbody_constraint->ob2;
89 if (rbc_ob1 && (DRW_object_visibility_in_active_context(rbc_ob1) & OB_VISIBLE_SELF)) {
90
91 relations_buf_.append(rbc_ob1->object_to_world().location(),
92 ob->object_to_world().location(),
93 relation_color);
94 }
95 if (rbc_ob2 && (DRW_object_visibility_in_active_context(rbc_ob2) & OB_VISIBLE_SELF)) {
96 relations_buf_.append(rbc_ob2->object_to_world().location(),
97 ob->object_to_world().location(),
98 relation_color);
99 }
100 }
101
102 /* Drawing the constraint lines */
104 Scene *scene = (Scene *)state.scene;
106 state.depsgraph, (Scene *)state.scene, ob, nullptr, CONSTRAINT_OBTYPE_OBJECT);
107
108 for (bConstraint *constraint : ListBaseWrapper<bConstraint>(ob->constraints)) {
110 /* special case for object solver and follow track constraints because they don't fill
111 * constraint targets properly (design limitation -- scene is needed for their target
112 * but it can't be accessed from get_targets callback) */
113 Object *camob = nullptr;
114
115 if (constraint->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
116 bFollowTrackConstraint *data = (bFollowTrackConstraint *)constraint->data;
117 camob = data->camera ? data->camera : scene->camera;
118 }
119 else if (constraint->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
120 bObjectSolverConstraint *data = (bObjectSolverConstraint *)constraint->data;
121 camob = data->camera ? data->camera : scene->camera;
122 }
123
124 if (camob) {
125 relations_buf_.append(camob->object_to_world().location(),
126 ob->object_to_world().location(),
127 constraint_color);
128 }
129 }
130 else {
131 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(constraint);
132 ListBase targets = {nullptr, nullptr};
133
134 if ((constraint->ui_expand_flag & (1 << 0)) &&
135 BKE_constraint_targets_get(constraint, &targets))
136 {
138
140 /* Calculate target's position. */
141 float3 target_pos = float3(0.0f);
142 if (target->flag & CONSTRAINT_TAR_CUSTOM_SPACE) {
143 target_pos = cob->space_obj_world_matrix[3];
144 }
145 else if (cti->get_target_matrix) {
147 state.depsgraph, constraint, cob, target, DEG_get_ctime(state.depsgraph));
148 target_pos = target->matrix[3];
149 }
150 relations_buf_.append(
151 target_pos, ob->object_to_world().location(), constraint_color);
152 }
153
154 BKE_constraint_targets_flush(constraint, &targets, true);
155 }
156 }
157 }
158 /* NOTE: Don't use #BKE_constraints_clear_evalob here as that will reset `ob->constinv`.
159 */
160 MEM_freeN(cob);
161 }
162 }
163
164 void end_sync(Resources &res, const State &state)
165 {
166 if (!enabled_) {
167 return;
168 }
169
170 ps_.init();
171 res.select_bind(ps_);
172 {
173 PassSimple::Sub &sub_pass = ps_.sub("lines");
176 state.clipping_plane_count);
177 sub_pass.shader_set(res.shaders.extra_wire.get());
178 sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
179 relations_buf_.end_sync(sub_pass);
180 }
181 {
182 PassSimple::Sub &sub_pass = ps_.sub("loose_points");
185 state.clipping_plane_count);
186 sub_pass.shader_set(res.shaders.extra_loose_points.get());
187 sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
188 points_buf_.end_sync(sub_pass);
189 }
190 }
191
192 void draw(Framebuffer &framebuffer, Manager &manager, View &view)
193 {
194 if (!enabled_) {
195 return;
196 }
197
198 GPU_framebuffer_bind(framebuffer);
199 manager.submit(ps_, view);
200 }
201};
202
203} // namespace blender::draw::overlay
void BKE_constraint_targets_flush(struct bConstraint *con, struct ListBase *targets, bool no_copy)
int BKE_constraint_targets_get(struct bConstraint *con, struct ListBase *r_targets)
void BKE_constraint_custom_object_space_init(struct bConstraintOb *cob, struct bConstraint *con)
const bConstraintTypeInfo * BKE_constraint_typeinfo_get(struct bConstraint *con)
struct bConstraintOb * BKE_constraints_make_evalob(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, void *subdata, short datatype)
@ OB_VISIBLE_SELF
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define ELEM(...)
float DEG_get_ctime(const Depsgraph *graph)
@ CONSTRAINT_TAR_CUSTOM_SPACE
@ CONSTRAINT_TYPE_FOLLOWTRACK
@ CONSTRAINT_TYPE_OBJECTSOLVER
@ CONSTRAINT_OBTYPE_OBJECT
@ eGpencilModifierType_Hook
@ eModifierType_Hook
@ SPACE_VIEW3D
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
void submit(PassSimple &pass, View &view)
PassBase< DrawCommandBufType > & sub(const char *name)
Definition draw_pass.hh:616
void state_set(DRWState state, int clip_plane_count=0)
Definition draw_pass.hh:954
void bind_ubo(const char *name, GPUUniformBuf *buffer)
void shader_set(GPUShader *shader)
Definition draw_pass.hh:971
void end_sync(Resources &res, const State &state)
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
void begin_sync(Resources &, const State &state)
void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
Relations(SelectionType selection_type)
int DRW_object_visibility_in_active_context(const Object *ob)
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition draw_state.hh:38
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static ulong state[N]
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
ListBaseWrapperTemplate< ListBase, T > ListBaseWrapper
VecBase< float, 3 > float3
struct Object * object
ListBase constraints
ObjectRuntimeHandle * runtime
ListBase modifiers
ListBase greasepencil_modifiers
struct Object * parent
struct RigidBodyCon * rigidbody_constraint
struct Object * ob1
struct Object * ob2
float space_obj_world_matrix[4][4]
void(* get_target_matrix)(struct Depsgraph *depsgraph, struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime)
void append(const float3 &start, const float3 &end, const float4 &color, select::ID select_id=select::SelectMap::select_invalid_id())
void append(const float3 &position, const float4 &color, select::ID select_id=select::SelectMap::select_invalid_id())
void select_bind(PassSimple &pass)