1 # SPDX-License-Identifier: GPL-2.0-or-later
4 "name": "3D-Coat Applink",
5 "author": "Kalle-Samuli Riihikoski (haikalle)",
8 "location": "Scene > 3D-Coat Applink",
9 "description": "Transfer data between 3D-Coat/Blender",
11 "doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/coat3D.html",
12 "category": "Import-Export",
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
39 from bpy
.types
import PropertyGroup
40 from bpy
.props
import (
48 global_exchange_folder
= ''
49 foundExchangeFolder
= True
50 saved_exchange_folder
= ''
55 def every_3_seconds():
57 global global_exchange_folder
64 folders
.loadExchangeFolder()
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
)
87 def load_handler(dummy
):
88 bpy
.app
.timers
.register(every_3_seconds
)
90 def removeFile(exportfile
):
91 if (os
.path
.isfile(exportfile
)):
95 def folder_size(path
):
97 folder_size_max
= int(bpy
.context
.scene
.coat3D
.folder_size
)
99 if(bpy
.context
.scene
.coat3D
.defaultfolder
== ''):
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
))
112 def make_texture_list(texturefolder
):
113 texturefolder
+= ('%stextures.txt'%(os
.sep
))
116 if (os
.path
.isfile(texturefolder
)):
117 texturefile
= open(texturefolder
)
119 for line
in texturefile
:
120 if line
!= '' and index
== 0:
121 line
= line
.rstrip('\n')
125 line
= line
.rstrip('\n')
129 line
= line
.rstrip('\n')
133 line
= line
.rstrip('\n')
135 texturelist
.append([objekti
,material
,type,address
])
142 #Updating objects MESH part ( Mesh, Vertex Groups, Vertex Colors )
145 def updatemesh(objekti
, proxy
, texturelist
):
147 if(len(proxy
.data
.vertex_colors
) > 0):
148 bring_vertex_map
= True
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':
157 vertex_map_copy
= vertex_map
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
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
176 udim_textures
= False
177 if(texturelist
!= []):
178 if(texturelist
[0][0].startswith('100')):
181 proxy
.select_set(True)
182 objekti
.select_set(True)
184 uv_count
= len(proxy
.data
.uv_layers
)
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):
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]
201 if(proxy
.name
.startswith('RetopoGroup')):
202 objekti
.data
= proxy
.data
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
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')
232 workflow1(ExportFolder
)
233 removeFile(Export_folder
)
234 removeFile(Blender_folder
)
236 elif os
.path
.isfile(Blender_folder
):
238 print('3DC -> BLENDER WORKFLLOW')
240 workflow2(BlenderFolder
)
241 removeFile(Blender_folder
)
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'
259 exchangeFile
= os
.path
.expanduser("~") + os
.sep
+ '3DC2Blender' + os
.sep
+ 'Exchange_folder.txt'
260 if(os
.path
.isfile(exchangeFile
)):
263 if(os
.path
.isfile(exchangeFile
)):
264 file = open(exchangeFile
, "w")
265 file.write("%s"%(coat3D
.exchangeFolder
))
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
)
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
))
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
))
319 for objekti
in bpy
.context
.selected_objects
:
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
)
331 def scaleBackParents(save
):
334 data
[0].scale
= data
[1]
336 def deleteNodes(type):
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
)
355 for node
in deletelist
:
356 material
.node_tree
.nodes
.remove(material
.node_tree
.nodes
[node
])
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
)
374 for node
in deletelist
:
375 material
.material
.node_tree
.nodes
.remove(material
.material
.node_tree
.nodes
[node
])
379 for image
in deleteimages
:
380 bpy
.data
.images
.remove(bpy
.data
.images
[image
])
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
)
397 for node
in deletelist
:
398 material
.material
.node_tree
.nodes
.remove(material
.material
.node_tree
.nodes
[node
])
402 for image
in deleteimages
:
403 bpy
.data
.images
.remove(bpy
.data
.images
[image
])
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
)
421 for node
in deletelist
:
422 material
.material
.node_tree
.nodes
.remove(material
.material
.node_tree
.nodes
[node
])
426 for image
in deleteimages
:
427 bpy
.data
.images
.remove(bpy
.data
.images
[image
])
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
)
440 for node
in deletegroup
:
441 bpy
.data
.node_groups
.remove(bpy
.data
.node_groups
[node
])
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
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()
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'
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'
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'
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'
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()
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
)
534 coat3D
= bpy
.context
.scene
.coat3D
536 if (bpy
.context
.selected_objects
== []):
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)
545 if (export_ok
== False):
548 scaled_objects
= scaleParents()
550 activeobj
= bpy
.context
.active_object
.name
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
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
))
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
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
)):
593 coa
.applink_name
= ("%s%.2d"%(activeobj
,object_index
))
594 coa
.applink_address
= checkname
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
)
606 objekti
.coat3D
.applink_name
= objekti
.name
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
)
615 os
.makedirs(bake_location
)
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
= []
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
)):
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
649 if(coat3D
.bake_diffuse
):
650 bake_list
.append(['DIFFUSE', '$LOADTEX'])
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'):
660 elif (coat3D
.bake_resolution
== 'res_128'):
662 elif (coat3D
.bake_resolution
== 'res_256'):
664 elif (coat3D
.bake_resolution
== 'res_512'):
666 elif (coat3D
.bake_resolution
== 'res_1024'):
668 elif (coat3D
.bake_resolution
== 'res_2048'):
670 elif (coat3D
.bake_resolution
== 'res_4096'):
672 elif (coat3D
.bake_resolution
== 'res_8192'):
675 if(len(bake_list
) > 0):
677 while(index_bake_tex
< len(bake_list
)):
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
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
)
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
)
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
+ '''");]'''
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
)
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')
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
)
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
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
:
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
)
805 for del_img
in img_list
:
806 bpy
.data
.images
.remove(del_img
)
808 bpy
.data
.materials
.remove(material
)
811 for image
in bpy
.data
.images
:
812 if (image
.name
.startswith('3DC')):
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()
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
]
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()
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
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
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
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
)
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
)
998 objekti
.coat3D
.applink_3b_just_name
= just_3b_name
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')
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)
1048 for data_mesh
in objekti
.data
.polygons
:
1049 data_mesh
.use_smooth
= True
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
):
1062 if(objekti
.coat3D
.retopo
== False):
1063 tex
.matlab(objekti
,mat_list
,texturelist
,is_new
)
1064 objekti
.select_set(False)
1067 if (objekti
.material_slots
):
1068 for obj_mat
in objekti
.material_slots
:
1069 mat_list
.append(obj_mat
.material
)
1071 if (coat3D
.importtextures
):
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
)):
1080 coat3D
.remove_path
= False
1082 bpy
.ops
.object.select_all(action
='DESELECT')
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)
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
))
1134 if (os
.path
.isfile(path3b_now
)):
1135 path3b_fil
= open(path3b_now
)
1136 for lin
in path3b_fil
:
1139 head
, tail
= os
.path
.split(osoite_3b
)
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
1181 facture_object
= False
1183 for c_index
in diff_objects
:
1184 bpy
.data
.objects
[c_index
].data
.coat3D
.name
= '3DC'
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
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
)
1221 texVR
.matlab(new_obj
, mat_list
, texturelist
, is_new
)
1222 new_obj
.scale
= (0.01, 0.01, 0.01)
1224 tex
.matlab(new_obj
, mat_list
, texturelist
, is_new
)
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'
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
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
)
1295 new_ref_function(new_applink_address
, nimi
)
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'
1321 new_ref_object
= False
1323 if(os
.path
.isfile(Blender_export
)):
1324 obj_pathh
= open(Blender_export
)
1326 for line
in obj_pathh
:
1327 new_applink_address
= line
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
):
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
)
1344 new_ref_function(new_applink_address
, nimi
)
1348 blender_3DC(texturelist
, new_applink_address
)
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'
1360 def poll(cls
, context
):
1361 if bpy
.context
.mode
== 'OBJECT':
1366 def draw(self
, context
):
1367 layout
= self
.layout
1368 coat3D
= bpy
.context
.scene
.coat3D
1369 global foundExchangeFolder
1371 if(foundExchangeFolder
== False):
1373 row
.label(text
="Applink didn't find your 3d-Coat/Exchange folder.")
1375 row
.label(text
="Please select it before using Applink.")
1377 row
.prop(coat3D
,"exchangeFolder",text
="")
1379 row
.operator("update_exchange_folder.pilgway_3d_coat", text
="Apply folder")
1382 #Here you add your GUI
1384 row
.prop(coat3D
,"type",text
= "")
1385 flow
= layout
.grid_flow(row_major
=True, columns
=0, even_columns
=False, even_rows
=False, align
=True)
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
):
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
):
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)
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")
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
):
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)
1463 col
.prop(coat3D
, "importmesh", text
="Update Mesh/UV")
1465 col
.prop(coat3D
, "createnodes", text
="Create Extra Nodes")
1467 col
.prop(coat3D
, "importtextures", text
="Update Textures")
1469 col
.prop(coat3D
, "exportmod", text
="Export with modifiers")
1471 class SCENE_PT_Bake_Settings(ObjectButtonsPanel
, bpy
.types
.Panel
):
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)
1486 col
.prop(coat3D
, "bake_resolution", text
="Resolution")
1488 col
.prop(coat3D
, "bake_diffuse", text
="Diffuse")
1490 col
.prop(coat3D
, "bake_ao", text
="AO")
1492 col
.prop(coat3D
, "bake_normal", text
="Normal")
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)
1511 col
.prop(coat3D
, "exchangeFolder", text
="Exchange folder")
1512 col
.operator("save_new_export.pilgway_3d_coat", text
="Save new Exchange folder")
1515 col
.prop(coat3D
, "defaultfolder", text
="Object/Texture folder")
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)
1535 col
.operator("delete_material_nodes.pilgway_3d_coat", text
="Material")
1537 col
.operator("delete_object_nodes.pilgway_3d_coat", text
="Object(s)")
1540 col
.operator("delete_collection_nodes.pilgway_3d_coat", text
="Collection")
1542 col
.operator("delete_scene_nodes.pilgway_3d_coat", text
="Scene")
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'
1560 if ob
.mode
== 'OBJECT':
1561 if(len(context
.selected_objects
) > 0):
1562 layout
.operator("import_applink.pilgway_3d_coat",
1563 text
="Update Scene")
1566 layout
.operator("export_applink.pilgway_3d_coat",
1567 text
="Transfer to 3D-Coat")
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
)
1576 layout
.operator("import_applink.pilgway_3d_coat",
1577 text
="Update Scene")
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")
1596 class ObjectCoat3D(PropertyGroup
):
1598 obj_mat
: StringProperty(
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(
1619 description
="FirstTime",
1622 retopo
: BoolProperty(
1623 name
="Retopo object",
1624 description
="Retopo object",
1627 delete_proxy_mesh
: BoolProperty(
1629 description
="FirstTime",
1632 applink_onlyone
: BoolProperty(
1634 description
="FirstTime",
1637 type: StringProperty(
1639 description
="shows type",
1642 import_mesh
: BoolProperty(
1644 description
="ImportMesh",
1647 applink_mesh
: BoolProperty(
1649 description
="ImportMesh",
1652 applink_old
: BoolProperty(
1654 description
="Old Object",
1657 applink_export
: BoolProperty(
1659 description
="Object is from 3d-ocat",
1662 objecttime
: StringProperty(
1666 path3b
: StringProperty(
1670 dime
: FloatVectorProperty(
1672 description
="Dimension"
1674 applink_scale
: FloatVectorProperty(
1679 class SceneCoat3D(PropertyGroup
):
1680 defaultfolder
: StringProperty(
1684 deleteMode
: StringProperty(
1689 coat3D_exe
: StringProperty(
1691 subtype
="FILE_PATH",
1693 exchangeFolder
: StringProperty(
1697 bring_retopo
: BoolProperty(
1698 name
="Import window",
1699 description
="Allows to skip import dialog",
1702 foundExchangeFolder
: BoolProperty(
1703 name
="found Exchange Folder",
1704 description
="found Exchange folder",
1707 delete_images
: BoolProperty(
1708 name
="Import window",
1709 description
="Allows to skip import dialog",
1712 bring_retopo_path
: StringProperty(
1716 remove_path
: BoolProperty(
1717 name
="Import window",
1718 description
="Allows to skip import dialog",
1721 exchange_found
: BoolProperty(
1722 name
="Exchange Found",
1723 description
="Alert if Exchange folder is not found",
1726 exportfile
: BoolProperty(
1727 name
="No Import File",
1728 description
="Add Modifiers and export",
1731 importmod
: BoolProperty(
1732 name
="Remove Modifiers",
1733 description
="Import and add modifiers",
1736 exportmod
: BoolProperty(
1738 description
="Export modifiers",
1741 importtextures
: BoolProperty(
1742 name
="Bring Textures",
1743 description
="Import Textures",
1746 createnodes
: BoolProperty(
1747 name
="Bring Textures",
1748 description
="Import Textures",
1751 importlevel
: BoolProperty(
1752 name
="Multires. Level",
1753 description
="Bring Specific Multires Level",
1756 importmesh
: BoolProperty(
1758 description
="Import Mesh",
1764 loca
: FloatVectorProperty(
1766 description
="Location",
1768 default
=(0.0, 0.0, 0.0)
1770 rota
: FloatVectorProperty(
1772 description
="Location",
1774 default
=(0.0, 0.0, 0.0)
1776 scal
: FloatVectorProperty(
1778 description
="Location",
1780 default
=(0.0, 0.0, 0.0)
1782 dime
: FloatVectorProperty(
1784 description
="Dimension",
1786 default
=(0.0, 0.0, 0.0)
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", ""),
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", ""),
1820 folder_size
: EnumProperty(
1821 name
="Applink folder size",
1822 description
="Applink folder size",
1823 items
=(("10", "10", ""),
1826 ("1000", "1000", ""),
1827 ("5000", "5000", ""),
1828 ("10000", "10000", ""),
1832 bake_textures
: BoolProperty(
1833 name
="Bake all textures",
1834 description
="Add Modifiers and export",
1837 bake_diffuse
: BoolProperty(
1838 name
="Bake diffuse texture",
1839 description
="Add Modifiers and export",
1842 bake_ao
: BoolProperty(
1843 name
="Bake AO texture",
1844 description
="Add Modifiers and export",
1847 bake_roughness
: BoolProperty(
1848 name
="Bake roughness texture",
1849 description
="Add Modifiers and export",
1852 bake_metalness
: BoolProperty(
1853 name
="Bake metalness texture",
1854 description
="Add Modifiers and export",
1857 bake_emissive
: BoolProperty(
1858 name
="Bake emissive texture",
1859 description
="Add Modifiers and export",
1862 bake_normal
: BoolProperty(
1863 name
="Bake normal texture",
1864 description
="Add Modifiers and export",
1867 bake_displacement
: BoolProperty(
1868 name
="Bake displacement",
1869 description
="Add Modifiers and export",
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",
1885 bring_diffuse
: BoolProperty(
1886 name
="Import diffuse texture",
1887 description
="Import diffuse texture",
1890 bring_metalness
: BoolProperty(
1891 name
="Import diffuse texture",
1892 description
="Import diffuse texture",
1895 bring_roughness
: BoolProperty(
1896 name
="Import diffuse texture",
1897 description
="Import diffuse texture",
1900 bring_normal
: BoolProperty(
1901 name
="Import diffuse texture",
1902 description
="Import diffuse texture",
1905 bring_displacement
: BoolProperty(
1906 name
="Import diffuse texture",
1907 description
="Import diffuse texture",
1910 bring_emissive
: BoolProperty(
1911 name
="Import diffuse texture",
1912 description
="Import diffuse texture",
1915 bring_gloss
: BoolProperty(
1916 name
="Import diffuse texture",
1917 description
="Import diffuse texture",
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
,
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
,
1948 bpy
.types
.Material
.coat3D_diffuse
= BoolProperty(
1949 name
="Import diffuse texture",
1950 description
="Import diffuse texture",
1953 bpy
.types
.Material
.coat3D_roughness
= BoolProperty(
1954 name
="Import diffuse texture",
1955 description
="Import diffuse texture",
1958 bpy
.types
.Material
.coat3D_metalness
= BoolProperty(
1959 name
="Import diffuse texture",
1960 description
="Import diffuse texture",
1963 bpy
.types
.Material
.coat3D_normal
= BoolProperty(
1964 name
="Import diffuse texture",
1965 description
="Import diffuse texture",
1968 bpy
.types
.Material
.coat3D_displacement
= BoolProperty(
1969 name
="Import diffuse texture",
1970 description
="Import diffuse texture",
1973 bpy
.types
.Material
.coat3D_emissive
= BoolProperty(
1974 name
="Import diffuse texture",
1975 description
="Import diffuse texture",
1978 bpy
.types
.Material
.coat3D_ao
= BoolProperty(
1979 name
="Import diffuse texture",
1980 description
="Import diffuse texture",
1983 bpy
.types
.Material
.coat3D_alpha
= BoolProperty(
1984 name
="Import alpha texture",
1985 description
="Import alpha texture",
1988 bpy
.types
.Material
.coat3D_gloss
= BoolProperty(
1989 name
="Import alpha texture",
1990 description
="Import alpha texture",
1997 from bpy
.utils
import register_class
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
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"
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
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
)