Blender V5.0
transform_gizmo_3d_shear.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12
13#include "BLI_listbase.h"
14#include "BLI_math_matrix.h"
15#include "BLI_math_vector.h"
16
17#include "BKE_context.hh"
18#include "BKE_scene.hh"
19
20#include "ED_gizmo_library.hh"
21#include "ED_gizmo_utils.hh"
22#include "ED_screen.hh"
23
24#include "WM_api.hh"
25
26#include "UI_resources.hh"
27
28#include "RNA_access.hh"
29
30/* Local module include. */
31#include "transform.hh"
32#include "transform_gizmo.hh"
33
34namespace blender::ed::transform {
35
36/* -------------------------------------------------------------------- */
39
41 wmGizmo *gizmo[3][2];
44
45 /* Only for view orientation. */
46 struct {
47 float viewinv_m3[3][3];
49};
50
52{
54 return false;
55 }
56 View3D *v3d = CTX_wm_view3d(C);
58 return false;
59 }
60 return true;
61}
62
63static void WIDGETGROUP_xform_shear_setup(const bContext * /*C*/, wmGizmoGroup *gzgroup)
64{
66 const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
67 wmOperatorType *ot_shear = WM_operatortype_find("TRANSFORM_OT_shear", true);
68
69 float axis_color[3][3];
70 for (int i = 0; i < 3; i++) {
71 UI_GetThemeColor3fv(TH_AXIS_X + i, axis_color[i]);
72 }
73
74 for (int i = 0; i < 3; i++) {
75 for (int j = 0; j < 2; j++) {
76 wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, nullptr);
77 RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
78 const int i_ortho_a = (i + j + 1) % 3;
79 const int i_ortho_b = (i + (1 - j) + 1) % 3;
80 interp_v3_v3v3(gz->color, axis_color[i_ortho_a], axis_color[i_ortho_b], 0.75f);
81 gz->color[3] = 0.5f;
82 PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, nullptr);
83 RNA_boolean_set(ptr, "release_confirm", true);
84 xgzgroup->gizmo[i][j] = gz;
85 }
86 }
87
88 for (int i = 0; i < 4; i++) {
89 wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, nullptr);
90 RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
91 RNA_enum_set(gz->ptr, "draw_options", 0); /* No stem. */
92 copy_v3_fl(gz->color, 1.0f);
93 gz->color[3] = 0.5f;
95 PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, nullptr);
96 RNA_boolean_set(ptr, "release_confirm", true);
97 xgzgroup->gizmo_view[i] = gz;
98
99 /* Unlike the other gizmos, this never changes so can be set on setup. */
101 RNA_enum_set(&gzop->ptr, "orient_type", V3D_ORIENT_VIEW);
102
103 RNA_enum_set(&gzop->ptr, "orient_axis", 2);
104 RNA_enum_set(&gzop->ptr, "orient_axis_ortho", ((i % 2) ? 0 : 1));
105 }
106
107 gzgroup->customdata = xgzgroup;
108}
109
111{
112 Scene *scene = CTX_data_scene(C);
113 ARegion *region = CTX_wm_region(C);
114 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
115
116 XFormShearWidgetGroup *xgzgroup = static_cast<XFormShearWidgetGroup *>(gzgroup->customdata);
117 TransformBounds tbounds;
118
119 /* Needed to test view orientation changes. */
120 copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
121
123 scene, SCE_ORIENT_ROTATE);
124 const int orient_index = BKE_scene_orientation_slot_get_index(orient_slot);
125
126 TransformCalcParams calc_params{};
127 calc_params.use_local_axis = false;
128 calc_params.orientation_index = orient_index + 1;
129 if (calc_gizmo_stats(C, &calc_params, &tbounds, rv3d) == 0) {
130 for (int i = 0; i < 3; i++) {
131 for (int j = 0; j < 2; j++) {
132 wmGizmo *gz = xgzgroup->gizmo[i][j];
134 }
135 }
136
137 for (int i = 0; i < 4; i++) {
138 wmGizmo *gz = xgzgroup->gizmo_view[i];
140 }
141 }
142 else {
143 gizmo_prepare_mat(C, rv3d, &tbounds);
144 for (int i = 0; i < 3; i++) {
145 for (int j = 0; j < 2; j++) {
146 wmGizmo *gz = xgzgroup->gizmo[i][j];
149
151 const int i_ortho_a = (i + j + 1) % 3;
152 const int i_ortho_b = (i + (1 - j) + 1) % 3;
153 WM_gizmo_set_matrix_rotation_from_yz_axis(gz, rv3d->twmat[i_ortho_a], rv3d->twmat[i]);
155
156 RNA_float_set_array(&gzop->ptr, "orient_matrix", &tbounds.axis[0][0]);
157 RNA_enum_set(&gzop->ptr, "orient_type", orient_slot->type);
158
159 RNA_enum_set(&gzop->ptr, "orient_axis", i_ortho_b);
160 RNA_enum_set(&gzop->ptr, "orient_axis_ortho", i_ortho_a);
161
162 mul_v3_fl(gz->matrix_basis[0], 0.5f);
163 mul_v3_fl(gz->matrix_basis[1], 6.0f);
164 }
165 }
166
167 for (int i = 0; i < 4; i++) {
168 wmGizmo *gz = xgzgroup->gizmo_view[i];
170 }
171 }
172}
173
175 wmGizmoGroup *gzgroup,
176 wmMsgBus *mbus)
177{
178 Scene *scene = CTX_data_scene(C);
179 bScreen *screen = CTX_wm_screen(C);
180 ScrArea *area = CTX_wm_area(C);
181 ARegion *region = CTX_wm_region(C);
183 gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_shear);
184}
185
187{
188 XFormShearWidgetGroup *xgzgroup = static_cast<XFormShearWidgetGroup *>(gzgroup->customdata);
190 {
191 Scene *scene = CTX_data_scene(C);
192 /* Shear is like rotate, use the rotate setting. */
194 scene, SCE_ORIENT_ROTATE);
195 switch (orient_slot->type) {
196 case V3D_ORIENT_VIEW: {
197 float viewinv_m3[3][3];
198 copy_m3_m4(viewinv_m3, rv3d->viewinv);
199 if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
200 /* Take care calling refresh from draw_prepare,
201 * this should be OK because it's only adjusting the cage orientation. */
203 }
204 break;
205 }
206 }
207 }
208
209 for (int i = 0; i < 4; i++) {
210 const float outer_thin = 0.3f;
211 const float outer_offset = 1.0f / 0.3f;
212 wmGizmo *gz = xgzgroup->gizmo_view[i];
214 gz, rv3d->viewinv[(i + 1) % 2], rv3d->viewinv[i % 2]);
215 if (i >= 2) {
216 negate_v3(gz->matrix_basis[1]);
217 negate_v3(gz->matrix_basis[2]);
218 }
219
220 /* No need for depth with view aligned gizmos. */
221 mul_v3_fl(gz->matrix_basis[0], 0.0f);
222 mul_v3_fl(gz->matrix_basis[1], 20.0f + ((1.0f / outer_thin) * 1.8f));
223 mul_v3_fl(gz->matrix_basis[2], outer_thin);
225 gz->matrix_offset[3][2] = outer_offset;
226 }
227
228 /* Basic ordering for drawing only. */
229 {
230 LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
231 /* Since we have two pairs of each axis,
232 * bias the values so gizmos that are orthogonal to the view get priority.
233 * This means we never default to shearing along
234 * the view axis in the case of an overlap. */
235 float axis_order[3], axis_bias[3];
236 copy_v3_v3(axis_order, gz->matrix_basis[2]);
237 copy_v3_v3(axis_bias, gz->matrix_basis[1]);
238 if (dot_v3v3(axis_bias, rv3d->viewinv[2]) < 0.0f) {
239 negate_v3(axis_bias);
240 }
241 madd_v3_v3fl(axis_order, axis_bias, 0.01f);
242 gz->temp.f = dot_v3v3(rv3d->viewinv[2], axis_order);
243 }
245 }
246}
247
266
268
269} // namespace blender::ed::transform
bScreen * CTX_wm_screen(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
TransformOrientationSlot * BKE_scene_orientation_slot_get(Scene *scene, int slot_index)
Definition scene.cc:2400
TransformOrientationSlot * BKE_scene_orientation_slot_get_from_flag(Scene *scene, int flag)
Definition scene.cc:2408
int BKE_scene_orientation_slot_get_index(const TransformOrientationSlot *orient_slot)
Definition scene.cc:2432
#define LISTBASE_FOREACH(type, var, list)
void void BLI_listbase_sort(ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void copy_m3_m4(float m1[3][3], const float m2[4][4])
bool equals_m3m3(const float mat1[3][3], const float mat2[3][3])
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
MINLINE void negate_v3(float r[3])
MINLINE void copy_v3_fl(float r[3], float f)
@ SCE_ORIENT_ROTATE
@ RGN_TYPE_WINDOW
@ SPACE_VIEW3D
@ V3D_GIZMO_HIDE_TOOL
@ V3D_GIZMO_HIDE
@ V3D_ORIENT_VIEW
@ ED_GIZMO_ARROW_STYLE_BOX
bool ED_gizmo_poll_or_unlink_delayed_from_tool(const bContext *C, wmGizmoGroupType *gzgt)
#define C
Definition RandGen.cpp:29
void UI_GetThemeColor3fv(int colorid, float col[3])
@ TH_AXIS_X
@ WM_GIZMO_HIDDEN
@ WM_GIZMO_MOVE_CURSOR
@ WM_GIZMO_DRAW_OFFSET_SCALE
@ WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE
@ WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP
@ WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK
@ WM_GIZMOGROUPTYPE_3D
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup, wmMsgBus *mbus, Scene *scene, bScreen *screen, ScrArea *area, ARegion *region, void(*type_fn)(wmGizmoGroupType *))
static void WIDGETGROUP_xform_shear_setup(const bContext *, wmGizmoGroup *gzgroup)
void gizmo_prepare_mat(const bContext *C, RegionView3D *rv3d, const TransformBounds *tbounds)
void VIEW3D_GGT_xform_shear(wmGizmoGroupType *gzgt)
static void WIDGETGROUP_xform_shear_refresh(const bContext *C, wmGizmoGroup *gzgroup)
static void WIDGETGROUP_xform_shear_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
static void WIDGETGROUP_xform_shear_message_subscribe(const bContext *C, wmGizmoGroup *gzgroup, wmMsgBus *mbus)
int calc_gizmo_stats(const bContext *C, const TransformCalcParams *params, TransformBounds *tbounds, RegionView3D *rv3d)
static bool WIDGETGROUP_xform_shear_poll(const bContext *C, wmGizmoGroupType *gzgt)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
void * regiondata
float twmat[4][4]
float viewinv[4][4]
struct blender::ed::transform::XFormShearWidgetGroup::@254274204305326036346342213015001121122112004012 prev
wmGizmoGroupFnSetupKeymap setup_keymap
wmGizmoGroupFnMsgBusSubscribe message_subscribe
wmGizmoGroupFnRefresh refresh
wmGizmoGroupFnInit setup
const char * idname
wmGizmoMapType_Params gzmap_params
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupFnPoll poll
wmGizmoGroupFnDrawPrepare draw_prepare
float matrix_basis[4][4]
float matrix_offset[4][4]
float color[4]
PointerRNA * ptr
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4238
wmGizmoOpElem * WM_gizmo_operator_get(wmGizmo *gz, int part_index)
Definition wm_gizmo.cc:195
void WM_gizmo_set_matrix_rotation_from_yz_axis(wmGizmo *gz, const float y_axis[3], const float z_axis[3])
Definition wm_gizmo.cc:281
wmGizmo * WM_gizmo_new_ptr(const wmGizmoType *gzt, wmGizmoGroup *gzgroup, PointerRNA *properties)
Definition wm_gizmo.cc:85
void WM_gizmo_set_matrix_location(wmGizmo *gz, const float origin[3])
Definition wm_gizmo.cc:287
void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
Definition wm_gizmo.cc:307
PointerRNA * WM_gizmo_operator_set(wmGizmo *gz, int part_index, wmOperatorType *ot, IDProperty *properties)
Definition wm_gizmo.cc:203
int WM_gizmo_cmp_temp_fl_reverse(const void *gz_a_ptr, const void *gz_b_ptr)
wmKeyMap * WM_gizmogroup_setup_keymap_generic_maybe_drag(const wmGizmoGroupType *, wmKeyConfig *kc)
const wmGizmoType * WM_gizmotype_find(const StringRef idname, bool quiet)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)