1# ##### BEGIN GPL LICENSE BLOCK #####
2#
3#  This program is free software; you can redistribute it and/or
4#  modify it under the terms of the GNU General Public License
5#  as published by the Free Software Foundation; either version 2
6#  of the License, or (at your option) any later version.
7#
8#  This program is distributed in the hope that it will be useful,
9#  but WITHOUT ANY WARRANTY; without even the implied warranty of
10#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11#  GNU General Public License for more details.
12#
13#  You should have received a copy of the GNU General Public License
14#  along with this program; if not, write to the Free Software Foundation,
15#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16#
17# ##### END GPL LICENSE BLOCK #####
18
19bl_info = {
20    "name": "3D-Coat Applink",
21    "author": "Kalle-Samuli Riihikoski (haikalle)",
22    "version": (4, 9, 34),
23    "blender": (2, 80, 0),
24    "location": "Scene > 3D-Coat Applink",
25    "description": "Transfer data between 3D-Coat/Blender",
26    "warning": "",
27    "doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/coat3D.html",
28    "category": "Import-Export",
29}
30
31if "bpy" in locals():
32    import importlib
33    importlib.reload(tex)
34else:
35    from . import tex
36from bpy.app.handlers import persistent
37
38from io_coat3D import tex
39from io_coat3D import texVR
40from io_coat3D import folders
41
42import os
43import platform
44import ntpath
45import re
46import shutil
47import pathlib
48
49
50import time
51import bpy
52
53import subprocess
54from bpy.types import PropertyGroup
55from bpy.props import (
56        BoolProperty,
57        EnumProperty,
58        FloatVectorProperty,
59        StringProperty,
60        PointerProperty,
61        )
62
63foundExchangeFolder = False
64saved_exchange_folder = ''
65liveUpdate = True
66mTime = 0
67
68@persistent
69def every_3_seconds():
70
71    global global_exchange_folder
72    global liveUpdate
73    global mTime
74    global foundExchangeFolder
75    try:
76        coat3D = bpy.context.scene.coat3D
77
78
79        if(foundExchangeFolder == False):
80            foundExchangeFolder, global_exchange_folder = folders.InitFolders()
81
82        Export_folder  = coat3D.exchangeFolder
83        Export_folder += ('%sexport.txt' % (os.sep))
84
85        if (os.path.isfile(Export_folder) and mTime != os.path.getmtime(Export_folder)):
86
87            for objekti in bpy.data.objects:
88                if(objekti.coat3D.applink_mesh):
89                    tex.updatetextures(objekti)
90
91            mTime = os.path.getmtime(Export_folder)
92
93        if (os.path.normpath(global_exchange_folder) != os.path.normpath(coat3D.exchangeFolder) and coat3D.exchangeFolder != ''):
94            folders.updateExchangeFile(coat3D.exchangeFolder)
95
96    except:
97        pass
98
99    return 3.0
100
101@persistent
102def load_handler(dummy):
103    global foundExchangeFolder
104    foundExchangeFolder = False
105    bpy.app.timers.register(every_3_seconds)
106
107def removeFile(exportfile):
108    if (os.path.isfile(exportfile)):
109        os.remove(exportfile)
110
111
112def folder_size(path):
113
114    folder_size_max = int(bpy.context.scene.coat3D.folder_size)
115
116    if(bpy.context.scene.coat3D.defaultfolder == ''):
117        tosi = True
118        while tosi:
119            list_of_files = []
120            for file in os.listdir(path):
121                list_of_files.append(path + os.sep + file)
122
123            if len(list_of_files) >= folder_size_max:
124                oldest_file = min(list_of_files, key=os.path.getctime)
125                os.remove(os.path.abspath(oldest_file))
126            else:
127                tosi = False
128
129def make_texture_list(texturefolder):
130    texturefolder += ('%stextures.txt'%(os.sep))
131    texturelist = []
132
133    if (os.path.isfile(texturefolder)):
134        texturefile = open(texturefolder)
135        index = 0
136        for line in texturefile:
137            if line != '' and index == 0:
138                line = line.rstrip('\n')
139                objekti = line
140                index += 1
141            elif index == 1:
142                line = line.rstrip('\n')
143                material = line
144                index += 1
145            elif index == 2:
146                line = line.rstrip('\n')
147                type = line
148                index += 1
149            elif index == 3:
150                line = line.rstrip('\n')
151                address = line
152                texturelist.append([objekti,material,type,address])
153                index = 0
154        texturefile.close()
155    return texturelist
156
157
158'''
159#Updating objects MESH part ( Mesh, Vertex Groups, Vertex Colors )
160'''
161
162def updatemesh(objekti, proxy, texturelist):
163    # Vertex colors
164    if(len(proxy.data.vertex_colors) > 0):
165        bring_vertex_map = True
166    else:
167        bring_vertex_map = False
168
169    if(bring_vertex_map):
170        if(len(objekti.data.vertex_colors) > 0):
171            for vertex_map in objekti.data.vertex_colors:
172                if vertex_map.name == 'Col':
173                    copy_data = True
174                    vertex_map_copy = vertex_map
175                    break
176                else:
177                    copy_data = False
178        else:
179            copy_data = False
180
181        if(copy_data):
182            for poly in objekti.data.polygons:
183                for loop_index in poly.loop_indices:
184                    vertex_map_copy.data[loop_index].color = proxy.data.vertex_colors[0].data[loop_index].color
185        else:
186            objekti.data.vertex_colors.new()
187            vertex_map_copy = objekti.data.vertex_colors[-1]
188            for poly in objekti.data.polygons:
189                for loop_index in poly.loop_indices:
190                    vertex_map_copy.data[loop_index].color = proxy.data.vertex_colors[0].data[loop_index].color
191
192    # UV -Sets
193    udim_textures = False
194    if(texturelist != []):
195        if(texturelist[0][0].startswith('100')):
196            udim_textures =True
197
198    proxy.select_set(True)
199    objekti.select_set(True)
200
201    uv_count = len(proxy.data.uv_layers)
202    index = 0
203    while(index < uv_count and len(proxy.data.polygons) == len(objekti.data.polygons)):
204        for poly in proxy.data.polygons:
205            for indi in poly.loop_indices:
206                if(proxy.data.uv_layers[index].data[indi].uv[0] != 0 and proxy.data.uv_layers[index].data[indi].uv[1] != 0):
207
208                    if(udim_textures):
209                        udim = proxy.data.uv_layers[index].name
210                        udim_index = int(udim[2:]) - 1
211
212                    objekti.data.uv_layers[0].data[indi].uv[0] = proxy.data.uv_layers[index].data[indi].uv[0]
213                    objekti.data.uv_layers[0].data[indi].uv[1] = proxy.data.uv_layers[index].data[indi].uv[1]
214
215        index = index + 1
216
217    # Mesh Copy
218    if(proxy.name.startswith('RetopoGroup')):
219        objekti.data = proxy.data
220    else:
221        for ind, v in enumerate(objekti.data.vertices):
222            v.co = proxy.data.vertices[ind].co
223
224class SCENE_OT_getback(bpy.types.Operator):
225    bl_idname = "getback.pilgway_3d_coat"
226    bl_label = "Export your custom property"
227    bl_description = "Export your custom property"
228    bl_options = {'UNDO'}
229
230    def invoke(self, context, event):
231
232        global global_exchange_folder
233        path_ex = ''
234
235        Export_folder  = global_exchange_folder
236        Blender_folder = os.path.join(Export_folder, 'Blender')
237
238        BlenderFolder = Blender_folder
239        ExportFolder = Export_folder
240
241        Blender_folder += ('%sexport.txt' % (os.sep))
242        Export_folder += ('%sexport.txt' % (os.sep))
243
244        if (bpy.app.background == False):
245            if os.path.isfile(Export_folder):
246
247                print('BLENDER -> 3DC -> BLENDER WORKFLLOW')
248                DeleteExtra3DC()
249                workflow1(ExportFolder)
250                removeFile(Export_folder)
251                removeFile(Blender_folder)
252
253            elif os.path.isfile(Blender_folder):
254
255                print('3DC -> BLENDER WORKFLLOW')
256                DeleteExtra3DC()
257                workflow2(BlenderFolder)
258                removeFile(Blender_folder)
259
260        return {'FINISHED'}
261
262class SCENE_OT_folder(bpy.types.Operator):
263    bl_idname = "update_exchange_folder.pilgway_3d_coat"
264    bl_label = "Export your custom property"
265    bl_description = "Export your custom property"
266    bl_options = {'UNDO'}
267
268    def invoke(self, context, event):
269        global foundExchangeFolder
270        coat3D = bpy.context.scene.coat3D
271        if(os.path.isdir(coat3D.exchangeFolder)):
272            foundExchangeFolder= True
273        else:
274            foundExchangeFolder = False
275
276        return {'FINISHED'}
277
278class SCENE_OT_opencoat(bpy.types.Operator):
279    bl_idname = "open_3dcoat.pilgway_3d_coat"
280    bl_label = "Export your custom property"
281    bl_description = "Export your custom property"
282    bl_options = {'UNDO'}
283
284    def invoke(self, context, event):
285
286        coat3D = bpy.context.selected_objects[0].coat3D.applink_3b_path
287        platform = os.sys.platform
288        if (platform == 'win32' or platform == 'darwin'):
289            importfile = bpy.context.scene.coat3D.exchangeFolder
290            importfile += ('%simport.txt' % (os.sep))
291            file = open(importfile, "w")
292            file.write("%s" % (coat3D))
293            file.write("\n%s" % (coat3D))
294            file.write("\n[3B]")
295            file.close()
296        else:
297            importfile = bpy.context.scene.coat3D.exchangeFolder
298            importfile += ('%simport.txt' % (os.sep))
299            file = open(importfile, "w")
300            file.write("%s" % (coat3D))
301            file.write("\n%s" % (coat3D))
302            file.write("\n[3B]")
303            file.close()
304
305        return {'FINISHED'}
306
307def scaleParents():
308    save = []
309    names =[]
310
311    for objekti in bpy.context.selected_objects:
312        temp = objekti
313        while (temp.parent is not None and temp.parent.name not in names):
314            save.append([temp.parent,(temp.parent.scale[0],temp.parent.scale[1],temp.parent.scale[2])])
315            names.append(temp.parent)
316            temp = temp.parent
317
318    for name in names:
319        name.scale = (1,1,1)
320
321    return save
322
323def scaleBackParents(save):
324
325    for data in save:
326        data[0].scale = data[1]
327
328def deleteNodes(type):
329
330    deletelist = []
331    deleteimages = []
332    deletegroup =[]
333    delete_images = bpy.context.scene.coat3D.delete_images
334
335    if type == 'Material':
336        if(len(bpy.context.selected_objects) == 1):
337            material = bpy.context.selected_objects[0].active_material
338            if(material.use_nodes):
339                for node in material.node_tree.nodes:
340                    if(node.name.startswith('3DC')):
341                        if (node.type == 'GROUP'):
342                            deletegroup.append(node.node_tree.name)
343                        deletelist.append(node.name)
344                        if node.type == 'TEX_IMAGE' and delete_images == True:
345                            deleteimages.append(node.image.name)
346                if deletelist:
347                    for node in deletelist:
348                        material.node_tree.nodes.remove(material.node_tree.nodes[node])
349                if deleteimages:
350                    for image in deleteimages:
351                        bpy.data.images.remove(bpy.data.images[image])
352
353    elif type == 'Object':
354        if (len(bpy.context.selected_objects) > 0):
355            for objekti in bpy.context.selected_objects:
356                for material in objekti.material_slots:
357                    if (material.material.use_nodes):
358                        for node in material.material.node_tree.nodes:
359                            if (node.name.startswith('3DC')):
360                                if(node.type == 'GROUP'):
361                                    deletegroup.append(node.node_tree.name)
362                                deletelist.append(node.name)
363                                if node.type == 'TEX_IMAGE' and delete_images == True:
364                                    deleteimages.append(node.image.name)
365                    if deletelist:
366                        for node in deletelist:
367                            material.material.node_tree.nodes.remove(material.material.node_tree.nodes[node])
368                            deletelist = []
369
370                    if deleteimages:
371                        for image in deleteimages:
372                            bpy.data.images.remove(bpy.data.images[image])
373                            deleteimages = []
374
375    elif type == 'Collection':
376        for collection_object in bpy.context.view_layer.active_layer_collection.collection.all_objects:
377            if(collection_object.type == 'MESH'):
378                for material in collection_object.material_slots:
379                    if (material.material.use_nodes):
380                        for node in material.material.node_tree.nodes:
381                            if (node.name.startswith('3DC')):
382                                if (node.type == 'GROUP'):
383                                    deletegroup.append(node.node_tree.name)
384                                deletelist.append(node.name)
385                                if node.type == 'TEX_IMAGE' and delete_images == True:
386                                    deleteimages.append(node.image.name)
387
388                    if deletelist:
389                        for node in deletelist:
390                            material.material.node_tree.nodes.remove(material.material.node_tree.nodes[node])
391                            deletelist = []
392
393                    if deleteimages:
394                        for image in deleteimages:
395                            bpy.data.images.remove(bpy.data.images[image])
396                            deleteimages = []
397
398    elif type == 'Scene':
399        for collection in bpy.data.collections:
400            for collection_object in collection.all_objects:
401                if (collection_object.type == 'MESH'):
402                    for material in collection_object.material_slots:
403                        if (material.material.use_nodes):
404                            for node in material.material.node_tree.nodes:
405                                if (node.name.startswith('3DC')):
406                                    if (node.type == 'GROUP'):
407                                        deletegroup.append(node.node_tree.name)
408
409                                    deletelist.append(node.name)
410                                    if node.type == 'TEX_IMAGE' and delete_images == True:
411                                        deleteimages.append(node.image.name)
412                        if deletelist:
413                            for node in deletelist:
414                                material.material.node_tree.nodes.remove(material.material.node_tree.nodes[node])
415                                deletelist = []
416
417                        if deleteimages:
418                            for image in deleteimages:
419                                bpy.data.images.remove(bpy.data.images[image])
420                                deleteimages = []
421
422        if(deletelist):
423            for node in deletelist:
424                bpy.data.node_groups.remove(bpy.data.node_groups[node])
425
426        for image in bpy.data.images:
427            if (image.name.startswith('3DC') and image.name[6] == '_'):
428                deleteimages.append(image.name)
429
430
431    if(deletegroup):
432        for node in deletegroup:
433            bpy.data.node_groups.remove(bpy.data.node_groups[node])
434
435    if deleteimages:
436        for image in deleteimages:
437            bpy.data.images.remove(bpy.data.images[image])
438
439
440def delete_materials_from_end(keep_materials_count, objekti):
441    #bpy.context.object.active_material_index = 0
442    index_t = 0
443    while (index_t < keep_materials_count):
444        temp_len = len(objekti.material_slots)-1
445        bpy.context.object.active_material_index = temp_len
446        bpy.ops.object.material_slot_remove()
447        index_t +=1
448
449''' DELETE NODES BUTTONS'''
450
451class SCENE_OT_delete_material_nodes(bpy.types.Operator):
452    bl_idname = "delete_material_nodes.pilgway_3d_coat"
453    bl_label = "Delete material nodes"
454    bl_description = "Delete material nodes"
455    bl_options = {'UNDO'}
456
457    def invoke(self, context, event):
458        type = bpy.context.scene.coat3D.deleteMode = 'Material'
459        deleteNodes(type)
460        return {'FINISHED'}
461
462class SCENE_OT_delete_object_nodes(bpy.types.Operator):
463    bl_idname = "delete_object_nodes.pilgway_3d_coat"
464    bl_label = "Delete material nodes"
465    bl_description = "Delete material nodes"
466    bl_options = {'UNDO'}
467
468    def invoke(self, context, event):
469        type = bpy.context.scene.coat3D.deleteMode = 'Object'
470        deleteNodes(type)
471        return {'FINISHED'}
472
473class SCENE_OT_delete_collection_nodes(bpy.types.Operator):
474    bl_idname = "delete_collection_nodes.pilgway_3d_coat"
475    bl_label = "Delete material nodes"
476    bl_description = "Delete material nodes"
477    bl_options = {'UNDO'}
478
479    def invoke(self, context, event):
480        type = bpy.context.scene.coat3D.deleteMode = 'Collection'
481        deleteNodes(type)
482        return {'FINISHED'}
483
484class SCENE_OT_delete_scene_nodes(bpy.types.Operator):
485    bl_idname = "delete_scene_nodes.pilgway_3d_coat"
486    bl_label = "Delete material nodes"
487    bl_description = "Delete material nodes"
488    bl_options = {'UNDO'}
489
490    def invoke(self, context, event):
491        type = bpy.context.scene.coat3D.deleteMode = 'Scene'
492        deleteNodes(type)
493        return {'FINISHED'}
494
495
496''' TRANSFER AND UPDATE BUTTONS'''
497
498class SCENE_OT_export(bpy.types.Operator):
499    bl_idname = "export_applink.pilgway_3d_coat"
500    bl_label = "Export your custom property"
501    bl_description = "Export your custom property"
502    bl_options = {'UNDO'}
503
504    def invoke(self, context, event):
505        bpy.ops.export_applink.pilgway_3d_coat()
506
507        return {'FINISHED'}
508
509    def execute(self, context):
510        global run_background_update
511        run_background_update = False
512        for mesh in bpy.data.meshes:
513            if (mesh.users == 0 and mesh.coat3D.name == '3DC'):
514                bpy.data.meshes.remove(mesh)
515
516        for material in bpy.data.materials:
517            if (material.users == 1 and material.coat3D.name == '3DC'):
518                bpy.data.materials.remove(material)
519
520        export_ok = False
521        coat3D = bpy.context.scene.coat3D
522
523        if (bpy.context.selected_objects == []):
524            return {'FINISHED'}
525        else:
526            for objec in bpy.context.selected_objects:
527                if objec.type == 'MESH':
528                    if(len(objec.data.uv_layers) == 0):
529                        objec.data.uv_layers.new(name='UVMap', do_init = False)
530
531                    export_ok = True
532            if (export_ok == False):
533                return {'FINISHED'}
534
535        scaled_objects = scaleParents()
536
537        activeobj = bpy.context.active_object.name
538        checkname = ''
539        coa = bpy.context.active_object.coat3D
540
541        p = pathlib.Path(coat3D.exchangeFolder)
542        kokeilu = coat3D.exchangeFolder[:-9]
543        Blender_folder2 = ("%s%sExchange" % (kokeilu, os.sep))
544        Blender_folder2 += ('%sexport.txt' % (os.sep))
545
546        if (os.path.isfile(Blender_folder2)):
547            os.remove(Blender_folder2)
548
549        if (not os.path.isdir(coat3D.exchangeFolder)):
550            coat3D.exchange_found = False
551            return {'FINISHED'}
552
553        folder_objects = folders.set_working_folders()
554        folder_size(folder_objects)
555
556        importfile = coat3D.exchangeFolder
557        texturefile = coat3D.exchangeFolder
558        importfile += ('%simport.txt'%(os.sep))
559        texturefile += ('%stextures.txt'%(os.sep))
560
561        looking = True
562        object_index = 0
563        active_render =  bpy.context.scene.render.engine
564
565        if(coat3D.type == 'autopo'):
566            checkname = folder_objects + os.sep
567            checkname = ("%sretopo.fbx" % (checkname))
568
569        elif(coat3D.type == 'update'):
570            checkname = bpy.context.selected_objects[0].coat3D.applink_address
571
572        else:
573            while(looking == True):
574                checkname = folder_objects + os.sep + "3DC"
575                checkname = ("%s%.3d.fbx"%(checkname,object_index))
576                if(os.path.isfile(checkname)):
577                    object_index += 1
578                else:
579                    looking = False
580                    coa.applink_name = ("%s%.2d"%(activeobj,object_index))
581                    coa.applink_address = checkname
582
583        matindex = 0
584
585        for objekti in bpy.context.selected_objects:
586            if objekti.type == 'MESH':
587                objekti.name = '__' + objekti.name
588                if(objekti.material_slots.keys() == []):
589                    newmat = bpy.data.materials.new('Material')
590                    newmat.use_nodes = True
591                    objekti.data.materials.append(newmat)
592                    matindex += 1
593                objekti.coat3D.applink_name = objekti.name
594        mod_mat_list = {}
595
596
597        bake_location = folder_objects + os.sep + 'Bake'
598        if (os.path.isdir(bake_location)):
599            shutil.rmtree(bake_location)
600            os.makedirs(bake_location)
601        else:
602            os.makedirs(bake_location)
603
604        # BAKING #
605
606        temp_string = ''
607        for objekti in bpy.context.selected_objects:
608            if objekti.type == 'MESH':
609                mod_mat_list[objekti.name] = []
610                objekti.coat3D.applink_scale = objekti.scale
611                objekti.coat3D.retopo = False
612
613                ''' Checks what materials are linked into UV '''
614
615                if(coat3D.type == 'ppp'):
616                    final_material_indexs = []
617                    uvtiles_index = []
618                    for poly in objekti.data.polygons:
619                        if(poly.material_index not in final_material_indexs):
620                            final_material_indexs.append(poly.material_index)
621                            loop_index = poly.loop_indices[0]
622                            uvtiles_index.append([poly.material_index,objekti.data.uv_layers.active.data[loop_index].uv[0]])
623                        if(len(final_material_indexs) == len(objekti.material_slots)):
624                            break
625
626                    material_index = 0
627                    if (len(final_material_indexs) != len(objekti.material_slots)):
628                        for material in objekti.material_slots:
629                            if material_index not in final_material_indexs:
630                                temp_mat = material.material
631                                material.material = objekti.material_slots[0].material
632                                mod_mat_list[objekti.name].append([material_index, temp_mat])
633                            material_index = material_index + 1
634
635                    bake_list = []
636                    if(coat3D.bake_diffuse):
637                        bake_list.append(['DIFFUSE', '$LOADTEX'])
638                    if (coat3D.bake_ao):
639                        bake_list.append(['AO', '$ExternalAO'])
640                    if (coat3D.bake_normal):
641                        bake_list.append(['NORMAL', '$LOADLOPOLYTANG'])
642                    if (coat3D.bake_roughness):
643                        bake_list.append(['ROUGHNESS', '$LOADROUGHNESS'])
644
645                    if(coat3D.bake_resolution == 'res_64'):
646                        res_size = 64
647                    elif (coat3D.bake_resolution == 'res_128'):
648                        res_size = 128
649                    elif (coat3D.bake_resolution == 'res_256'):
650                        res_size = 256
651                    elif (coat3D.bake_resolution == 'res_512'):
652                        res_size = 512
653                    elif (coat3D.bake_resolution == 'res_1024'):
654                        res_size = 1024
655                    elif (coat3D.bake_resolution == 'res_2048'):
656                        res_size = 2048
657                    elif (coat3D.bake_resolution == 'res_4096'):
658                        res_size = 4096
659                    elif (coat3D.bake_resolution == 'res_8192'):
660                        res_size = 8192
661
662                    if(len(bake_list) > 0):
663                        index_bake_tex = 0
664                        while(index_bake_tex < len(bake_list)):
665                            bake_index = 0
666                            for bake_mat_index in final_material_indexs:
667                                bake_node = objekti.material_slots[bake_mat_index].material.node_tree.nodes.new('ShaderNodeTexImage')
668                                bake_node.name = 'ApplinkBake' + str(bake_index)
669                                bpy.ops.image.new(name=bake_node.name, width=res_size, height=res_size)
670                                bake_node.image = bpy.data.images[bake_node.name]
671                                objekti.material_slots[bake_mat_index].material.node_tree.nodes.active = bake_node
672
673                                bake_index += 1
674                            if(bpy.context.scene.render.engine != 'CYCLES'):
675                                bpy.context.scene.render.engine = 'CYCLES'
676                            bpy.context.scene.render.bake.use_pass_direct = False
677                            bpy.context.scene.render.bake.use_pass_indirect = False
678                            bpy.context.scene.render.bake.use_pass_color = True
679
680                            bpy.ops.object.bake(type=bake_list[index_bake_tex][0], margin=1, width=res_size, height=res_size)
681
682                            bake_index = 0
683                            for bake_mat_index in final_material_indexs:
684                                bake_image = 'ApplinkBake' + str(bake_index)
685                                bpy.data.images[bake_image].filepath_raw = bake_location + os.sep + objekti.name + '_' + bake_image + '_' + bake_list[index_bake_tex][0] + ".png"
686                                image_bake_name =  bpy.data.images[bake_image].filepath_raw
687                                tie = image_bake_name.split(os.sep)
688                                toi = ''
689                                for sana in tie:
690                                    toi += sana
691                                    toi += "/"
692                                final_bake_name = toi[:-1]
693                                bpy.data.images[bake_image].save()
694                                temp_string += '''\n[script ImportTexture("''' + bake_list[index_bake_tex][1] + '''","''' + objekti.material_slots[bake_mat_index].material.name + '''","''' +  final_bake_name + '''");]'''
695
696                                bake_index += 1
697
698                            for material in objekti.material_slots:
699                                if material.material.use_nodes == True:
700                                    for node in material.material.node_tree.nodes:
701                                        if (node.name.startswith('ApplinkBake') == True):
702                                            material.material.node_tree.nodes.remove(node)
703
704                            for image in bpy.data.images:
705                                if (image.name.startswith('ApplinkBake') == True):
706                                    bpy.data.images.remove(image)
707
708                            index_bake_tex += 1
709
710        #BAKING ENDS
711
712        #bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
713        if(len(bpy.context.selected_objects) > 1 and coat3D.type != 'vox'):
714            bpy.ops.object.transforms_to_deltas(mode='ROT')
715
716        if(coat3D.type == 'autopo'):
717            coat3D.bring_retopo = True
718            coat3D.bring_retopo_path = checkname
719            bpy.ops.export_scene.fbx(filepath=checkname, global_scale = 0.01, use_selection=True, use_mesh_modifiers=coat3D.exportmod, axis_forward='-Z', axis_up='Y')
720
721        elif (coat3D.type == 'vox'):
722            coat3D.bring_retopo = False
723            bpy.ops.export_scene.fbx(filepath=coa.applink_address, global_scale = 0.01, use_selection=True,
724                                     use_mesh_modifiers=coat3D.exportmod, axis_forward='-Z', axis_up='Y')
725
726        else:
727            coat3D.bring_retopo = False
728            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')
729
730        file = open(importfile, "w")
731        file.write("%s"%(checkname))
732        file.write("\n%s"%(checkname))
733        file.write("\n[%s]"%(coat3D.type))
734        if(coat3D.type == 'ppp' or coat3D.type == 'mv' or coat3D.type == 'ptex'):
735            file.write("\n[export_preset Blender Cycles]")
736            file.write(temp_string)
737
738        file.close()
739        for idx, objekti in enumerate(bpy.context.selected_objects):
740            if objekti.type == 'MESH':
741                objekti.name = objekti.name[2:]
742                if(len(bpy.context.selected_objects) == 1):
743                    objekti.coat3D.applink_onlyone = True
744                objekti.coat3D.type = coat3D.type
745                objekti.coat3D.applink_mesh = True
746                objekti.coat3D.obj_mat = ''
747                objekti.coat3D.applink_index = ("3DC%.3d" % (object_index))
748
749                objekti.coat3D.applink_firsttime = True
750                if(coat3D.type != 'autopo'):
751                    objekti.coat3D.applink_address = coa.applink_address
752                    objekti.coat3D.objecttime = str(os.path.getmtime(objekti.coat3D.applink_address))
753                objekti.data.coat3D.name = '3DC'
754
755                if(coat3D.type != 'vox'):
756                    if(objekti.material_slots.keys() != []):
757                        for material in objekti.material_slots:
758                            if material.material.use_nodes == True:
759                                for node in material.material.node_tree.nodes:
760                                    if(node.name.startswith('3DC_') == True):
761                                        material.material.node_tree.nodes.remove(node)
762
763
764                for ind, mat_list in enumerate(mod_mat_list):
765                    if(mat_list == '__' + objekti.name):
766                        for ind, mat in enumerate(mod_mat_list[mat_list]):
767                            objekti.material_slots[mod_mat_list[mat_list][ind][0]].material = mod_mat_list[mat_list][ind][1]
768
769        scaleBackParents(scaled_objects)
770        bpy.context.scene.render.engine = active_render
771        return {'FINISHED'}
772
773
774def DeleteExtra3DC():
775
776    for node_group in bpy.data.node_groups:
777        if(node_group.users == 0):
778            bpy.data.node_groups.remove(node_group)
779
780    for mesh in bpy.data.meshes:
781        if(mesh.users == 0 and mesh.coat3D.name == '3DC'):
782            bpy.data.meshes.remove(mesh)
783
784    for material in bpy.data.materials:
785        img_list = []
786        if (material.users == 1 and material.coat3D.name == '3DC'):
787            if material.use_nodes == True:
788                for node in material.node_tree.nodes:
789                    if node.type == 'TEX_IMAGE' and node.name.startswith('3DC'):
790                        img_list.append(node.image)
791            if img_list != []:
792                for del_img in img_list:
793                    bpy.data.images.remove(del_img)
794
795            bpy.data.materials.remove(material)
796
797    image_del_list = []
798    for image in bpy.data.images:
799        if (image.name.startswith('3DC')):
800            if image.users == 0:
801                image_del_list.append(image.name)
802
803    if (image_del_list != []):
804        for image in image_del_list:
805            bpy.data.images.remove(bpy.data.images[image])
806
807def new_ref_function(new_applink_address, nimi):
808
809    create_collection = True
810    for collection in bpy.data.collections:
811        if collection.name == 'Applink_Objects':
812            create_collection = False
813
814    if create_collection:
815        bpy.data.collections.new('Applink_Objects')
816
817    coll_items = bpy.context.scene.collection.children.items()
818
819    add_applink_collection = True
820    for coll in coll_items:
821        if coll[0] == 'Applink_Objects':
822            add_applink_collection = False
823
824    if add_applink_collection:
825        bpy.context.scene.collection.children.link(bpy.data.collections['Applink_Objects'])
826
827    bpy.context.view_layer.active_layer_collection = bpy.context.view_layer.layer_collection.children['Applink_Objects']
828
829    old_objects = bpy.data.objects.keys()
830    object_list = []
831
832
833    bpy.ops.import_scene.fbx(filepath=new_applink_address, global_scale = 0.01,axis_forward='X', axis_up='Y',use_custom_normals=False)
834    new_objects = bpy.data.objects.keys()
835    diff_objects = [i for i in new_objects if i not in old_objects]
836    texturelist = []
837
838    for diff_object in diff_objects:
839
840        refmesh = bpy.data.objects[nimi]
841        copymesh = bpy.data.objects[nimi].copy()
842
843        copymesh.data = bpy.data.objects[diff_object].data
844        copymesh.coat3D.applink_name = bpy.data.objects[diff_object].data.name
845        copymesh.coat3D.applink_address = refmesh.coat3D.applink_address
846        ne_name = bpy.data.objects[diff_object].data.name
847
848        copymesh.coat3D.type = 'ppp'
849        copymesh.coat3D.retopo = True
850
851        bpy.data.collections['Applink_Objects'].objects.link(copymesh)
852
853        bpy.data.objects.remove(bpy.data.objects[diff_object])
854        bpy.ops.object.select_all(action='DESELECT')
855        copymesh.select_set(True)
856        copymesh.delta_rotation_euler[0] = 1.5708
857        copymesh.name = ne_name
858
859        normal_node = copymesh.material_slots[0].material.node_tree.nodes['Normal Map']
860        copymesh.material_slots[0].material.node_tree.nodes.remove(normal_node)
861        copymesh.material_slots[0].material.node_tree.nodes['Principled BSDF'].inputs['Metallic'].default_value = 0
862        copymesh.material_slots[0].material.node_tree.nodes['Principled BSDF'].inputs['Specular'].default_value = 0.5
863
864
865    refmesh.coat3D.applink_name = ''
866    refmesh.coat3D.applink_address = ''
867    refmesh.coat3D.type = ''
868    copymesh.scale = (1,1,1)
869    copymesh.coat3D.applink_scale = (1,1,1)
870    copymesh.location = (0,0,0)
871    copymesh.rotation_euler = (0,0,0)
872
873
874def blender_3DC_blender(texturelist, file_applink_address):
875
876    coat3D = bpy.context.scene.coat3D
877
878    old_materials = bpy.data.materials.keys()
879    old_objects = bpy.data.objects.keys()
880    cache_base = bpy.data.objects.keys()
881
882    object_list = []
883    import_list = []
884    import_type = []
885
886    for objekti in bpy.data.objects:
887        if objekti.type == 'MESH' and objekti.coat3D.applink_address == file_applink_address:
888            obj_coat = objekti.coat3D
889
890            object_list.append(objekti.name)
891            if(os.path.isfile(obj_coat.applink_address)):
892                if (obj_coat.objecttime != str(os.path.getmtime(obj_coat.applink_address))):
893                    obj_coat.dime = objekti.dimensions
894                    obj_coat.import_mesh = True
895                    obj_coat.objecttime = str(os.path.getmtime(obj_coat.applink_address))
896                    if(obj_coat.applink_address not in import_list):
897                        import_list.append(obj_coat.applink_address)
898                        import_type.append(coat3D.type)
899
900    if(import_list or coat3D.importmesh):
901        for idx, list in enumerate(import_list):
902
903            bpy.ops.import_scene.fbx(filepath=list, global_scale = 0.01,axis_forward='X',use_custom_normals=False)
904            cache_objects = bpy.data.objects.keys()
905            cache_objects = [i for i in cache_objects if i not in cache_base]
906            for cache_object in cache_objects:
907
908                bpy.data.objects[cache_object].coat3D.type = import_type[idx]
909                bpy.data.objects[cache_object].coat3D.applink_address = list
910                cache_base.append(cache_object)
911
912        bpy.ops.object.select_all(action='DESELECT')
913        new_materials = bpy.data.materials.keys()
914        new_objects = bpy.data.objects.keys()
915
916
917        diff_mat = [i for i in new_materials if i not in old_materials]
918        diff_objects = [i for i in new_objects if i not in old_objects]
919
920        for mark_mesh in diff_objects:
921            bpy.data.objects[mark_mesh].data.coat3D.name = '3DC'
922
923        for c_index in diff_mat:
924            bpy.data.materials.remove(bpy.data.materials[c_index])
925
926    '''The main Applink Object Loop'''
927
928    for oname in object_list:
929
930        objekti = bpy.data.objects[oname]
931        if(objekti.coat3D.applink_mesh == True):
932
933            path3b_n = coat3D.exchangeFolder
934            path3b_n += ('%slast_saved_3b_file.txt' % (os.sep))
935
936            if(objekti.coat3D.import_mesh and coat3D.importmesh == True):
937
938                objekti.coat3D.import_mesh = False
939                objekti.select_set(True)
940
941                use_smooth = objekti.data.polygons[0].use_smooth
942                found_obj = False
943
944                '''Changes objects mesh into proxy mesh'''
945                if(objekti.coat3D.type != 'ref'):
946
947                    for proxy_objects in diff_objects:
948                        if(objekti.coat3D.retopo == False):
949                            if (proxy_objects == objekti.coat3D.applink_name):
950                                obj_proxy = bpy.data.objects[proxy_objects]
951                                obj_proxy.coat3D.delete_proxy_mesh = True
952                                found_obj = True
953                        else:
954                            if (proxy_objects == objekti.coat3D.applink_name + '.001'):
955                                obj_proxy = bpy.data.objects[proxy_objects]
956                                obj_proxy.coat3D.delete_proxy_mesh = True
957                                found_obj = True
958
959
960                mat_list = []
961                if (objekti.material_slots):
962                    for obj_mat in objekti.material_slots:
963                        mat_list.append(obj_mat.material)
964
965                if(found_obj == True):
966                    exportfile = coat3D.exchangeFolder
967                    path3b_n = coat3D.exchangeFolder
968                    path3b_n += ('%slast_saved_3b_file.txt' % (os.sep))
969                    exportfile += ('%sBlender' % (os.sep))
970                    exportfile += ('%sexport.txt'%(os.sep))
971                    if(os.path.isfile(exportfile)):
972                        export_file = open(exportfile)
973                        export_file.close()
974                        os.remove(exportfile)
975                    if(os.path.isfile(path3b_n)):
976
977                        mesh_time = os.path.getmtime(objekti.coat3D.applink_address)
978                        b_time = os.path.getmtime(path3b_n)
979                        if (abs(mesh_time - b_time) < 240):
980                            export_file = open(path3b_n)
981                            for line in export_file:
982                                objekti.coat3D.applink_3b_path = line
983                                head, tail = os.path.split(line)
984                                just_3b_name = tail
985                                objekti.coat3D.applink_3b_just_name = just_3b_name
986                            export_file.close()
987                            coat3D.remove_path = True
988
989                    bpy.ops.object.select_all(action='DESELECT')
990                    obj_proxy.select_set(True)
991
992                    bpy.ops.object.select_all(action='TOGGLE')
993
994                    if objekti.coat3D.applink_firsttime == True and objekti.coat3D.type == 'vox':
995                        objekti.select_set(True)
996                        objekti.scale = (0.01, 0.01, 0.01)
997                        objekti.rotation_euler[0] = 1.5708
998                        objekti.rotation_euler[2] = 1.5708
999                        bpy.ops.object.transforms_to_deltas(mode='ROT')
1000                        bpy.ops.object.transforms_to_deltas(mode='SCALE')
1001                        objekti.coat3D.applink_firsttime = False
1002                        objekti.select_set(False)
1003
1004                    elif objekti.coat3D.applink_firsttime == True:
1005                        objekti.scale = (objekti.scale[0]/objekti.coat3D.applink_scale[0],objekti.scale[1]/objekti.coat3D.applink_scale[1],objekti.scale[2]/objekti.coat3D.applink_scale[2])
1006                        #bpy.ops.object.transforms_to_deltas(mode='SCALE')
1007                        if(objekti.coat3D.applink_onlyone == False):
1008                            objekti.rotation_euler = (0,0,0)
1009                        objekti.coat3D.applink_firsttime = False
1010
1011                    if(coat3D.importlevel):
1012                        obj_proxy.select = True
1013                        obj_proxy.modifiers.new(name='temp',type='MULTIRES')
1014                        objekti.select = True
1015                        bpy.ops.object.multires_reshape(modifier=multires_name)
1016                        bpy.ops.object.select_all(action='TOGGLE')
1017                    else:
1018
1019                        bpy.context.view_layer.objects.active = obj_proxy
1020                        keep_materials_count = len(obj_proxy.material_slots) - len(objekti.material_slots)
1021
1022                        #delete_materials_from_end(keep_materials_count, obj_proxy)
1023
1024
1025                        updatemesh(objekti,obj_proxy, texturelist)
1026                        bpy.context.view_layer.objects.active = objekti
1027
1028
1029
1030                    #tärkee että saadaan oikein käännettyä objekt
1031
1032                    objekti.select_set(True)
1033
1034                    if (use_smooth):
1035                        for data_mesh in objekti.data.polygons:
1036                            data_mesh.use_smooth = True
1037                    else:
1038                        for data_mesh in objekti.data.polygons:
1039                            data_mesh.use_smooth = False
1040
1041                        bpy.ops.object.select_all(action='DESELECT')
1042
1043                    if(coat3D.importmesh and not(os.path.isfile(objekti.coat3D.applink_address))):
1044                        coat3D.importmesh = False
1045
1046                    objekti.select_set(True)
1047                if(coat3D.importtextures):
1048                    is_new = False
1049                    if(objekti.coat3D.retopo == False):
1050                        tex.matlab(objekti,mat_list,texturelist,is_new)
1051                objekti.select_set(False)
1052            else:
1053                mat_list = []
1054                if (objekti.material_slots):
1055                    for obj_mat in objekti.material_slots:
1056                        mat_list.append(obj_mat.material)
1057
1058                if (coat3D.importtextures):
1059                    is_new = False
1060                    if(objekti.coat3D.retopo == False):
1061                        tex.matlab(objekti,mat_list,texturelist, is_new)
1062                objekti.select_set(False)
1063
1064    if(coat3D.remove_path == True):
1065        if(os.path.isfile(path3b_n)):
1066            os.remove(path3b_n)
1067        coat3D.remove_path = False
1068
1069    bpy.ops.object.select_all(action='DESELECT')
1070    if(import_list):
1071
1072        for del_obj in diff_objects:
1073
1074            if(bpy.context.collection.all_objects[del_obj].coat3D.type == 'vox' and bpy.context.collection.all_objects[del_obj].coat3D.delete_proxy_mesh == False):
1075                bpy.context.collection.all_objects[del_obj].select_set(True)
1076                objekti = bpy.context.collection.all_objects[del_obj]
1077                #bpy.ops.object.transforms_to_deltas(mode='ROT')
1078                objekti.scale = (1, 1, 1)
1079                bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
1080
1081                objekti.data.coat3D.name = '3DC'
1082
1083                objekti.coat3D.objecttime = str(os.path.getmtime(objekti.coat3D.applink_address))
1084                objekti.coat3D.applink_name = objekti.name
1085                objekti.coat3D.applink_mesh = True
1086                objekti.coat3D.import_mesh = False
1087
1088                #bpy.ops.object.transforms_to_deltas(mode='SCALE')
1089                objekti.coat3D.applink_firsttime = False
1090                bpy.context.collection.all_objects[del_obj].select_set(False)
1091
1092            else:
1093                bpy.context.collection.all_objects[del_obj].select_set(True)
1094                bpy.data.objects.remove(bpy.data.objects[del_obj])
1095
1096    if (coat3D.bring_retopo or coat3D.bring_retopo_path):
1097        if(os.path.isfile(coat3D.bring_retopo_path)):
1098            bpy.ops.import_scene.fbx(filepath=coat3D.bring_retopo_path, global_scale=1, axis_forward='X', use_custom_normals=False)
1099            os.remove(coat3D.bring_retopo_path)
1100
1101    kokeilu = coat3D.exchangeFolder[:-9]
1102    Blender_folder2 = ("%s%sExchange" % (kokeilu, os.sep))
1103    Blender_folder2 += ('%sexport.txt' % (os.sep))
1104    if (os.path.isfile(Blender_folder2)):
1105        os.remove(Blender_folder2)
1106
1107def blender_3DC(texturelist, new_applink_address):
1108
1109    bpy.ops.object.select_all(action='DESELECT')
1110    for old_obj in bpy.context.collection.objects:
1111        old_obj.coat3D.applink_old = True
1112
1113    coat3D = bpy.context.scene.coat3D
1114    Blender_folder = ("%s%sBlender"%(coat3D.exchangeFolder,os.sep))
1115    Blender_export = Blender_folder
1116    path3b_now = coat3D.exchangeFolder + os.sep
1117    path3b_now += ('last_saved_3b_file.txt')
1118    Blender_export += ('%sexport.txt'%(os.sep))
1119    mat_list = []
1120    osoite_3b = ''
1121    if (os.path.isfile(path3b_now)):
1122        path3b_fil = open(path3b_now)
1123        for lin in path3b_fil:
1124            osoite_3b = lin
1125        path3b_fil.close()
1126        head, tail = os.path.split(osoite_3b)
1127        just_3b_name = tail
1128        os.remove(path3b_now)
1129
1130    create_collection = True
1131    for collection in bpy.data.collections:
1132        if collection.name == 'Applink_Objects':
1133            create_collection = False
1134
1135    if create_collection:
1136        bpy.data.collections.new('Applink_Objects')
1137
1138    coll_items = bpy.context.scene.collection.children.items()
1139
1140    add_applink_collection = True
1141    for coll in coll_items:
1142        if coll[0] == 'Applink_Objects':
1143            add_applink_collection = False
1144
1145    if add_applink_collection:
1146        bpy.context.scene.collection.children.link(bpy.data.collections['Applink_Objects'])
1147
1148    bpy.context.view_layer.active_layer_collection = bpy.context.view_layer.layer_collection.children['Applink_Objects']
1149
1150    old_materials = bpy.data.materials.keys()
1151    old_objects = bpy.data.objects.keys()
1152
1153    bpy.ops.import_scene.fbx(filepath=new_applink_address, global_scale = 1, axis_forward='-Z', axis_up='Y')
1154
1155    new_materials = bpy.data.materials.keys()
1156    new_objects = bpy.data.objects.keys()
1157
1158    diff_mat = [i for i in new_materials if i not in old_materials]
1159    diff_objects = [i for i in new_objects if i not in old_objects]
1160
1161
1162    for mark_mesh in diff_mat:
1163        bpy.data.materials[mark_mesh].coat3D.name = '3DC'
1164        bpy.data.materials[mark_mesh].use_fake_user = True
1165    laskuri = 0
1166    index = 0
1167
1168    facture_object = False
1169
1170    for c_index in diff_objects:
1171        bpy.data.objects[c_index].data.coat3D.name = '3DC'
1172        laskuri += 1
1173        if(laskuri == 2 and c_index == ('vt_' + diff_objects[0])):
1174            facture_object = True
1175            print('Facture object founded!!')
1176
1177    #bpy.ops.object.transforms_to_deltas(mode='SCALE')
1178    bpy.ops.object.select_all(action='DESELECT')
1179    for new_obj in bpy.context.collection.objects:
1180
1181        if(new_obj.coat3D.applink_old == False):
1182            new_obj.select_set(True)
1183            new_obj.coat3D.applink_firsttime = False
1184            new_obj.select_set(False)
1185            new_obj.coat3D.type = 'ppp'
1186            new_obj.coat3D.applink_address = new_applink_address
1187            new_obj.coat3D.applink_mesh = True
1188            new_obj.coat3D.objecttime = str(os.path.getmtime(new_obj.coat3D.applink_address))
1189
1190            new_obj.coat3D.applink_name = new_obj.name
1191            index = index + 1
1192
1193            bpy.context.view_layer.objects.active = new_obj
1194
1195            new_obj.coat3D.applink_export = True
1196
1197            if (os.path.isfile(osoite_3b)):
1198                mesh_time = os.path.getmtime(new_obj.coat3D.applink_address)
1199                b_time = os.path.getmtime(osoite_3b)
1200                if (abs(mesh_time-b_time) < 240):
1201                    new_obj.coat3D.applink_3b_path = osoite_3b
1202                    new_obj.coat3D.applink_3b_just_name = just_3b_name
1203
1204            mat_list.append(new_obj.material_slots[0].material)
1205            is_new = True
1206
1207            if(facture_object):
1208                texVR.matlab(new_obj, mat_list, texturelist, is_new)
1209                new_obj.scale = (0.01, 0.01, 0.01)
1210            else:
1211                tex.matlab(new_obj, mat_list, texturelist, is_new)
1212
1213            mat_list.pop()
1214
1215    for new_obj in bpy.context.collection.objects:
1216        if(new_obj.coat3D.applink_old == False):
1217            new_obj.coat3D.applink_old = True
1218
1219    kokeilu = coat3D.exchangeFolder[:-10]
1220    Blender_folder2 = ("%s%sExchange%sBlender" % (kokeilu, os.sep, os.sep))
1221    Blender_folder2 += ('%sexport.txt' % (os.sep))
1222
1223    if (os.path.isfile(Blender_export)):
1224        os.remove(Blender_export)
1225    if (os.path.isfile(Blender_folder2)):
1226        os.remove(Blender_folder2)
1227
1228    for material in bpy.data.materials:
1229        if material.use_nodes == True:
1230            for node in material.node_tree.nodes:
1231                if (node.name).startswith('3DC'):
1232                    node.location = node.location
1233
1234
1235def workflow1(ExportFolder):
1236
1237    coat3D = bpy.context.scene.coat3D
1238
1239    texturelist = make_texture_list(ExportFolder)
1240
1241    for texturepath in texturelist:
1242        for image in bpy.data.images:
1243            if(image.filepath == texturepath[3] and image.users == 0):
1244                bpy.data.images.remove(image)
1245
1246    path3b_now = coat3D.exchangeFolder
1247
1248    path3b_now += ('last_saved_3b_file.txt')
1249    new_applink_address = 'False'
1250    new_object = False
1251    new_ref_object = False
1252
1253    exportfile3 = coat3D.exchangeFolder
1254    exportfile3 += ('%sexport.txt' % (os.sep))
1255
1256    if(os.path.isfile(exportfile3)):
1257
1258        obj_pathh = open(exportfile3)
1259
1260        for line in obj_pathh:
1261            new_applink_address = line
1262            break
1263        obj_pathh.close()
1264        for scene_objects in bpy.context.collection.all_objects:
1265            if(scene_objects.type == 'MESH'):
1266                if(scene_objects.coat3D.applink_address == new_applink_address and scene_objects.coat3D.type == 'ref'):
1267                    scene_objects.coat3D.type == ''
1268                    new_ref_object = True
1269                    nimi = scene_objects.name
1270
1271
1272
1273
1274    exportfile = coat3D.exchangeFolder
1275    exportfile += ('%sBlender' % (os.sep))
1276    exportfile += ('%sexport.txt' % (os.sep))
1277    if (os.path.isfile(exportfile)):
1278        os.remove(exportfile)
1279
1280    if(new_ref_object):
1281
1282        new_ref_function(new_applink_address, nimi)
1283
1284    else:
1285        blender_3DC_blender(texturelist, new_applink_address)
1286
1287def workflow2(BlenderFolder):
1288
1289    coat3D = bpy.context.scene.coat3D
1290
1291    texturelist = make_texture_list(BlenderFolder)
1292
1293    for texturepath in texturelist:
1294        for image in bpy.data.images:
1295            if(image.filepath == texturepath[3] and image.users == 0):
1296                bpy.data.images.remove(image)
1297
1298    kokeilu = coat3D.exchangeFolder
1299
1300    Blender_export = os.path.join(kokeilu, 'Blender')
1301
1302    path3b_now = coat3D.exchangeFolder
1303
1304    path3b_now += ('last_saved_3b_file.txt')
1305    Blender_export += ('%sexport.txt'%(os.sep))
1306    new_applink_address = 'False'
1307    new_object = False
1308    new_ref_object = False
1309
1310    if(os.path.isfile(Blender_export)):
1311        obj_pathh = open(Blender_export)
1312        new_object = True
1313        for line in obj_pathh:
1314            new_applink_address = line
1315            break
1316        obj_pathh.close()
1317
1318        for scene_objects in bpy.context.collection.all_objects:
1319            if(scene_objects.type == 'MESH'):
1320                if(scene_objects.coat3D.applink_address == new_applink_address):
1321                    new_object = False
1322
1323    exportfile = coat3D.exchangeFolder
1324    exportfile += ('%sBlender' % (os.sep))
1325    exportfile += ('%sexport.txt' % (os.sep))
1326    if (os.path.isfile(exportfile)):
1327        os.remove(exportfile)
1328
1329    if(new_ref_object):
1330
1331        new_ref_function(new_applink_address, nimi)
1332
1333    else:
1334
1335        blender_3DC(texturelist, new_applink_address)
1336
1337from bpy import *
1338from mathutils import Vector, Matrix
1339
1340class SCENE_PT_Main(bpy.types.Panel):
1341    bl_label = "3D-Coat Applink"
1342    bl_space_type = "VIEW_3D"
1343    bl_region_type = "UI"
1344    bl_category = '3D-Coat'
1345
1346    @classmethod
1347    def poll(cls, context):
1348        if bpy.context.mode == 'OBJECT':
1349            return True
1350        else:
1351            return False
1352
1353    def draw(self, context):
1354        layout = self.layout
1355        coat3D = bpy.context.scene.coat3D
1356        global foundExchangeFolder
1357
1358        if(foundExchangeFolder == False):
1359            row = layout.row()
1360            row.label(text="Applink didn't find your 3d-Coat/Exchange folder.")
1361            row = layout.row()
1362            row.label(text="Please select it before using Applink.")
1363            row = layout.row()
1364            row.prop(coat3D,"exchangeFolder",text="")
1365            row = layout.row()
1366            row.operator("update_exchange_folder.pilgway_3d_coat", text="Apply folder")
1367
1368        else:
1369            #Here you add your GUI
1370            row = layout.row()
1371            row.prop(coat3D,"type",text = "")
1372            flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
1373
1374            row = layout.row()
1375
1376            row.operator("export_applink.pilgway_3d_coat", text="Send")
1377            row.operator("getback.pilgway_3d_coat", text="GetBack")
1378
1379
1380class ObjectButtonsPanel():
1381    bl_space_type = 'PROPERTIES'
1382    bl_region_type = 'WINDOW'
1383    bl_context = "object"
1384
1385class SCENE_PT_Settings(ObjectButtonsPanel,bpy.types.Panel):
1386    bl_label = "3D-Coat Applink Settings"
1387    bl_space_type = "PROPERTIES"
1388    bl_region_type = "WINDOW"
1389    bl_context = "scene"
1390
1391    def draw(self, context):
1392        pass
1393
1394class MaterialButtonsPanel():
1395    bl_space_type = 'PROPERTIES'
1396    bl_region_type = 'WINDOW'
1397    bl_context = "material"
1398
1399class SCENE_PT_Material(MaterialButtonsPanel,bpy.types.Panel):
1400    bl_label = "3D-Coat Applink"
1401    bl_space_type = "PROPERTIES"
1402    bl_region_type = "WINDOW"
1403    bl_context = "material"
1404
1405    def draw(self, context):
1406        pass
1407
1408class SCENE_PT_Material_Import(MaterialButtonsPanel, bpy.types.Panel):
1409    bl_label = "Import Textures:"
1410    bl_parent_id = "SCENE_PT_Material"
1411    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
1412
1413    def draw(self, context):
1414        layout = self.layout
1415        layout.use_property_split = False
1416        coat3D = bpy.context.active_object.active_material
1417
1418        layout.active = True
1419
1420        flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
1421
1422        col = flow.column()
1423        col.prop(coat3D, "coat3D_diffuse", text="Diffuse")
1424        col.prop(coat3D, "coat3D_metalness", text="Metalness")
1425        col.prop(coat3D, "coat3D_roughness", text="Roughness")
1426        col.prop(coat3D, "coat3D_ao", text="AO")
1427        col = flow.column()
1428        col.prop(coat3D, "coat3D_normal", text="NormalMap")
1429        col.prop(coat3D, "coat3D_displacement", text="Displacement")
1430        col.prop(coat3D, "coat3D_emissive", text="Emissive")
1431        col.prop(coat3D, "coat3D_alpha", text="Alpha")
1432
1433
1434
1435class SCENE_PT_Settings_Update(ObjectButtonsPanel, bpy.types.Panel):
1436    bl_label = "Update"
1437    bl_parent_id = "SCENE_PT_Settings"
1438    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
1439
1440    def draw(self, context):
1441        layout = self.layout
1442        layout.use_property_split = False
1443        coat3D = bpy.context.scene.coat3D
1444
1445        layout.active = True
1446
1447        flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
1448
1449        col = flow.column()
1450        col.prop(coat3D, "importmesh", text="Update Mesh/UV")
1451        col = flow.column()
1452        col.prop(coat3D, "createnodes", text="Create Extra Nodes")
1453        col = flow.column()
1454        col.prop(coat3D, "importtextures", text="Update Textures")
1455        col = flow.column()
1456        col.prop(coat3D, "exportmod", text="Export with modifiers")
1457
1458class SCENE_PT_Bake_Settings(ObjectButtonsPanel, bpy.types.Panel):
1459    bl_label = "Bake"
1460    bl_parent_id = "SCENE_PT_Settings"
1461    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
1462
1463    def draw(self, context):
1464        layout = self.layout
1465        layout.use_property_split = False
1466        coat3D = bpy.context.scene.coat3D
1467
1468        layout.active = True
1469
1470        flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
1471
1472        col = flow.column()
1473        col.prop(coat3D, "bake_resolution", text="Resolution")
1474        col = flow.column()
1475        col.prop(coat3D, "bake_diffuse", text="Diffuse")
1476        col = flow.column()
1477        col.prop(coat3D, "bake_ao", text="AO")
1478        col = flow.column()
1479        col.prop(coat3D, "bake_normal", text="Normal")
1480        col = flow.column()
1481        col.prop(coat3D, "bake_roughness", text="Roughness")
1482
1483class SCENE_PT_Settings_Folders(ObjectButtonsPanel, bpy.types.Panel):
1484    bl_label = "Folders"
1485    bl_parent_id = "SCENE_PT_Settings"
1486    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
1487
1488    def draw(self, context):
1489        layout = self.layout
1490        layout.use_property_split = False
1491        coat3D = bpy.context.scene.coat3D
1492
1493        layout.active = True
1494
1495        flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
1496
1497        col = flow.column()
1498        col.prop(coat3D, "exchangeFolder", text="Exchange folder")
1499
1500        col = flow.column()
1501        col.prop(coat3D, "defaultfolder", text="Object/Texture folder")
1502
1503        col = flow.column()
1504        col.prop(coat3D, "folder_size", text="Max count in Applink folder")
1505
1506class SCENE_PT_Settings_DeleteNodes(ObjectButtonsPanel, bpy.types.Panel):
1507    bl_label = "Delete 3DC nodes from selected..."
1508    bl_parent_id = "SCENE_PT_Settings"
1509    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
1510
1511    def draw(self, context):
1512        layout = self.layout
1513        layout.use_property_split = False
1514        coat3D = bpy.context.scene.coat3D
1515
1516        layout.active = True
1517
1518        flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
1519
1520        col = flow.column()
1521        col.operator("delete_material_nodes.pilgway_3d_coat", text="Material")
1522
1523        col.operator("delete_object_nodes.pilgway_3d_coat", text="Object(s)")
1524
1525        col = flow.column()
1526        col.operator("delete_collection_nodes.pilgway_3d_coat", text="Collection")
1527
1528        col.operator("delete_scene_nodes.pilgway_3d_coat", text="Scene")
1529
1530        col = flow.column()
1531        col.prop(coat3D, "delete_images", text="Delete nodes images")
1532
1533
1534
1535
1536# 3D-Coat Dynamic Menu
1537class VIEW3D_MT_Coat_Dynamic_Menu(bpy.types.Menu):
1538    bl_label = "3D-Coat Applink Menu"
1539
1540    def draw(self, context):
1541        layout = self.layout
1542
1543        layout.operator_context = 'INVOKE_REGION_WIN'
1544
1545        ob = context
1546        if ob.mode == 'OBJECT':
1547            if(len(context.selected_objects) > 0):
1548                layout.operator("import_applink.pilgway_3d_coat",
1549                                text="Update Scene")
1550                layout.separator()
1551
1552                layout.operator("export_applink.pilgway_3d_coat",
1553                                text="Transfer to 3D-Coat")
1554                layout.separator()
1555
1556                if(context.selected_objects[0].coat3D.applink_3b_path != ''):
1557                    layout.operator("open_3dcoat.pilgway_3d_coat",
1558                                    text="Open " +context.selected_objects[0].coat3D.applink_3b_just_name)
1559                    layout.separator()
1560
1561            else:
1562                layout.operator("import_applink.pilgway_3d_coat",
1563                                text="Update Scene")
1564                layout.separator()
1565
1566            if (len(context.selected_objects) > 0):
1567                layout.operator("delete_material_nodes.pilgway_3d_coat",
1568                                text="Delete 3D-Coat nodes from active material")
1569
1570                layout.operator("delete_object_nodes.pilgway_3d_coat",
1571                                text="Delete 3D-Coat nodes from selected objects")
1572
1573            layout.operator("delete_collection_nodes.pilgway_3d_coat",
1574                            text="Delete 3D-Coat nodes from active collection")
1575
1576            layout.operator("delete_scene_nodes.pilgway_3d_coat",
1577                            text="Delete all 3D-Coat nodes")
1578            layout.separator()
1579
1580
1581
1582class ObjectCoat3D(PropertyGroup):
1583
1584    obj_mat: StringProperty(
1585        name="Object_Path",
1586        default=''
1587    )
1588    applink_address: StringProperty(
1589        name="Object_Applink_address"
1590    )
1591    applink_index: StringProperty(
1592        name="Object_Applink_address"
1593    )
1594    applink_3b_path: StringProperty(
1595        name="Object_3B_Path"
1596    )
1597    applink_name: StringProperty(
1598        name="Applink object name"
1599    )
1600    applink_3b_just_name: StringProperty(
1601        name="Applink object name"
1602    )
1603    applink_firsttime: BoolProperty(
1604        name="FirstTime",
1605        description="FirstTime",
1606        default=True
1607    )
1608    retopo: BoolProperty(
1609        name="Retopo object",
1610        description="Retopo object",
1611        default=False
1612    )
1613    delete_proxy_mesh: BoolProperty(
1614        name="FirstTime",
1615        description="FirstTime",
1616        default=False
1617    )
1618    applink_onlyone: BoolProperty(
1619        name="FirstTime",
1620        description="FirstTime",
1621        default=False
1622    )
1623    type: StringProperty(
1624        name="type",
1625        description="shows type",
1626        default=''
1627    )
1628    import_mesh: BoolProperty(
1629        name="ImportMesh",
1630        description="ImportMesh",
1631        default=False
1632    )
1633    applink_mesh: BoolProperty(
1634        name="ImportMesh",
1635        description="ImportMesh",
1636        default=False
1637    )
1638    applink_old: BoolProperty(
1639        name="OldObject",
1640        description="Old Object",
1641        default=False
1642    )
1643    applink_export: BoolProperty(
1644        name="FirstTime",
1645        description="Object is from 3d-ocat",
1646        default=False
1647    )
1648    objecttime: StringProperty(
1649        name="ObjectTime",
1650        subtype="FILE_PATH"
1651    )
1652    path3b: StringProperty(
1653        name="3B Path",
1654        subtype="FILE_PATH"
1655    )
1656    dime: FloatVectorProperty(
1657        name="dime",
1658        description="Dimension"
1659    )
1660    applink_scale: FloatVectorProperty(
1661        name="Scale",
1662        description="Scale"
1663    )
1664
1665class SceneCoat3D(PropertyGroup):
1666    defaultfolder: StringProperty(
1667        name="FilePath",
1668        subtype="DIR_PATH",
1669    )
1670    deleteMode: StringProperty(
1671        name="FilePath",
1672        subtype="DIR_PATH",
1673        default=''
1674    )
1675    coat3D_exe: StringProperty(
1676        name="FilePath",
1677        subtype="FILE_PATH",
1678    )
1679    exchangeFolder: StringProperty(
1680        name="FilePath",
1681        subtype="DIR_PATH"
1682    )
1683    bring_retopo: BoolProperty(
1684        name="Import window",
1685        description="Allows to skip import dialog",
1686        default=False
1687    )
1688    foundExchangeFolder: BoolProperty(
1689        name="found Exchange Folder",
1690        description="found Excahnge folder",
1691        default=False
1692    )
1693    delete_images: BoolProperty(
1694        name="Import window",
1695        description="Allows to skip import dialog",
1696        default=True
1697    )
1698    bring_retopo_path: StringProperty(
1699        name="FilePath",
1700        subtype="DIR_PATH",
1701    )
1702    remove_path: BoolProperty(
1703        name="Import window",
1704        description="Allows to skip import dialog",
1705        default=False
1706    )
1707    exchange_found: BoolProperty(
1708        name="Exchange Found",
1709        description="Alert if Exchange folder is not found",
1710        default=True
1711    )
1712    exportfile: BoolProperty(
1713        name="No Import File",
1714        description="Add Modifiers and export",
1715        default=False
1716    )
1717    importmod: BoolProperty(
1718        name="Remove Modifiers",
1719        description="Import and add modifiers",
1720        default=False
1721    )
1722    exportmod: BoolProperty(
1723        name="Modifiers",
1724        description="Export modifiers",
1725        default=False
1726    )
1727    importtextures: BoolProperty(
1728        name="Bring Textures",
1729        description="Import Textures",
1730        default=True
1731    )
1732    createnodes: BoolProperty(
1733        name="Bring Textures",
1734        description="Import Textures",
1735        default=True
1736    )
1737    importlevel: BoolProperty(
1738        name="Multires. Level",
1739        description="Bring Specific Multires Level",
1740        default=False
1741    )
1742    importmesh: BoolProperty(
1743        name="Mesh",
1744        description="Import Mesh",
1745        default=True
1746    )
1747
1748    # copy location
1749
1750    loca: FloatVectorProperty(
1751        name="location",
1752        description="Location",
1753        subtype="XYZ",
1754        default=(0.0, 0.0, 0.0)
1755    )
1756    rota: FloatVectorProperty(
1757        name="location",
1758        description="Location",
1759        subtype="EULER",
1760        default=(0.0, 0.0, 0.0)
1761    )
1762    scal: FloatVectorProperty(
1763        name="location",
1764        description="Location",
1765        subtype="XYZ",
1766        default=(0.0, 0.0, 0.0)
1767    )
1768    dime: FloatVectorProperty(
1769        name="dimension",
1770        description="Dimension",
1771        subtype="XYZ",
1772        default=(0.0, 0.0, 0.0)
1773    )
1774    type: EnumProperty(
1775        name="Export Type",
1776        description="Different Export Types",
1777        items=(("ppp", "Per-Pixel Painting", ""),
1778               ("mv", "Microvertex Painting", ""),
1779               ("ptex", "Ptex Painting", ""),
1780               ("uv", "UV-Mapping", ""),
1781               ("ref", "Reference Mesh", ""),
1782               ("retopo", "Retopo mesh as new layer", ""),
1783               ("vox", "Mesh As Voxel Object", ""),
1784               ("alpha", "Mesh As New Pen Alpha", ""),
1785               ("prim", "Mesh As Voxel Primitive", ""),
1786               ("curv", "Mesh As a Curve Profile", ""),
1787               ("autopo", "Mesh For Auto-retopology", ""),
1788               ("update", "Update mesh/uvs", ""),
1789               ),
1790        default="ppp"
1791    )
1792    bake_resolution: EnumProperty(
1793        name="Bake Resolution",
1794        description="Bake resolution.",
1795        items=(("res_64", "64 x 64", ""),
1796               ("res_128", "128 x 128", ""),
1797               ("res_256", "256 x 256", ""),
1798               ("res_512", "512 x 512", ""),
1799               ("res_1024", "1024 x 1024", ""),
1800               ("res_2048", "2048 x 2048", ""),
1801               ("res_4096", "4096 x 4096", ""),
1802               ("res_8192", "8192 x 8192", ""),
1803               ),
1804        default="res_1024"
1805    )
1806    folder_size: EnumProperty(
1807        name="Applink folder size",
1808        description="Applink folder size.",
1809        items=(("10", "10", ""),
1810               ("100", "100", ""),
1811               ("500", "500", ""),
1812               ("1000", "1000", ""),
1813               ("5000", "5000", ""),
1814               ("10000", "10000", ""),
1815               ),
1816        default="500"
1817    )
1818    bake_textures: BoolProperty(
1819        name="Bake all textures",
1820        description="Add Modifiers and export",
1821        default=False
1822    )
1823    bake_diffuse: BoolProperty(
1824        name="Bake diffuse texture",
1825        description="Add Modifiers and export",
1826        default=False
1827    )
1828    bake_ao: BoolProperty(
1829        name="Bake AO texture",
1830        description="Add Modifiers and export",
1831        default=False
1832    )
1833    bake_roughness: BoolProperty(
1834        name="Bake roughness texture",
1835        description="Add Modifiers and export",
1836        default=False
1837    )
1838    bake_metalness: BoolProperty(
1839        name="Bake metalness texture",
1840        description="Add Modifiers and export",
1841        default=False
1842    )
1843    bake_emissive: BoolProperty(
1844        name="Bake emissive texture",
1845        description="Add Modifiers and export",
1846        default=False
1847    )
1848    bake_normal: BoolProperty(
1849        name="Bake normal texture",
1850        description="Add Modifiers and export",
1851        default=False
1852    )
1853    bake_displacement: BoolProperty(
1854        name="Bake displacement",
1855        description="Add Modifiers and export",
1856        default=False
1857    )
1858
1859class MeshCoat3D(PropertyGroup):
1860    applink_address: StringProperty(
1861        name="ApplinkAddress",
1862        # subtype="APPLINK_ADDRESS",
1863    )
1864
1865class MaterialCoat3D(PropertyGroup):
1866    name: StringProperty(
1867        name="ApplinkAddress",
1868        # subtype="APPLINK_ADDRESS",
1869        default=''
1870    )
1871    bring_diffuse: BoolProperty(
1872        name="Import diffuse texture",
1873        description="Import diffuse texture",
1874        default=True
1875    )
1876    bring_metalness: BoolProperty(
1877        name="Import diffuse texture",
1878        description="Import diffuse texture",
1879        default=True
1880    )
1881    bring_roughness: BoolProperty(
1882        name="Import diffuse texture",
1883        description="Import diffuse texture",
1884        default=True
1885    )
1886    bring_normal: BoolProperty(
1887        name="Import diffuse texture",
1888        description="Import diffuse texture",
1889        default=True
1890    )
1891    bring_displacement: BoolProperty(
1892        name="Import diffuse texture",
1893        description="Import diffuse texture",
1894        default=True
1895    )
1896    bring_emissive: BoolProperty(
1897        name="Import diffuse texture",
1898        description="Import diffuse texture",
1899        default=True
1900    )
1901    bring_gloss: BoolProperty(
1902        name="Import diffuse texture",
1903        description="Import diffuse texture",
1904        default=True
1905    )
1906
1907classes = (
1908    SCENE_PT_Main,
1909    SCENE_PT_Settings,
1910    SCENE_PT_Material,
1911    SCENE_PT_Settings_Update,
1912    SCENE_PT_Bake_Settings,
1913    SCENE_PT_Settings_DeleteNodes,
1914    SCENE_PT_Settings_Folders,
1915    SCENE_PT_Material_Import,
1916    SCENE_OT_folder,
1917    SCENE_OT_opencoat,
1918    SCENE_OT_export,
1919    SCENE_OT_getback,
1920    SCENE_OT_delete_material_nodes,
1921    SCENE_OT_delete_object_nodes,
1922    SCENE_OT_delete_collection_nodes,
1923    SCENE_OT_delete_scene_nodes,
1924    VIEW3D_MT_Coat_Dynamic_Menu,
1925    ObjectCoat3D,
1926    SceneCoat3D,
1927    MeshCoat3D,
1928    MaterialCoat3D,
1929    )
1930
1931def register():
1932
1933    bpy.types.Material.coat3D_diffuse = BoolProperty(
1934        name="Import diffuse texture",
1935        description="Import diffuse texture",
1936        default=True
1937    )
1938    bpy.types.Material.coat3D_roughness = BoolProperty(
1939        name="Import diffuse texture",
1940        description="Import diffuse texture",
1941        default=True
1942    )
1943    bpy.types.Material.coat3D_metalness = BoolProperty(
1944        name="Import diffuse texture",
1945        description="Import diffuse texture",
1946        default=True
1947    )
1948    bpy.types.Material.coat3D_normal = BoolProperty(
1949        name="Import diffuse texture",
1950        description="Import diffuse texture",
1951        default=True
1952    )
1953    bpy.types.Material.coat3D_displacement = BoolProperty(
1954        name="Import diffuse texture",
1955        description="Import diffuse texture",
1956        default=True
1957    )
1958    bpy.types.Material.coat3D_emissive = BoolProperty(
1959        name="Import diffuse texture",
1960        description="Import diffuse texture",
1961        default=True
1962    )
1963    bpy.types.Material.coat3D_ao = BoolProperty(
1964        name="Import diffuse texture",
1965        description="Import diffuse texture",
1966        default=True
1967    )
1968    bpy.types.Material.coat3D_alpha = BoolProperty(
1969        name="Import alpha texture",
1970        description="Import alpha texture",
1971        default=True
1972    )
1973    bpy.types.Material.coat3D_gloss = BoolProperty(
1974        name="Import alpha texture",
1975        description="Import alpha texture",
1976        default=True
1977    )
1978
1979
1980
1981
1982    from bpy.utils import register_class
1983    for cls in classes:
1984        register_class(cls)
1985
1986    bpy.types.Object.coat3D = PointerProperty(type=ObjectCoat3D)
1987    bpy.types.Scene.coat3D = PointerProperty(type=SceneCoat3D)
1988    bpy.types.Mesh.coat3D = PointerProperty(type=MeshCoat3D)
1989    bpy.types.Material.coat3D = PointerProperty(type=MaterialCoat3D)
1990    bpy.app.handlers.load_post.append(load_handler)
1991
1992    kc = bpy.context.window_manager.keyconfigs.addon
1993
1994    if kc:
1995        km = kc.keymaps.new(name="3D View", space_type="VIEW_3D")
1996        kmi = km.keymap_items.new('wm.call_menu', 'Q', 'PRESS', shift=True)
1997        kmi.properties.name = "VIEW3D_MT_Coat_Dynamic_Menu"
1998
1999def unregister():
2000
2001    import bpy
2002    from bpy.utils import unregister_class
2003
2004    del bpy.types.Object.coat3D
2005    del bpy.types.Scene.coat3D
2006    del bpy.types.Material.coat3D
2007    bpy.types.Material.coat3D_diffuse
2008    bpy.types.Material.coat3D_metalness
2009    bpy.types.Material.coat3D_roughness
2010    bpy.types.Material.coat3D_normal
2011    bpy.types.Material.coat3D_displacement
2012    bpy.types.Material.coat3D_emissive
2013    bpy.types.Material.coat3D_alpha
2014
2015    kc = bpy.context.window_manager.keyconfigs.addon
2016    if kc:
2017        km = kc.keymaps.get('3D View')
2018        for kmi in km.keymap_items:
2019            if kmi.idname == 'wm.call_menu':
2020                if kmi.properties.name == "VIEW3D_MT_Coat_Dynamic_Menu":
2021                    km.keymap_items.remove(kmi)
2022
2023    for cls in reversed(classes):
2024        unregister_class(cls)
2025