Blender V5.0
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
8
9#include <cstring>
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_object_types.h"
14#include "DNA_scene_types.h"
15#include "DNA_screen_types.h"
16#include "DNA_space_types.h"
17
18#include "BLI_listbase.h"
19#include "BLI_math_vector.h"
20#include "BLI_string_utf8.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"
38
39#include "WM_api.hh"
40#include "WM_types.hh"
41
42using blender::Span;
43using blender::Vector;
44
45#define B_UVEDIT_VERTEX 3
46
47/* UV Utilities */
48
49static int uvedit_center(Scene *scene, const Span<Object *> objects, float center[2])
50{
51 BMFace *f;
52 BMLoop *l;
53 BMIter iter, liter;
54 float *luv;
55 int tot = 0;
56
57 zero_v2(center);
58
59 for (Object *obedit : objects) {
61 const BMUVOffsets offsets = BM_uv_map_offsets_get(em->bm);
62
63 BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
64 if (!uvedit_face_visible_test(scene, f)) {
65 continue;
66 }
67
68 BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
69 if (uvedit_uv_select_test(scene, em->bm, l, offsets)) {
70 luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
71 add_v2_v2(center, luv);
72 tot++;
73 }
74 }
75 }
76 }
77
78 if (tot > 0) {
79 center[0] /= tot;
80 center[1] /= tot;
81 }
82
83 return tot;
84}
85
86static void uvedit_translate(Scene *scene, const Span<Object *> objects, const float delta[2])
87{
88 BMFace *f;
89 BMLoop *l;
90 BMIter iter, liter;
91 float *luv;
92
93 for (Object *obedit : objects) {
95
96 const BMUVOffsets offsets = BM_uv_map_offsets_get(em->bm);
97
98 BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
99 if (!uvedit_face_visible_test(scene, f)) {
100 continue;
101 }
102
103 BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
104 if (uvedit_uv_select_test(scene, em->bm, l, offsets)) {
105 luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
106 add_v2_v2(luv, delta);
107 }
108 }
109 }
110 }
111}
112
113/* Button Functions, using an evil static variable */
114
115static float uvedit_old_center[2];
116
117static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
118{
120 Scene *scene = CTX_data_scene(C);
121 float center[2];
122 int imx, imy, step, digits;
125
126 ED_space_image_get_size(sima, &imx, &imy);
127
128 if (uvedit_center(scene, objects, center)) {
129 float range_xy[2][2] = {
130 {-10.0f, 10.0f},
131 {-10.0f, 10.0f},
132 };
133
135
136 /* expand UI range by center */
137 CLAMP_MAX(range_xy[0][0], uvedit_old_center[0]);
138 CLAMP_MIN(range_xy[0][1], uvedit_old_center[0]);
139 CLAMP_MAX(range_xy[1][0], uvedit_old_center[1]);
140 CLAMP_MIN(range_xy[1][1], uvedit_old_center[1]);
141
142 if (!(sima->flag & SI_COORDFLOATS)) {
143 uvedit_old_center[0] *= imx;
144 uvedit_old_center[1] *= imy;
145
146 mul_v2_fl(range_xy[0], imx);
147 mul_v2_fl(range_xy[1], imy);
148 }
149
150 if (sima->flag & SI_COORDFLOATS) {
151 step = 1;
152 digits = 3;
153 }
154 else {
155 step = 100;
156 digits = 2;
157 }
158
159 uiBut *but;
160
161 int y = 0;
163 but = uiDefButF(block,
166 IFACE_("X:"),
167 0,
168 y -= UI_UNIT_Y,
169 200,
170 UI_UNIT_Y,
172 UNPACK2(range_xy[0]),
173 "");
175 UI_but_number_precision_set(but, digits);
176 but = uiDefButF(block,
179 IFACE_("Y:"),
180 0,
181 y -= UI_UNIT_Y,
182 200,
183 UI_UNIT_Y,
185 UNPACK2(range_xy[1]),
186 "");
188 UI_but_number_precision_set(but, digits);
189 UI_block_align_end(block);
190 }
191}
192
193static void do_uvedit_vertex(bContext *C, void * /*arg*/, int event)
194{
196 Scene *scene = CTX_data_scene(C);
197 float center[2], delta[2];
198 int imx, imy;
199
200 if (event != B_UVEDIT_VERTEX) {
201 return;
202 }
203
206
207 ED_space_image_get_size(sima, &imx, &imy);
208 uvedit_center(scene, objects, center);
209
210 if (sima->flag & SI_COORDFLOATS) {
211 delta[0] = uvedit_old_center[0] - center[0];
212 delta[1] = uvedit_old_center[1] - center[1];
213 }
214 else {
215 delta[0] = uvedit_old_center[0] / imx - center[0];
216 delta[1] = uvedit_old_center[1] / imy - center[1];
217 }
218
219 uvedit_translate(scene, objects, delta);
220
222 for (Object *obedit : objects) {
223 DEG_id_tag_update((ID *)obedit->data, ID_RECALC_GEOMETRY);
224 }
225}
226
227/* Panels */
228
229static bool image_panel_uv_poll(const bContext *C, PanelType * /*pt*/)
230{
232 if (sima->mode != SI_MODE_UV) {
233 return false;
234 }
235 Object *obedit = CTX_data_edit_object(C);
236 return ED_uvedit_test(obedit);
237}
238
239static void image_panel_uv(const bContext *C, Panel *panel)
240{
241 uiBlock *block;
242
243 block = panel->layout->absolute_block();
245
246 uvedit_vertex_buttons(C, block);
247}
248
250{
251 PanelType *pt = MEM_callocN<PanelType>(__func__);
252
253 STRNCPY_UTF8(pt->idname, "IMAGE_PT_uv");
254 STRNCPY_UTF8(pt->label, N_("UV Vertex")); /* XXX C panels unavailable through RNA bpy.types! */
255 /* Could be 'Item' matching 3D view, avoid new tab for two buttons. */
256 STRNCPY_UTF8(pt->category, "Image");
257 pt->draw = image_panel_uv;
259 BLI_addtail(&art->paneltypes, pt);
260}
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:61
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(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
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_UTF8(dst, src)
#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:1074
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:73
bool uvedit_uv_select_test(const Scene *scene, const BMesh *bm, const BMLoop *l, const BMUVOffsets &offsets)
bool uvedit_face_visible_test(const Scene *scene, const BMFace *efa)
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
uiBut * uiDefButF(uiBlock *block, ButType type, int retval, blender::StringRef str, int x, int y, short width, short height, float *poin, float min, float max, std::optional< blender::StringRef > tip)
#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)
void UI_block_align_begin(uiBlock *block)
void UI_but_number_precision_set(uiBut *but, float precision)
void UI_block_align_end(uiBlock *block)
#define NC_IMAGE
Definition WM_types.hh:384
#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_offsets_get(const BMesh *bm)
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
ListBase paneltypes
Definition DNA_ID.h:414
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
uiBlock * absolute_block()
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)