Skip to content
Snippets Groups Projects
__init__.py 71.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • # SPDX-License-Identifier: GPL-2.0-or-later
    
    bl_info = {
    
        "name": "3D-Coat Applink",
        "author": "Kalle-Samuli Riihikoski (haikalle)",
    
        "version": (4, 9, 34),
    
        "blender": (2, 80, 0),
    
        "location": "Scene > 3D-Coat Applink",
    
        "description": "Transfer data between 3D-Coat/Blender",
        "warning": "",
    
        "doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/coat3D.html",
    
        "category": "Import-Export",
    
    if "bpy" in locals():
    
        import importlib
        importlib.reload(tex)
    
    else:
        from . import tex
    
    from bpy.app.handlers import persistent
    
    from io_coat3D import tex
    
    from io_coat3D import texVR
    
    from io_coat3D import folders
    
    import ntpath
    import re
    
    import subprocess
    
    from bpy.types import PropertyGroup
    from bpy.props import (
            BoolProperty,
            EnumProperty,
            FloatVectorProperty,
            StringProperty,
            PointerProperty,
            )
    
    only_one_time = True
    
    global_exchange_folder = ''
    
    foundExchangeFolder = True
    
    saved_exchange_folder = ''
    
    liveUpdate = True
    mTime = 0
    
    @persistent
    def every_3_seconds():
    
        global global_exchange_folder
        global liveUpdate
        global mTime
    
        global only_one_time
    
        if(only_one_time):
            only_one_time = False
            folders.loadExchangeFolder()
    
        try:
            coat3D = bpy.context.scene.coat3D
    
            Export_folder  = coat3D.exchangeFolder
            Export_folder += ('%sexport.txt' % (os.sep))
    
            if (os.path.isfile(Export_folder) and mTime != os.path.getmtime(Export_folder)):
    
                for objekti in bpy.data.objects:
                    if(objekti.coat3D.applink_mesh):
                        tex.updatetextures(objekti)
    
                mTime = os.path.getmtime(Export_folder)
    
        except:
            pass
    
        return 3.0
    
    @persistent
    def load_handler(dummy):
        bpy.app.timers.register(every_3_seconds)
    
    
    def removeFile(exportfile):
        if (os.path.isfile(exportfile)):
            os.remove(exportfile)
    
    
        folder_size_max = int(bpy.context.scene.coat3D.folder_size)
    
        if(bpy.context.scene.coat3D.defaultfolder == ''):
            tosi = True
            while tosi:
                list_of_files = []
                for file in os.listdir(path):
                    list_of_files.append(path + os.sep + file)
    
                if len(list_of_files) >= folder_size_max:
                    oldest_file = min(list_of_files, key=os.path.getctime)
                    os.remove(os.path.abspath(oldest_file))
                else:
                    tosi = False
    
    
    def make_texture_list(texturefolder):
        texturefolder += ('%stextures.txt'%(os.sep))
        texturelist = []
    
        if (os.path.isfile(texturefolder)):
            texturefile = open(texturefolder)
            index = 0
            for line in texturefile:
                if line != '' and index == 0:
    
                    line = line.rstrip('\n')
    
                    objekti = line
                    index += 1
                elif index == 1:
    
                    line = line.rstrip('\n')
    
                    material = line
                    index += 1
                elif index == 2:
    
                    line = line.rstrip('\n')
    
                    line = line.rstrip('\n')
    
                    address = line
                    texturelist.append([objekti,material,type,address])
                    index = 0
            texturefile.close()
        return texturelist
    
    #Updating objects MESH part ( Mesh, Vertex Groups, Vertex Colors )
    
    def updatemesh(objekti, proxy, texturelist):
    
        # Vertex colors
        if(len(proxy.data.vertex_colors) > 0):
            bring_vertex_map = True
        else:
            bring_vertex_map = False
    
        if(bring_vertex_map):
            if(len(objekti.data.vertex_colors) > 0):
                for vertex_map in objekti.data.vertex_colors:
                    if vertex_map.name == 'Col':
                        copy_data = True
                        vertex_map_copy = vertex_map
                        break
                    else:
                        copy_data = False
            else:
                copy_data = False
    
            if(copy_data):
                for poly in objekti.data.polygons:
                    for loop_index in poly.loop_indices:
                        vertex_map_copy.data[loop_index].color = proxy.data.vertex_colors[0].data[loop_index].color
            else:
                objekti.data.vertex_colors.new()
                vertex_map_copy = objekti.data.vertex_colors[-1]
                for poly in objekti.data.polygons:
                    for loop_index in poly.loop_indices:
                        vertex_map_copy.data[loop_index].color = proxy.data.vertex_colors[0].data[loop_index].color
    
        if(texturelist != []):
            if(texturelist[0][0].startswith('100')):
                udim_textures =True
    
        proxy.select_set(True)
        objekti.select_set(True)
    
        uv_count = len(proxy.data.uv_layers)
        index = 0
    
        while(index < uv_count and len(proxy.data.polygons) == len(objekti.data.polygons)):
    
            for poly in proxy.data.polygons:
                for indi in poly.loop_indices:
    
                    if(proxy.data.uv_layers[index].data[indi].uv[0] != 0 and proxy.data.uv_layers[index].data[indi].uv[1] != 0):
    
    
                        if(udim_textures):
                            udim = proxy.data.uv_layers[index].name
                            udim_index = int(udim[2:]) - 1
    
                        objekti.data.uv_layers[0].data[indi].uv[0] = proxy.data.uv_layers[index].data[indi].uv[0]
                        objekti.data.uv_layers[0].data[indi].uv[1] = proxy.data.uv_layers[index].data[indi].uv[1]
    
        if(proxy.name.startswith('RetopoGroup')):
            objekti.data = proxy.data
        else:
            for ind, v in enumerate(objekti.data.vertices):
                v.co = proxy.data.vertices[ind].co
    
    class SCENE_OT_getback(bpy.types.Operator):
        bl_idname = "getback.pilgway_3d_coat"
        bl_label = "Export your custom property"
        bl_description = "Export your custom property"
        bl_options = {'UNDO'}
    
        def invoke(self, context, event):
    
            global global_exchange_folder
            path_ex = ''
    
            Export_folder  = global_exchange_folder
            Blender_folder = os.path.join(Export_folder, 'Blender')
    
            BlenderFolder = Blender_folder
            ExportFolder = Export_folder
    
            Blender_folder += ('%sexport.txt' % (os.sep))
            Export_folder += ('%sexport.txt' % (os.sep))
    
            if (bpy.app.background == False):
                if os.path.isfile(Export_folder):
    
                    print('BLENDER -> 3DC -> BLENDER WORKFLLOW')
    
                    DeleteExtra3DC()
    
                    workflow1(ExportFolder)
                    removeFile(Export_folder)
    
                    removeFile(Blender_folder)
    
    
                elif os.path.isfile(Blender_folder):
    
                    print('3DC -> BLENDER WORKFLLOW')
    
                    DeleteExtra3DC()
    
                    workflow2(BlenderFolder)
                    removeFile(Blender_folder)
    
            return {'FINISHED'}
    
    
    class SCENE_OT_savenew(bpy.types.Operator):
        bl_idname = "save_new_export.pilgway_3d_coat"
        bl_label = "Export your custom property"
        bl_description = "Export your custom property"
        bl_options = {'UNDO'}
    
        def invoke(self, context, event):
    
            coat3D = bpy.context.scene.coat3D
            platform = os.sys.platform
    
            if(platform == 'win32' or platform == 'darwin'):
                exchangeFile = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt'
            else:
                exchangeFile = os.path.expanduser("~") + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt'
            if(os.path.isfile(exchangeFile)):
                folderPath = ''
    
            if(os.path.isfile(exchangeFile)):
                file = open(exchangeFile, "w")
                file.write("%s"%(coat3D.exchangeFolder))
    
                file.close()
    
    class SCENE_OT_folder(bpy.types.Operator):
        bl_idname = "update_exchange_folder.pilgway_3d_coat"
        bl_label = "Export your custom property"
        bl_description = "Export your custom property"
        bl_options = {'UNDO'}
    
        def invoke(self, context, event):
    
            global foundExchangeFolder
    
            if(os.path.isdir(coat3D.exchangeFolder)):
    
                foundExchangeFolder= True
    
                folders.updateExchangeFile(coat3D.exchangeFolder)
    
    class SCENE_OT_opencoat(bpy.types.Operator):
        bl_idname = "open_3dcoat.pilgway_3d_coat"
        bl_label = "Export your custom property"
        bl_description = "Export your custom property"
        bl_options = {'UNDO'}
    
        def invoke(self, context, event):
    
            coat3D = bpy.context.selected_objects[0].coat3D.applink_3b_path
    
            platform = os.sys.platform
    
            if (platform == 'win32' or platform == 'darwin'):
    
                importfile = bpy.context.scene.coat3D.exchangeFolder
    
                importfile += ('%simport.txt' % (os.sep))
                file = open(importfile, "w")
                file.write("%s" % (coat3D))
                file.write("\n%s" % (coat3D))
                file.write("\n[3B]")
                file.close()
    
                importfile = bpy.context.scene.coat3D.exchangeFolder
    
                importfile += ('%simport.txt' % (os.sep))
                file = open(importfile, "w")
                file.write("%s" % (coat3D))
                file.write("\n%s" % (coat3D))
                file.write("\n[3B]")
                file.close()
    
    
            return {'FINISHED'}
    
    
    def scaleParents():
        save = []
        names =[]
    
        for objekti in bpy.context.selected_objects:
            temp = objekti
            while (temp.parent is not None and temp.parent.name not in names):
                save.append([temp.parent,(temp.parent.scale[0],temp.parent.scale[1],temp.parent.scale[2])])
                names.append(temp.parent)
                temp = temp.parent
    
        for name in names:
            name.scale = (1,1,1)
    
        return save
    
    def scaleBackParents(save):
    
        for data in save:
            data[0].scale = data[1]
    
    
    def deleteNodes(type):
    
        deletelist = []
        deleteimages = []
        deletegroup =[]
        delete_images = bpy.context.scene.coat3D.delete_images
    
        if type == 'Material':
            if(len(bpy.context.selected_objects) == 1):
                material = bpy.context.selected_objects[0].active_material
                if(material.use_nodes):
                    for node in material.node_tree.nodes:
                        if(node.name.startswith('3DC')):
                            if (node.type == 'GROUP'):
                                deletegroup.append(node.node_tree.name)
                            deletelist.append(node.name)
                            if node.type == 'TEX_IMAGE' and delete_images == True:
                                deleteimages.append(node.image.name)
                    if deletelist:
                        for node in deletelist:
                            material.node_tree.nodes.remove(material.node_tree.nodes[node])
                    if deleteimages:
                        for image in deleteimages:
                            bpy.data.images.remove(bpy.data.images[image])
    
        elif type == 'Object':
            if (len(bpy.context.selected_objects) > 0):
                for objekti in bpy.context.selected_objects:
                    for material in objekti.material_slots:
                        if (material.material.use_nodes):
                            for node in material.material.node_tree.nodes:
                                if (node.name.startswith('3DC')):
                                    if(node.type == 'GROUP'):
                                        deletegroup.append(node.node_tree.name)
                                    deletelist.append(node.name)
                                    if node.type == 'TEX_IMAGE' and delete_images == True:
                                        deleteimages.append(node.image.name)
                        if deletelist:
                            for node in deletelist:
                                material.material.node_tree.nodes.remove(material.material.node_tree.nodes[node])
                                deletelist = []
    
                        if deleteimages:
                            for image in deleteimages:
                                bpy.data.images.remove(bpy.data.images[image])
                                deleteimages = []
    
        elif type == 'Collection':
            for collection_object in bpy.context.view_layer.active_layer_collection.collection.all_objects:
                if(collection_object.type == 'MESH'):
                    for material in collection_object.material_slots:
                        if (material.material.use_nodes):
                            for node in material.material.node_tree.nodes:
                                if (node.name.startswith('3DC')):
                                    if (node.type == 'GROUP'):
                                        deletegroup.append(node.node_tree.name)
                                    deletelist.append(node.name)
                                    if node.type == 'TEX_IMAGE' and delete_images == True:
                                        deleteimages.append(node.image.name)
    
                        if deletelist:
                            for node in deletelist:
                                material.material.node_tree.nodes.remove(material.material.node_tree.nodes[node])
                                deletelist = []
    
                        if deleteimages:
                            for image in deleteimages:
                                bpy.data.images.remove(bpy.data.images[image])
                                deleteimages = []
    
        elif type == 'Scene':
            for collection in bpy.data.collections:
                for collection_object in collection.all_objects:
                    if (collection_object.type == 'MESH'):
                        for material in collection_object.material_slots:
                            if (material.material.use_nodes):
                                for node in material.material.node_tree.nodes:
                                    if (node.name.startswith('3DC')):
                                        if (node.type == 'GROUP'):
                                            deletegroup.append(node.node_tree.name)
    
                                        deletelist.append(node.name)
                                        if node.type == 'TEX_IMAGE' and delete_images == True:
                                            deleteimages.append(node.image.name)
                            if deletelist:
                                for node in deletelist:
                                    material.material.node_tree.nodes.remove(material.material.node_tree.nodes[node])
                                    deletelist = []
    
                            if deleteimages:
                                for image in deleteimages:
                                    bpy.data.images.remove(bpy.data.images[image])
                                    deleteimages = []
    
            if(deletelist):
                for node in deletelist:
                    bpy.data.node_groups.remove(bpy.data.node_groups[node])
    
            for image in bpy.data.images:
                if (image.name.startswith('3DC') and image.name[6] == '_'):
                    deleteimages.append(image.name)
    
    
        if(deletegroup):
            for node in deletegroup:
                bpy.data.node_groups.remove(bpy.data.node_groups[node])
    
        if deleteimages:
            for image in deleteimages:
                bpy.data.images.remove(bpy.data.images[image])
    
    
    
    def delete_materials_from_end(keep_materials_count, objekti):
    
        #bpy.context.object.active_material_index = 0
    
        index_t = 0
        while (index_t < keep_materials_count):
            temp_len = len(objekti.material_slots)-1
            bpy.context.object.active_material_index = temp_len
            bpy.ops.object.material_slot_remove()
            index_t +=1
    
    
    ''' DELETE NODES BUTTONS'''
    
    class SCENE_OT_delete_material_nodes(bpy.types.Operator):
        bl_idname = "delete_material_nodes.pilgway_3d_coat"
        bl_label = "Delete material nodes"
        bl_description = "Delete material nodes"
        bl_options = {'UNDO'}
    
        def invoke(self, context, event):
            type = bpy.context.scene.coat3D.deleteMode = 'Material'
            deleteNodes(type)
            return {'FINISHED'}
    
    class SCENE_OT_delete_object_nodes(bpy.types.Operator):
        bl_idname = "delete_object_nodes.pilgway_3d_coat"
        bl_label = "Delete material nodes"
        bl_description = "Delete material nodes"
        bl_options = {'UNDO'}
    
        def invoke(self, context, event):
            type = bpy.context.scene.coat3D.deleteMode = 'Object'
            deleteNodes(type)
            return {'FINISHED'}
    
    class SCENE_OT_delete_collection_nodes(bpy.types.Operator):
        bl_idname = "delete_collection_nodes.pilgway_3d_coat"
        bl_label = "Delete material nodes"
        bl_description = "Delete material nodes"
        bl_options = {'UNDO'}
    
        def invoke(self, context, event):
            type = bpy.context.scene.coat3D.deleteMode = 'Collection'
            deleteNodes(type)
            return {'FINISHED'}
    
    class SCENE_OT_delete_scene_nodes(bpy.types.Operator):
        bl_idname = "delete_scene_nodes.pilgway_3d_coat"
        bl_label = "Delete material nodes"
        bl_description = "Delete material nodes"
        bl_options = {'UNDO'}
    
        def invoke(self, context, event):
            type = bpy.context.scene.coat3D.deleteMode = 'Scene'
            deleteNodes(type)
            return {'FINISHED'}
    
    
    ''' TRANSFER AND UPDATE BUTTONS'''
    
    
    class SCENE_OT_export(bpy.types.Operator):
        bl_idname = "export_applink.pilgway_3d_coat"
        bl_label = "Export your custom property"
        bl_description = "Export your custom property"
        bl_options = {'UNDO'}
    
        def invoke(self, context, event):
    
            bpy.ops.export_applink.pilgway_3d_coat()
    
            return {'FINISHED'}
    
        def execute(self, context):
    
            global foundExchangeFolder
    
            global global_exchange_folder
    
            global run_background_update
            run_background_update = False
    
    
            foundExchangeFolder, global_exchange_folder = folders.InitFolders()
    
    
    Kalle-Samuli Riihikoski's avatar
    Kalle-Samuli Riihikoski committed
            for mesh in bpy.data.meshes:
    
                if (mesh.users == 0 and mesh.coat3D.name == '3DC'):
    
    Kalle-Samuli Riihikoski's avatar
    Kalle-Samuli Riihikoski committed
                    bpy.data.meshes.remove(mesh)
    
            for material in bpy.data.materials:
    
                if (material.users == 1 and material.coat3D.name == '3DC'):
    
    Kalle-Samuli Riihikoski's avatar
    Kalle-Samuli Riihikoski committed
                    bpy.data.materials.remove(material)
    
            export_ok = False
    
            coat3D = bpy.context.scene.coat3D
    
            if (bpy.context.selected_objects == []):
    
                return {'FINISHED'}
            else:
                for objec in bpy.context.selected_objects:
                    if objec.type == 'MESH':
    
                        if(len(objec.data.uv_layers) == 0):
                            objec.data.uv_layers.new(name='UVMap', do_init = False)
    
    
            activeobj = bpy.context.active_object.name
            checkname = ''
            coa = bpy.context.active_object.coat3D
    
    
            p = pathlib.Path(coat3D.exchangeFolder)
            kokeilu = coat3D.exchangeFolder[:-9]
    
            Blender_folder2 = ("%s%sExchange" % (kokeilu, os.sep))
            Blender_folder2 += ('%sexport.txt' % (os.sep))
    
            if (os.path.isfile(Blender_folder2)):
                os.remove(Blender_folder2)
    
            if (not os.path.isdir(coat3D.exchangeFolder)):
    
                coat3D.exchange_found = False
                return {'FINISHED'}
    
            folder_objects = folders.set_working_folders()
    
            importfile = coat3D.exchangeFolder
            texturefile = coat3D.exchangeFolder
    
            importfile += ('%simport.txt'%(os.sep))
            texturefile += ('%stextures.txt'%(os.sep))
    
            looking = True
            object_index = 0
    
            active_render =  bpy.context.scene.render.engine
    
            if(coat3D.type == 'autopo'):
                checkname = folder_objects + os.sep
                checkname = ("%sretopo.fbx" % (checkname))
    
    
            elif(coat3D.type == 'update'):
                checkname = bpy.context.selected_objects[0].coat3D.applink_address
    
    
            else:
                while(looking == True):
                    checkname = folder_objects + os.sep + "3DC"
                    checkname = ("%s%.3d.fbx"%(checkname,object_index))
                    if(os.path.isfile(checkname)):
                        object_index += 1
                    else:
                        looking = False
                        coa.applink_name = ("%s%.2d"%(activeobj,object_index))
                        coa.applink_address = checkname
    
    Kalle-Samuli Riihikoski's avatar
    Kalle-Samuli Riihikoski committed
            matindex = 0
    
            for objekti in bpy.context.selected_objects:
    
                if objekti.type == 'MESH':
                    objekti.name = '__' + objekti.name
                    if(objekti.material_slots.keys() == []):
                        newmat = bpy.data.materials.new('Material')
                        newmat.use_nodes = True
                        objekti.data.materials.append(newmat)
                        matindex += 1
                    objekti.coat3D.applink_name = objekti.name
    
            mod_mat_list = {}
    
    
            bake_location = folder_objects + os.sep + 'Bake'
            if (os.path.isdir(bake_location)):
                shutil.rmtree(bake_location)
                os.makedirs(bake_location)
            else:
                os.makedirs(bake_location)
    
            for objekti in bpy.context.selected_objects:
    
                if objekti.type == 'MESH':
                    mod_mat_list[objekti.name] = []
                    objekti.coat3D.applink_scale = objekti.scale
                    objekti.coat3D.retopo = False
    
                    ''' Checks what materials are linked into UV '''
    
                    if(coat3D.type == 'ppp'):
                        final_material_indexs = []
                        uvtiles_index = []
                        for poly in objekti.data.polygons:
                            if(poly.material_index not in final_material_indexs):
                                final_material_indexs.append(poly.material_index)
                                loop_index = poly.loop_indices[0]
                                uvtiles_index.append([poly.material_index,objekti.data.uv_layers.active.data[loop_index].uv[0]])
                            if(len(final_material_indexs) == len(objekti.material_slots)):
                                break
    
                        material_index = 0
                        if (len(final_material_indexs) != len(objekti.material_slots)):
    
                            for material in objekti.material_slots:
    
                                if material_index not in final_material_indexs:
                                    temp_mat = material.material
                                    material.material = objekti.material_slots[0].material
                                    mod_mat_list[objekti.name].append([material_index, temp_mat])
                                material_index = material_index + 1
    
                        bake_list = []
                        if(coat3D.bake_diffuse):
                            bake_list.append(['DIFFUSE', '$LOADTEX'])
                        if (coat3D.bake_ao):
                            bake_list.append(['AO', '$ExternalAO'])
                        if (coat3D.bake_normal):
                            bake_list.append(['NORMAL', '$LOADLOPOLYTANG'])
                        if (coat3D.bake_roughness):
                            bake_list.append(['ROUGHNESS', '$LOADROUGHNESS'])
    
                        if(coat3D.bake_resolution == 'res_64'):
                            res_size = 64
                        elif (coat3D.bake_resolution == 'res_128'):
                            res_size = 128
                        elif (coat3D.bake_resolution == 'res_256'):
                            res_size = 256
                        elif (coat3D.bake_resolution == 'res_512'):
                            res_size = 512
                        elif (coat3D.bake_resolution == 'res_1024'):
                            res_size = 1024
                        elif (coat3D.bake_resolution == 'res_2048'):
                            res_size = 2048
                        elif (coat3D.bake_resolution == 'res_4096'):
                            res_size = 4096
                        elif (coat3D.bake_resolution == 'res_8192'):
                            res_size = 8192
    
                        if(len(bake_list) > 0):
                            index_bake_tex = 0
                            while(index_bake_tex < len(bake_list)):
                                bake_index = 0
                                for bake_mat_index in final_material_indexs:
                                    bake_node = objekti.material_slots[bake_mat_index].material.node_tree.nodes.new('ShaderNodeTexImage')
                                    bake_node.name = 'ApplinkBake' + str(bake_index)
                                    bpy.ops.image.new(name=bake_node.name, width=res_size, height=res_size)
                                    bake_node.image = bpy.data.images[bake_node.name]
                                    objekti.material_slots[bake_mat_index].material.node_tree.nodes.active = bake_node
    
                                    bake_index += 1
                                if(bpy.context.scene.render.engine != 'CYCLES'):
                                    bpy.context.scene.render.engine = 'CYCLES'
                                bpy.context.scene.render.bake.use_pass_direct = False
                                bpy.context.scene.render.bake.use_pass_indirect = False
                                bpy.context.scene.render.bake.use_pass_color = True
    
                                bpy.ops.object.bake(type=bake_list[index_bake_tex][0], margin=1, width=res_size, height=res_size)
    
                                bake_index = 0
                                for bake_mat_index in final_material_indexs:
                                    bake_image = 'ApplinkBake' + str(bake_index)
                                    bpy.data.images[bake_image].filepath_raw = bake_location + os.sep + objekti.name + '_' + bake_image + '_' + bake_list[index_bake_tex][0] + ".png"
                                    image_bake_name =  bpy.data.images[bake_image].filepath_raw
                                    tie = image_bake_name.split(os.sep)
                                    toi = ''
                                    for sana in tie:
                                        toi += sana
                                        toi += "/"
                                    final_bake_name = toi[:-1]
                                    bpy.data.images[bake_image].save()
                                    temp_string += '''\n[script ImportTexture("''' + bake_list[index_bake_tex][1] + '''","''' + objekti.material_slots[bake_mat_index].material.name + '''","''' +  final_bake_name + '''");]'''
    
                                    bake_index += 1
    
                                for material in objekti.material_slots:
                                    if material.material.use_nodes == True:
                                        for node in material.material.node_tree.nodes:
                                            if (node.name.startswith('ApplinkBake') == True):
                                                material.material.node_tree.nodes.remove(node)
    
                                for image in bpy.data.images:
                                    if (image.name.startswith('ApplinkBake') == True):
                                        bpy.data.images.remove(image)
    
                                index_bake_tex += 1
    
            #bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
    
            if(len(bpy.context.selected_objects) > 1 and coat3D.type != 'vox'):
                bpy.ops.object.transforms_to_deltas(mode='ROT')
    
            if(coat3D.type == 'autopo'):
                coat3D.bring_retopo = True
                coat3D.bring_retopo_path = checkname
    
                bpy.ops.export_scene.fbx(filepath=checkname, global_scale = 1, use_selection=True, use_mesh_modifiers=coat3D.exportmod, axis_forward='-Z', axis_up='Y')
    
    
            elif (coat3D.type == 'vox'):
                coat3D.bring_retopo = False
    
                bpy.ops.export_scene.fbx(filepath=coa.applink_address, global_scale = 0.01, use_selection=True,
    
                                         use_mesh_modifiers=coat3D.exportmod, axis_forward='-Z', axis_up='Y')
    
    
            else:
                coat3D.bring_retopo = False
    
                bpy.ops.export_scene.fbx(filepath=coa.applink_address,global_scale = 0.01, use_selection=True, use_mesh_modifiers=coat3D.exportmod, axis_forward='-Z', axis_up='Y')
    
    
            file = open(importfile, "w")
            file.write("%s"%(checkname))
            file.write("\n%s"%(checkname))
            file.write("\n[%s]"%(coat3D.type))
    
            if(coat3D.type == 'ppp' or coat3D.type == 'mv' or coat3D.type == 'ptex'):
                file.write("\n[export_preset Blender Cycles]")
                file.write(temp_string)
    
            for idx, objekti in enumerate(bpy.context.selected_objects):
    
                if objekti.type == 'MESH':
                    objekti.name = objekti.name[2:]
                    if(len(bpy.context.selected_objects) == 1):
                        objekti.coat3D.applink_onlyone = True
                    objekti.coat3D.type = coat3D.type
                    objekti.coat3D.applink_mesh = True
                    objekti.coat3D.obj_mat = ''
                    objekti.coat3D.applink_index = ("3DC%.3d" % (object_index))
    
                    objekti.coat3D.applink_firsttime = True
                    if(coat3D.type != 'autopo'):
                        objekti.coat3D.applink_address = coa.applink_address
                        objekti.coat3D.objecttime = str(os.path.getmtime(objekti.coat3D.applink_address))
                    objekti.data.coat3D.name = '3DC'
    
                    if(coat3D.type != 'vox'):
                        if(objekti.material_slots.keys() != []):
                            for material in objekti.material_slots:
                                if material.material.use_nodes == True:
                                    for node in material.material.node_tree.nodes:
                                        if(node.name.startswith('3DC_') == True):
                                            material.material.node_tree.nodes.remove(node)
    
                    for ind, mat_list in enumerate(mod_mat_list):
                        if(mat_list == '__' + objekti.name):
                            for ind, mat in enumerate(mod_mat_list[mat_list]):
                                objekti.material_slots[mod_mat_list[mat_list][ind][0]].material = mod_mat_list[mat_list][ind][1]
    
            bpy.context.scene.render.engine = active_render
    
        for node_group in bpy.data.node_groups:
            if(node_group.users == 0):
                bpy.data.node_groups.remove(node_group)
    
        for mesh in bpy.data.meshes:
            if(mesh.users == 0 and mesh.coat3D.name == '3DC'):
                bpy.data.meshes.remove(mesh)
    
        for material in bpy.data.materials:
            img_list = []
            if (material.users == 1 and material.coat3D.name == '3DC'):
                if material.use_nodes == True:
                    for node in material.node_tree.nodes:
                        if node.type == 'TEX_IMAGE' and node.name.startswith('3DC'):
                            img_list.append(node.image)
                if img_list != []:
                    for del_img in img_list:
                        bpy.data.images.remove(del_img)
    
                bpy.data.materials.remove(material)
    
        image_del_list = []
        for image in bpy.data.images:
            if (image.name.startswith('3DC')):
                if image.users == 0:
                    image_del_list.append(image.name)
    
        if (image_del_list != []):
            for image in image_del_list:
                bpy.data.images.remove(bpy.data.images[image])
    
    def new_ref_function(new_applink_address, nimi):
    
        create_collection = True
        for collection in bpy.data.collections:
            if collection.name == 'Applink_Objects':
                create_collection = False
    
        if create_collection:
            bpy.data.collections.new('Applink_Objects')
    
        coll_items = bpy.context.scene.collection.children.items()
    
        add_applink_collection = True
        for coll in coll_items:
            if coll[0] == 'Applink_Objects':
                add_applink_collection = False
    
        if add_applink_collection:
            bpy.context.scene.collection.children.link(bpy.data.collections['Applink_Objects'])
    
        bpy.context.view_layer.active_layer_collection = bpy.context.view_layer.layer_collection.children['Applink_Objects']
    
        old_objects = bpy.data.objects.keys()
        object_list = []
    
        bpy.ops.import_scene.fbx(filepath=new_applink_address, global_scale = 0.01,axis_forward='X', axis_up='Y',use_custom_normals=False)
        new_objects = bpy.data.objects.keys()
        diff_objects = [i for i in new_objects if i not in old_objects]
        texturelist = []
    
        for diff_object in diff_objects:
    
            refmesh = bpy.data.objects[nimi]
            copymesh = bpy.data.objects[nimi].copy()
    
            copymesh.data = bpy.data.objects[diff_object].data
            copymesh.coat3D.applink_name = bpy.data.objects[diff_object].data.name
            copymesh.coat3D.applink_address = refmesh.coat3D.applink_address
            ne_name = bpy.data.objects[diff_object].data.name
    
            copymesh.coat3D.type = 'ppp'
            copymesh.coat3D.retopo = True
    
            bpy.data.collections['Applink_Objects'].objects.link(copymesh)
    
            bpy.data.objects.remove(bpy.data.objects[diff_object])
            bpy.ops.object.select_all(action='DESELECT')
            copymesh.select_set(True)
            copymesh.delta_rotation_euler[0] = 1.5708
            copymesh.name = ne_name
    
            normal_node = copymesh.material_slots[0].material.node_tree.nodes['Normal Map']
            copymesh.material_slots[0].material.node_tree.nodes.remove(normal_node)
            copymesh.material_slots[0].material.node_tree.nodes['Principled BSDF'].inputs['Metallic'].default_value = 0
            copymesh.material_slots[0].material.node_tree.nodes['Principled BSDF'].inputs['Specular'].default_value = 0.5
    
        refmesh.coat3D.applink_name = ''
        refmesh.coat3D.applink_address = ''
        refmesh.coat3D.type = ''
    
        copymesh.scale = (1,1,1)
        copymesh.coat3D.applink_scale = (1,1,1)
        copymesh.location = (0,0,0)
        copymesh.rotation_euler = (0,0,0)
    
    def blender_3DC_blender(texturelist, file_applink_address):
    
        coat3D = bpy.context.scene.coat3D
    
        old_materials = bpy.data.materials.keys()
        old_objects = bpy.data.objects.keys()
        cache_base = bpy.data.objects.keys()
    
        object_list = []
        import_list = []
        import_type = []
    
        for objekti in bpy.data.objects:
    
            if objekti.type == 'MESH' and objekti.coat3D.applink_address == file_applink_address:
    
                object_list.append(objekti.name)
                if(os.path.isfile(obj_coat.applink_address)):
                    if (obj_coat.objecttime != str(os.path.getmtime(obj_coat.applink_address))):
                        obj_coat.dime = objekti.dimensions
                        obj_coat.import_mesh = True
                        obj_coat.objecttime = str(os.path.getmtime(obj_coat.applink_address))
                        if(obj_coat.applink_address not in import_list):
                            import_list.append(obj_coat.applink_address)
                            import_type.append(coat3D.type)
    
        if(import_list or coat3D.importmesh):
            for idx, list in enumerate(import_list):
    
                bpy.ops.import_scene.fbx(filepath=list, global_scale = 0.01,axis_forward='X',use_custom_normals=False)
                cache_objects = bpy.data.objects.keys()
                cache_objects = [i for i in cache_objects if i not in cache_base]
                for cache_object in cache_objects:
    
                    bpy.data.objects[cache_object].coat3D.type = import_type[idx]
                    bpy.data.objects[cache_object].coat3D.applink_address = list
                    cache_base.append(cache_object)
    
            bpy.ops.object.select_all(action='DESELECT')
            new_materials = bpy.data.materials.keys()
            new_objects = bpy.data.objects.keys()
    
            diff_mat = [i for i in new_materials if i not in old_materials]
            diff_objects = [i for i in new_objects if i not in old_objects]
    
            for mark_mesh in diff_objects:
                bpy.data.objects[mark_mesh].data.coat3D.name = '3DC'
    
            for c_index in diff_mat:
                bpy.data.materials.remove(bpy.data.materials[c_index])
    
        '''The main Applink Object Loop'''
    
            objekti = bpy.data.objects[oname]
            if(objekti.coat3D.applink_mesh == True):
    
                path3b_n = coat3D.exchangeFolder
    
                path3b_n += ('%slast_saved_3b_file.txt' % (os.sep))
    
                if(objekti.coat3D.import_mesh and coat3D.importmesh == True):
    
                    objekti.coat3D.import_mesh = False
                    objekti.select_set(True)
    
                    use_smooth = objekti.data.polygons[0].use_smooth
                    found_obj = False
    
                    '''Changes objects mesh into proxy mesh'''
                    if(objekti.coat3D.type != 'ref'):
    
                        for proxy_objects in diff_objects:
                            if(objekti.coat3D.retopo == False):
                                if (proxy_objects == objekti.coat3D.applink_name):
                                    obj_proxy = bpy.data.objects[proxy_objects]
                                    obj_proxy.coat3D.delete_proxy_mesh = True
                                    found_obj = True
    
                                if (proxy_objects == objekti.coat3D.applink_name + '.001'):
                                    obj_proxy = bpy.data.objects[proxy_objects]
                                    obj_proxy.coat3D.delete_proxy_mesh = True
                                    found_obj = True
    
                    mat_list = []
                    if (objekti.material_slots):
                        for obj_mat in objekti.material_slots:
                            mat_list.append(obj_mat.material)
    
                    if(found_obj == True):
    
                        exportfile = coat3D.exchangeFolder
                        path3b_n = coat3D.exchangeFolder
    
                        path3b_n += ('%slast_saved_3b_file.txt' % (os.sep))
                        exportfile += ('%sBlender' % (os.sep))
                        exportfile += ('%sexport.txt'%(os.sep))
                        if(os.path.isfile(exportfile)):
                            export_file = open(exportfile)
                            export_file.close()
                            os.remove(exportfile)
                        if(os.path.isfile(path3b_n)):
    
                            mesh_time = os.path.getmtime(objekti.coat3D.applink_address)
                            b_time = os.path.getmtime(path3b_n)
                            if (abs(mesh_time - b_time) < 240):
                                export_file = open(path3b_n)
                                for line in export_file:
                                    objekti.coat3D.applink_3b_path = line
                                    head, tail = os.path.split(line)
                                    just_3b_name = tail
                                    objekti.coat3D.applink_3b_just_name = just_3b_name
                                export_file.close()
                                coat3D.remove_path = True