1 # SPDX-License-Identifier: GPL-2.0-or-later
5 __author__
= "Nutti <nutti.metro@gmail.com>"
6 __status__
= "production"
8 __date__
= "6 Mar 2021"
11 from bpy
.props
import (
17 from ..utils
.bl_class_registry
import BlClassRegistry
18 from ..utils
.property_class_registry
import PropertyClassRegistry
21 def _is_valid_context(context
):
22 # Multiple objects editing mode is not supported in this feature.
23 objs
= common
.get_uv_editable_objects(context
)
27 # only edit mode is allowed to execute
28 if context
.object.mode
!= 'EDIT':
31 # only 'VIEW_3D' space is allowed to execute
32 if not common
.is_valid_space(context
, ['VIEW_3D']):
38 @PropertyClassRegistry()
40 idname
= "texture_wrap"
43 def init_props(cls
, scene
):
48 scene
.muv_props
.texture_wrap
= Props()
50 scene
.muv_texture_wrap_enabled
= BoolProperty(
52 description
="Texture Wrap is enabled",
55 scene
.muv_texture_wrap_set_and_refer
= BoolProperty(
57 description
="Refer and set UV",
60 scene
.muv_texture_wrap_selseq
= BoolProperty(
61 name
="Selection Sequence",
62 description
="Set UV sequentially",
67 def del_props(cls
, scene
):
68 del scene
.muv_props
.texture_wrap
69 del scene
.muv_texture_wrap_enabled
70 del scene
.muv_texture_wrap_set_and_refer
71 del scene
.muv_texture_wrap_selseq
75 class MUV_OT_TextureWrap_Refer(bpy
.types
.Operator
):
77 Operation class: Refer UV
80 bl_idname
= "uv.muv_texture_wrap_refer"
82 bl_description
= "Refer UV"
83 bl_options
= {'REGISTER', 'UNDO'}
86 def poll(cls
, context
):
87 # we can not get area/space/region from console
88 if common
.is_console_mode():
90 return _is_valid_context(context
)
92 def execute(self
, context
):
93 props
= context
.scene
.muv_props
.texture_wrap
95 objs
= common
.get_uv_editable_objects(context
)
96 # poll() method ensures that only one object is selected.
98 bm
= bmesh
.from_edit_mesh(obj
.data
)
99 if common
.check_version(2, 73, 0) >= 0:
100 bm
.faces
.ensure_lookup_table()
102 if not bm
.loops
.layers
.uv
:
103 self
.report({'WARNING'}, "Object must have more than one UV map")
106 sel_faces
= [f
for f
in bm
.faces
if f
.select
]
107 if len(sel_faces
) != 1:
108 self
.report({'WARNING'}, "Must select only one face")
111 props
.ref_face_index
= sel_faces
[0].index
118 class MUV_OT_TextureWrap_Set(bpy
.types
.Operator
):
120 Operation class: Set UV
123 bl_idname
= "uv.muv_texture_wrap_set"
125 bl_description
= "Set UV"
126 bl_options
= {'REGISTER', 'UNDO'}
129 def poll(cls
, context
):
130 # we can not get area/space/region from console
131 if common
.is_console_mode():
134 props
= sc
.muv_props
.texture_wrap
135 if not props
.ref_obj
:
137 return _is_valid_context(context
)
139 def execute(self
, context
):
141 props
= sc
.muv_props
.texture_wrap
143 objs
= common
.get_uv_editable_objects(context
)
144 # poll() method ensures that only one object is selected.
146 bm
= bmesh
.from_edit_mesh(obj
.data
)
147 if common
.check_version(2, 73, 0) >= 0:
148 bm
.faces
.ensure_lookup_table()
150 if not bm
.loops
.layers
.uv
:
151 self
.report({'WARNING'}, "Object must have more than one UV map")
153 uv_layer
= bm
.loops
.layers
.uv
.verify()
155 if sc
.muv_texture_wrap_selseq
:
157 for hist
in bm
.select_history
:
158 if isinstance(hist
, bmesh
.types
.BMFace
) and hist
.select
:
159 sel_faces
.append(hist
)
161 self
.report({'WARNING'}, "Must select more than one face")
164 sel_faces
= [f
for f
in bm
.faces
if f
.select
]
165 if len(sel_faces
) != 1:
166 self
.report({'WARNING'}, "Must select only one face")
169 ref_face_index
= props
.ref_face_index
170 for face
in sel_faces
:
171 tgt_face_index
= face
.index
172 if ref_face_index
== tgt_face_index
:
173 self
.report({'WARNING'}, "Must select different face")
176 if props
.ref_obj
!= obj
:
177 self
.report({'WARNING'}, "Object must be same")
180 ref_face
= bm
.faces
[ref_face_index
]
181 tgt_face
= bm
.faces
[tgt_face_index
]
183 # get common vertices info
185 for sl
in ref_face
.loops
:
186 for dl
in tgt_face
.loops
:
187 if sl
.vert
== dl
.vert
:
188 info
= {"vert": sl
.vert
, "ref_loop": sl
,
190 common_verts
.append(info
)
193 if len(common_verts
) != 2:
194 self
.report({'WARNING'},
195 "2 vertices must be shared among faces")
198 # get reference other vertices info
200 for sl
in ref_face
.loops
:
201 for ci
in common_verts
:
202 if sl
.vert
== ci
["vert"]:
205 info
= {"vert": sl
.vert
, "loop": sl
}
206 ref_other_verts
.append(info
)
208 if not ref_other_verts
:
209 self
.report({'WARNING'}, "More than 1 vertex must be unshared")
214 cv0
= common_verts
[0]["vert"].co
215 cv1
= common_verts
[1]["vert"].co
216 cuv0
= common_verts
[0]["ref_loop"][uv_layer
].uv
217 cuv1
= common_verts
[1]["ref_loop"][uv_layer
].uv
218 ov0
= ref_other_verts
[0]["vert"].co
219 ouv0
= ref_other_verts
[0]["loop"][uv_layer
].uv
220 ref_info
["vert_vdiff"] = cv1
- cv0
221 ref_info
["uv_vdiff"] = cuv1
- cuv0
222 ref_info
["vert_hdiff"], _
= common
.diff_point_to_segment(
224 ref_info
["uv_hdiff"], _
= common
.diff_point_to_segment(
227 # get target other vertices info
229 for dl
in tgt_face
.loops
:
230 for ci
in common_verts
:
231 if dl
.vert
== ci
["vert"]:
234 info
= {"vert": dl
.vert
, "loop": dl
}
235 tgt_other_verts
.append(info
)
237 if not tgt_other_verts
:
238 self
.report({'WARNING'}, "More than 1 vertex must be unshared")
242 for info
in tgt_other_verts
:
243 cv0
= common_verts
[0]["vert"].co
244 cv1
= common_verts
[1]["vert"].co
245 cuv0
= common_verts
[0]["ref_loop"][uv_layer
].uv
247 info
["vert_hdiff"], x
= common
.diff_point_to_segment(
249 info
["vert_vdiff"] = x
- common_verts
[0]["vert"].co
252 fact_h
= -info
["vert_hdiff"].length
/ \
253 ref_info
["vert_hdiff"].length
254 fact_v
= info
["vert_vdiff"].length
/ \
255 ref_info
["vert_vdiff"].length
256 duv_h
= ref_info
["uv_hdiff"] * fact_h
257 duv_v
= ref_info
["uv_vdiff"] * fact_v
260 info
["target_uv"] = cuv0
+ duv_h
+ duv_v
262 # apply to common UVs
263 for info
in common_verts
:
264 info
["tgt_loop"][uv_layer
].uv
= \
265 info
["ref_loop"][uv_layer
].uv
.copy()
267 for info
in tgt_other_verts
:
268 info
["loop"][uv_layer
].uv
= info
["target_uv"]
270 common
.debug_print("===== Target Other Vertices =====")
271 common
.debug_print(tgt_other_verts
)
273 bmesh
.update_edit_mesh(obj
.data
)
275 ref_face_index
= tgt_face_index
277 if sc
.muv_texture_wrap_set_and_refer
:
278 props
.ref_face_index
= tgt_face_index