52 int cd_loop_uv_offset,
54 bool *r_search_abandoned);
58 const int cd_loop_uv_offset,
71 for (
const int64_t index : graph.index_range()) {
87 const int island_index)
96 return index - base_index;
108 if (index_v == -1 || index_w == -1) {
112 BLI_assert(0 <= index_v && index_v < graph->n);
113 BLI_assert(0 <= index_w && index_w < graph->n);
121 const int island_index,
125 for (
int i = 0;
i < g->
n;
i++) {
133 for (
int i = i0;
i < i1;
i++) {
153 for (
int island_index = 0; island_index < element_map->
total_islands; island_index++) {
154 offset.append(uv.size());
155 graph.append(
build_iso_graph(element_map, island_index, cd_loop_uv_offset));
164 uv.append(std::make_pair(luv[0], luv[1]));
172 const int cd_loop_uv_offset,
187 const std::pair<float, float> &source_uv =
uv_clipboard->uv[label[unique_uv]];
190 luv[0] = source_uv.first;
191 luv[1] = source_uv.second;
207 const int dest_island_index,
209 const int cd_loop_uv_offset,
211 bool *r_search_abandoned)
215 if (island_total_unique_uvs != graph_source->
n) {
218 r_label.
resize(island_total_unique_uvs);
222 int (*solution)[2] = (int (*)[2])
MEM_mallocN(graph_source->
n *
sizeof(*solution), __func__);
223 int solution_length = 0;
225 graph_source, graph_dest, solution, &solution_length, r_search_abandoned);
231 for (
int i = 0;
i < solution_length;
i++) {
232 int index_s = solution[
i][0];
233 int index_t = solution[
i][1];
234 BLI_assert(0 <= index_s && index_s < solution_length);
235 BLI_assert(0 <= index_t && index_t < solution_length);
236 r_label[index_t] = index_s;
246 const int dest_island_index,
247 const int cd_loop_uv_offset,
249 bool *r_search_abandoned)
251 for (
const int64_t source_island_index : graph.index_range()) {
254 graph[source_island_index],
259 const int island_total_unique_uvs =
261 const int island_offset = offset[source_island_index];
263 for (
int i = 0;
i < island_total_unique_uvs;
i++) {
264 r_label[
i] += island_offset;
284 scene, view_layer,
nullptr);
286 for (
Object *ob : objects) {
289 const bool use_seams =
false;
291 em->
bm, scene,
true,
false, use_seams,
true);
314 scene, view_layer,
nullptr);
316 bool changed_multi =
false;
317 int complicated_search = 0;
318 int total_search = 0;
319 for (
Object *ob : objects) {
322 const bool use_seams =
false;
326 em->
bm, scene,
true,
false, use_seams,
true);
328 if (!dest_element_map) {
332 bool changed =
false;
337 bool search_abandoned =
false;
339 dest_element_map,
i, cd_loop_uv_offset, label, &search_abandoned);
341 if (search_abandoned) {
342 complicated_search++;
347 uv_clipboard->write_uvs(dest_element_map,
i, cd_loop_uv_offset, label);
354 changed_multi =
true;
361 if (complicated_search) {
364 "Skipped %d of %d island(s), geometry was too complicated to detect a match",
375 ot->name =
"Copy UVs";
376 ot->description =
"Copy selected UV vertices";
377 ot->idname =
"UV_OT_copy";
388 ot->name =
"Paste UVs";
389 ot->description =
"Paste selected UV vertices";
390 ot->idname =
"UV_OT_paste";
Scene * CTX_data_scene(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
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 BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void DEG_id_tag_update(ID *id, unsigned int flags)
UvElement * BM_uv_element_get(const UvElementMap *element_map, const BMLoop *l)
int BM_uv_element_get_unique_index(UvElementMap *element_map, UvElement *child)
void BM_uv_element_map_free(UvElementMap *element_map)
UvElementMap * BM_uv_element_map_create(BMesh *bm, const Scene *scene, bool uv_selected, bool use_winding, bool use_seams, bool do_islands)
bool ED_operator_uvedit(bContext *C)
#define BM_ELEM_CD_GET_FLOAT_P(ele, offset)
ATTR_WARN_UNUSED_RESULT const void * element
void add_edge(int v, int w)
void write_uvs(UvElementMap *element_map, int island_index, const int cd_loop_uv_offset, const blender::Vector< int > &label)
bool find_isomorphism(UvElementMap *dest_element_map, int island_index, int cd_loop_uv_offset, blender::Vector< int > &r_label, bool *r_search_abandoned)
void append(UvElementMap *element_map, const int cd_loop_uv_offset)
void resize(const int64_t new_size)
void * MEM_mallocN(size_t len, const char *str)
int * island_total_unique_uvs
struct ReportList * reports
void UV_OT_copy(wmOperatorType *ot)
static GraphISO * build_iso_graph(UvElementMap *element_map, const int island_index, int)
static wmOperatorStatus uv_copy_exec(bContext *C, wmOperator *)
static void add_iso_edge(GraphISO *graph, BMLoop *loop_v, BMLoop *loop_w, UvElementMap *element_map, int island_index)
static bool find_isomorphism(UvElementMap *dest, const int dest_island_index, GraphISO *graph_source, const int cd_loop_uv_offset, blender::Vector< int > &r_label, bool *r_search_abandoned)
static wmOperatorStatus uv_paste_exec(bContext *C, wmOperator *op)
static UV_ClipboardBuffer * uv_clipboard
static int iso_index_for_loop(const BMLoop *loop, UvElementMap *element_map, const int island_index)
void UV_OT_paste(wmOperatorType *ot)
bool ED_uvedit_clipboard_maximum_common_subgraph(GraphISO *g0_input, GraphISO *g1_input, int solution[][2], int *solution_length, bool *r_search_abandoned)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)