3 # ##### BEGIN GPL LICENSE BLOCK #####
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software Foundation,
17 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 # ##### END GPL LICENSE BLOCK #####
21 __author__
= "Nutti <nutti.metro@gmail.com>"
22 __status__
= "production"
24 __date__
= "24 Feb 2018"
26 from collections
import namedtuple
32 from bpy_extras
import view3d_utils
37 Rect
= namedtuple('Rect', 'x0 y0 x1 y1')
38 Rect2
= namedtuple('Rect2', 'x y width height')
41 def get_canvas(context
, magnitude
):
43 Get canvas to be renderred texture
46 prefs
= context
.user_preferences
.addons
["uv_magic_uv"].preferences
48 region_w
= context
.region
.width
49 region_h
= context
.region
.height
50 canvas_w
= region_w
- prefs
.texproj_canvas_padding
[0] * 2.0
51 canvas_h
= region_h
- prefs
.texproj_canvas_padding
[1] * 2.0
53 img
= bpy
.data
.images
[sc
.muv_texproj_tex_image
]
57 center_x
= region_w
* 0.5
58 center_y
= region_h
* 0.5
60 if sc
.muv_texproj_adjust_window
:
61 ratio_x
= canvas_w
/ tex_w
62 ratio_y
= canvas_h
/ tex_h
63 if sc
.muv_texproj_apply_tex_aspect
:
64 ratio
= ratio_y
if ratio_x
> ratio_y
else ratio_x
71 if sc
.muv_texproj_apply_tex_aspect
:
72 len_x
= tex_w
* magnitude
73 len_y
= tex_h
* magnitude
75 len_x
= region_w
* magnitude
76 len_y
= region_h
* magnitude
78 x0
= int(center_x
- len_x
* 0.5)
79 y0
= int(center_y
- len_y
* 0.5)
80 x1
= int(center_x
+ len_x
* 0.5)
81 y1
= int(center_y
+ len_y
* 0.5)
83 return Rect(x0
, y0
, x1
, y1
)
86 def rect_to_rect2(rect
):
88 Convert Rect1 to Rect2
91 return Rect2(rect
.x0
, rect
.y0
, rect
.x1
- rect
.x0
, rect
.y1
- rect
.y0
)
94 def region_to_canvas(rg_vec
, canvas
):
96 Convert screen region to canvas
99 cv_rect
= rect_to_rect2(canvas
)
100 cv_vec
= mathutils
.Vector()
101 cv_vec
.x
= (rg_vec
.x
- cv_rect
.x
) / cv_rect
.width
102 cv_vec
.y
= (rg_vec
.y
- cv_rect
.y
) / cv_rect
.height
107 class MUV_TexProjRenderer(bpy
.types
.Operator
):
109 Operation class: Render selected texture
110 No operation (only rendering texture)
113 bl_idname
= "uv.muv_texproj_renderer"
114 bl_description
= "Render selected texture"
115 bl_label
= "Texture renderer"
120 def handle_add(obj
, context
):
121 MUV_TexProjRenderer
.__handle
= bpy
.types
.SpaceView3D
.draw_handler_add(
122 MUV_TexProjRenderer
.draw_texture
,
123 (obj
, context
), 'WINDOW', 'POST_PIXEL')
127 if MUV_TexProjRenderer
.__handle
is not None:
128 bpy
.types
.SpaceView3D
.draw_handler_remove(
129 MUV_TexProjRenderer
.__handle
, 'WINDOW')
130 MUV_TexProjRenderer
.__handle
= None
133 def draw_texture(_
, context
):
136 # no textures are selected
137 if sc
.muv_texproj_tex_image
== "None":
140 # get texture to be renderred
141 img
= bpy
.data
.images
[sc
.muv_texproj_tex_image
]
143 # setup rendering region
144 rect
= get_canvas(context
, sc
.muv_texproj_tex_magnitude
)
158 # OpenGL configuration
159 bgl
.glEnable(bgl
.GL_BLEND
)
160 bgl
.glEnable(bgl
.GL_TEXTURE_2D
)
162 bind
= img
.bindcode
[0]
163 bgl
.glBindTexture(bgl
.GL_TEXTURE_2D
, bind
)
165 bgl
.GL_TEXTURE_2D
, bgl
.GL_TEXTURE_MIN_FILTER
, bgl
.GL_LINEAR
)
167 bgl
.GL_TEXTURE_2D
, bgl
.GL_TEXTURE_MAG_FILTER
, bgl
.GL_LINEAR
)
169 bgl
.GL_TEXTURE_ENV
, bgl
.GL_TEXTURE_ENV_MODE
, bgl
.GL_MODULATE
)
172 bgl
.glBegin(bgl
.GL_QUADS
)
173 bgl
.glColor4f(1.0, 1.0, 1.0, sc
.muv_texproj_tex_transparency
)
174 for (v1
, v2
), (u
, v
) in zip(positions
, tex_coords
):
175 bgl
.glTexCoord2f(u
, v
)
176 bgl
.glVertex2f(v1
, v2
)
180 class MUV_TexProjStart(bpy
.types
.Operator
):
182 Operation class: Start Texture Projection
185 bl_idname
= "uv.muv_texproj_start"
186 bl_label
= "Start Texture Projection"
187 bl_description
= "Start Texture Projection"
188 bl_options
= {'REGISTER', 'UNDO'}
190 def execute(self
, context
):
191 props
= context
.scene
.muv_props
.texproj
192 if props
.running
is False:
193 MUV_TexProjRenderer
.handle_add(self
, context
)
196 context
.area
.tag_redraw()
201 class MUV_TexProjStop(bpy
.types
.Operator
):
203 Operation class: Stop Texture Projection
206 bl_idname
= "uv.muv_texproj_stop"
207 bl_label
= "Stop Texture Projection"
208 bl_description
= "Stop Texture Projection"
209 bl_options
= {'REGISTER', 'UNDO'}
211 def execute(self
, context
):
212 props
= context
.scene
.muv_props
.texproj
213 if props
.running
is True:
214 MUV_TexProjRenderer
.handle_remove()
215 props
.running
= False
217 context
.area
.tag_redraw()
222 class MUV_TexProjProject(bpy
.types
.Operator
):
224 Operation class: Project texture
227 bl_idname
= "uv.muv_texproj_project"
228 bl_label
= "Project Texture"
229 bl_description
= "Project Texture"
230 bl_options
= {'REGISTER', 'UNDO'}
233 def poll(cls
, context
):
234 obj
= context
.active_object
235 return obj
is not None and obj
.type == "MESH"
237 def execute(self
, context
):
240 if sc
.muv_texproj_tex_image
== "None":
241 self
.report({'WARNING'}, "No textures are selected")
244 _
, region
, space
= common
.get_space(
245 'VIEW_3D', 'WINDOW', 'VIEW_3D')
247 # get faces to be texture projected
248 obj
= context
.active_object
249 world_mat
= obj
.matrix_world
250 bm
= bmesh
.from_edit_mesh(obj
.data
)
251 if common
.check_version(2, 73, 0) >= 0:
252 bm
.faces
.ensure_lookup_table()
254 # get UV and texture layer
255 if not bm
.loops
.layers
.uv
:
256 if sc
.muv_texproj_assign_uvmap
:
257 bm
.loops
.layers
.uv
.new()
259 self
.report({'WARNING'},
260 "Object must have more than one UV map")
263 uv_layer
= bm
.loops
.layers
.uv
.verify()
264 tex_layer
= bm
.faces
.layers
.tex
.verify()
266 sel_faces
= [f
for f
in bm
.faces
if f
.select
]
268 # transform 3d space to screen region
270 view3d_utils
.location_3d_to_region_2d(
273 world_mat
* l
.vert
.co
)
274 for f
in sel_faces
for l
in f
.loops
277 # transform screen region to canvas
281 get_canvas(bpy
.context
, sc
.muv_texproj_tex_magnitude
))
285 # project texture to object
288 f
[tex_layer
].image
= bpy
.data
.images
[sc
.muv_texproj_tex_image
]
290 l
[uv_layer
].uv
= v_canvas
[i
].to_2d()
293 common
.redraw_all_areas()
294 bmesh
.update_edit_mesh(obj
.data
)