Blender V4.3
overlay_next_edit_text.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_vfont.hh"
12#include "BLI_math_matrix.hh"
13
15
16namespace blender::draw::overlay {
17
18class EditText {
19
20 private:
21 PassSimple ps_ = {"Selection&Cursor"};
22
23 View view_edit_text = {"view_edit_text"};
24 float view_dist = 0.0f;
25
26 StorageVectorBuffer<ObjectMatrices> text_selection_buf;
28 LinePrimitiveBuf box_line_buf_;
29
30 bool enabled_ = false;
31
32 public:
33 EditText(SelectionType selection_type) : box_line_buf_(selection_type, "box_line_buf_") {}
34
35 void begin_sync(const State &state)
36 {
37 enabled_ = state.v3d;
38 text_selection_buf.clear();
39 text_cursor_buf.clear();
40 box_line_buf_.clear();
41 }
42
43 void edit_object_sync(const ObjectRef &ob_ref, const Resources &res)
44 {
45 if (!enabled_) {
46 return;
47 }
48
49 const Curve &cu = *static_cast<Curve *>(ob_ref.object->data);
50 add_select(cu, ob_ref.object->object_to_world());
51 add_cursor(cu, ob_ref.object->object_to_world());
52 add_boxes(res, cu, ob_ref.object->object_to_world());
53 }
54
55 void end_sync(Resources &res, const ShapeCache &shapes, const State &state)
56 {
57 ps_.init();
58 res.select_bind(ps_);
59 {
62
63 /* Selection Boxes. */
64 {
65 auto &sub = ps_.sub("text_selection");
66 sub.state_set(default_state, state.clipping_plane_count);
67 sub.shader_set(res.shaders.uniform_color_batch.get());
70 sub.push_constant("ucolor", color);
71
72 auto &buf = text_selection_buf;
73 buf.push_update();
74 sub.bind_ssbo("matrix_buf", &buf);
75 sub.draw(shapes.quad_solid.get(), buf.size());
76 }
77
78 /* Highlight text within selection boxes. */
79 {
80 auto &sub = ps_.sub("highlight_text_selection");
83 state.clipping_plane_count);
84 sub.shader_set(res.shaders.uniform_color_batch.get());
87 sub.push_constant("ucolor", color);
88
89 auto &buf = text_selection_buf;
90 buf.push_update();
91 sub.bind_ssbo("matrix_buf", &buf);
92 sub.draw(shapes.quad_solid.get(), buf.size());
93 }
94
95 /* Cursor (text caret). */
96 {
97 auto &sub = ps_.sub("text_cursor");
98 sub.state_set(default_state, state.clipping_plane_count);
99 sub.shader_set(res.shaders.uniform_color_batch.get());
100 sub.state_set(default_state, state.clipping_plane_count);
103 sub.push_constant("ucolor", color);
104
105 auto &buf = text_cursor_buf;
106 buf.push_update();
107 sub.bind_ssbo("matrix_buf", &buf);
108 sub.draw(shapes.quad_solid.get(), buf.size());
109 }
110
111 /* Text boxes. */
112 {
113 auto &sub_pass = ps_.sub("text_boxes");
114 sub_pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
116 state.clipping_plane_count);
117 sub_pass.shader_set(res.shaders.extra_wire.get());
118 sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
119 box_line_buf_.end_sync(sub_pass);
120 }
121 }
122 }
123
124 void draw(Framebuffer &framebuffer, Manager &manager, View &view)
125 {
126 if (!enabled_) {
127 return;
128 }
129 view_edit_text.sync(view.viewmat(), winmat_polygon_offset(view.winmat(), view_dist, -5.0f));
130
131 GPU_framebuffer_bind(framebuffer);
132 manager.submit(ps_, view_edit_text);
133 }
134
135 private:
136 /* Use 2D quad corners to create a matrix that set
137 * a [-1..1] quad at the right position. */
138 static void v2_quad_corners_to_mat4(const float4x2 &corners, float4x4 &r_mat)
139 {
140 const float2 &origin = corners[0];
141 const float2 half_size_x = (float2(corners[1]) - float2(corners[0])) * 0.5f;
142 const float2 half_size_y = (float2(corners[3]) - float2(corners[0])) * 0.5f;
143
144 r_mat = float4x4(float4(half_size_x, 0.0f, 0.0f),
145 float4(half_size_y, 0.0f, 0.0f),
146 float4(0.0f, 0.0f, 1.0f, 0.0f),
147 float4(origin + half_size_x + half_size_y, 0.0f, 1.0f));
148 }
149
150 void add_select(const Curve &cu, const float4x4 &ob_to_world)
151 {
152 EditFont *ef = cu.editfont;
153 float4x4 final_mat;
154 float4x2 box;
155
156 for (const int i : IndexRange(ef->selboxes_len)) {
157 EditFontSelBox *sb = &ef->selboxes[i];
158
159 float selboxw;
160 if (i + 1 != ef->selboxes_len) {
161 if (ef->selboxes[i + 1].y == sb->y) {
162 selboxw = ef->selboxes[i + 1].x - sb->x;
163 }
164 else {
165 selboxw = sb->w;
166 }
167 }
168 else {
169 selboxw = sb->w;
170 }
171 /* NOTE: v2_quad_corners_to_mat4 don't need the 3rd corner. */
172 if (sb->rot == 0.0f) {
173 box[0] = float2(sb->x, sb->y);
174 box[1] = float2(sb->x + selboxw, sb->y);
175 box[3] = float2(sb->x, sb->y + sb->h);
176 }
177 else {
179 box[0] = float2(sb->x, sb->y);
180 box[1] = mat[0] * selboxw + float2(&sb->x);
181 box[3] = mat[1] * sb->h + float2(&sb->x);
182 }
183 v2_quad_corners_to_mat4(box, final_mat);
184 final_mat = ob_to_world * final_mat;
185 ObjectMatrices obj_mat;
186 obj_mat.sync(final_mat);
187 text_selection_buf.append(obj_mat);
188 }
189 }
190
191 void add_cursor(const Curve &cu, const float4x4 &ob_to_world)
192 {
193 EditFont *edit_font = cu.editfont;
194 float4x2 cursor = float4x2(&edit_font->textcurs[0][0]);
195 float4x4 mat;
196
197 v2_quad_corners_to_mat4(cursor, mat);
198 ObjectMatrices ob_mat;
199 ob_mat.sync(ob_to_world * mat);
200 text_cursor_buf.append(ob_mat);
201 }
202
203 void add_boxes(const Resources &res, const Curve &cu, const float4x4 &ob_to_world)
204 {
205 for (const int i : IndexRange(cu.totbox)) {
206 const TextBox &tb = cu.tb[i];
207 const bool is_active = (i == (cu.actbox - 1));
208 const float4 &color = is_active ? res.theme_settings.color_active :
209 res.theme_settings.color_wire;
210
211 if ((tb.w != 0.0f) || (tb.h != 0.0f)) {
212 const float3 top_left = float3(cu.xof + tb.x, cu.yof + tb.y + cu.fsize_realtime, 0.001);
213 const float3 w = float3(tb.w, 0.0f, 0.0f);
214 const float3 h = float3(0.0f, tb.h, 0.0f);
215 float4x3 vecs = float4x3(top_left, top_left + w, top_left + w - h, top_left - h);
216
217 for (const int j : IndexRange(4)) {
218 vecs[j] = math::transform_point(ob_to_world, vecs[j]);
219 }
220 for (const int j : IndexRange(4)) {
221 box_line_buf_.append(vecs[j], vecs[(j + 1) % 4], color);
222 }
223 }
224 }
225 }
226};
227} // namespace blender::draw::overlay
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
struct Curve Curve
struct TextBox TextBox
static AppView * view
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
@ TH_WIDGET_TEXT_HIGHLIGHT
@ TH_WIDGET_TEXT_SELECTION
@ TH_WIDGET_TEXT_CURSOR
void UI_GetThemeColor4fv(int colorid, float col[4])
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
void submit(PassSimple &pass, View &view)
EditText(SelectionType selection_type)
void end_sync(Resources &res, const ShapeCache &shapes, const State &state)
void edit_object_sync(const ObjectRef &ob_ref, const Resources &res)
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
DRWState
Definition draw_state.hh:25
@ DRW_STATE_BLEND_ALPHA
Definition draw_state.hh:55
@ DRW_STATE_DEPTH_GREATER_EQUAL
Definition draw_state.hh:41
@ 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
ObjectMatrices
static ulong state[N]
static float4x4 winmat_polygon_offset(float4x4 winmat, float view_dist, float offset)
select::SelectionType SelectionType
detail::Pass< command::DrawCommandBuf > PassSimple
MatT from_rotation(const RotationT &rotation)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
MatBase< float, 2, 2 > float2x2
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< float, 2 > float2
MatBase< float, 4, 2 > float4x2
MatBase< float, 4, 3 > float4x3
VecBase< float, 3 > float3
static void v2_quad_corners_to_mat4(const float corners[4][2], float r_mat[4][4])
struct TextBox * tb
struct EditFont * editfont
float fsize_realtime
float textcurs[4][2]
Definition BKE_vfont.hh:40
EditFontSelBox * selboxes
Definition BKE_vfont.hh:41
int selboxes_len
Definition BKE_vfont.hh:42
void select_bind(PassSimple &pass)