diff options
Diffstat (limited to 'uv_magic_uv/op/texture_projection.py')
-rw-r--r-- | uv_magic_uv/op/texture_projection.py | 245 |
1 files changed, 172 insertions, 73 deletions
diff --git a/uv_magic_uv/op/texture_projection.py b/uv_magic_uv/op/texture_projection.py index 77a81aa0..bdf0ad67 100644 --- a/uv_magic_uv/op/texture_projection.py +++ b/uv_magic_uv/op/texture_projection.py @@ -20,8 +20,8 @@ __author__ = "Nutti <nutti.metro@gmail.com>" __status__ = "production" -__version__ = "5.1" -__date__ = "24 Feb 2018" +__version__ = "5.2" +__date__ = "17 Nov 2018" from collections import namedtuple @@ -30,14 +30,32 @@ import bgl import bmesh import mathutils from bpy_extras import view3d_utils +from bpy.props import ( + BoolProperty, + EnumProperty, + FloatProperty, +) from .. import common +__all__ = [ + 'Properties', + 'Operator', + 'OperatorProject', +] + + Rect = namedtuple('Rect', 'x0 y0 x1 y1') Rect2 = namedtuple('Rect2', 'x y width height') +def get_loaded_texture_name(_, __): + items = [(key, key, "") for key in bpy.data.images.keys()] + items.append(("None", "None", "")) + return items + + def get_canvas(context, magnitude): """ Get canvas to be renderred texture @@ -47,20 +65,20 @@ def get_canvas(context, magnitude): 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 + canvas_w = region_w - prefs.texture_projection_canvas_padding[0] * 2.0 + canvas_h = region_h - prefs.texture_projection_canvas_padding[1] * 2.0 - img = bpy.data.images[sc.muv_texproj_tex_image] + img = bpy.data.images[sc.muv_texture_projection_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: + if sc.muv_texture_projection_adjust_window: ratio_x = canvas_w / tex_w ratio_y = canvas_h / tex_h - if sc.muv_texproj_apply_tex_aspect: + if sc.muv_texture_projection_apply_tex_aspect: ratio = ratio_y if ratio_x > ratio_y else ratio_x len_x = ratio * tex_w len_y = ratio * tex_h @@ -68,7 +86,7 @@ def get_canvas(context, magnitude): len_x = canvas_w len_y = canvas_h else: - if sc.muv_texproj_apply_tex_aspect: + if sc.muv_texture_projection_apply_tex_aspect: len_x = tex_w * magnitude len_y = tex_h * magnitude else: @@ -104,44 +122,149 @@ def region_to_canvas(rg_vec, canvas): return cv_vec -class MUV_TexProjRenderer(bpy.types.Operator): +def is_valid_context(context): + obj = context.object + + # only edit mode is allowed to execute + if obj is None: + return False + if obj.type != 'MESH': + return False + if context.object.mode != 'EDIT': + return False + + # only 'VIEW_3D' space is allowed to execute + for space in context.area.spaces: + if space.type == 'VIEW_3D': + break + else: + return False + + return True + + +class Properties: + @classmethod + def init_props(cls, scene): + def get_func(_): + return Operator.is_running(bpy.context) + + def set_func(_, __): + pass + + def update_func(_, __): + bpy.ops.uv.muv_texture_projection_operator('INVOKE_REGION_WIN') + + scene.muv_texture_projection_enabled = BoolProperty( + name="Texture Projection Enabled", + description="Texture Projection is enabled", + default=False + ) + scene.muv_texture_projection_enable = BoolProperty( + name="Texture Projection Enabled", + description="Texture Projection is enabled", + default=False, + get=get_func, + set=set_func, + update=update_func + ) + scene.muv_texture_projection_tex_magnitude = FloatProperty( + name="Magnitude", + description="Texture Magnitude", + default=0.5, + min=0.0, + max=100.0 + ) + scene.muv_texture_projection_tex_image = EnumProperty( + name="Image", + description="Texture Image", + items=get_loaded_texture_name + ) + scene.muv_texture_projection_tex_transparency = FloatProperty( + name="Transparency", + description="Texture Transparency", + default=0.2, + min=0.0, + max=1.0 + ) + scene.muv_texture_projection_adjust_window = BoolProperty( + name="Adjust Window", + description="Size of renderered texture is fitted to window", + default=True + ) + scene.muv_texture_projection_apply_tex_aspect = BoolProperty( + name="Texture Aspect Ratio", + description="Apply Texture Aspect ratio to displayed texture", + default=True + ) + scene.muv_texture_projection_assign_uvmap = BoolProperty( + name="Assign UVMap", + description="Assign UVMap when no UVmaps are available", + default=True + ) + + @classmethod + def del_props(cls, scene): + del scene.muv_texture_projection_enabled + del scene.muv_texture_projection_tex_magnitude + del scene.muv_texture_projection_tex_image + del scene.muv_texture_projection_tex_transparency + del scene.muv_texture_projection_adjust_window + del scene.muv_texture_projection_apply_tex_aspect + del scene.muv_texture_projection_assign_uvmap + + +class Operator(bpy.types.Operator): """ - Operation class: Render selected texture - No operation (only rendering texture) + Operation class: Texture Projection + Render texture """ - bl_idname = "uv.muv_texproj_renderer" + bl_idname = "uv.muv_texture_projection_operator" 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, + @classmethod + def poll(cls, context): + # we can not get area/space/region from console + if common.is_console_mode(): + return False + return is_valid_context(context) + + @classmethod + def is_running(cls, _): + return 1 if cls.__handle else 0 + + @classmethod + def handle_add(cls, obj, context): + cls.__handle = bpy.types.SpaceView3D.draw_handler_add( + Operator.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 + @classmethod + def handle_remove(cls): + if cls.__handle is not None: + bpy.types.SpaceView3D.draw_handler_remove(cls.__handle, 'WINDOW') + cls.__handle = None - @staticmethod - def draw_texture(_, context): + @classmethod + def draw_texture(cls, _, context): sc = context.scene + if not cls.is_running(context): + return + # no textures are selected - if sc.muv_texproj_tex_image == "None": + if sc.muv_texture_projection_tex_image == "None": return # get texture to be renderred - img = bpy.data.images[sc.muv_texproj_tex_image] + img = bpy.data.images[sc.muv_texture_projection_tex_image] # setup rendering region - rect = get_canvas(context, sc.muv_texproj_tex_magnitude) + rect = get_canvas(context, sc.muv_texture_projection_tex_magnitude) positions = [ [rect.x0, rect.y0], [rect.x0, rect.y1], @@ -170,74 +293,48 @@ class MUV_TexProjRenderer(bpy.types.Operator): # render texture bgl.glBegin(bgl.GL_QUADS) - bgl.glColor4f(1.0, 1.0, 1.0, sc.muv_texproj_tex_transparency) + bgl.glColor4f(1.0, 1.0, 1.0, + sc.muv_texture_projection_tex_transparency) for (v1, v2), (u, v) in zip(positions, tex_coords): bgl.glTexCoord2f(u, v) bgl.glVertex2f(v1, v2) bgl.glEnd() + def invoke(self, context, _): + if not Operator.is_running(context): + Operator.handle_add(self, context) + else: + Operator.handle_remove() -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): +class OperatorProject(bpy.types.Operator): """ Operation class: Project texture """ - bl_idname = "uv.muv_texproj_project" + bl_idname = "uv.muv_texture_projection_operator_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" + # we can not get area/space/region from console + if common.is_console_mode(): + return True + if not Operator.is_running(context): + return False + return is_valid_context(context) def execute(self, context): sc = context.scene - if sc.muv_texproj_tex_image == "None": + if sc.muv_texture_projection_tex_image == "None": self.report({'WARNING'}, "No textures are selected") return {'CANCELLED'} @@ -253,7 +350,7 @@ class MUV_TexProjProject(bpy.types.Operator): # get UV and texture layer if not bm.loops.layers.uv: - if sc.muv_texproj_assign_uvmap: + if sc.muv_texture_projection_assign_uvmap: bm.loops.layers.uv.new() else: self.report({'WARNING'}, @@ -278,14 +375,16 @@ class MUV_TexProjProject(bpy.types.Operator): v_canvas = [ region_to_canvas( v, - get_canvas(bpy.context, sc.muv_texproj_tex_magnitude)) - for v in v_screen + get_canvas(bpy.context, + sc.muv_texture_projection_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] + f[tex_layer].image = \ + bpy.data.images[sc.muv_texture_projection_tex_image] for l in f.loops: l[uv_layer].uv = v_canvas[i].to_2d() i = i + 1 |