diff --git a/uv_texture_atlas.py b/uv_texture_atlas.py
new file mode 100644
index 0000000000000000000000000000000000000000..a21a74d7898513ee252389e49557438d28dd0a18
--- /dev/null
+++ b/uv_texture_atlas.py
@@ -0,0 +1,763 @@
+# 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 #####
+
+
+bl_info = {
+    "name": "Texture Atlas",
+    "author": "Andreas Esau, Paul Geraskin",
+    "version": (0, 18),
+    "blender": (2, 6, 6),
+    "location": "Properties > Render",
+    "description": "A simple Texture Atlas for unwrapping many objects. It creates additional UV",
+    "wiki_url": "http://code.google.com/p/blender-addons-by-mifth/",
+    "tracker_url": "http://code.google.com/p/blender-addons-by-mifth/issues/list",
+    "category": "UV"}
+
+import bpy
+from bpy.types import (Operator,
+                       Panel,
+                       PropertyGroup,
+                       )
+
+from bpy.props import (BoolProperty,
+                       CollectionProperty,
+                       EnumProperty,
+                       FloatProperty,
+                       IntProperty,
+                       StringProperty,
+                       )
+import mathutils
+
+
+def check_all_objects_visible(self, context):
+    scene = context.scene
+    group = scene.ms_lightmap_groups[scene.ms_lightmap_groups_index]
+    isAllObjectsVisible = True
+    bpy.ops.object.select_all(action='DESELECT')
+    for thisObject in bpy.data.groups[group.name].objects:
+        isThisObjectVisible = False
+        # scene.objects.active = thisObject
+        for thisLayerNumb in range(20):
+            if thisObject.layers[thisLayerNumb] is True and scene.layers[thisLayerNumb] is True:
+                isThisObjectVisible = True
+                break
+        # If Object is on an invisible Layer
+        if isThisObjectVisible is False:
+            isAllObjectsVisible = False
+    return isAllObjectsVisible
+
+
+def check_group_exist(self, context, use_report=True):
+    scene = context.scene
+    group = scene.ms_lightmap_groups[scene.ms_lightmap_groups_index]
+
+    if group.name in bpy.data.groups:
+        return True
+    else:
+        if use_report:
+            self.report({'INFO'}, "No Such Group %r!" % group.name)
+        return False
+
+
+class TextureAtlas(Panel):
+    bl_label = "Texture Atlas"
+    bl_space_type = 'PROPERTIES'
+    bl_region_type = 'WINDOW'
+    bl_context = "render"
+    COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+    def draw(self, context):
+        scene = context.scene
+        ob = context.object
+
+        col = self.layout.column()
+        row = self.layout.row()
+        split = self.layout.split()
+
+        row.template_list("UI_UL_list", "template_list_controls", scene,
+                          "ms_lightmap_groups", scene, "ms_lightmap_groups_index", rows=2, maxrows=5)
+        col = row.column(align=True)
+        col.operator("scene.ms_add_lightmap_group", icon='ZOOMIN', text="")
+        col.operator("scene.ms_del_lightmap_group", icon='ZOOMOUT', text="")
+
+        row = self.layout.row(align=True)
+
+        # Resolution and Unwrap types (only if Lightmap group is added)
+        if context.scene.ms_lightmap_groups:
+            group = scene.ms_lightmap_groups[scene.ms_lightmap_groups_index]
+            row.prop(group, 'resolution', text='Resolution', expand=True)
+            row = self.layout.row()
+            row.prop(group, 'unwrap_type', text='Lightmap', expand=True)
+            row = self.layout.row()
+
+            row = self.layout.row()
+            row.operator("scene.ms_remove_other_uv",
+                         text="RemoveOtherUVs", icon="GROUP")
+            row.operator("scene.ms_remove_selected",
+                         text="RemoveSelected", icon="GROUP")
+            row = self.layout.row()
+            row = self.layout.row()
+            row = self.layout.row()
+            row.operator("scene.ms_add_selected_to_group",
+                         text="AddSelected", icon="GROUP")
+            row.operator("scene.ms_select_group",
+                         text="SelectGroup", icon="GROUP")
+
+            row = self.layout.row()
+            row.operator(
+                "object.ms_auto", text="Auto Unwrap", icon="LAMP_SPOT")
+            row = self.layout.row()
+            row.operator(
+                "object.ms_run", text="StartManualUnwrap", icon="LAMP_SPOT")
+            row.operator(
+                "object.ms_run_remove", text="FinshManualUnwrap", icon="LAMP_SPOT")
+
+
+class RunAuto(Operator):
+    bl_idname = "object.ms_auto"
+    bl_label = "Auto Unwrapping"
+    bl_description = "Auto Unwrapping"
+
+    def execute(self, context):
+        scene = context.scene
+        old_context = context.area.type
+
+        # Check if group exists
+        if check_group_exist(self, context) is False:
+            return {'CANCELLED'}
+
+        group = scene.ms_lightmap_groups[scene.ms_lightmap_groups_index]
+        context.area.type = 'VIEW_3D'
+        if scene.objects.active is not None:
+            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+        if group.bake is True and bpy.data.groups[group.name].objects:
+
+            # Check if objects are all on the visible Layers.
+            isAllObjVisible = check_all_objects_visible(self, context)
+
+            if isAllObjVisible is True:
+                res = int(group.resolution)
+                bpy.ops.object.ms_create_lightmap(
+                    group_name=group.name, resolution=res)
+                bpy.ops.object.ms_merge_objects(
+                    group_name=group.name, unwrap=True)
+                bpy.ops.object.ms_separate_objects(group_name=group.name)
+            else:
+                self.report({'INFO'}, "Not All Objects Are Visible!!!")
+
+        context.area.type = old_context
+
+        return{'FINISHED'}
+
+
+class RunStart(Operator):
+    bl_idname = "object.ms_run"
+    bl_label = "Make Manual Unwrapping Object"
+    bl_description = "Makes Manual Unwrapping Object"
+
+    def execute(self, context):
+        scene = context.scene
+        # old_context = context.area.type
+
+        # Check if group exists
+        if check_group_exist(self, context) is False:
+            return {'CANCELLED'}
+
+        group = scene.ms_lightmap_groups[scene.ms_lightmap_groups_index]
+
+        if scene.objects.active is not None:
+            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+        if group.bake is True and bpy.data.groups[group.name].objects and bpy.data.objects.get(group.name + "_mergedObject") is None:
+
+            # Check if objects are all on the visible Layers.
+            isAllObjVisible = check_all_objects_visible(self, context)
+
+            if isAllObjVisible is True:
+                res = int(group.resolution)
+                bpy.ops.object.ms_create_lightmap(
+                    group_name=group.name, resolution=res)
+                bpy.ops.object.ms_merge_objects(
+                    group_name=group.name, unwrap=False)
+            else:
+                self.report({'INFO'}, "Not All Objects Are Visible!!!")
+
+        return{'FINISHED'}
+
+
+class RunFinish(Operator):
+    bl_idname = "object.ms_run_remove"
+    bl_label = "Remove Manual Unwrapping Object"
+    bl_description = "Removes Manual Unwrapping Object"
+
+    def execute(self, context):
+        scene = context.scene
+        old_context = context.area.type
+
+        # Check if group exists
+        if check_group_exist(self, context) is False:
+            return {'CANCELLED'}
+
+        group = scene.ms_lightmap_groups[scene.ms_lightmap_groups_index]
+        context.area.type = 'VIEW_3D'
+
+        if scene.objects.active is not None:
+            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+        if group.bake is True and bpy.data.groups[group.name].objects:
+
+            # Check if objects are all on the visible Layers.
+            isAllObjVisible = check_all_objects_visible(self, context)
+
+            if isAllObjVisible is True:
+                bpy.ops.object.ms_separate_objects(group_name=group.name)
+            else:
+                self.report({'INFO'}, "Not All Objects Are Visible!!!")
+
+        context.area.type = old_context
+        return{'FINISHED'}
+
+
+class MSUVLayers(PropertyGroup):
+    name = StringProperty(default="")
+
+
+class MSVertexGroups(PropertyGroup):
+    name = StringProperty(default="")
+
+
+class MSGroups(PropertyGroup):
+    name = StringProperty(default="")
+
+
+class MSLightmapGroups(PropertyGroup):
+
+    name = StringProperty(default="")
+    bake = BoolProperty(default=True)
+
+    unwrap_type = EnumProperty(
+        name="unwrap_type",
+        items=(('0', 'Smart_Unwrap', 'Smart_Unwrap'),
+               ('1', 'Lightmap', 'Lightmap'),
+               ('2', 'No_Unwrap', 'No_Unwrap'),
+               ),
+    )
+    resolution = EnumProperty(
+        name="resolution",
+        items=(('256', '256', ''),
+               ('512', '512', ''),
+               ('1024', '1024', ''),
+               ('2048', '2048', ''),
+               ('4096', '4096', ''),
+               ('8192', '8192', ''),
+               ('16384', '16384', ''),
+               ),
+    )
+    template_list_controls = StringProperty(
+        default="bake",
+        options={"HIDDEN"},
+    )
+
+
+class MSMergedObjects(PropertyGroup):
+    name = StringProperty()
+    vertex_groups = CollectionProperty(
+        type=MSVertexGroups,
+    )
+    groups = CollectionProperty(type=MSGroups)
+    uv_layers = CollectionProperty(type=MSUVLayers)
+
+
+class AddSelectedToGroup(Operator):
+    bl_idname = "scene.ms_add_selected_to_group"
+    bl_label = "Add to Group"
+    bl_description = "Adds selected Objects to current Group"
+
+    def execute(self, context):
+        scene = context.scene
+        group_name = scene.ms_lightmap_groups[
+            scene.ms_lightmap_groups_index].name
+
+        # Create a New Group if it was deleted.
+        obj_group = bpy.data.groups.get(group_name)
+        if obj_group is None:
+            obj_group = bpy.data.groups.new(group_name)
+
+        # Add objects to  a group
+        if scene.objects.active is not None:
+            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+        for object in context.selected_objects:
+            if object.type == 'MESH' and object.name not in obj_group.objects:
+                obj_group.objects.link(object)
+
+        return {'FINISHED'}
+
+
+class SelectGroup(Operator):
+    bl_idname = "scene.ms_select_group"
+    bl_label = "sel Group"
+    bl_description = "Selected Objects of current Group"
+
+    def execute(self, context):
+        scene = context.scene
+        group_name = scene.ms_lightmap_groups[
+            scene.ms_lightmap_groups_index].name
+
+        # Check if group exists
+        if check_group_exist(self, context) is False:
+            return {'CANCELLED'}
+
+        if scene.objects.active is not None:
+            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+        bpy.ops.object.select_all(action='DESELECT')
+        obj_group = bpy.data.groups[group_name]
+        for object in obj_group.objects:
+            object.select = True
+        return {'FINISHED'}
+
+
+class RemoveFromGroup(Operator):
+    bl_idname = "scene.ms_remove_selected"
+    bl_label = "del Selected"
+    bl_description = "Remove Selected Group and UVs"
+
+        # remove all modifiers
+        # for m in mesh.modifiers:
+            # bpy.ops.object.modifier_remove(modifier=m.name)
+
+    def execute(self, context):
+        scene = context.scene
+
+        # Check if group exists
+        if check_group_exist(self, context) is False:
+            return {'CANCELLED'}
+
+        if scene.objects.active is not None:
+            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+        for group in scene.ms_lightmap_groups:
+            group_name = group.name
+
+            obj_group = bpy.data.groups[group_name]
+            for object in context.selected_objects:
+                scene.objects.active = object
+
+                if object.type == 'MESH' and object.name in obj_group.objects:
+
+                    # remove UV
+                    tex = object.data.uv_textures.get(group_name)
+                    if tex is not None:
+                        object.data.uv_textures.remove(tex)
+
+                    # remove from group
+                    obj_group.objects.unlink(object)
+                    object.hide_render = False
+
+        return {'FINISHED'}
+
+
+class RemoveOtherUVs(Operator):
+    bl_idname = "scene.ms_remove_other_uv"
+    bl_label = "remOther"
+    bl_description = "Remove Other UVs from Selected"
+
+    def execute(self, context):
+        scene = context.scene
+        group_name = scene.ms_lightmap_groups[
+            scene.ms_lightmap_groups_index].name
+
+        # Check if group exists
+        if check_group_exist(self, context) is False:
+            return {'CANCELLED'}
+
+        if scene.objects.active is not None:
+            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+        # bpy.ops.object.select_all(action='DESELECT')
+
+        obj_group = bpy.data.groups[group_name]
+
+        # Remove other UVs of selected objects
+        for object in context.selected_objects:
+            scene.objects.active = object
+            if object.type == 'MESH' and object.name in obj_group.objects:
+
+                # remove UVs
+                UVLIST = []
+                for uv in object.data.uv_textures:
+                    if uv.name != group_name:
+                        UVLIST.append(uv.name)
+
+                for uvName in UVLIST:
+                    tex = object.data.uv_textures[uvName]
+                    object.data.uv_textures.remove(tex)
+
+                UVLIST.clear()  # clear array
+
+        return {'FINISHED'}
+
+
+class AddLightmapGroup(Operator):
+    bl_idname = "scene.ms_add_lightmap_group"
+    bl_label = "add Lightmap"
+    bl_description = "Adds a new Lightmap Group"
+
+    name = StringProperty(name="Group Name", default='TextureAtlas')
+
+    def execute(self, context):
+        scene = context.scene
+        obj_group = bpy.data.groups.new(self.name)
+
+        item = scene.ms_lightmap_groups.add()
+        item.name = obj_group.name
+        item.resolution = '1024'
+        scene.ms_lightmap_groups_index = len(scene.ms_lightmap_groups) - 1
+
+        # if len(context.selected_objects) > 0:
+        for object in context.selected_objects:
+            # scene.objects.active = object
+            if context.active_object.type == 'MESH':
+                obj_group.objects.link(object)
+
+        return {'FINISHED'}
+
+    def invoke(self, context, event):
+        wm = context.window_manager
+        return wm.invoke_props_dialog(self)
+
+
+class DelLightmapGroup(Operator):
+    bl_idname = "scene.ms_del_lightmap_group"
+    bl_label = "delete Lightmap"
+    bl_description = "Deletes active Lightmap Group"
+
+    def execute(self, context):
+        scene = context.scene
+        if len(scene.ms_lightmap_groups) > 0:
+            idx = scene.ms_lightmap_groups_index
+            group_name = scene.ms_lightmap_groups[idx].name
+
+            # Remove Group
+            group = bpy.data.groups.get(group_name)
+            if group is not None:
+
+                # Unhide Objects if they are hidden
+                for obj in group.objects:
+                    obj.hide_render = False
+                    obj.hide = False
+
+                bpy.data.groups.remove(group)
+
+            # Remove Lightmap Group
+            scene.ms_lightmap_groups.remove(scene.ms_lightmap_groups_index)
+            scene.ms_lightmap_groups_index -= 1
+            if scene.ms_lightmap_groups_index < 0:
+                scene.ms_lightmap_groups_index = 0
+
+        return {'FINISHED'}
+
+
+class CreateLightmap(Operator):
+    bl_idname = "object.ms_create_lightmap"
+    bl_label = "TextureAtlas - Generate Lightmap"
+    bl_description = "Generates a Lightmap"
+
+    group_name = StringProperty(default='')
+    resolution = IntProperty(default=1024)
+
+    def execute(self, context):
+        scene = context.scene
+
+        # Create/Update Image
+        image = bpy.data.images.get(self.group_name)
+        if image is None:
+            image = bpy.data.images.new(
+                name=self.group_name, width=self.resolution, height=self.resolution)
+
+        image.generated_type = 'COLOR_GRID'
+        image.generated_width = self.resolution
+        image.generated_height = self.resolution
+
+        for object in bpy.data.groups[self.group_name].objects:
+            if object.data.uv_textures.active is None:
+                tex = object.data.uv_textures.new()
+                tex.name = self.group_name
+            else:
+                if self.group_name not in object.data.uv_textures:
+                    tex = object.data.uv_textures.new()
+                    tex.name = self.group_name
+                    tex.active = True
+                    tex.active_render = True
+                else:
+                    tex = object.data.uv_textures[self.group_name]
+                    tex.active = True
+                    tex.active_render = True
+
+            for face_tex in tex.data:
+                face_tex.image = image
+        return{'FINISHED'}
+
+
+class MergeObjects(Operator):
+    bl_idname = "object.ms_merge_objects"
+    bl_label = "TextureAtlas - MergeObjects"
+    bl_description = "Merges Objects and stores Origins"
+
+    group_name = StringProperty(default='')
+    unwrap = BoolProperty(default=False)
+
+    def execute(self, context):
+        scene = context.scene
+
+        # objToDelete = None
+        bpy.ops.object.select_all(action='DESELECT')
+        for obj in scene.objects:
+            if obj.name == self.group_name + "_mergedObject":
+                obj.select = True
+                scene.objects.active = obj
+                bpy.ops.object.delete(use_global=False)
+
+        me = bpy.data.meshes.new(self.group_name + '_mergedObject')
+        ob_merge = bpy.data.objects.new(self.group_name + '_mergedObject', me)
+        ob_merge.location = scene.cursor_location   # position object at 3d-cursor
+        scene.objects.link(ob_merge)                # Link object to scene
+        me.update()
+        ob_merge.select = False
+
+        activeNowObject = bpy.data.groups[self.group_name].objects[0]
+        bpy.ops.object.select_all(action='DESELECT')
+
+        OBJECTLIST = bpy.data.groups[self.group_name].objects[:]
+        for obj in OBJECTLIST:
+            obj.select = True
+        scene.objects.active = activeNowObject
+
+        # Make Object Single User
+        # bpy.ops.object.make_single_user(type='SELECTED_OBJECTS', object=True,
+        # obdata=True, material=False, texture=False, animation=False)
+        for object in OBJECTLIST:
+
+            bpy.ops.object.select_all(action='DESELECT')
+            object.select = True
+
+            # activate lightmap uv if existant
+            for uv in object.data.uv_textures:
+                if uv.name == self.group_name:
+                    uv.active = True
+                    scene.objects.active = object
+
+            # generate temp Duplicate Objects with copied modifier,properties
+            # and logic bricks
+            bpy.ops.object.select_all(action='DESELECT')
+            object.select = True
+            scene.objects.active = object
+            bpy.ops.object.duplicate(linked=False, mode='TRANSLATION')
+            activeNowObject = scene.objects.active
+            activeNowObject.select = True
+
+            # hide render of original mesh
+            object.hide_render = True
+            object.hide = True
+            object.select = False
+
+            # remove unused UV
+            # remove UVs
+            UVLIST = []
+            for uv in activeNowObject.data.uv_textures:
+                if uv.name != self.group_name:
+                    UVLIST.append(uv.name)
+
+            for uvName in UVLIST:
+                tex = activeNowObject.data.uv_textures[uvName]
+                activeNowObject.data.uv_textures.remove(tex)
+
+            UVLIST.clear()  # clear array
+
+            # create vertex groups for each selected object
+            scene.objects.active = activeNowObject
+            vgroup = activeNowObject.vertex_groups.new(name=object.name)
+            vgroup.add(
+                list(range(len(activeNowObject.data.vertices))), weight=1.0, type='ADD')
+
+            # save object name and object location in merged object
+            item = ob_merge.ms_merged_objects.add()
+            item.name = object.name
+
+            # merge objects together
+            bpy.ops.object.select_all(action='DESELECT')
+            activeNowObject.select = True
+            ob_merge.select = True
+            scene.objects.active = ob_merge
+            bpy.ops.object.join()
+
+        OBJECTLIST.clear()  # clear array
+
+        # make Unwrap
+        bpy.ops.object.select_all(action='DESELECT')
+        ob_merge.select = True
+        scene.objects.active = ob_merge
+        bpy.ops.object.mode_set(mode='EDIT')
+        bpy.ops.mesh.select_all(action='SELECT')
+
+        if self.unwrap is True and scene.ms_lightmap_groups[self.group_name].unwrap_type == '0':
+            bpy.ops.uv.smart_project(
+                angle_limit=72.0, island_margin=0.2, user_area_weight=0.0)
+        elif self.unwrap is True and scene.ms_lightmap_groups[self.group_name].unwrap_type == '1':
+            bpy.ops.uv.lightmap_pack(
+                PREF_CONTEXT='ALL_FACES', PREF_PACK_IN_ONE=True, PREF_NEW_UVLAYER=False,
+                PREF_APPLY_IMAGE=False, PREF_IMG_PX_SIZE=1024, PREF_BOX_DIV=48, PREF_MARGIN_DIV=0.2)
+        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+        # remove all materials
+        # for material in ob_merge.material_slots:
+            # bpy.ops.object.material_slot_remove()
+
+        return{'FINISHED'}
+
+
+class SeparateObjects(Operator):
+    bl_idname = "object.ms_separate_objects"
+    bl_label = "TextureAtlas - Separate Objects"
+    bl_description = "Separates Objects and restores Origin"
+
+    group_name = StringProperty(default='')
+
+    def execute(self, context):
+        scene = context.scene
+
+        for obj in scene.objects:
+            if obj.name == self.group_name + "_mergedObject":
+
+                # if scene.objects.active is not None:
+                    # bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+                bpy.ops.object.select_all(action='DESELECT')
+                ob_merged = obj
+                obj.hide = False
+                ob_merged.select = True
+                groupSeparate = bpy.data.groups.new(ob_merged.name)
+                groupSeparate.objects.link(ob_merged)
+                ob_merged.select = False
+
+                for ms_obj in ob_merged.ms_merged_objects:
+                    # select vertex groups and separate group from merged
+                    # object
+                    bpy.ops.object.select_all(action='DESELECT')
+                    ob_merged.select = True
+                    scene.objects.active = ob_merged
+
+                    bpy.ops.object.mode_set(mode='EDIT')
+                    bpy.ops.mesh.select_all(action='DESELECT')
+                    ob_merged.vertex_groups.active_index = ob_merged.vertex_groups[
+                        ms_obj.name].index
+                    bpy.ops.object.vertex_group_select()
+                    bpy.ops.mesh.separate(type='SELECTED')
+                    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+                    # scene.objects.active.select = False
+
+                    # find separeted object
+                    ob_separeted = None
+                    for obj in groupSeparate.objects:
+                        if obj != ob_merged:
+                            ob_separeted = obj
+                            break
+
+                    # Copy UV Coordinates to the original mesh
+                    if ms_obj.name in scene.objects:
+                        ob_merged.select = False
+                        ob_original = scene.objects[ms_obj.name]
+                        ob_original.hide = False
+                        ob_original.select = True
+                        scene.objects.active = ob_separeted
+                        bpy.ops.object.join_uvs()
+                        ob_original.hide_render = False
+
+                    # delete separeted object
+                    bpy.ops.object.select_all(action='DESELECT')
+                    ob_separeted.select = True
+                    bpy.ops.object.delete(use_global=False)
+
+                # delete duplicated object
+                bpy.ops.object.select_all(action='DESELECT')
+                ob_merged.select = True
+                bpy.ops.object.delete(use_global=False)
+
+        return{'FINISHED'}
+
+
+def register():
+    bpy.utils.register_class(TextureAtlas)
+
+    bpy.utils.register_class(AddLightmapGroup)
+    bpy.utils.register_class(DelLightmapGroup)
+    bpy.utils.register_class(AddSelectedToGroup)
+    bpy.utils.register_class(SelectGroup)
+    bpy.utils.register_class(RemoveFromGroup)
+    bpy.utils.register_class(RemoveOtherUVs)
+
+    bpy.utils.register_class(RunAuto)
+    bpy.utils.register_class(RunStart)
+    bpy.utils.register_class(RunFinish)
+    bpy.utils.register_class(MergeObjects)
+    bpy.utils.register_class(SeparateObjects)
+    bpy.utils.register_class(CreateLightmap)
+
+    # types
+    bpy.utils.register_class(MSUVLayers)
+    bpy.utils.register_class(MSVertexGroups)
+    bpy.utils.register_class(MSGroups)
+
+    bpy.utils.register_class(MSMergedObjects)
+    bpy.types.Object.ms_merged_objects = CollectionProperty(
+        type=MSMergedObjects)
+
+    bpy.utils.register_class(MSLightmapGroups)
+    bpy.types.Scene.ms_lightmap_groups = CollectionProperty(
+        type=MSLightmapGroups)
+    bpy.types.Scene.ms_lightmap_groups_index = IntProperty()
+
+
+def unregister():
+    bpy.utils.unregister_class(TextureAtlas)
+
+    bpy.utils.unregister_class(AddLightmapGroup)
+    bpy.utils.unregister_class(DelLightmapGroup)
+    bpy.utils.unregister_class(AddSelectedToGroup)
+    bpy.utils.unregister_class(SelectGroup)
+    bpy.utils.unregister_class(RemoveFromGroup)
+    bpy.utils.unregister_class(RemoveOtherUVs)
+
+    bpy.utils.unregister_class(RunAuto)
+    bpy.utils.unregister_class(RunStart)
+    bpy.utils.unregister_class(RunFinish)
+    bpy.utils.unregister_class(MergeObjects)
+    bpy.utils.unregister_class(SeparateObjects)
+    bpy.utils.unregister_class(CreateLightmap)
+
+    # types
+    bpy.utils.unregister_class(MSUVLayers)
+    bpy.utils.unregister_class(MSVertexGroups)
+    bpy.utils.unregister_class(MSGroups)
+
+    bpy.utils.unregister_class(MSMergedObjects)
+
+    bpy.utils.unregister_class(MSLightmapGroups)
+
+
+if __name__ == "__main__":
+    register()