Blender V4.3
uvedit_buttons.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstdio>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "DNA_object_types.h"
15#include "DNA_scene_types.h"
16#include "DNA_screen_types.h"
17#include "DNA_space_types.h"
18
19#include "BLI_blenlib.h"
20#include "BLI_math_vector.h"
21#include "BLI_utildefines.h"
22
23#include "BLT_translation.hh"
24
25#include "BKE_context.hh"
26#include "BKE_customdata.hh"
27#include "BKE_editmesh.hh"
28#include "BKE_layer.hh"
29#include "BKE_screen.hh"
30
31#include "DEG_depsgraph.hh"
32
33#include "ED_image.hh"
34#include "ED_uvedit.hh"
35
36#include "UI_interface.hh"
37
38#include "WM_api.hh"
39#include "WM_types.hh"
40
41using blender::Span;
42using blender::Vector;
43
44#define B_UVEDIT_VERTEX 3
45
46/* UV Utilities */
47
48static int uvedit_center(Scene *scene, const Span<Object *> objects, float center[2])
49{
50 BMFace *f;
51 BMLoop *l;
52 BMIter iter, liter;
53 float *luv;
54 int tot = 0;
55
56 zero_v2(center);
57
58 for (Object *obedit : objects) {
60 const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
61
62 BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
63 if (!uvedit_face_visible_test(scene, f)) {
64 continue;
65 }
66
67 BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
68 if (uvedit_uv_select_test(scene, l, offsets)) {
69 luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
70 add_v2_v2(center, luv);
71 tot++;
72 }
73 }
74 }
75 }
76
77 if (tot > 0) {
78 center[0] /= tot;
79 center[1] /= tot;
80 }
81
82 return tot;
83}
84
85static void uvedit_translate(Scene *scene, const Span<Object *> objects, const float delta[2])
86{
87 BMFace *f;
88 BMLoop *l;
89 BMIter iter, liter;
90 float *luv;
91
92 for (Object *obedit : objects) {
94
95 const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
96
97 BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
98 if (!uvedit_face_visible_test(scene, f)) {
99 continue;
100 }
101
102 BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
103 if (uvedit_uv_select_test(scene, l, offsets)) {
104 luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
105 add_v2_v2(luv, delta);
106 }
107 }
108 }
109 }
110}
111
112/* Button Functions, using an evil static variable */
113
114static float uvedit_old_center[2];
115
116static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
117{
119 Scene *scene = CTX_data_scene(C);
120 float center[2];
121 int imx, imy, step, digits;
123 scene, CTX_data_view_layer(C), CTX_wm_view3d(C));
124
125 ED_space_image_get_size(sima, &imx, &imy);
126
127 if (uvedit_center(scene, objects, center)) {
128 float range_xy[2][2] = {
129 {-10.0f, 10.0f},
130 {-10.0f, 10.0f},
131 };
132
134
135 /* expand UI range by center */
136 CLAMP_MAX(range_xy[0][0], uvedit_old_center[0]);
137 CLAMP_MIN(range_xy[0][1], uvedit_old_center[0]);
138 CLAMP_MAX(range_xy[1][0], uvedit_old_center[1]);
139 CLAMP_MIN(range_xy[1][1], uvedit_old_center[1]);
140
141 if (!(sima->flag & SI_COORDFLOATS)) {
142 uvedit_old_center[0] *= imx;
143 uvedit_old_center[1] *= imy;
144
145 mul_v2_fl(range_xy[0], imx);
146 mul_v2_fl(range_xy[1], imy);
147 }
148
149 if (sima->flag & SI_COORDFLOATS) {
150 step = 1;
151 digits = 3;
152 }
153 else {
154 step = 100;
155 digits = 2;
156 }
157
158 uiBut *but;
159
160 int y = 0;
162 but = uiDefButF(block,
165 IFACE_("X:"),
166 0,
167 y -= UI_UNIT_Y,
168 200,
169 UI_UNIT_Y,
171 UNPACK2(range_xy[0]),
172 "");
174 UI_but_number_precision_set(but, digits);
175 but = uiDefButF(block,
178 IFACE_("Y:"),
179 0,
180 y -= UI_UNIT_Y,
181 200,
182 UI_UNIT_Y,
184 UNPACK2(range_xy[1]),
185 "");
187 UI_but_number_precision_set(but, digits);
188 UI_block_align_end(block);
189 }
190}
191
192static void do_uvedit_vertex(bContext *C, void * /*arg*/, int event)
193{
195 Scene *scene = CTX_data_scene(C);
196 float center[2], delta[2];
197 int imx, imy;
198
199 if (event != B_UVEDIT_VERTEX) {
200 return;
201 }
202
204 scene, CTX_data_view_layer(C), CTX_wm_view3d(C));
205
206 ED_space_image_get_size(sima, &imx, &imy);
207 uvedit_center(scene, objects, center);
208
209 if (sima->flag & SI_COORDFLOATS) {
210 delta[0] = uvedit_old_center[0] - center[0];
211 delta[1] = uvedit_old_center[1] - center[1];
212 }
213 else {
214 delta[0] = uvedit_old_center[0] / imx - center[0];
215 delta[1] = uvedit_old_center[1] / imy - center[1];
216 }
217
218 uvedit_translate(scene, objects, delta);
219
221 for (Object *obedit : objects) {
222 DEG_id_tag_update((ID *)obedit->data, ID_RECALC_GEOMETRY);
223 }
224}
225
226/* Panels */
227
228static bool image_panel_uv_poll(const bContext *C, PanelType * /*pt*/)
229{
231 if (sima->mode != SI_MODE_UV) {
232 return false;
233 }
234 Object *obedit = CTX_data_edit_object(C);
235 return ED_uvedit_test(obedit);
236}
237
238static void image_panel_uv(const bContext *C, Panel *panel)
239{
240 uiBlock *block;
241
242 block = uiLayoutAbsoluteBlock(panel->layout);
244
245 uvedit_vertex_buttons(C, block);
246}
247
249{
250 PanelType *pt = MEM_cnew<PanelType>(__func__);
251
252 STRNCPY(pt->idname, "IMAGE_PT_uv");
253 STRNCPY(pt->label, N_("UV Vertex")); /* XXX C panels unavailable through RNA bpy.types! */
254 /* Could be 'Item' matching 3D view, avoid new tab for two buttons. */
255 STRNCPY(pt->category, "Image");
256 pt->draw = image_panel_uv;
258 BLI_addtail(&art->paneltypes, pt);
259}
SpaceImage * CTX_wm_space_image(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:63
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void zero_v2(float r[2])
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define UNPACK2(a)
#define CLAMP_MAX(a, c)
#define CLAMP_MIN(a, b)
#define IFACE_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
Object is a sort of wrapper for general info.
@ SI_COORDFLOATS
@ SI_MODE_UV
void ED_space_image_get_size(SpaceImage *sima, int *r_width, int *r_height)
bool ED_uvedit_test(Object *obedit)
Definition uvedit_ops.cc:69
bool uvedit_face_visible_test(const Scene *scene, BMFace *efa)
bool uvedit_uv_select_test(const Scene *scene, BMLoop *l, BMUVOffsets offsets)
Read Guarded memory(de)allocation.
#define UI_UNIT_Y
void UI_but_number_step_size_set(uiBut *but, float step_size)
void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg)
uiBut * uiDefButF(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, float *poin, float min, float max, const char *tip)
void UI_block_align_begin(uiBlock *block)
void UI_but_number_precision_set(uiBut *but, float precision)
uiBlock * uiLayoutAbsoluteBlock(uiLayout *layout)
@ UI_BTYPE_NUM
void UI_block_align_end(uiBlock *block)
#define NC_IMAGE
Definition WM_types.hh:351
#define BM_ELEM_CD_GET_FLOAT_P(ele, offset)
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_FACE
ATTR_WARN_UNUSED_RESULT const BMLoop * l
BMUVOffsets BM_uv_map_get_offsets(const BMesh *bm)
ListBase paneltypes
Definition DNA_ID.h:413
void(* draw)(const bContext *C, Panel *panel)
char idname[BKE_ST_MAXNAME]
bool(* poll)(const bContext *C, PanelType *pt)
char category[BKE_ST_MAXNAME]
char label[BKE_ST_MAXNAME]
struct uiLayout * layout
struct Image * image
void ED_uvedit_buttons_register(ARegionType *art)
static void uvedit_translate(Scene *scene, const Span< Object * > objects, const float delta[2])
static bool image_panel_uv_poll(const bContext *C, PanelType *)
static void do_uvedit_vertex(bContext *C, void *, int event)
static float uvedit_old_center[2]
static int uvedit_center(Scene *scene, const Span< Object * > objects, float center[2])
static void image_panel_uv(const bContext *C, Panel *panel)
static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
#define B_UVEDIT_VERTEX
#define N_(msgid)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)