diff --git a/oscurart_tools/__init__.py b/oscurart_tools/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..9b2817cd5f24b4a4ad19461b97e744cfa0bd856e
--- /dev/null
+++ b/oscurart_tools/__init__.py
@@ -0,0 +1,166 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+bl_info = {
+    "name": "Oscurart Tools",
+    "author": "Oscurart, CodemanX",
+    "version": (4, 0, 0),
+    "blender": (2, 80, 0),
+    "location": "View3D > Toolbar and View3D > Specials (W-key)",
+    "description": "Tools for objects, render, shapes, and files.",
+    "warning": "",
+    "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
+                "Scripts/3D_interaction/Oscurart_Tools",
+    "category": "Object",
+    }
+    
+
+import bpy
+from bpy.types import Menu
+from oscurart_tools.files import reload_images
+from oscurart_tools.files import save_incremental
+from oscurart_tools.files import collect_images
+from oscurart_tools.mesh import overlap_uvs
+from oscurart_tools.mesh import overlap_island
+from oscurart_tools.mesh import select_doubles
+from oscurart_tools.mesh import shapes_to_objects
+from oscurart_tools.object import distribute
+from oscurart_tools.object import selection
+from oscurart_tools.object import search_and_select
+from oscurart_tools.mesh import apply_linked_meshes
+
+from bpy.types import (
+        AddonPreferences,
+        Panel,
+        PropertyGroup,
+        )
+from bpy.props import (
+        StringProperty,
+        BoolProperty,
+        IntProperty,
+        PointerProperty,
+        CollectionProperty,
+        )
+
+# mesh
+class VIEW3D_MT_edit_mesh_oscurarttools(Menu):
+    bl_label = "OscurartTools"   
+    
+    def draw(self, context):
+        layout = self.layout
+        
+        layout.operator("mesh.uv_island_copy")
+        layout.operator("mesh.uv_island_paste")
+        layout.operator("mesh.select_doubles")
+        layout.separator()          
+        layout.operator("image.reload_images_osc")      
+        layout.operator("file.save_incremental_backup")
+        layout.operator("file.collect_all_images")
+
+def menu_funcMesh(self, context):
+    self.layout.menu("VIEW3D_MT_edit_mesh_oscurarttools")
+    self.layout.separator()
+
+# image
+class IMAGE_MT_uvs_oscurarttools(Menu):
+    bl_label = "OscurartTools"   
+    
+    def draw(self, context):
+        layout = self.layout
+        
+        layout.operator("mesh.uv_island_copy")
+        layout.operator("mesh.uv_island_paste")
+        layout.operator("mesh.overlap_uv_faces")
+        layout.separator()          
+        layout.operator("image.reload_images_osc")      
+        layout.operator("file.save_incremental_backup")
+        layout.operator("file.collect_all_images")
+
+def menu_funcImage(self, context):
+    self.layout.menu("IMAGE_MT_uvs_oscurarttools")
+    self.layout.separator()
+
+
+# object
+class VIEW3D_MT_object_oscurarttools(Menu):
+    bl_label = "OscurartTools"   
+    
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator("object.distribute_osc")
+        layout.operator("object.search_and_select_osc")
+        layout.operator("object.shape_key_to_objects_osc")
+        layout.operator("mesh.apply_linked_meshes")        
+        layout.separator()          
+        layout.operator("image.reload_images_osc")      
+        layout.operator("file.save_incremental_backup")
+        layout.operator("file.collect_all_images")
+
+def menu_funcObject(self, context):
+    self.layout.menu("VIEW3D_MT_object_oscurarttools")
+    self.layout.separator()
+
+# ========================= End of Scripts =========================
+
+
+classes = (
+    VIEW3D_MT_edit_mesh_oscurarttools,
+    IMAGE_MT_uvs_oscurarttools,
+    VIEW3D_MT_object_oscurarttools,
+    reload_images.reloadImages,  
+    overlap_uvs.CopyUvIsland, 
+    overlap_uvs.PasteUvIsland,
+    distribute.DistributeOsc,
+    selection.OscSelection,
+    save_incremental.saveIncrementalBackup,
+    collect_images.collectImagesOsc,
+    overlap_island.OscOverlapUv,
+    select_doubles.SelectDoubles,
+    shapes_to_objects.ShapeToObjects,
+    search_and_select.SearchAndSelectOt,
+    apply_linked_meshes.ApplyLRT,
+    )
+
+def register():
+    from bpy.types import Scene
+    Scene.multimeshedit = StringProperty()
+    bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_funcMesh)
+    bpy.types.IMAGE_MT_specials.prepend(menu_funcImage)
+    bpy.types.VIEW3D_MT_object_specials.prepend(menu_funcObject)
+
+    from bpy.utils import register_class
+    for cls in classes:
+        register_class(cls)                                            
+                                                                              
+
+def unregister():
+    del bpy.types.Scene.SearchAndSelectOt
+    bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_funcMesh)
+    bpy.types.IMAGE_MT_specials.remove(menu_funcImage)
+    bpy.types.VIEW3D_MT_object_specials.remove(menu_funcObject)
+
+    from bpy.utils import unregister_class
+    for cls in reversed(classes):
+        unregister_class(cls)
+
+
+if __name__ == "__main__":
+    register()
diff --git a/oscurart_tools/files/collect_images.py b/oscurart_tools/files/collect_images.py
new file mode 100644
index 0000000000000000000000000000000000000000..ce22700a751cc45820ff3cdb3eae3886b5132724
--- /dev/null
+++ b/oscurart_tools/files/collect_images.py
@@ -0,0 +1,59 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+from bpy.types import Operator
+import os
+import shutil
+
+
+class collectImagesOsc(Operator):
+    """Collect all images in the blend file and put them in IMAGES folder"""
+    bl_idname = "file.collect_all_images"
+    bl_label = "Collect Images"
+    bl_options = {"REGISTER", "UNDO"}
+
+    def execute(self, context):
+
+        imagespath = "%s/IMAGES"  % (os.path.dirname(bpy.data.filepath))
+
+        if not os.path.exists(imagespath):
+            os.mkdir(imagespath)
+
+        bpy.ops.file.make_paths_absolute()
+
+        for image in bpy.data.images:
+            try:
+                image.update()
+
+                if image.has_data:
+                    if not os.path.exists(os.path.join(imagespath,os.path.basename(image.filepath))):
+                        shutil.copy(image.filepath, os.path.join(imagespath,os.path.basename(image.filepath)))
+                        image.filepath = os.path.join(imagespath,os.path.basename(image.filepath))
+                    else:
+                        print("%s exists." % (image.name))
+                else:
+                    print("%s missing path." % (image.name))
+            except:
+                print("%s missing path." % (image.name))
+
+        bpy.ops.file.make_paths_relative()
+
+        return {'FINISHED'}
diff --git a/oscurart_tools/files/reload_images.py b/oscurart_tools/files/reload_images.py
new file mode 100644
index 0000000000000000000000000000000000000000..68b5c61be97893ed85c3c531b573a1b1ede28443
--- /dev/null
+++ b/oscurart_tools/files/reload_images.py
@@ -0,0 +1,37 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+from bpy.types import Operator
+
+
+
+class reloadImages (Operator):
+    """Reloads all bitmaps in the scene"""
+    bl_idname = "image.reload_images_osc"
+    bl_label = "Reload Images"
+    bl_options = {"REGISTER", "UNDO"}
+
+    def execute(self, context):
+        for imgs in bpy.data.images:
+            imgs.reload()
+        return {'FINISHED'}
+
+
diff --git a/oscurart_tools/files/save_incremental.py b/oscurart_tools/files/save_incremental.py
new file mode 100644
index 0000000000000000000000000000000000000000..d655b08e9b02df8a34f8ed26238bb415c0e7ddc0
--- /dev/null
+++ b/oscurart_tools/files/save_incremental.py
@@ -0,0 +1,70 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+from bpy.types import Operator
+import os
+
+
+def saveBkp (self, context):
+    fileFolder = os.path.dirname(bpy.data.filepath)
+    versionFolder = os.path.join(fileFolder,"VERSIONS")
+    
+    #creo folder
+    if os.path.exists(versionFolder):
+        print("existe")
+    else:
+        os.mkdir(versionFolder)  
+    
+    #sin version a versionada
+    if not bpy.data.filepath.count("_v"): 
+        filelist = [file  for file in os.listdir(versionFolder) if file.count("_v") and not file.count("blend1")] 
+
+        filelower = 0
+        print(filelist)
+        for file in filelist:
+            if int(file.split(".")[0][-2:]) > filelower:
+                filelower = int(file.split(".")[0][-2:])        
+
+        savepath = "%s/VERSIONS/%s_v%02d.blend" % (os.path.dirname(bpy.data.filepath),bpy.path.basename(bpy.data.filepath).split('.')[0],filelower+1)   
+        print("Copia versionada guardada.")   
+        bpy.ops.wm.save_as_mainfile()
+        bpy.ops.wm.save_as_mainfile(filepath=savepath, copy=True)        
+
+    else:        
+        #versionada a sin version
+        if bpy.data.filepath.count("_v"):
+            filename = "%s/../%s.blend" % (os.path.dirname(bpy.data.filepath),os.path.basename(bpy.data.filepath).rpartition(".")[0].rpartition("_")[0])
+            print(filename)
+            bpy.ops.wm.save_as_mainfile(filepath=filename, copy=True)       
+        print("Copia sin version guardada.")
+
+
+class saveIncrementalBackup (bpy.types.Operator):
+    """Save incremental backup in versions folder"""
+    bl_idname = "file.save_incremental_backup"
+    bl_label = "Save Incremental Backup"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    def execute(self, context):
+        saveBkp(self, context)
+        return {'FINISHED'}
+   
+
diff --git a/oscurart_tools/mesh/apply_linked_meshes.py b/oscurart_tools/mesh/apply_linked_meshes.py
new file mode 100644
index 0000000000000000000000000000000000000000..7615c426b27bcf458979c1474c8b766a0622cff5
--- /dev/null
+++ b/oscurart_tools/mesh/apply_linked_meshes.py
@@ -0,0 +1,60 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+
+
+
+def applyLRTEx(self, context):
+    actObj = bpy.context.active_object
+    actObjMatrixWorld = actObj.matrix_world.copy()
+    bpy.ops.object.select_linked(extend=False, type="OBDATA")
+    linkedObjects = bpy.context.selected_objects
+    linkedObjects.remove(actObj)
+
+    for vert in actObj.data.vertices:
+        vert.co = actObjMatrixWorld @ vert.co
+        actObj.location = (0,0,0)
+        actObj.rotation_euler = (0,0,0)
+        actObj.scale = (1,1,1)
+
+    for ob in linkedObjects:     
+        ob.matrix_world = ob.matrix_world @ actObj.matrix_world.inverted()
+
+
+class ApplyLRT(bpy.types.Operator):
+    """Apply LRT with linked mesh data"""
+    bl_idname = "mesh.apply_linked_meshes"
+    bl_label = "Apply LRT with linked meshes"
+    bl_options = {"REGISTER", "UNDO"}
+
+    @classmethod
+    def poll(cls, context):
+        return (context.view_layer.objects.active is not None and
+                context.view_layer.objects.active.type == 'MESH')
+
+    def execute(self, context):
+        applyLRTEx(self, context)
+        return {'FINISHED'}
+    
+  
+
+
+
diff --git a/oscurart_tools/mesh/overlap_island.py b/oscurart_tools/mesh/overlap_island.py
new file mode 100644
index 0000000000000000000000000000000000000000..68b3d3393b2604af9d8d85277964fb890b065a94
--- /dev/null
+++ b/oscurart_tools/mesh/overlap_island.py
@@ -0,0 +1,100 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+from mathutils import Vector
+from bpy.types import Operator
+from bpy.props import (
+        IntProperty,
+        BoolProperty,
+        FloatProperty,
+        EnumProperty,
+        )
+import bmesh
+import time
+
+C = bpy.context
+D = bpy.data
+
+
+def DefOscOverlapUv(self,offset,rotate):
+    me = bpy.context.object.data
+    bm = bmesh.from_edit_mesh(me)
+    bm.faces.ensure_lookup_table()
+    faces = [face for face in bm.faces if face.select]
+    uv_layer = bm.loops.layers.uv[bpy.context.object.data.uv_layers.active.name]
+
+    faceDict = {}
+    faceReverse = []
+    bm.select_mode = {'FACE'}
+    for face in faces:
+        bpy.ops.mesh.select_all(action="DESELECT")
+        face.select = True
+        bpy.ops.mesh.select_mirror()
+        faceDict[face.index] = [mirrorface for mirrorface in bm.faces if mirrorface.select][0].index
+        faceReverse.append([mirrorface for mirrorface in bm.faces if mirrorface.select][0])
+
+
+
+    for selFace,mirrorFace in faceDict.items():
+        for loop,mirrorLoop in zip(bm.faces[selFace].loops,bm.faces[mirrorFace].loops):
+            mirrorLoop.copy_from(loop)
+        if offset:
+            for loop,mirrorLoop in zip(bm.faces[selFace].loops,bm.faces[mirrorFace].loops):
+                mirrorLoop[uv_layer].uv += Vector((1,0))
+
+
+    #invierto direcciones
+    bmesh.ops.reverse_uvs(bm, faces=[f for f in faceReverse])
+    bmesh.ops.rotate_uvs(bm, faces=[f for f in faceReverse])
+    if rotate:
+        bmesh.ops.rotate_uvs(bm, faces=[f for f in faceReverse])
+
+    bmesh.update_edit_mesh(me)
+
+
+class OscOverlapUv(Operator):
+    """Overlaps the uvs on one side of the model symmetry plane. """ \
+    """Useful to get more detail on fixed resolution bitmaps"""
+    bl_idname = "mesh.overlap_uv_faces"
+    bl_label = "Overlap Uvs"
+    bl_options = {"REGISTER", "UNDO"}
+
+    @classmethod
+    def poll(cls, context):
+        return (context.active_object is not None and
+                context.active_object.type == 'MESH')
+
+
+    offset : BoolProperty(
+            default=True,
+            name="Offset"
+            )
+    rotate : BoolProperty(
+            default=False,
+            name="Rotate"
+            )
+
+    def execute(self, context):
+        DefOscOverlapUv(self,self.offset,self.rotate)
+        return {'FINISHED'}
+
+
+
diff --git a/oscurart_tools/mesh/overlap_uvs.py b/oscurart_tools/mesh/overlap_uvs.py
new file mode 100644
index 0000000000000000000000000000000000000000..2960bb3d66c07df6ea58ee9316f988fb0688d4b5
--- /dev/null
+++ b/oscurart_tools/mesh/overlap_uvs.py
@@ -0,0 +1,131 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+from mathutils import Vector
+from bpy.types import Operator
+from bpy.props import (
+        IntProperty,
+        BoolProperty,
+        FloatProperty,
+        EnumProperty,
+        )
+import os
+import bmesh
+
+C = bpy.context
+D = bpy.data
+
+
+
+# -------------------------- OVERLAP UV ISLANDS
+
+def defCopyUvsIsland(self, context):
+    bpy.ops.object.mode_set(mode="OBJECT")
+    global obLoop
+    global islandFaces
+    obLoop = []
+    islandFaces = []
+    for poly in bpy.context.object.data.polygons:
+        if poly.select:
+            islandFaces.append(poly.index)
+            for li in poly.loop_indices:
+                obLoop.append(li)
+
+    bpy.ops.object.mode_set(mode="EDIT")
+
+def defPasteUvsIsland(self, uvOffset, rotateUv,context):
+    bpy.ops.object.mode_set(mode="OBJECT")
+    selPolys = [poly.index for poly in bpy.context.object.data.polygons if poly.select]
+
+    for island in selPolys:
+        bpy.ops.object.mode_set(mode="EDIT")
+        bpy.ops.mesh.select_all(action="DESELECT")
+        bpy.ops.object.mode_set(mode="OBJECT")
+        bpy.context.object.data.polygons[island].select = True
+        bpy.ops.object.mode_set(mode="EDIT")
+        bpy.ops.mesh.select_linked()
+        bpy.ops.object.mode_set(mode="OBJECT")
+        TobLoop = []
+        TislandFaces = []
+        for poly in bpy.context.object.data.polygons:
+            if poly.select:
+                TislandFaces.append(poly.index)
+                for li in poly.loop_indices:
+                    TobLoop.append(li)
+
+        for source,target in zip(range(min(obLoop),max(obLoop)+1),range(min(TobLoop),max(TobLoop)+1)):
+            bpy.context.object.data.uv_layers.active.data[target].uv = bpy.context.object.data.uv_layers.active.data[source].uv + Vector((uvOffset,0))
+
+        bpy.ops.object.mode_set(mode="EDIT")
+
+    if rotateUv:
+        bpy.ops.object.mode_set(mode="OBJECT")
+        for poly in selPolys:
+            bpy.context.object.data.polygons[poly].select = True
+        bpy.ops.object.mode_set(mode="EDIT")
+        bm = bmesh.from_edit_mesh(bpy.context.object.data)
+        bmesh.ops.reverse_uvs(bm, faces=[f for f in bm.faces if f.select])
+        bmesh.ops.rotate_uvs(bm, faces=[f for f in bm.faces if f.select])
+        #bmesh.update_edit_mesh(bpy.context.object.data, tessface=False, destructive=False)
+
+
+
+class CopyUvIsland(Operator):
+    """Copy Uv Island"""
+    bl_idname = "mesh.uv_island_copy"
+    bl_label = "Copy Uv Island"
+    bl_options = {"REGISTER", "UNDO"}
+
+    @classmethod
+    def poll(cls, context):
+        return (context.active_object is not None and
+                context.active_object.type == 'MESH' and
+                context.active_object.mode == "EDIT")
+
+    def execute(self, context):
+        defCopyUvsIsland(self, context)
+        return {'FINISHED'}
+
+class PasteUvIsland(Operator):
+    """Paste Uv Island"""
+    bl_idname = "mesh.uv_island_paste"
+    bl_label = "Paste Uv Island"
+    bl_options = {"REGISTER", "UNDO"}
+
+    uvOffset : BoolProperty(
+            name="Uv Offset",
+            default=False
+            )
+
+    rotateUv : BoolProperty(
+            name="Rotate Uv Corner",
+            default=False
+            )
+    @classmethod
+    def poll(cls, context):
+        return (context.active_object is not None and
+                context.active_object.type == 'MESH' and
+                context.active_object.mode == "EDIT")
+
+    def execute(self, context):
+        defPasteUvsIsland(self, self.uvOffset, self.rotateUv, context)
+        return {'FINISHED'}
+
diff --git a/oscurart_tools/mesh/select_doubles.py b/oscurart_tools/mesh/select_doubles.py
new file mode 100644
index 0000000000000000000000000000000000000000..15282b0b2a47339a263532518a58f56dcb404869
--- /dev/null
+++ b/oscurart_tools/mesh/select_doubles.py
@@ -0,0 +1,76 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+from mathutils import Vector
+from bpy.types import Operator
+from bpy.props import (
+        IntProperty,
+        BoolProperty,
+        FloatProperty,
+        EnumProperty,
+        )
+import os
+import bmesh
+
+C = bpy.context
+D = bpy.data
+
+
+
+def SelDoubles(self, context):
+    bm = bmesh.from_edit_mesh(bpy.context.object.data)
+
+    for v in bm.verts:
+        v.select = 0
+
+    dictloc = {}
+
+    rd = lambda x: (round(x[0], 4), round(x[1], 4), round(x[2], 4))
+
+    for vert in bm.verts:
+        dictloc.setdefault(rd(vert.co), []).append(vert.index)
+
+    for loc, ind in dictloc.items():
+        if len(ind) > 1:
+            for v in ind:
+                bm.verts[v].select = 1
+
+    bpy.context.view_layer.objects.active = bpy.context.view_layer.objects.active
+
+
+class SelectDoubles(Operator):
+    """Selects duplicated vertex without merge them"""
+    bl_idname = "mesh.select_doubles"
+    bl_label = "Select Doubles"
+    bl_options = {"REGISTER", "UNDO"}
+
+    @classmethod
+    def poll(cls, context):
+        return (context.view_layer.objects.active is not None and
+                context.view_layer.objects.active.type == 'MESH' and
+                context.view_layer.objects.active.mode == "EDIT")
+
+    def execute(self, context):
+        SelDoubles(self, context)
+        return {'FINISHED'}
+
+
+
diff --git a/oscurart_tools/mesh/shapes_to_objects.py b/oscurart_tools/mesh/shapes_to_objects.py
new file mode 100644
index 0000000000000000000000000000000000000000..3b9a80a18637efcbed02764590cb074d69327ea6
--- /dev/null
+++ b/oscurart_tools/mesh/shapes_to_objects.py
@@ -0,0 +1,58 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+from bpy.types import Operator
+from bpy.props import (
+            BoolProperty,
+            FloatProperty,
+            )
+import math
+
+
+
+class ShapeToObjects(Operator):
+    """It creates a new object for every shapekey in the selected object, ideal to export to other 3D software Apps"""
+    bl_idname = "object.shape_key_to_objects_osc"
+    bl_label = "Shapes To Objects"
+    bl_options = {"REGISTER", "UNDO"}
+
+    @classmethod
+    def poll(cls, context):
+        return (context.view_layer.objects.active is not None and
+                context.view_layer.objects.active.type in
+                {'MESH', 'SURFACE', 'CURVE'})
+
+    def execute(self, context):
+        OBJACT = bpy.context.view_layer.objects.active
+        has_keys = hasattr(getattr(OBJACT.data, "shape_keys", None), "key_blocks")
+        if has_keys:
+            for SHAPE in OBJACT.data.shape_keys.key_blocks[:]:
+                print(SHAPE.name)
+                bpy.ops.object.shape_key_clear()
+                SHAPE.value = 1
+                mesh = OBJACT.to_mesh(bpy.context.depsgraph, True, calc_undeformed=False)
+                object = bpy.data.objects.new(SHAPE.name, mesh)
+                bpy.context.scene.collection.objects.link(object)
+        else:
+            self.report({'INFO'}, message="Active object doesn't have shape keys")
+            return {'CANCELLED'}
+
+        return {'FINISHED'}
diff --git a/oscurart_tools/object/distribute.py b/oscurart_tools/object/distribute.py
new file mode 100644
index 0000000000000000000000000000000000000000..991d664b4a7ff9ae7464e55cf36f369519e4ab24
--- /dev/null
+++ b/oscurart_tools/object/distribute.py
@@ -0,0 +1,70 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+import os
+from bpy.types import Operator
+from bpy.props import BoolProperty
+
+
+
+def ObjectDistributeOscurart(self, X, Y, Z):
+    if len(bpy.selection_osc[:]) > 1:
+        # VARIABLES
+        dif = bpy.selection_osc[-1].location - bpy.selection_osc[0].location
+        chunkglobal = dif / (len(bpy.selection_osc[:]) - 1)
+        chunkx = 0
+        chunky = 0
+        chunkz = 0
+        deltafst = bpy.selection_osc[0].location
+
+        # ORDENA
+        for OBJECT in bpy.selection_osc[:]:
+            if X:
+                OBJECT.location.x = deltafst[0] + chunkx
+            if Y:
+                OBJECT.location[1] = deltafst[1] + chunky
+            if Z:
+                OBJECT.location.z = deltafst[2] + chunkz
+            chunkx += chunkglobal[0]
+            chunky += chunkglobal[1]
+            chunkz += chunkglobal[2]
+    else:
+        self.report({'INFO'}, "Needs at least two selected objects")
+
+
+class DistributeOsc(Operator):
+    """Distribute evenly the selected objects in x y z"""
+    bl_idname = "object.distribute_osc"
+    bl_label = "Distribute Objects"
+    Boolx : BoolProperty(name="X")
+    Booly : BoolProperty(name="Y")
+    Boolz : BoolProperty(name="Z")
+
+    def execute(self, context):
+        ObjectDistributeOscurart(self, self.Boolx, self.Booly, self.Boolz)
+        return {'FINISHED'}
+
+    def invoke(self, context, event):
+        self.Boolx = True
+        self.Booly = True
+        self.Boolz = True
+        return context.window_manager.invoke_props_dialog(self)
+
diff --git a/oscurart_tools/object/search_and_select.py b/oscurart_tools/object/search_and_select.py
new file mode 100644
index 0000000000000000000000000000000000000000..a576457c01a57f9fe3a8e4cdf46136c4f086fe84
--- /dev/null
+++ b/oscurart_tools/object/search_and_select.py
@@ -0,0 +1,62 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+from bpy.types import Operator
+from bpy.props import BoolProperty
+from bpy.props import StringProperty
+
+# ------------------------ SEARCH AND SELECT ------------------------
+
+
+class SearchAndSelectOt(bpy.types.Operator):
+    """Search and select objects, by name"""
+    bl_idname = "object.search_and_select_osc"
+    bl_label = "Search And Select"
+    bl_options = {"REGISTER", "UNDO"}
+
+    keyword : StringProperty(name="Keyword", default="Type Here")
+    start : BoolProperty(name="Start With", default=True)
+    count : BoolProperty(name="Contain", default=True)
+    end : BoolProperty(name="End", default=True)
+
+    def execute(self, context):
+        for objeto in bpy.context.scene.objects:
+            variableNombre = self.keyword
+            if self.start:
+                if objeto.name.startswith(variableNombre):
+                    objeto.select_set(True)
+            if self.count:
+                if objeto.name.count(variableNombre):
+                    objeto.select_set(True)
+            if self.end:
+                if objeto.name.count(variableNombre):
+                    objeto.select_set(True)
+        return {'FINISHED'}
+
+    def invoke(self, context, event):
+        self.keyword = "Type Here"
+        self.start = True
+        self.count = True
+        self.end = True
+        return context.window_manager.invoke_props_dialog(self)
+    
+
+
diff --git a/oscurart_tools/object/selection.py b/oscurart_tools/object/selection.py
new file mode 100644
index 0000000000000000000000000000000000000000..c2a264bc2d79173511193af8c4c60c6d774aa893
--- /dev/null
+++ b/oscurart_tools/object/selection.py
@@ -0,0 +1,65 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import bpy
+
+
+
+# ------------------------------------ SELECTION -------------------------
+bpy.selection_osc = []
+
+
+def select_osc():
+    if bpy.context.mode == "OBJECT":
+        obj = bpy.context.object
+        sel = len(bpy.context.selected_objects)
+
+        if sel == 0:
+            bpy.selection_osc = []
+        else:
+            if sel == 1:
+                bpy.selection_osc = []
+                bpy.selection_osc.append(obj)
+            elif sel > len(bpy.selection_osc):
+                for sobj in bpy.context.selected_objects:
+                    if (sobj in bpy.selection_osc) is False:
+                        bpy.selection_osc.append(sobj)
+
+            elif sel < len(bpy.selection_osc):
+                for it in bpy.selection_osc:
+                    if (it in bpy.context.selected_objects) is False:
+                        bpy.selection_osc.remove(it)
+
+
+class OscSelection(bpy.types.Header):
+    bl_label = "Selection Osc"
+    bl_space_type = "VIEW_3D"
+
+    def __init__(self):
+        select_osc()
+
+    def draw(self, context):
+        """
+        layout = self.layout
+        row = layout.row()
+        row.label("Sels: "+str(len(bpy.selection_osc)))
+        """
+ 
+