Blender V5.0
overlay_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
8
9#pragma once
10
11#include "BKE_constraint.h"
15#include "DNA_modifier_types.h"
16#include "DNA_rigidbody_types.h"
17
18#include "overlay_base.hh"
19
20namespace blender::draw::overlay {
21
27
28 private:
29 PassSimple ps_ = {"Relations"};
30
31 LinePrimitiveBuf relations_buf_;
32 PointPrimitiveBuf points_buf_;
33
34 public:
35 Relations(SelectionType selection_type)
36 : relations_buf_(selection_type, "relations_buf_"),
37 points_buf_(selection_type, "points_buf_")
38 {
39 }
40
41 void begin_sync(Resources &res, const State &state) final
42 {
43 enabled_ = state.is_space_v3d();
44 enabled_ &= (state.v3d_flag & V3D_HIDE_HELPLINES) == 0;
45 enabled_ &= !res.is_selection();
46
47 points_buf_.clear();
48 relations_buf_.clear();
49 }
50
51 void object_sync(Manager & /*manager*/,
52 const ObjectRef &ob_ref,
53 Resources &res,
54 const State &state) final
55 {
56 if (!enabled_) {
57 return;
58 }
59
60 /* Don't show object extras in set's. */
61 if (is_from_dupli_or_set(ob_ref)) {
62 return;
63 }
64
65 Object *ob = ob_ref.object;
66 const float4 &relation_color = res.theme.colors.wire;
67 const float4 &constraint_color = res.theme.colors.grid_axis_z; /* ? */
68
70 const float3 &parent_pos = ob->runtime->parent_display_origin;
71 /* Reverse order to have less stipple overlap. */
72 relations_buf_.append(ob->object_to_world().location(), parent_pos, relation_color);
73 }
74
75 /* Drawing the hook lines. */
77 if (md->type == eModifierType_Hook) {
78 HookModifierData *hmd = reinterpret_cast<HookModifierData *>(md);
79 const float3 center = math::transform_point(ob->object_to_world(), float3(hmd->cent));
80 if (hmd->object) {
81 relations_buf_.append(hmd->object->object_to_world().location(), center, relation_color);
82 }
83 points_buf_.append(center, relation_color);
84 }
85 }
86
87 for (GpencilModifierData *md :
89 {
90 if (md->type == eGpencilModifierType_Hook) {
91 HookGpencilModifierData *hmd = reinterpret_cast<HookGpencilModifierData *>(md);
92 const float3 center = math::transform_point(ob->object_to_world(), float3(hmd->cent));
93 if (hmd->object) {
94 relations_buf_.append(hmd->object->object_to_world().location(), center, relation_color);
95 }
96 points_buf_.append(center, relation_color);
97 }
98 }
99
100 if (ob->rigidbody_constraint) {
101 Object *rbc_ob1 = ob->rigidbody_constraint->ob1;
102 Object *rbc_ob2 = ob->rigidbody_constraint->ob2;
103 if (rbc_ob1 && (DRW_object_visibility_in_active_context(rbc_ob1) & OB_VISIBLE_SELF)) {
104
105 relations_buf_.append(rbc_ob1->object_to_world().location(),
106 ob->object_to_world().location(),
107 relation_color);
108 }
109 if (rbc_ob2 && (DRW_object_visibility_in_active_context(rbc_ob2) & OB_VISIBLE_SELF)) {
110 relations_buf_.append(rbc_ob2->object_to_world().location(),
111 ob->object_to_world().location(),
112 relation_color);
113 }
114 }
115
116 /* Drawing the constraint lines */
118 Scene *scene = (Scene *)state.scene;
120 state.depsgraph, (Scene *)state.scene, ob, nullptr, CONSTRAINT_OBTYPE_OBJECT);
121
122 for (bConstraint *constraint : ListBaseWrapper<bConstraint>(ob->constraints)) {
124 /* special case for object solver and follow track constraints because they don't fill
125 * constraint targets properly (design limitation -- scene is needed for their target
126 * but it can't be accessed from get_targets callback) */
127 Object *camob = nullptr;
128
129 if (constraint->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
131 camob = data->camera ? data->camera : scene->camera;
132 }
133 else if (constraint->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
135 camob = data->camera ? data->camera : scene->camera;
136 }
137
138 if (camob) {
139 relations_buf_.append(camob->object_to_world().location(),
140 ob->object_to_world().location(),
141 constraint_color);
142 }
143 }
144 else {
145 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(constraint);
146 ListBase targets = {nullptr, nullptr};
147
148 if ((constraint->ui_expand_flag & (1 << 0)) &&
149 BKE_constraint_targets_get(constraint, &targets))
150 {
152
154 /* Calculate target's position. */
155 float3 target_pos = float3(0.0f);
156 bool has_target = false;
157 if (target->flag & CONSTRAINT_TAR_CUSTOM_SPACE) {
158 target_pos = cob->space_obj_world_matrix[3];
159 has_target = true;
160 }
161 else if (cti->get_target_matrix &&
162 cti->get_target_matrix(state.depsgraph,
163 constraint,
164 cob,
165 target,
166 DEG_get_ctime(state.depsgraph)))
167 {
168 has_target = true;
169 target_pos = target->matrix[3];
170 }
171
172 if (has_target) {
173 /* Only draw this relationship line when there is actually a target. Otherwise it
174 * would always draw to the world origin, which is visually rather noisy and not
175 * that useful. */
176 relations_buf_.append(
177 target_pos, ob->object_to_world().location(), constraint_color);
178 }
179 }
180
181 BKE_constraint_targets_flush(constraint, &targets, true);
182 }
183 }
184 }
185 /* NOTE: Don't use #BKE_constraints_clear_evalob here as that will reset `ob->constinv`.
186 */
187 MEM_freeN(cob);
188 }
189 }
190
191 void end_sync(Resources &res, const State &state) final
192 {
193 if (!enabled_) {
194 return;
195 }
196
197 ps_.init();
198 ps_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
199 ps_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
200 res.select_bind(ps_);
201 {
202 PassSimple::Sub &sub_pass = ps_.sub("lines");
205 state.clipping_plane_count);
206 sub_pass.shader_set(res.shaders->extra_wire.get());
207 relations_buf_.end_sync(sub_pass);
208 }
209 {
210 PassSimple::Sub &sub_pass = ps_.sub("loose_points");
213 state.clipping_plane_count);
214 sub_pass.shader_set(res.shaders->extra_loose_points.get());
215 points_buf_.end_sync(sub_pass);
216 }
217 }
218
219 void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
220 {
221 if (!enabled_) {
222 return;
223 }
224
225 GPU_framebuffer_bind(framebuffer);
226 manager.submit(ps_, view);
227 }
228};
229
230} // 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 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
Types and defines for representing Rigid Body entities.
@ V3D_HIDE_HELPLINES
static AppView * view
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
BMesh const char void * data
void shader_set(gpu::Shader *shader)
void state_set(DRWState state, int clip_plane_count=0)
detail::PassBase< command::DrawCommandBuf > Sub
Definition draw_pass.hh:499
void begin_sync(Resources &res, const State &state) final
void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
Relations(SelectionType selection_type)
void end_sync(Resources &res, const State &state) final
int DRW_object_visibility_in_active_context(const Object *ob)
#define DRW_CLIPPING_UBO_SLOT
#define OVERLAY_GLOBALS_SLOT
@ 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:113
static ulong state[N]
select::SelectionType SelectionType
static bool is_from_dupli_or_set(const Object *ob)
detail::Pass< command::DrawCommandBuf > PassSimple
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
VecBase< float, 4 > float4
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
struct Object * camera
float space_obj_world_matrix[4][4]
bool(* get_target_matrix)(struct Depsgraph *depsgraph, struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime)