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