Skip to content
Snippets Groups Projects
space_view3d_paint_bprojection.py 68.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • Geo Kgeo's avatar
    Geo Kgeo committed
    bl_info = {
    
        "name": "BProjection",
    
    Geo Kgeo's avatar
    Geo Kgeo committed
        "description": "Help Clone tool",
        "author": "kgeogeo",
    
    Geo Kgeo's avatar
    Geo Kgeo committed
        "version": (2, 0),
    
        "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/3D_interaction/bprojection",
    
        "tracker_url":"https://developer.blender.org/T30521",
    
    Geo Kgeo's avatar
    Geo Kgeo committed
        "category": "Paint"}
    
    import bpy
    
    from bpy.app.handlers import persistent
    
    Geo Kgeo's avatar
    Geo Kgeo committed
    from bpy.types import Panel, Operator
    
    from bpy.props import IntProperty, FloatProperty, BoolProperty, IntVectorProperty, StringProperty, FloatVectorProperty, CollectionProperty
    
    Geo Kgeo's avatar
    Geo Kgeo committed
    from bpy_extras import view3d_utils
    import math
    
    Geo Kgeo's avatar
    Geo Kgeo committed
    
    
    BProjection_Empty    = 'Empty for BProjection'
    BProjection_Material = 'Material for BProjection'
    BProjection_Texture  = 'Texture for BProjection'
    
    # Main function for align the plan to view
    def align_to_view(context):
    
        global last_mouse
        last_mouse = Vector((0,0))
    
        ob = context.object
    
        rotation = em.custom_rotation
        scale = em.custom_scale
        z = em.custom_location.z
        pos = [em.custom_location.x, em.custom_location.y]
    
        width = reg.width
    
        height = reg.height
    
        sd = context.space_data
        r3d = sd.region_3d
    
        r3d.update()
        vr = r3d.view_rotation
        quat = mathutils.Quaternion((0.0, 0.0, 1.0), math.radians(float(rotation)))
        v = Vector((pos[0],pos[1],z))
        v.rotate(vr)
    
        em = bpy.data.objects[BProjection_Empty]
        img = bpy.data.textures[BProjection_Texture].image
        if img and img.size[1] != 0:
            prop = img.size[0]/img.size[1]
    
            em.scale = Vector((prop*scale[0], scale[0], 1))
        else:
            em.scale = Vector((prop*scale[0], scale[1], 1))
        pos_cur = em.location - sd.cursor_location
        rot_cur1 = em.rotation_euler.to_quaternion()
        em.location = v + ob.location
    
        em.rotation_euler = Quaternion.to_euler(vr*quat)
    
        if em.custom_c3d:
            if em.custom_old_scale != em.custom_scale:
    
                pos_cur = em.location - sd.cursor_location
    
            rot_cur2 = em.rotation_euler.to_quaternion()
            rot_cur1.invert()
            pos_cur.rotate(rot_cur1)
            pos_cur.rotate(rot_cur2)
            v = em.location - pos_cur
            sd.cursor_location =  v
    
    
            img = bpy.data.textures[BProjection_Texture].image
            em = bpy.data.objects[BProjection_Empty]
            ob = context.object
    
            face = ob.data.polygons
    
            for f,d in zip(face,uvdata):
                if f.select:
                    d.image = img
    
            align_to_view(context)
            ob.data.update()
    
    # Function to update the properties
    
        align_to_view(context)
    
    def find_uv(context):
        obj = context.object
        me = obj.data.vertices
        vg = obj.vertex_groups
        l=[]
    
        for face in obj.data.polygons:
            x=len(face.vertices)
            for vertex in face.vertices:
                if len(me[vertex].groups)>0:
                    for g in me[vertex].groups:
                        if vg[g.group].name == 'texture plane':
                            x-=1
    
            if x == 0:
                l.append([index_uv,len(face.vertices)])
            index_uv += len(face.vertices)
        return l
    
    # Function to update the scaleUV
    def update_UVScale(self, context):
        ob = context.object
        em = bpy.data.objects[BProjection_Empty]
        v = Vector((em.custom_offsetuv[0]/10 + 0.5, em.custom_offsetuv[1]/10 + 0.5))
        l = Vector((0.0,0.0))
        s = em.custom_scaleuv
    
        scale = s - os
        l = find_uv(context)
        for i,j in l:
            for t in range(j):
                d = context.object.data.uv_layers.active.data[i+t]
    
                d.uv.x = v.x - vres.x/os[0]*s[0]
                d.uv.y = v.y - vres.y/os[1]*s[1]
    
    
        applyimage(context)
    
    def update_PropUVScale(self, context):
        em = bpy.data.objects[BProjection_Empty]
        if em.custom_linkscaleuv:
            em.custom_scaleuv = [em.custom_propscaleuv,em.custom_propscaleuv]
    
    def update_LinkUVScale(self, context):
        em = bpy.data.objects[BProjection_Empty]
        if em.custom_linkscaleuv:
            em.custom_propscaleuv = em.custom_scaleuv.x
            update_PropUVScale(self, context)
        else:
    
    # Function to update the offsetUV
    def update_UVOffset(self, context):
        ob = context.object
        em = bpy.data.objects[BProjection_Empty]
        o = em.custom_offsetuv
    
        l = find_uv(context)
        for i,j in l:
            for t in range(j):
                d = context.object.data.uv_layers.active.data[i+t]
    
                d.uv = [d.uv[0] - oo[0]/10 + o[0]/10, d.uv[1] - oo[1]/10 + o[1]/10]
    
        em.custom_old_offsetuv = o
    
        applyimage(context)
    
    # Function to update the flip horizontal
    def update_FlipUVX(self, context):
        l = find_uv(context)
        for i,j in l:
            for t in range(j):
                d = context.object.data.uv_layers.active.data[i+t]
                x = d.uv.x
                d.uv.x = 1 - x
    
        applyimage(context)
    
    # Function to update the flip vertical
    def update_FlipUVY(self, context):
        l = find_uv(context)
        for i,j in l:
            for t in range(j):
                d = context.object.data.uv_layers.active.data[i+t]
                y = d.uv[1]
                d.uv[1] = 1 - y
    
        applyimage(context)
    
    # Function to update
    
        ob = context.object
        em = bpy.data.objects[BProjection_Empty]
        if em.custom_rotc3d:
            angle = em.custom_rotation - em.custom_old_rotation
            sd = context.space_data
    
            c = sd.cursor_location - ob.location
            e = bpy.data.objects[BProjection_Empty].location - ob.location
            vo = Vector((0.0, 0.0, 1.0))
            vo.rotate(vr)
            quat = mathutils.Quaternion(vo, math.radians(angle))
            v = e-c
            v.rotate(quat)
            vr.invert()
            v.rotate(vr)
            c.rotate(vr)
            em.custom_location = c + v
    
            align_to_view(context)
    
        em.custom_old_rotation = em.custom_rotation
    
    # Function to update scale
    
        ob = context.object
        em = bpy.data.objects[BProjection_Empty]
    
        if em.custom_scac3d:
            sd = context.space_data
            r3d =  sd.region_3d
            vr = r3d.view_rotation.copy()
            vr.invert()
            e = em.location - ob.location
            c = sd.cursor_location - ob.location
            ce = e - c
    
            s = em.custom_scale
            os = em.custom_old_scale
            c.rotate(vr)
            ce.rotate(vr)
    
            img = bpy.data.textures[BProjection_Texture].image
            if img and img.size[1] != 0:
                prop = img.size[0]/img.size[1]
            else: prop = 1
    
            v = Vector((s.x*ce.x/os.x, s.y*ce.y/os.y,0.0))
            em.custom_location = c + v
    
    
            align_to_view(context)
    
        em.custom_old_scale = em.custom_scale
    
    def update_PropScale(self, context):
        em = bpy.data.objects[BProjection_Empty]
        if em.custom_linkscale:
            em.custom_scale = [em.custom_propscale,em.custom_propscale]
    
    def update_LinkScale(self, context):
        em = bpy.data.objects[BProjection_Empty]
        if em.custom_linkscale:
            em.custom_propscale = em.custom_scale.x
            update_PropScale(self, context)
        else:
    
    
    def update_activeviewname(self, context):
        em = bpy.data.objects[BProjection_Empty]
        if self.custom_active:
            em.custom_active_view = self.custom_active_view
    
    
        km = context.window_manager.keyconfigs.default.keymaps['Image Paint']
        for kmi in km.keymap_items:
    
                if kmi.idname == 'paint.image_paint':
                    kmi.idname = 'paint.bp_paint'
            else:
                if kmi.idname == 'paint.bp_paint':
    
    class custom_props(bpy.types.PropertyGroup):
        custom_fnlevel = IntProperty(name="Fast navigate level", description="Increase or decrease the SubSurf level, decrease make navigation faster", default=0)
    
        custom_location = FloatVectorProperty(name="Location", description="Location of the plane",
                                              default=(1.0,0,-1.0),
    
                                              soft_min = -10,
                                              soft_max = 10,
                                              step=0.1,
                                              size=3)
    
        custom_rotation = FloatProperty(name="Rotation", description="Rotate the plane",
                                        min=-180, max=180, default=0)
    
        custom_scale = FloatVectorProperty(name="Scales", description="Scale the planes",
                                           default=(1.0, 1.0),
                                           subtype = 'XYZ',
                                           min = 0.1,
                                           max = 10,
                                           soft_min=0.1,
                                           soft_max=10,
                                           step=0.1,
                                           size=2)
        custom_propscale = FloatProperty(name="PropScale", description="Scale the Plane",
                                         default=1.0,
                                         min = 0.1,
                                         max = 10,
                                         soft_min=0.1,
                                         soft_max=10,
                                         step=0.1)
    
        custom_linkscale = BoolProperty(name="linkscale", default=True)
    
        # UV properties
        custom_scaleuv = FloatVectorProperty(name="ScaleUV", description="Scale the texture's UV",
                                                default=(1.0,1.0),min = 0.01, subtype = 'XYZ', size=2)
        custom_propscaleuv = FloatProperty(name="PropScaleUV", description="Scale the texture's UV",
    
        custom_offsetuv = FloatVectorProperty(name="OffsetUV", description="Decal the texture's UV",
    
                                                default=(0.0,0.0), subtype = 'XYZ', size=2)
    
        custom_linkscaleuv = BoolProperty(name="linkscaleUV", default=True)
        custom_flipuvx = BoolProperty(name="flipuvx", default=False)
        custom_flipuvy = BoolProperty(name="flipuvy", default=False)
    
        # other properties
    
        custom_active= BoolProperty(name="custom_active", default=True)
    
        custom_expand = BoolProperty(name="expand", default=False)
    
        custom_style_clone = BoolProperty(name="custom_style_clone", default=False)
    
        custom_active_view = StringProperty(name = "custom_active_view",default = "View",update = update_activeviewname)
    
        custom_image = StringProperty(name = "custom_image",default = "")
    
        custom_index = IntProperty()
    
    # Function to create custom properties
    def createcustomprops(context):
        Ob = bpy.types.Object
    
        Ob.custom_fnlevel = IntProperty(name="Fast navigate level", description="Increase or decrease the SubSurf level, decrease make navigation faster", default=0)
    
        Ob.custom_location = FloatVectorProperty(name="Location", description="Location of the plane",
                                               default  = (1.0, 0, -1.0),
    
                                               size     = 3,
                                               step     = 0.5,
                                               soft_min = -10,
                                               soft_max = 10,
    
                                               update = update_Location)
    
        Ob.custom_rotation = FloatProperty(name="Rotation", description="Rotate the plane",
                                           min=-180, max=180, default=0,update = update_Rotation)
    
        Ob.custom_old_rotation = FloatProperty(name="old_Rotation", description="Old Rotate the plane",
                                               min=-180, max=180, default=0)
    
        Ob.custom_scale = FloatVectorProperty(name="Scales", description="Scale the planes",
                                              subtype = 'XYZ',
                                              default=(1.0, 1.0),
                                              min = 0.1,
                                              max = 10,
                                              soft_min = 0.1,
                                              soft_max = 10,
                                              size=2,
                                              step=0.5,
                                              update = update_Scale)
    
        Ob.custom_propscale = FloatProperty(name="PropScale", description="Scale the Plane",
                                            default  = 1.0,
                                            min      = 0.1,
                                            soft_min = 0.1,
                                            soft_max = 10,
                                            step     = 0.5,
                                            update   = update_PropScale)
    
        Ob.custom_old_scale = FloatVectorProperty(name="old_Scales", description="Old Scale the planes",
                                              subtype = 'XYZ', default=(1.0, 1.0),min = 0.1, size=2)
    
        Ob.custom_linkscale = BoolProperty(name="linkscale", default=True, update = update_LinkScale)
    
        Ob.custom_sub = IntProperty(name="Subdivide", description="Number of subdivision of the plane",
    
        # UV properties
        Ob.custom_scaleuv = FloatVectorProperty(name="ScaleUV", description="Scale the texture's UV",
                                                default  = (1.0,1.0),
                                                soft_min = 0.01,
                                                soft_max = 100,
    
                                                subtype  = 'XYZ',
                                                size     = 2,
                                                update   = update_UVScale)
    
        Ob.custom_propscaleuv = FloatProperty(name="PropScaleUV", description="Scale the texture's UV",
                                              default    = 1.0,
                                              soft_min   = 0.01,
                                              soft_max   = 100,
                                              min        = 0.01,
    
    
        Ob.custom_old_scaleuv = FloatVectorProperty(name="old_ScaleUV", description="Scale the texture's UV",
                                                    default=(1.0,1.0),min = 0.01, subtype = 'XYZ', size=2)
        Ob.custom_offsetuv = FloatVectorProperty(name="OffsetUV", description="Decal the texture's UV",
    
                                                default=(0.0,0.0), subtype = 'XYZ', size=2,update = update_UVOffset)
    
        Ob.custom_old_offsetuv = FloatVectorProperty(name="old_OffsetUV", description="Decal the texture's UV",
    
                                                     default=(0.0,0.0), subtype = 'XYZ', size=2)
    
        Ob.custom_linkscaleuv = BoolProperty(name="linkscaleUV", default=True, update = update_LinkUVScale)
        Ob.custom_flipuvx = BoolProperty(name="flipuvx", default=False, update = update_FlipUVX)
        Ob.custom_flipuvy = BoolProperty(name="flipuvy", default=False, update = update_FlipUVY)
    
        Ob.custom_c3d = BoolProperty(name="c3d", default=True)
        Ob.custom_rotc3d = BoolProperty(name="rotc3d", default=False)
        Ob.custom_scac3d = BoolProperty(name="scac3d", default=False)
        Ob.custom_expand = BoolProperty(name="expand", default=True)
    
        Ob.custom_style_clone = BoolProperty(name="custom_style_clone", default=False, update = update_style_clone)
    
        Ob.custom_active_view = StringProperty(name = "custom_active_view",default = "View")
        try:
            Ob.custom_active_object = StringProperty(name = "custom_active_object",default = context.object.name)
        except:
    
            Ob.custom_active_object = StringProperty(name = "custom_active_object",default = 'debut')
    
        Ob.custom_props = CollectionProperty(type = custom_props)
    
    # Function to remove custom properties
    
        list_prop = ['custom_location', 'custom_rotation', 'custom_old_rotation', 'custom_scale', 'custom_old_scale', 'custom_c3d',
                     'custom_rotc3d', 'custom_scaleuv', 'custom_flipuvx', 'custom_flipuvy', 'custom_linkscale',
                     'custom_linkscaleuv', 'custom_old_scaleuv', 'custom_offsetuv', 'custom_old_offsetuv', 'custom_scac3d', 'custom_sub',
    
                     'custom_expand', 'custom_style_clone', 'custom_active_view', 'custom_propscaleuv', 'custom_props', 'custom_propscale']
    
        for prop in list_prop:
            try:
                del bpy.data.objects[BProjection_Empty][prop]
            except:
                pass
    
    def clear_props(context):
    
        em.custom_scale = [1,1]
        em.custom_rotation = 0
        em.custom_scaleuv =[1.0,1.0]
        em.custom_offsetuv =[0.0,0.0]
        em.custom_propscaleuv = 1.0
        em.custom_propscale = 1.0
        if em.custom_flipuvx == True:
            em.custom_flipuvx = False
        if em.custom_flipuvy == True:
            em.custom_flipuvy = False
    
    
    class CreateView(Operator):
        bl_idname = "object.create_view"
        bl_label = "Create a new view"
    
    
            ob = context.object
            em = bpy.data.objects[BProjection_Empty]
    
            new_props = em.custom_props.add()
            em.custom_active_view = new_props.custom_active_view
    
            ob.data.shape_keys.key_blocks[ob.active_shape_key_index].mute = True
            bpy.ops.object.shape_key_add(from_mix = False)
            ob.data.shape_keys.key_blocks[ob.active_shape_key_index].value = 1.0
            new_props.custom_index = len(em.custom_props)-1
            bpy.ops.object.active_view(index = new_props.custom_index)
            return {'FINISHED'}
    
    
    class SaveView(Operator):
        bl_idname = "object.save_view"
        bl_label = "copy the view"
    
        index = IntProperty(default = 0)
    
            em = bpy.data.objects[BProjection_Empty]
    
            prop = em.custom_props[self.index]
            prop.custom_rotation =  em.custom_rotation
            prop.custom_scale =  em.custom_scale
            prop.custom_linkscale =  em.custom_linkscale
    
            prop.custom_scaleuv = em.custom_scaleuv
            prop.custom_propscale = em.custom_propscale
    
            prop.custom_linkscaleuv = em.custom_linkscaleuv
            prop.custom_propscaleuv = em.custom_propscaleuv
            prop.custom_flipuvx = em.custom_flipuvx
            prop.custom_flipuvy = em.custom_flipuvy
            try:
                prop.custom_image = bpy.data.textures[BProjection_Texture].image.name
            except:
                pass
    
    class PasteView(Operator):
        bl_idname = "object.paste_view"
        bl_label = "paste the view"
    
        index = IntProperty(default = 0)
    
            em = bpy.data.objects[BProjection_Empty]
            tmp_scac3d = em.custom_scac3d
            tmp_rotc3d = em.custom_rotc3d
            em.custom_scac3d = False
            em.custom_rotc3d = False
            prop = em.custom_props[self.index]
            em.custom_linkscale =  prop.custom_linkscale
    
            em.custom_linkscaleuv = prop.custom_linkscaleuv
            em.custom_scaleuv = prop.custom_scaleuv
    
            em.custom_propscaleuv = prop.custom_propscaleuv
            em.custom_rotation =  prop.custom_rotation
    
            em.custom_scale =  prop.custom_scale
    
            em.custom_propscale = prop.custom_propscale
    
            if prop.custom_image != '':
                if bpy.data.textures[BProjection_Texture].image.name != prop.custom_image:
                    bpy.data.textures[BProjection_Texture].image = bpy.data.images[prop.custom_image]
                    applyimage(context)
            if em.custom_flipuvx != prop.custom_flipuvx:
                em.custom_flipuvx = prop.custom_flipuvx
            if em.custom_flipuvy != prop.custom_flipuvy:
                em.custom_flipuvy = prop.custom_flipuvy
            em.custom_scac3d = tmp_scac3d
    
    class RemoveView(Operator):
        bl_idname = "object.remove_view"
        bl_label = "Rmeove the view"
    
        index = IntProperty(default = 0)
    
            ob = context.object
            em = bpy.data.objects[BProjection_Empty]
    
            ob.active_shape_key_index =  self.index + 1
            bpy.ops.object.shape_key_remove()
    
                if len(em.custom_props) > 0:
                    bpy.ops.object.active_view(index = self.index-1)
                if self.index == 0 and len(em.custom_props) > 1:
    
            em.custom_props.remove(self.index)
    
            if len(em.custom_props) == 0:
                clear_props(context)
    
            i=0
            for item in em.custom_props:
    
    
            for item in (item for item in em.custom_props if item.custom_active):
                    ob.active_shape_key_index = item.custom_index+1
    
    class ActiveView(Operator):
        bl_idname = "object.active_view"
        bl_label = "Active the view"
    
        index = IntProperty(default = 0)
    
        def execute(self, context):
            ob = context.object
            em = bpy.data.objects[BProjection_Empty]
            for item in (item for item in em.custom_props if item.custom_active == True):
                bpy.ops.object.save_view(index = item.custom_index)
                item.custom_active = False
            em.custom_props[self.index].custom_active  = True
    
            em.custom_active_view = em.custom_props[self.index].custom_active_view
    
            ob.active_shape_key_index =  self.index + 1
    
            for i in ob.data.shape_keys.key_blocks:
                i.mute = True
    
            ob.data.shape_keys.key_blocks[ob.active_shape_key_index].mute = False
    
            return {'FINISHED'}
    
    # Draw Class to show the panel
    class BProjection(Panel):
        bl_space_type = 'VIEW_3D'
        bl_region_type = 'UI'
        bl_label = "BProjection"
    
        @classmethod
        def poll(cls, context):
            return (context.image_paint_object or context.sculpt_object)
    
        def draw(self, context):
    
            if  BProjection_Empty in [ob.name for ob in bpy.data.objects]:
                tex = bpy.data.textures[BProjection_Texture]
    
                ob = context.object
                em = bpy.data.objects[BProjection_Empty]
    
                if ob == bpy.data.objects[em.custom_active_object]:
    
                    col = layout.column(align =True)
    
                    col.operator("object.removebprojectionplane", text="Remove BProjection plane")
    
    
                try:
                    matBProjection = bpy.data.materials[BProjection_Material]
                except:
                    matBProjection = None
    
                box = layout.box()
    
                row = box.row()
                if not em.custom_expand:
                    row.prop(em, "custom_expand", text  = "", icon="TRIA_RIGHT", emboss=False)
                    row.label(text= 'Paint Object: '+ ob.name)
                else:
    
                    row.prop(em, "custom_expand", text = "" , icon="TRIA_DOWN", emboss=False)
    
                    row.label(text= 'Paint Object: '+ ob.name)
    
                    if ob == bpy.data.objects[em.custom_active_object]:
                        col = box.column(align =True)
                        col.template_ID(tex, "image", open="image.open")
                        row  = box.row(align=True)
                        row.operator('object.applyimage', text="Apply image", icon = 'FILE_TICK')
                        row.prop(em, "custom_c3d",text="", icon='CURSOR')
                        row  = box.row(align =True)
                        row.label(text="Location:")
                        row  = box.row(align =True)
                        row.prop(em,'custom_location', text='')
    
                        row.prop(em,'custom_rotation')
    
                        row.prop(em,'custom_rotc3d',text="",icon='MANIPUL')
    
                        row  = box.row(align =True)
                        row.label(text="Scale:")
    
                        if em.custom_linkscale :
                            row.prop(em, "custom_propscale",text="")
                            row.prop(em, "custom_linkscale",text="",icon='LINKED')
    
                            row.prop(em,'custom_scale',text='')
                            row.prop(em, "custom_linkscale",text="",icon='UNLINKED')
    
                        row.prop(em,'custom_scac3d',text="",icon='MANIPUL')
    
                        row  = box.row(align =True)
                        row.label(text="UV's Offset:")
                        row  = box.row(align =True)
                        row.prop(em,'custom_offsetuv',text='')
    
                        row.prop(em, "custom_flipuvx",text="",icon='ARROW_LEFTRIGHT')
                        row.prop(em, "custom_flipuvy",text="",icon='FULLSCREEN_ENTER')
    
                        row  = box.row(align =True)
                        row.label(text="UV's Scale:")
    
                        if em.custom_linkscaleuv:
                            row.prop(em,'custom_propscaleuv',text='')
                            row.prop(em, "custom_linkscaleuv",text="",icon='LINKED')
    
                            row.prop(em,'custom_scaleuv',text='')
    
                            row.prop(em, "custom_linkscaleuv",text="",icon='UNLINKED')
    
    
                        if matBProjection:
                            if context.scene.game_settings.material_mode == 'GLSL' and context.space_data.viewport_shade == 'TEXTURED':
                                row = box.column(align =True)
                                row.prop(matBProjection,'alpha', slider = True)
    
                        row = box.column(align =True)
                        row.prop(ob,"custom_fnlevel")
                        row = box.column(align =True)
    
                        if not em.custom_style_clone:
                            row.prop(em,"custom_style_clone",text="Style Clone Normal", icon='RENDERLAYERS')
                        else:
    
                            row.prop(em,"custom_style_clone",text="Style Clone New", icon='RENDERLAYERS')
                        row = box.column(align =True)
    
                    if ob == bpy.data.objects[em.custom_active_object]:
    
                        for item in em.custom_props:
                            box = layout.box()
                            row = box.row()
                            if item.custom_active:
    
                                row.operator("object.active_view",text = "", icon='RADIOBUT_ON', emboss = False).index = item.custom_index
    
                                row.operator("object.active_view",text = "", icon='RADIOBUT_OFF', emboss = False).index = item.custom_index
                            row.prop(item, "custom_active_view", text="")
    
                            row.operator('object.remove_view', text="", icon = 'PANEL_CLOSE', emboss = False).index = item.custom_index
                        row = layout.row()
    
                        row.operator('object.create_view', text="Create View", icon = 'RENDER_STILL')
    
                    else:
                        col = box.column(align =True)
    
                        col.operator("object.change_object", text="Change Object")
    
    
            else:
                ob = context.object
                col = layout.column(align = True)
    
                if ob.active_material is None:
                    col.label(text="Add a material first!", icon="ERROR")
                elif ob.data.uv_textures.active is None:
                    col.label(text="Create UVMap first!!", icon="ERROR")
                else:
                    col.operator("object.addbprojectionplane", text="Add BProjection plane")
                    col = layout.column(align = True)
                    col.prop(ob, "custom_sub",text="Subdivision level")
    
    
    
    # Oprerator Class to apply the image to the plane
    
    class ApplyImage(Operator):
        bl_idname = "object.applyimage"
        bl_label = "Apply image"
    
    
            applyimage(context)
    
            return {'FINISHED'}
    
    # Oprerator Class to make the 4 or 6 point and scale the plan
    class IntuitiveScale(Operator):
        bl_idname = "object.intuitivescale"
        bl_label = "Draw lines"
    
        def invoke(self, context, event):
            ob = context.object
            em = bpy.data.objects[BProjection_Empty]
            x = event.mouse_region_x
    
            y = event.mouse_region_y
            if len(ob.grease_pencil.layers.active.frames) == 0:
    
                bpy.ops.gpencil.draw(mode='DRAW', stroke=[{"name":"", "pen_flip":False,
                                                           "is_start":True, "location":(0, 0, 0),
                                                           "mouse":(x,y), "pressure":1, "time":0}])
            else:
                if em.custom_linkscale:
                    nb_point = 4
                else:
                    nb_point = 6
    
                if len(ob.grease_pencil.layers.active.frames[0].strokes) < nb_point:
                    bpy.ops.gpencil.draw(mode='DRAW', stroke=[{"name":"", "pen_flip":False,
                                                               "is_start":True, "location":(0, 0, 0),
                                                               "mouse":(x,y), "pressure":1, "time":0}])
    
                if len(ob.grease_pencil.layers.active.frames[0].strokes) == nb_point:
                    s = ob.grease_pencil.layers.active.frames[0]
                    v1 = s.strokes[1].points[0].co - s.strokes[0].points[0].co
                    if not em.custom_linkscale:
                        v2 = s.strokes[4].points[0].co - s.strokes[3].points[0].co
                    else:
                        v2 = s.strokes[3].points[0].co - s.strokes[2].points[0].co
    
                    em.custom_scale[0] *= abs(propx)
    
                    if not em.custom_linkscale:
                        v1 = s.strokes[2].points[0].co - s.strokes[0].points[0].co
                        v2 = s.strokes[5].points[0].co - s.strokes[3].points[0].co
                        propy = v1.y/v2.y
                        em.custom_scale[1] *= abs(propy)
                    bpy.ops.gpencil.active_frame_delete()
    
            return {'FINISHED'}
    
    # Oprerator Class to configure all wath is needed
    class AddBProjectionPlane(Operator):
        bl_idname = "object.addbprojectionplane"
        bl_label = "Configure"
    
    
        def creatematerial(self, context):
            if 'Material for BProjection' not in [mat.name for mat in bpy.data.materials]:
    
                bpy.data.textures.new(name='Texture for BProjection',type='IMAGE')
    
                bpy.data.materials.new(name='Material for BProjection')
    
                matBProjection = bpy.data.materials['Material for BProjection']
                matBProjection.texture_slots.add()
                matBProjection.use_shadeless = True
                matBProjection.use_transparency = True
                matBProjection.active_texture = bpy.data.textures['Texture for BProjection']
    
                index = matBProjection.active_texture_index
                matBProjection.texture_slots[index].texture_coords = 'UV'
    
            old_index = ob.active_material_index
            bpy.ops.object.material_slot_add()
            index = ob.active_material_index
            ob.material_slots[index].material = bpy.data.materials['Material for BProjection']
            bpy.ops.object.material_slot_assign()
            ob.active_material_index = old_index
            ob.data.update()
    
    
        def execute(self, context):
            if  BProjection_Empty not in [ob.name for ob in bpy.data.objects]:
    
    
                cm = bpy.context.object.mode
                '''tmp = context.object
                for ob in (ob for ob in bpy.data.objects if ob.type == 'MESH' and ob.hide == False and context.scene in ob.users_scene):
                    context.scene.objects.active = ob
    
                    bpy.ops.object.mode_set(mode = cm, toggle=False)
    
    
                context.scene.objects.active = tmp'''
                bpy.ops.object.mode_set(mode = 'OBJECT', toggle=False)
    
                context.space_data.show_relationship_lines = False
    
                ob = context.object
    
                bpy.ops.object.add()
                em = context.object
                em.name = BProjection_Empty
    
                context.scene.objects.active = ob
                ob.select = True
    
                bpy.ops.object.editmode_toggle()
    
                bpy.ops.mesh.primitive_plane_add()
                bpy.ops.object.vertex_group_assign(new = True)
    
                ob.vertex_groups.active.name = 'texture plane'
    
                bpy.ops.uv.unwrap()
    
                bpy.ops.object.vertex_group_select()
    
                bpy.ops.object.editmode_toggle()
                for i in range(4):
                    ob.data.edges[len(ob.data.edges)-1-i].crease = 1
                bpy.ops.object.editmode_toggle()
    
                em.custom_sub = ob.custom_sub
                if em.custom_sub > 0:
                    bpy.ops.mesh.subdivide(number_cuts = em.custom_sub)
    
                em.select = True
                bpy.ops.object.hook_add_selob()
                em.select = False
    
                self.creatematerial(context)
    
                bpy.ops.gpencil.data_add()
                ob.grease_pencil.draw_mode = 'VIEW'
                bpy.ops.gpencil.layer_add()
                ob.grease_pencil.layers.active.color = [1.0,0,0]
    
                bpy.ops.object.editmode_toggle()
    
                bpy.ops.object.shape_key_add(from_mix = False)
    
                bpy.ops.object.create_view()
    
                km = bpy.data.window_managers['WinMan'].keyconfigs['Blender'].keymaps['3D View']
    
                l = ['view3d.rotate','view3d.move','view3d.zoom','view3d.viewnumpad','paint.bp_paint','MOUSE','KEYBOARD','LEFT','MIDDLEMOUSE','WHEELINMOUSE','WHEELOUTMOUSE','NUMPAD_1','NUMPAD_3','NUMPAD_7']
    
                for kmi in km.keymap_items:
                    if kmi.idname in l and kmi.map_type in l and kmi.type in l:
                        try:
                            p = kmi.properties.delta
                            if p == -1 or p == 1:
                                kmi.idname = 'view3d.zoom_view3d'
                                kmi.properties.delta = p
                        except:
                            try:
                                p = kmi.properties.type
                                if kmi.shift == False :
                                    kmi.idname = 'view3d.preset_view3d'
                                    kmi.properties.view = p
                            except:
                                if kmi.idname == 'view3d.rotate':
    
                                if kmi.idname == 'view3d.move':
    
                                    kmi.idname = 'view3d.pan_view3d'
    
                km = context.window_manager.keyconfigs.default.keymaps['Image Paint']
    
                kmi = km.keymap_items.new("object.intuitivescale", 'LEFTMOUSE', 'PRESS', shift=True)
                kmi = km.keymap_items.new("object.bp_grab", 'G', 'PRESS')
    
                kmi = km.keymap_items.new("object.bp_rotate", 'R', 'PRESS')
                kmi = km.keymap_items.new("object.bp_scale", 'S', 'PRESS')
    
                kmi = km.keymap_items.new("object.bp_scaleuv", 'U', 'PRESS')
                kmi = km.keymap_items.new("object.bp_offsetuv", 'Y', 'PRESS')
                kmi = km.keymap_items.new("object.bp_clear_prop", 'C', 'PRESS')
    
                kmi = km.keymap_items.new("object.bp_toggle_alpha", 'Q', 'PRESS')
    
                align_to_view(context)
    
                context.space_data.cursor_location = em.location
    
                bpy.ops.object.mode_set(mode = cm, toggle=False)
                bpy.data.objects[BProjection_Empty].custom_active_object = context.object.name
    
    # Oprerator Class to remove what is no more needed
    
    class RemoveBProjectionPlane(Operator):
        bl_idname = "object.removebprojectionplane"
        bl_label = "Configure"
    
        def removematerial(self, context):
    
            i = 0
    
            for ms in ob.material_slots:
                if ms.name == BProjection_Material:
                    index = i
                i+=1
    
            ob.active_material_index = index
            bpy.ops.object.material_slot_remove()
    
        def execute(self, context):
    
                cm = bpy.context.object.mode
                bpy.ops.object.mode_set(mode = 'OBJECT', toggle=False)
    
                context.space_data.show_relationship_lines = True
    
                bpy.ops.object.modifier_remove(modifier="Hook-Empty for BProjection")
    
                self.removematerial(context)
    
                ob = context.object
    
                bpy.ops.object.editmode_toggle()
    
                bpy.ops.mesh.reveal()
    
                ob.vertex_groups.active_index = ob.vertex_groups['texture plane'].index
                bpy.ops.object.vertex_group_select()
                bpy.ops.mesh.delete()
                bpy.ops.object.vertex_group_remove()
    
                bpy.ops.object.editmode_toggle()
    
                ob.select = False
    
                em = bpy.data.objects[BProjection_Empty]
                context.scene.objects.active = em
                em.hide = False
                em.select = True
                bpy.ops.object.delete()
    
                context.scene.objects.active = ob
                ob.select = True
    
                '''tmp = context.object
                for ob in (ob for ob in bpy.data.objects if ob.type == 'MESH' and ob.hide == False and context.scene in ob.users_scene):
                    context.scene.objects.active = ob
    
                    bpy.ops.object.mode_set(mode = 'OBJECT', toggle=False)
    
    
                context.scene.objects.active = tmp'''
    
                for i in ob.data.shape_keys.key_blocks:
                    bpy.ops.object.shape_key_remove()
                bpy.ops.object.shape_key_remove()
    
                bpy.ops.object.mode_set(mode = cm, toggle=False)
                removecustomprops()
    
            return {'FINISHED'}
    
    def reinitkey():
        km = bpy.data.window_managers['WinMan'].keyconfigs['Blender'].keymaps['3D View']
        l = ['view3d.zoom_view3d','view3d.preset_view3d','view3d.rotate_view3d','view3d.pan_view3d','MOUSE','KEYBOARD','MIDDLEMOUSE','WHEELINMOUSE','WHEELOUTMOUSE','NUMPAD_1','NUMPAD_3','NUMPAD_7']
        for kmi in km.keymap_items:
            if kmi.idname in l and kmi.map_type in l and kmi.type in l:
                try:
                    p = kmi.properties.delta
                    if p == -1 or p == 1:
                        kmi.idname = 'view3d.zoom'
                        kmi.properties.delta = p
                except:
                    try:
                        p = kmi.properties.view
                        if kmi.shift == False :
                            kmi.idname = 'view3d.viewnumpad'
                            kmi.properties.type = p
                    except:
                        if kmi.idname == 'view3d.rotate_view3d':
    
                        if kmi.idname == 'view3d.pan_view3d':
    
        km = bpy.context.window_manager.keyconfigs.default.keymaps['Image Paint']
    
        for kmi in km.keymap_items:
            if kmi.idname == 'paint.bp_paint':
                kmi.idname = 'paint.image_paint'
    
        for kmi in (kmi for kmi in km.keymap_items if kmi.idname in {"object.intuitivescale", "object.bp_grab", "object.bp_rotate", "object.bp_scale", "object.bp_scaleuv", "object.bp_clear_prop", "object.bp_offsetuv","object.bp_toggle_alpha", }):
    
                km.keymap_items.remove(kmi)
    
    
    # Oprerator Class to remove what is no more needed
    
    class ChangeObject(Operator):
        bl_idname = "object.change_object"
        bl_label = "Change Object"
    
        def removematerial(self, context):
    
            i = 0
    
            for ms in ob.material_slots:
                if ms.name == BProjection_Material: