From fdc914d653d4cf9e8c6ad5ea3d71fdefb9529491 Mon Sep 17 00:00:00 2001 From: Nutti Date: Fri, 16 Feb 2018 21:04:36 +0900 Subject: Magic UV: Release v5.0 * Add features - Align UV Cursor - UV Cursor Location - Align UV - Smooth UV - UV Inspection - Select UV - Texture Wrap - UV Sculpt * Improve features - Copy/Paste UV: Add menu to UV/Image Editor - World Scale UV: Add information about Texel Density - UV Bounding Box: Add option "Bound" - Texture Projection: Add option "Assign UVMap" - UVW: Add option "Assign UVMap" * Improve UI * Fixed bugs * Optimization/Refactoring --- uv_magic_uv/op/texture_projection.py | 296 +++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 uv_magic_uv/op/texture_projection.py (limited to 'uv_magic_uv/op/texture_projection.py') diff --git a/uv_magic_uv/op/texture_projection.py b/uv_magic_uv/op/texture_projection.py new file mode 100644 index 00000000..9c2dc521 --- /dev/null +++ b/uv_magic_uv/op/texture_projection.py @@ -0,0 +1,296 @@ +# + +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +__author__ = "Nutti " +__status__ = "production" +__version__ = "5.0" +__date__ = "16 Feb 2018" + +from collections import namedtuple + +import bpy +import bgl +import bmesh +import mathutils +from bpy_extras import view3d_utils + +from .. import common + + +Rect = namedtuple('Rect', 'x0 y0 x1 y1') +Rect2 = namedtuple('Rect2', 'x y width height') + + +def get_canvas(context, magnitude): + """ + Get canvas to be renderred texture + """ + sc = context.scene + prefs = context.user_preferences.addons["uv_magic_uv"].preferences + + region_w = context.region.width + region_h = context.region.height + canvas_w = region_w - prefs.texproj_canvas_padding[0] * 2.0 + canvas_h = region_h - prefs.texproj_canvas_padding[1] * 2.0 + + img = bpy.data.images[sc.muv_texproj_tex_image] + tex_w = img.size[0] + tex_h = img.size[1] + + center_x = region_w * 0.5 + center_y = region_h * 0.5 + + if sc.muv_texproj_adjust_window: + ratio_x = canvas_w / tex_w + ratio_y = canvas_h / tex_h + if sc.muv_texproj_apply_tex_aspect: + ratio = ratio_y if ratio_x > ratio_y else ratio_x + len_x = ratio * tex_w + len_y = ratio * tex_h + else: + len_x = canvas_w + len_y = canvas_h + else: + if sc.muv_texproj_apply_tex_aspect: + len_x = tex_w * magnitude + len_y = tex_h * magnitude + else: + len_x = region_w * magnitude + len_y = region_h * magnitude + + x0 = int(center_x - len_x * 0.5) + y0 = int(center_y - len_y * 0.5) + x1 = int(center_x + len_x * 0.5) + y1 = int(center_y + len_y * 0.5) + + return Rect(x0, y0, x1, y1) + + +def rect_to_rect2(rect): + """ + Convert Rect1 to Rect2 + """ + + return Rect2(rect.x0, rect.y0, rect.x1 - rect.x0, rect.y1 - rect.y0) + + +def region_to_canvas(rg_vec, canvas): + """ + Convert screen region to canvas + """ + + cv_rect = rect_to_rect2(canvas) + cv_vec = mathutils.Vector() + cv_vec.x = (rg_vec.x - cv_rect.x) / cv_rect.width + cv_vec.y = (rg_vec.y - cv_rect.y) / cv_rect.height + + return cv_vec + + +class MUV_TexProjRenderer(bpy.types.Operator): + """ + Operation class: Render selected texture + No operation (only rendering texture) + """ + + bl_idname = "uv.muv_texproj_renderer" + bl_description = "Render selected texture" + bl_label = "Texture renderer" + + __handle = None + + @staticmethod + def handle_add(obj, context): + MUV_TexProjRenderer.__handle = bpy.types.SpaceView3D.draw_handler_add( + MUV_TexProjRenderer.draw_texture, + (obj, context), 'WINDOW', 'POST_PIXEL') + + @staticmethod + def handle_remove(): + if MUV_TexProjRenderer.__handle is not None: + bpy.types.SpaceView3D.draw_handler_remove( + MUV_TexProjRenderer.__handle, 'WINDOW') + MUV_TexProjRenderer.__handle = None + + @staticmethod + def draw_texture(_, context): + sc = context.scene + + # no textures are selected + if sc.muv_texproj_tex_image == "None": + return + + # get texture to be renderred + img = bpy.data.images[sc.muv_texproj_tex_image] + + # setup rendering region + rect = get_canvas(context, sc.muv_texproj_tex_magnitude) + positions = [ + [rect.x0, rect.y0], + [rect.x0, rect.y1], + [rect.x1, rect.y1], + [rect.x1, rect.y0] + ] + tex_coords = [ + [0.0, 0.0], + [0.0, 1.0], + [1.0, 1.0], + [1.0, 0.0] + ] + + # OpenGL configuration + bgl.glEnable(bgl.GL_BLEND) + bgl.glEnable(bgl.GL_TEXTURE_2D) + if img.bindcode: + bind = img.bindcode[0] + bgl.glBindTexture(bgl.GL_TEXTURE_2D, bind) + bgl.glTexParameteri( + bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR) + bgl.glTexParameteri( + bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR) + bgl.glTexEnvi( + bgl.GL_TEXTURE_ENV, bgl.GL_TEXTURE_ENV_MODE, bgl.GL_MODULATE) + + # render texture + bgl.glBegin(bgl.GL_QUADS) + bgl.glColor4f(1.0, 1.0, 1.0, sc.muv_texproj_tex_transparency) + for (v1, v2), (u, v) in zip(positions, tex_coords): + bgl.glTexCoord2f(u, v) + bgl.glVertex2f(v1, v2) + bgl.glEnd() + + +class MUV_TexProjStart(bpy.types.Operator): + """ + Operation class: Start Texture Projection + """ + + bl_idname = "uv.muv_texproj_start" + bl_label = "Start Texture Projection" + bl_description = "Start Texture Projection" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self, context): + props = context.scene.muv_props.texproj + if props.running is False: + MUV_TexProjRenderer.handle_add(self, context) + props.running = True + if context.area: + context.area.tag_redraw() + + return {'FINISHED'} + + +class MUV_TexProjStop(bpy.types.Operator): + """ + Operation class: Stop Texture Projection + """ + + bl_idname = "uv.muv_texproj_stop" + bl_label = "Stop Texture Projection" + bl_description = "Stop Texture Projection" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self, context): + props = context.scene.muv_props.texproj + if props.running is True: + MUV_TexProjRenderer.handle_remove() + props.running = False + if context.area: + context.area.tag_redraw() + + return {'FINISHED'} + + +class MUV_TexProjProject(bpy.types.Operator): + """ + Operation class: Project texture + """ + + bl_idname = "uv.muv_texproj_project" + bl_label = "Project Texture" + bl_description = "Project Texture" + bl_options = {'REGISTER', 'UNDO'} + + @classmethod + def poll(cls, context): + obj = context.active_object + return obj is not None and obj.type == "MESH" + + def execute(self, context): + sc = context.scene + + if sc.muv_texproj_tex_image == "None": + self.report({'WARNING'}, "No textures are selected") + return {'CANCELLED'} + + _, region, space = common.get_space( + 'VIEW_3D', 'WINDOW', 'VIEW_3D') + + # get faces to be texture projected + obj = context.active_object + world_mat = obj.matrix_world + bm = bmesh.from_edit_mesh(obj.data) + if common.check_version(2, 73, 0) >= 0: + bm.faces.ensure_lookup_table() + + # get UV and texture layer + if not bm.loops.layers.uv: + if sc.muv_texproj_assign_uvmap: + bm.loops.layers.uv.new() + else: + self.report({'WARNING'}, + "Object must have more than one UV map") + return {'CANCELLED'} + + uv_layer = bm.loops.layers.uv.verify() + tex_layer = bm.faces.layers.tex.verify() + + sel_faces = [f for f in bm.faces if f.select] + + # transform 3d space to screen region + v_screen = [ + view3d_utils.location_3d_to_region_2d( + region, + space.region_3d, + world_mat * l.vert.co) + for f in sel_faces for l in f.loops + ] + + # transform screen region to canvas + v_canvas = [ + region_to_canvas( + v, + get_canvas(bpy.context, sc.muv_texproj_tex_magnitude)) + for v in v_screen + ] + + # project texture to object + i = 0 + for f in sel_faces: + f[tex_layer].image = bpy.data.images[sc.muv_texproj_tex_image] + for l in f.loops: + l[uv_layer].uv = v_canvas[i].to_2d() + i = i + 1 + + common.redraw_all_areas() + bmesh.update_edit_mesh(obj.data) + + return {'FINISHED'} -- cgit v1.2.3 From cc56b808ca8338fe5d2b3ff1aba65429025cacf5 Mon Sep 17 00:00:00 2001 From: Nutti Date: Sat, 24 Feb 2018 11:37:05 +0900 Subject: Magic UV: Release v5.1 Fixed bugs --- uv_magic_uv/op/texture_projection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'uv_magic_uv/op/texture_projection.py') diff --git a/uv_magic_uv/op/texture_projection.py b/uv_magic_uv/op/texture_projection.py index 9c2dc521..77a81aa0 100644 --- a/uv_magic_uv/op/texture_projection.py +++ b/uv_magic_uv/op/texture_projection.py @@ -20,8 +20,8 @@ __author__ = "Nutti " __status__ = "production" -__version__ = "5.0" -__date__ = "16 Feb 2018" +__version__ = "5.1" +__date__ = "24 Feb 2018" from collections import namedtuple -- cgit v1.2.3