1 # SPDX-FileCopyrightText: 2010-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
6 "name": "3D-Coat Applink",
7 "author": "Kalle-Samuli Riihikoski (haikalle)",
10 "location": "Scene > 3D-Coat Applink",
11 "description": "Transfer data between 3D-Coat/Blender",
13 "doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/coat3D.html",
14 "category": "Import-Export",
22 from bpy
.app
.handlers
import persistent
24 from io_coat3D
import tex
25 from io_coat3D
import texVR
26 from io_coat3D
import folders
41 from bpy
.types
import PropertyGroup
42 from bpy
.props
import (
50 global_exchange_folder
= ''
51 foundExchangeFolder
= True
52 saved_exchange_folder
= ''
57 def every_3_seconds():
59 global global_exchange_folder
66 folders
.loadExchangeFolder()
70 coat3D
= bpy
.context
.scene
.coat3D
72 Export_folder
= coat3D
.exchangeFolder
73 Export_folder
+= ('%sexport.txt' % (os
.sep
))
75 if (os
.path
.isfile(Export_folder
) and mTime
!= os
.path
.getmtime(Export_folder
)):
77 for objekti
in bpy
.data
.objects
:
78 if(objekti
.coat3D
.applink_mesh
):
79 tex
.updatetextures(objekti
)
81 mTime
= os
.path
.getmtime(Export_folder
)
89 def load_handler(dummy
):
90 bpy
.app
.timers
.register(every_3_seconds
)
92 def removeFile(exportfile
):
93 if (os
.path
.isfile(exportfile
)):
97 def folder_size(path
):
99 folder_size_max
= int(bpy
.context
.scene
.coat3D
.folder_size
)
101 if(bpy
.context
.scene
.coat3D
.defaultfolder
== ''):
105 for file in os
.listdir(path
):
106 list_of_files
.append(path
+ os
.sep
+ file)
108 if len(list_of_files
) >= folder_size_max
:
109 oldest_file
= min(list_of_files
, key
=os
.path
.getctime
)
110 os
.remove(os
.path
.abspath(oldest_file
))
114 def make_texture_list(texturefolder
):
115 texturefolder
+= ('%stextures.txt'%(os
.sep
))
118 if (os
.path
.isfile(texturefolder
)):
119 texturefile
= open(texturefolder
)
121 for line
in texturefile
:
122 if line
!= '' and index
== 0:
123 line
= line
.rstrip('\n')
127 line
= line
.rstrip('\n')
131 line
= line
.rstrip('\n')
135 line
= line
.rstrip('\n')
137 texturelist
.append([objekti
,material
,type,address
])
144 #Updating objects MESH part ( Mesh, Vertex Groups, Vertex Colors )
147 def updatemesh(objekti
, proxy
, texturelist
):
149 if(len(proxy
.data
.vertex_colors
) > 0):
150 bring_vertex_map
= True
152 bring_vertex_map
= False
154 if(bring_vertex_map
):
155 if(len(objekti
.data
.vertex_colors
) > 0):
156 for vertex_map
in objekti
.data
.vertex_colors
:
157 if vertex_map
.name
== 'Col':
159 vertex_map_copy
= vertex_map
167 for poly
in objekti
.data
.polygons
:
168 for loop_index
in poly
.loop_indices
:
169 vertex_map_copy
.data
[loop_index
].color
= proxy
.data
.vertex_colors
[0].data
[loop_index
].color
171 objekti
.data
.vertex_colors
.new()
172 vertex_map_copy
= objekti
.data
.vertex_colors
[-1]
173 for poly
in objekti
.data
.polygons
:
174 for loop_index
in poly
.loop_indices
:
175 vertex_map_copy
.data
[loop_index
].color
= proxy
.data
.vertex_colors
[0].data
[loop_index
].color
178 udim_textures
= False
179 if(texturelist
!= []):
180 if(texturelist
[0][0].startswith('100')):
183 proxy
.select_set(True)
184 objekti
.select_set(True)
186 uv_count
= len(proxy
.data
.uv_layers
)
188 while(index
< uv_count
and len(proxy
.data
.polygons
) == len(objekti
.data
.polygons
)):
189 for poly
in proxy
.data
.polygons
:
190 for indi
in poly
.loop_indices
:
191 if(proxy
.data
.uv_layers
[index
].data
[indi
].uv
[0] != 0 and proxy
.data
.uv_layers
[index
].data
[indi
].uv
[1] != 0):
194 udim
= proxy
.data
.uv_layers
[index
].name
195 udim_index
= int(udim
[2:]) - 1
197 objekti
.data
.uv_layers
[0].data
[indi
].uv
[0] = proxy
.data
.uv_layers
[index
].data
[indi
].uv
[0]
198 objekti
.data
.uv_layers
[0].data
[indi
].uv
[1] = proxy
.data
.uv_layers
[index
].data
[indi
].uv
[1]
203 if(proxy
.name
.startswith('RetopoGroup')):
204 objekti
.data
= proxy
.data
206 for ind
, v
in enumerate(objekti
.data
.vertices
):
207 v
.co
= proxy
.data
.vertices
[ind
].co
209 class SCENE_OT_getback(bpy
.types
.Operator
):
210 bl_idname
= "getback.pilgway_3d_coat"
211 bl_label
= "Export your custom property"
212 bl_description
= "Export your custom property"
213 bl_options
= {'UNDO'}
215 def invoke(self
, context
, event
):
217 global global_exchange_folder
220 Export_folder
= global_exchange_folder
221 Blender_folder
= os
.path
.join(Export_folder
, 'Blender')
223 BlenderFolder
= Blender_folder
224 ExportFolder
= Export_folder
226 Blender_folder
+= ('%sexport.txt' % (os
.sep
))
227 Export_folder
+= ('%sexport.txt' % (os
.sep
))
229 if (bpy
.app
.background
== False):
230 if os
.path
.isfile(Export_folder
):
232 print('BLENDER -> 3DC -> BLENDER WORKFLLOW')
234 workflow1(ExportFolder
)
235 removeFile(Export_folder
)
236 removeFile(Blender_folder
)
238 elif os
.path
.isfile(Blender_folder
):
240 print('3DC -> BLENDER WORKFLLOW')
242 workflow2(BlenderFolder
)
243 removeFile(Blender_folder
)
247 class SCENE_OT_savenew(bpy
.types
.Operator
):
248 bl_idname
= "save_new_export.pilgway_3d_coat"
249 bl_label
= "Export your custom property"
250 bl_description
= "Export your custom property"
251 bl_options
= {'UNDO'}
253 def invoke(self
, context
, event
):
255 coat3D
= bpy
.context
.scene
.coat3D
256 platform
= os
.sys
.platform
258 if(platform
== 'win32' or platform
== 'darwin'):
259 exchangeFile
= os
.path
.expanduser("~") + os
.sep
+ 'Documents' + os
.sep
+ '3DC2Blender' + os
.sep
+ 'Exchange_folder.txt'
261 exchangeFile
= os
.path
.expanduser("~") + os
.sep
+ '3DC2Blender' + os
.sep
+ 'Exchange_folder.txt'
262 if(os
.path
.isfile(exchangeFile
)):
265 if(os
.path
.isfile(exchangeFile
)):
266 file = open(exchangeFile
, "w")
267 file.write("%s"%(coat3D
.exchangeFolder
))
273 class SCENE_OT_folder(bpy
.types
.Operator
):
274 bl_idname
= "update_exchange_folder.pilgway_3d_coat"
275 bl_label
= "Export your custom property"
276 bl_description
= "Export your custom property"
277 bl_options
= {'UNDO'}
279 def invoke(self
, context
, event
):
280 global foundExchangeFolder
281 coat3D
= bpy
.context
.scene
.coat3D
282 if(os
.path
.isdir(coat3D
.exchangeFolder
)):
283 foundExchangeFolder
= True
284 folders
.updateExchangeFile(coat3D
.exchangeFolder
)
288 class SCENE_OT_opencoat(bpy
.types
.Operator
):
289 bl_idname
= "open_3dcoat.pilgway_3d_coat"
290 bl_label
= "Export your custom property"
291 bl_description
= "Export your custom property"
292 bl_options
= {'UNDO'}
294 def invoke(self
, context
, event
):
296 coat3D
= bpy
.context
.selected_objects
[0].coat3D
.applink_3b_path
297 platform
= os
.sys
.platform
298 if (platform
== 'win32' or platform
== 'darwin'):
299 importfile
= bpy
.context
.scene
.coat3D
.exchangeFolder
300 importfile
+= ('%simport.txt' % (os
.sep
))
301 file = open(importfile
, "w")
302 file.write("%s" % (coat3D
))
303 file.write("\n%s" % (coat3D
))
307 importfile
= bpy
.context
.scene
.coat3D
.exchangeFolder
308 importfile
+= ('%simport.txt' % (os
.sep
))
309 file = open(importfile
, "w")
310 file.write("%s" % (coat3D
))
311 file.write("\n%s" % (coat3D
))
321 for objekti
in bpy
.context
.selected_objects
:
323 while (temp
.parent
is not None and temp
.parent
.name
not in names
):
324 save
.append([temp
.parent
,(temp
.parent
.scale
[0],temp
.parent
.scale
[1],temp
.parent
.scale
[2])])
325 names
.append(temp
.parent
)
333 def scaleBackParents(save
):
336 data
[0].scale
= data
[1]
338 def deleteNodes(type):
343 delete_images
= bpy
.context
.scene
.coat3D
.delete_images
345 if type == 'Material':
346 if(len(bpy
.context
.selected_objects
) == 1):
347 material
= bpy
.context
.selected_objects
[0].active_material
348 if(material
.use_nodes
):
349 for node
in material
.node_tree
.nodes
:
350 if(node
.name
.startswith('3DC')):
351 if (node
.type == 'GROUP'):
352 deletegroup
.append(node
.node_tree
.name
)
353 deletelist
.append(node
.name
)
354 if node
.type == 'TEX_IMAGE' and delete_images
== True:
355 deleteimages
.append(node
.image
.name
)
357 for node
in deletelist
:
358 material
.node_tree
.nodes
.remove(material
.node_tree
.nodes
[node
])
360 for image
in deleteimages
:
361 bpy
.data
.images
.remove(bpy
.data
.images
[image
])
363 elif type == 'Object':
364 if (len(bpy
.context
.selected_objects
) > 0):
365 for objekti
in bpy
.context
.selected_objects
:
366 for material
in objekti
.material_slots
:
367 if (material
.material
.use_nodes
):
368 for node
in material
.material
.node_tree
.nodes
:
369 if (node
.name
.startswith('3DC')):
370 if(node
.type == 'GROUP'):
371 deletegroup
.append(node
.node_tree
.name
)
372 deletelist
.append(node
.name
)
373 if node
.type == 'TEX_IMAGE' and delete_images
== True:
374 deleteimages
.append(node
.image
.name
)
376 for node
in deletelist
:
377 material
.material
.node_tree
.nodes
.remove(material
.material
.node_tree
.nodes
[node
])
381 for image
in deleteimages
:
382 bpy
.data
.images
.remove(bpy
.data
.images
[image
])
385 elif type == 'Collection':
386 for collection_object
in bpy
.context
.view_layer
.active_layer_collection
.collection
.all_objects
:
387 if(collection_object
.type == 'MESH'):
388 for material
in collection_object
.material_slots
:
389 if (material
.material
.use_nodes
):
390 for node
in material
.material
.node_tree
.nodes
:
391 if (node
.name
.startswith('3DC')):
392 if (node
.type == 'GROUP'):
393 deletegroup
.append(node
.node_tree
.name
)
394 deletelist
.append(node
.name
)
395 if node
.type == 'TEX_IMAGE' and delete_images
== True:
396 deleteimages
.append(node
.image
.name
)
399 for node
in deletelist
:
400 material
.material
.node_tree
.nodes
.remove(material
.material
.node_tree
.nodes
[node
])
404 for image
in deleteimages
:
405 bpy
.data
.images
.remove(bpy
.data
.images
[image
])
408 elif type == 'Scene':
409 for collection
in bpy
.data
.collections
:
410 for collection_object
in collection
.all_objects
:
411 if (collection_object
.type == 'MESH'):
412 for material
in collection_object
.material_slots
:
413 if (material
.material
.use_nodes
):
414 for node
in material
.material
.node_tree
.nodes
:
415 if (node
.name
.startswith('3DC')):
416 if (node
.type == 'GROUP'):
417 deletegroup
.append(node
.node_tree
.name
)
419 deletelist
.append(node
.name
)
420 if node
.type == 'TEX_IMAGE' and delete_images
== True:
421 deleteimages
.append(node
.image
.name
)
423 for node
in deletelist
:
424 material
.material
.node_tree
.nodes
.remove(material
.material
.node_tree
.nodes
[node
])
428 for image
in deleteimages
:
429 bpy
.data
.images
.remove(bpy
.data
.images
[image
])
433 for node
in deletelist
:
434 bpy
.data
.node_groups
.remove(bpy
.data
.node_groups
[node
])
436 for image
in bpy
.data
.images
:
437 if (image
.name
.startswith('3DC') and image
.name
[6] == '_'):
438 deleteimages
.append(image
.name
)
442 for node
in deletegroup
:
443 bpy
.data
.node_groups
.remove(bpy
.data
.node_groups
[node
])
446 for image
in deleteimages
:
447 bpy
.data
.images
.remove(bpy
.data
.images
[image
])
450 def delete_materials_from_end(keep_materials_count
, objekti
):
451 #bpy.context.object.active_material_index = 0
453 while (index_t
< keep_materials_count
):
454 temp_len
= len(objekti
.material_slots
)-1
455 bpy
.context
.object.active_material_index
= temp_len
456 bpy
.ops
.object.material_slot_remove()
459 ''' DELETE NODES BUTTONS'''
461 class SCENE_OT_delete_material_nodes(bpy
.types
.Operator
):
462 bl_idname
= "delete_material_nodes.pilgway_3d_coat"
463 bl_label
= "Delete material nodes"
464 bl_description
= "Delete material nodes"
465 bl_options
= {'UNDO'}
467 def invoke(self
, context
, event
):
468 type = bpy
.context
.scene
.coat3D
.deleteMode
= 'Material'
472 class SCENE_OT_delete_object_nodes(bpy
.types
.Operator
):
473 bl_idname
= "delete_object_nodes.pilgway_3d_coat"
474 bl_label
= "Delete material nodes"
475 bl_description
= "Delete material nodes"
476 bl_options
= {'UNDO'}
478 def invoke(self
, context
, event
):
479 type = bpy
.context
.scene
.coat3D
.deleteMode
= 'Object'
483 class SCENE_OT_delete_collection_nodes(bpy
.types
.Operator
):
484 bl_idname
= "delete_collection_nodes.pilgway_3d_coat"
485 bl_label
= "Delete material nodes"
486 bl_description
= "Delete material nodes"
487 bl_options
= {'UNDO'}
489 def invoke(self
, context
, event
):
490 type = bpy
.context
.scene
.coat3D
.deleteMode
= 'Collection'
494 class SCENE_OT_delete_scene_nodes(bpy
.types
.Operator
):
495 bl_idname
= "delete_scene_nodes.pilgway_3d_coat"
496 bl_label
= "Delete material nodes"
497 bl_description
= "Delete material nodes"
498 bl_options
= {'UNDO'}
500 def invoke(self
, context
, event
):
501 type = bpy
.context
.scene
.coat3D
.deleteMode
= 'Scene'
506 ''' TRANSFER AND UPDATE BUTTONS'''
508 class SCENE_OT_export(bpy
.types
.Operator
):
509 bl_idname
= "export_applink.pilgway_3d_coat"
510 bl_label
= "Export your custom property"
511 bl_description
= "Export your custom property"
512 bl_options
= {'UNDO'}
514 def invoke(self
, context
, event
):
515 bpy
.ops
.export_applink
.pilgway_3d_coat()
519 def execute(self
, context
):
520 global foundExchangeFolder
521 global global_exchange_folder
522 global run_background_update
523 run_background_update
= False
525 foundExchangeFolder
, global_exchange_folder
= folders
.InitFolders()
527 for mesh
in bpy
.data
.meshes
:
528 if (mesh
.users
== 0 and mesh
.coat3D
.name
== '3DC'):
529 bpy
.data
.meshes
.remove(mesh
)
531 for material
in bpy
.data
.materials
:
532 if (material
.users
== 1 and material
.coat3D
.name
== '3DC'):
533 bpy
.data
.materials
.remove(material
)
536 coat3D
= bpy
.context
.scene
.coat3D
538 if (bpy
.context
.selected_objects
== []):
541 for objec
in bpy
.context
.selected_objects
:
542 if objec
.type == 'MESH':
543 if(len(objec
.data
.uv_layers
) == 0):
544 objec
.data
.uv_layers
.new(name
='UVMap', do_init
= False)
547 if (export_ok
== False):
550 scaled_objects
= scaleParents()
552 activeobj
= bpy
.context
.active_object
.name
554 coa
= bpy
.context
.active_object
.coat3D
556 p
= pathlib
.Path(coat3D
.exchangeFolder
)
557 kokeilu
= coat3D
.exchangeFolder
[:-9]
558 Blender_folder2
= ("%s%sExchange" % (kokeilu
, os
.sep
))
559 Blender_folder2
+= ('%sexport.txt' % (os
.sep
))
561 if (os
.path
.isfile(Blender_folder2
)):
562 os
.remove(Blender_folder2
)
564 if (not os
.path
.isdir(coat3D
.exchangeFolder
)):
565 coat3D
.exchange_found
= False
568 folder_objects
= folders
.set_working_folders()
569 folder_size(folder_objects
)
571 importfile
= coat3D
.exchangeFolder
572 texturefile
= coat3D
.exchangeFolder
573 importfile
+= ('%simport.txt'%(os
.sep
))
574 texturefile
+= ('%stextures.txt'%(os
.sep
))
578 active_render
= bpy
.context
.scene
.render
.engine
580 if(coat3D
.type == 'autopo'):
581 checkname
= folder_objects
+ os
.sep
582 checkname
= ("%sretopo.fbx" % (checkname
))
584 elif(coat3D
.type == 'update'):
585 checkname
= bpy
.context
.selected_objects
[0].coat3D
.applink_address
588 while(looking
== True):
589 checkname
= folder_objects
+ os
.sep
+ "3DC"
590 checkname
= ("%s%.3d.fbx"%(checkname
,object_index
))
591 if(os
.path
.isfile(checkname
)):
595 coa
.applink_name
= ("%s%.2d"%(activeobj
,object_index
))
596 coa
.applink_address
= checkname
600 for objekti
in bpy
.context
.selected_objects
:
601 if objekti
.type == 'MESH':
602 objekti
.name
= '__' + objekti
.name
603 if(objekti
.material_slots
.keys() == []):
604 newmat
= bpy
.data
.materials
.new('Material')
605 newmat
.use_nodes
= True
606 objekti
.data
.materials
.append(newmat
)
608 objekti
.coat3D
.applink_name
= objekti
.name
612 bake_location
= folder_objects
+ os
.sep
+ 'Bake'
613 if (os
.path
.isdir(bake_location
)):
614 shutil
.rmtree(bake_location
)
615 os
.makedirs(bake_location
)
617 os
.makedirs(bake_location
)
622 for objekti
in bpy
.context
.selected_objects
:
623 if objekti
.type == 'MESH':
624 mod_mat_list
[objekti
.name
] = []
625 objekti
.coat3D
.applink_scale
= objekti
.scale
626 objekti
.coat3D
.retopo
= False
628 ''' Checks what materials are linked into UV '''
630 if(coat3D
.type == 'ppp'):
631 final_material_indexs
= []
633 for poly
in objekti
.data
.polygons
:
634 if(poly
.material_index
not in final_material_indexs
):
635 final_material_indexs
.append(poly
.material_index
)
636 loop_index
= poly
.loop_indices
[0]
637 uvtiles_index
.append([poly
.material_index
,objekti
.data
.uv_layers
.active
.data
[loop_index
].uv
[0]])
638 if(len(final_material_indexs
) == len(objekti
.material_slots
)):
642 if (len(final_material_indexs
) != len(objekti
.material_slots
)):
643 for material
in objekti
.material_slots
:
644 if material_index
not in final_material_indexs
:
645 temp_mat
= material
.material
646 material
.material
= objekti
.material_slots
[0].material
647 mod_mat_list
[objekti
.name
].append([material_index
, temp_mat
])
648 material_index
= material_index
+ 1
651 if(coat3D
.bake_diffuse
):
652 bake_list
.append(['DIFFUSE', '$LOADTEX'])
654 bake_list
.append(['AO', '$ExternalAO'])
655 if (coat3D
.bake_normal
):
656 bake_list
.append(['NORMAL', '$LOADLOPOLYTANG'])
657 if (coat3D
.bake_roughness
):
658 bake_list
.append(['ROUGHNESS', '$LOADROUGHNESS'])
660 if(coat3D
.bake_resolution
== 'res_64'):
662 elif (coat3D
.bake_resolution
== 'res_128'):
664 elif (coat3D
.bake_resolution
== 'res_256'):
666 elif (coat3D
.bake_resolution
== 'res_512'):
668 elif (coat3D
.bake_resolution
== 'res_1024'):
670 elif (coat3D
.bake_resolution
== 'res_2048'):
672 elif (coat3D
.bake_resolution
== 'res_4096'):
674 elif (coat3D
.bake_resolution
== 'res_8192'):
677 if(len(bake_list
) > 0):
679 while(index_bake_tex
< len(bake_list
)):
681 for bake_mat_index
in final_material_indexs
:
682 bake_node
= objekti
.material_slots
[bake_mat_index
].material
.node_tree
.nodes
.new('ShaderNodeTexImage')
683 bake_node
.name
= 'ApplinkBake' + str(bake_index
)
684 bpy
.ops
.image
.new(name
=bake_node
.name
, width
=res_size
, height
=res_size
)
685 bake_node
.image
= bpy
.data
.images
[bake_node
.name
]
686 objekti
.material_slots
[bake_mat_index
].material
.node_tree
.nodes
.active
= bake_node
689 if(bpy
.context
.scene
.render
.engine
!= 'CYCLES'):
690 bpy
.context
.scene
.render
.engine
= 'CYCLES'
691 bpy
.context
.scene
.render
.bake
.use_pass_direct
= False
692 bpy
.context
.scene
.render
.bake
.use_pass_indirect
= False
693 bpy
.context
.scene
.render
.bake
.use_pass_color
= True
695 bpy
.ops
.object.bake(type=bake_list
[index_bake_tex
][0], margin
=1, width
=res_size
, height
=res_size
)
698 for bake_mat_index
in final_material_indexs
:
699 bake_image
= 'ApplinkBake' + str(bake_index
)
700 bpy
.data
.images
[bake_image
].filepath_raw
= bake_location
+ os
.sep
+ objekti
.name
+ '_' + bake_image
+ '_' + bake_list
[index_bake_tex
][0] + ".png"
701 image_bake_name
= bpy
.data
.images
[bake_image
].filepath_raw
702 tie
= image_bake_name
.split(os
.sep
)
707 final_bake_name
= toi
[:-1]
708 bpy
.data
.images
[bake_image
].save()
709 temp_string
+= '''\n[script ImportTexture("''' + bake_list
[index_bake_tex
][1] + '''","''' + objekti
.material_slots
[bake_mat_index
].material
.name
+ '''","''' + final_bake_name
+ '''");]'''
713 for material
in objekti
.material_slots
:
714 if material
.material
.use_nodes
== True:
715 for node
in material
.material
.node_tree
.nodes
:
716 if (node
.name
.startswith('ApplinkBake') == True):
717 material
.material
.node_tree
.nodes
.remove(node
)
719 for image
in bpy
.data
.images
:
720 if (image
.name
.startswith('ApplinkBake') == True):
721 bpy
.data
.images
.remove(image
)
727 #bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
728 if(len(bpy
.context
.selected_objects
) > 1 and coat3D
.type != 'vox'):
729 bpy
.ops
.object.transforms_to_deltas(mode
='ROT')
731 if(coat3D
.type == 'autopo'):
732 coat3D
.bring_retopo
= True
733 coat3D
.bring_retopo_path
= checkname
734 bpy
.ops
.export_scene
.fbx(filepath
=checkname
, global_scale
= 1, use_selection
=True, use_mesh_modifiers
=coat3D
.exportmod
, axis_forward
='-Z', axis_up
='Y')
736 elif (coat3D
.type == 'vox'):
737 coat3D
.bring_retopo
= False
738 bpy
.ops
.export_scene
.fbx(filepath
=coa
.applink_address
, global_scale
= 0.01, use_selection
=True,
739 use_mesh_modifiers
=coat3D
.exportmod
, axis_forward
='-Z', axis_up
='Y')
742 coat3D
.bring_retopo
= False
743 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')
745 file = open(importfile
, "w")
746 file.write("%s"%(checkname))
747 file.write("\n%s"%(checkname))
748 file.write("\n[%s]"%(coat3D
.type))
749 if(coat3D
.type == 'ppp' or coat3D
.type == 'mv' or coat3D
.type == 'ptex'):
750 file.write("\n[export_preset Blender Cycles]")
751 file.write(temp_string
)
754 for idx
, objekti
in enumerate(bpy
.context
.selected_objects
):
755 if objekti
.type == 'MESH':
756 objekti
.name
= objekti
.name
[2:]
757 if(len(bpy
.context
.selected_objects
) == 1):
758 objekti
.coat3D
.applink_onlyone
= True
759 objekti
.coat3D
.type = coat3D
.type
760 objekti
.coat3D
.applink_mesh
= True
761 objekti
.coat3D
.obj_mat
= ''
762 objekti
.coat3D
.applink_index
= ("3DC%.3d" % (object_index
))
764 objekti
.coat3D
.applink_firsttime
= True
765 if(coat3D
.type != 'autopo'):
766 objekti
.coat3D
.applink_address
= coa
.applink_address
767 objekti
.coat3D
.objecttime
= str(os
.path
.getmtime(objekti
.coat3D
.applink_address
))
768 objekti
.data
.coat3D
.name
= '3DC'
770 if(coat3D
.type != 'vox'):
771 if(objekti
.material_slots
.keys() != []):
772 for material
in objekti
.material_slots
:
773 if material
.material
.use_nodes
== True:
774 for node
in material
.material
.node_tree
.nodes
:
775 if(node
.name
.startswith('3DC_') == True):
776 material
.material
.node_tree
.nodes
.remove(node
)
779 for ind
, mat_list
in enumerate(mod_mat_list
):
780 if(mat_list
== '__' + objekti
.name
):
781 for ind
, mat
in enumerate(mod_mat_list
[mat_list
]):
782 objekti
.material_slots
[mod_mat_list
[mat_list
][ind
][0]].material
= mod_mat_list
[mat_list
][ind
][1]
784 scaleBackParents(scaled_objects
)
785 bpy
.context
.scene
.render
.engine
= active_render
789 def DeleteExtra3DC():
791 for node_group
in bpy
.data
.node_groups
:
792 if(node_group
.users
== 0):
793 bpy
.data
.node_groups
.remove(node_group
)
795 for mesh
in bpy
.data
.meshes
:
796 if(mesh
.users
== 0 and mesh
.coat3D
.name
== '3DC'):
797 bpy
.data
.meshes
.remove(mesh
)
799 for material
in bpy
.data
.materials
:
801 if (material
.users
== 1 and material
.coat3D
.name
== '3DC'):
802 if material
.use_nodes
== True:
803 for node
in material
.node_tree
.nodes
:
804 if node
.type == 'TEX_IMAGE' and node
.name
.startswith('3DC'):
805 img_list
.append(node
.image
)
807 for del_img
in img_list
:
808 bpy
.data
.images
.remove(del_img
)
810 bpy
.data
.materials
.remove(material
)
813 for image
in bpy
.data
.images
:
814 if (image
.name
.startswith('3DC')):
816 image_del_list
.append(image
.name
)
818 if (image_del_list
!= []):
819 for image
in image_del_list
:
820 bpy
.data
.images
.remove(bpy
.data
.images
[image
])
822 def new_ref_function(new_applink_address
, nimi
):
824 create_collection
= True
825 for collection
in bpy
.data
.collections
:
826 if collection
.name
== 'Applink_Objects':
827 create_collection
= False
829 if create_collection
:
830 bpy
.data
.collections
.new('Applink_Objects')
832 coll_items
= bpy
.context
.scene
.collection
.children
.items()
834 add_applink_collection
= True
835 for coll
in coll_items
:
836 if coll
[0] == 'Applink_Objects':
837 add_applink_collection
= False
839 if add_applink_collection
:
840 bpy
.context
.scene
.collection
.children
.link(bpy
.data
.collections
['Applink_Objects'])
842 bpy
.context
.view_layer
.active_layer_collection
= bpy
.context
.view_layer
.layer_collection
.children
['Applink_Objects']
844 old_objects
= bpy
.data
.objects
.keys()
848 bpy
.ops
.import_scene
.fbx(filepath
=new_applink_address
, global_scale
= 0.01,axis_forward
='X', axis_up
='Y',use_custom_normals
=False)
849 new_objects
= bpy
.data
.objects
.keys()
850 diff_objects
= [i
for i
in new_objects
if i
not in old_objects
]
853 for diff_object
in diff_objects
:
855 refmesh
= bpy
.data
.objects
[nimi
]
856 copymesh
= bpy
.data
.objects
[nimi
].copy()
858 copymesh
.data
= bpy
.data
.objects
[diff_object
].data
859 copymesh
.coat3D
.applink_name
= bpy
.data
.objects
[diff_object
].data
.name
860 copymesh
.coat3D
.applink_address
= refmesh
.coat3D
.applink_address
861 ne_name
= bpy
.data
.objects
[diff_object
].data
.name
863 copymesh
.coat3D
.type = 'ppp'
864 copymesh
.coat3D
.retopo
= True
866 bpy
.data
.collections
['Applink_Objects'].objects
.link(copymesh
)
868 bpy
.data
.objects
.remove(bpy
.data
.objects
[diff_object
])
869 bpy
.ops
.object.select_all(action
='DESELECT')
870 copymesh
.select_set(True)
871 copymesh
.delta_rotation_euler
[0] = 1.5708
872 copymesh
.name
= ne_name
874 normal_node
= copymesh
.material_slots
[0].material
.node_tree
.nodes
['Normal Map']
875 copymesh
.material_slots
[0].material
.node_tree
.nodes
.remove(normal_node
)
876 copymesh
.material_slots
[0].material
.node_tree
.nodes
['Principled BSDF'].inputs
['Metallic'].default_value
= 0
877 copymesh
.material_slots
[0].material
.node_tree
.nodes
['Principled BSDF'].inputs
['Specular'].default_value
= 0.5
880 refmesh
.coat3D
.applink_name
= ''
881 refmesh
.coat3D
.applink_address
= ''
882 refmesh
.coat3D
.type = ''
883 copymesh
.scale
= (1,1,1)
884 copymesh
.coat3D
.applink_scale
= (1,1,1)
885 copymesh
.location
= (0,0,0)
886 copymesh
.rotation_euler
= (0,0,0)
889 def blender_3DC_blender(texturelist
, file_applink_address
):
891 coat3D
= bpy
.context
.scene
.coat3D
893 old_materials
= bpy
.data
.materials
.keys()
894 old_objects
= bpy
.data
.objects
.keys()
895 cache_base
= bpy
.data
.objects
.keys()
901 for objekti
in bpy
.data
.objects
:
902 if objekti
.type == 'MESH' and objekti
.coat3D
.applink_address
== file_applink_address
:
903 obj_coat
= objekti
.coat3D
905 object_list
.append(objekti
.name
)
906 if(os
.path
.isfile(obj_coat
.applink_address
)):
907 if (obj_coat
.objecttime
!= str(os
.path
.getmtime(obj_coat
.applink_address
))):
908 obj_coat
.dime
= objekti
.dimensions
909 obj_coat
.import_mesh
= True
910 obj_coat
.objecttime
= str(os
.path
.getmtime(obj_coat
.applink_address
))
911 if(obj_coat
.applink_address
not in import_list
):
912 import_list
.append(obj_coat
.applink_address
)
913 import_type
.append(coat3D
.type)
915 if(import_list
or coat3D
.importmesh
):
916 for idx
, list in enumerate(import_list
):
918 bpy
.ops
.import_scene
.fbx(filepath
=list, global_scale
= 0.01,axis_forward
='X',use_custom_normals
=False)
919 cache_objects
= bpy
.data
.objects
.keys()
920 cache_objects
= [i
for i
in cache_objects
if i
not in cache_base
]
921 for cache_object
in cache_objects
:
923 bpy
.data
.objects
[cache_object
].coat3D
.type = import_type
[idx
]
924 bpy
.data
.objects
[cache_object
].coat3D
.applink_address
= list
925 cache_base
.append(cache_object
)
927 bpy
.ops
.object.select_all(action
='DESELECT')
928 new_materials
= bpy
.data
.materials
.keys()
929 new_objects
= bpy
.data
.objects
.keys()
932 diff_mat
= [i
for i
in new_materials
if i
not in old_materials
]
933 diff_objects
= [i
for i
in new_objects
if i
not in old_objects
]
935 for mark_mesh
in diff_objects
:
936 bpy
.data
.objects
[mark_mesh
].data
.coat3D
.name
= '3DC'
938 for c_index
in diff_mat
:
939 bpy
.data
.materials
.remove(bpy
.data
.materials
[c_index
])
941 '''The main Applink Object Loop'''
943 for oname
in object_list
:
945 objekti
= bpy
.data
.objects
[oname
]
946 if(objekti
.coat3D
.applink_mesh
== True):
948 path3b_n
= coat3D
.exchangeFolder
949 path3b_n
+= ('%slast_saved_3b_file.txt' % (os
.sep
))
951 if(objekti
.coat3D
.import_mesh
and coat3D
.importmesh
== True):
953 objekti
.coat3D
.import_mesh
= False
954 objekti
.select_set(True)
956 use_smooth
= objekti
.data
.polygons
[0].use_smooth
959 '''Changes objects mesh into proxy mesh'''
960 if(objekti
.coat3D
.type != 'ref'):
962 for proxy_objects
in diff_objects
:
963 if(objekti
.coat3D
.retopo
== False):
964 if (proxy_objects
== objekti
.coat3D
.applink_name
):
965 obj_proxy
= bpy
.data
.objects
[proxy_objects
]
966 obj_proxy
.coat3D
.delete_proxy_mesh
= True
969 if (proxy_objects
== objekti
.coat3D
.applink_name
+ '.001'):
970 obj_proxy
= bpy
.data
.objects
[proxy_objects
]
971 obj_proxy
.coat3D
.delete_proxy_mesh
= True
976 if (objekti
.material_slots
):
977 for obj_mat
in objekti
.material_slots
:
978 mat_list
.append(obj_mat
.material
)
980 if(found_obj
== True):
981 exportfile
= coat3D
.exchangeFolder
982 path3b_n
= coat3D
.exchangeFolder
983 path3b_n
+= ('%slast_saved_3b_file.txt' % (os
.sep
))
984 exportfile
+= ('%sBlender' % (os
.sep
))
985 exportfile
+= ('%sexport.txt'%(os
.sep
))
986 if(os
.path
.isfile(exportfile
)):
987 export_file
= open(exportfile
)
989 os
.remove(exportfile
)
990 if(os
.path
.isfile(path3b_n
)):
992 mesh_time
= os
.path
.getmtime(objekti
.coat3D
.applink_address
)
993 b_time
= os
.path
.getmtime(path3b_n
)
994 if (abs(mesh_time
- b_time
) < 240):
995 export_file
= open(path3b_n
)
996 for line
in export_file
:
997 objekti
.coat3D
.applink_3b_path
= line
998 head
, tail
= os
.path
.split(line
)
1000 objekti
.coat3D
.applink_3b_just_name
= just_3b_name
1002 coat3D
.remove_path
= True
1004 bpy
.ops
.object.select_all(action
='DESELECT')
1005 obj_proxy
.select_set(True)
1007 bpy
.ops
.object.select_all(action
='TOGGLE')
1009 if objekti
.coat3D
.applink_firsttime
== True and objekti
.coat3D
.type == 'vox':
1010 objekti
.select_set(True)
1011 objekti
.scale
= (0.01, 0.01, 0.01)
1012 objekti
.rotation_euler
[0] = 1.5708
1013 objekti
.rotation_euler
[2] = 1.5708
1014 bpy
.ops
.object.transforms_to_deltas(mode
='ROT')
1015 bpy
.ops
.object.transforms_to_deltas(mode
='SCALE')
1016 objekti
.coat3D
.applink_firsttime
= False
1017 objekti
.select_set(False)
1019 elif objekti
.coat3D
.applink_firsttime
== True:
1020 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])
1021 #bpy.ops.object.transforms_to_deltas(mode='SCALE')
1022 if(objekti
.coat3D
.applink_onlyone
== False):
1023 objekti
.rotation_euler
= (0,0,0)
1024 objekti
.coat3D
.applink_firsttime
= False
1026 if(coat3D
.importlevel
):
1027 obj_proxy
.select
= True
1028 obj_proxy
.modifiers
.new(name
='temp',type='MULTIRES')
1029 objekti
.select
= True
1030 bpy
.ops
.object.multires_reshape(modifier
=multires_name
)
1031 bpy
.ops
.object.select_all(action
='TOGGLE')
1034 bpy
.context
.view_layer
.objects
.active
= obj_proxy
1035 keep_materials_count
= len(obj_proxy
.material_slots
) - len(objekti
.material_slots
)
1037 #delete_materials_from_end(keep_materials_count, obj_proxy)
1040 updatemesh(objekti
,obj_proxy
, texturelist
)
1041 bpy
.context
.view_layer
.objects
.active
= objekti
1045 #it is important to get the object translated correctly
1047 objekti
.select_set(True)
1050 for data_mesh
in objekti
.data
.polygons
:
1051 data_mesh
.use_smooth
= True
1053 for data_mesh
in objekti
.data
.polygons
:
1054 data_mesh
.use_smooth
= False
1056 bpy
.ops
.object.select_all(action
='DESELECT')
1058 if(coat3D
.importmesh
and not(os
.path
.isfile(objekti
.coat3D
.applink_address
))):
1059 coat3D
.importmesh
= False
1061 objekti
.select_set(True)
1062 if(coat3D
.importtextures
):
1064 if(objekti
.coat3D
.retopo
== False):
1065 tex
.matlab(objekti
,mat_list
,texturelist
,is_new
)
1066 objekti
.select_set(False)
1069 if (objekti
.material_slots
):
1070 for obj_mat
in objekti
.material_slots
:
1071 mat_list
.append(obj_mat
.material
)
1073 if (coat3D
.importtextures
):
1075 if(objekti
.coat3D
.retopo
== False):
1076 tex
.matlab(objekti
,mat_list
,texturelist
, is_new
)
1077 objekti
.select_set(False)
1079 if(coat3D
.remove_path
== True):
1080 if(os
.path
.isfile(path3b_n
)):
1082 coat3D
.remove_path
= False
1084 bpy
.ops
.object.select_all(action
='DESELECT')
1087 for del_obj
in diff_objects
:
1089 if(bpy
.context
.collection
.all_objects
[del_obj
].coat3D
.type == 'vox' and bpy
.context
.collection
.all_objects
[del_obj
].coat3D
.delete_proxy_mesh
== False):
1090 bpy
.context
.collection
.all_objects
[del_obj
].select_set(True)
1091 objekti
= bpy
.context
.collection
.all_objects
[del_obj
]
1092 #bpy.ops.object.transforms_to_deltas(mode='ROT')
1093 objekti
.scale
= (1, 1, 1)
1094 bpy
.ops
.object.origin_set(type='ORIGIN_GEOMETRY')
1096 objekti
.data
.coat3D
.name
= '3DC'
1098 objekti
.coat3D
.objecttime
= str(os
.path
.getmtime(objekti
.coat3D
.applink_address
))
1099 objekti
.coat3D
.applink_name
= objekti
.name
1100 objekti
.coat3D
.applink_mesh
= True
1101 objekti
.coat3D
.import_mesh
= False
1103 #bpy.ops.object.transforms_to_deltas(mode='SCALE')
1104 objekti
.coat3D
.applink_firsttime
= False
1105 bpy
.context
.collection
.all_objects
[del_obj
].select_set(False)
1108 bpy
.context
.collection
.all_objects
[del_obj
].select_set(True)
1109 bpy
.data
.objects
.remove(bpy
.data
.objects
[del_obj
])
1111 if (coat3D
.bring_retopo
or coat3D
.bring_retopo_path
):
1112 if(os
.path
.isfile(coat3D
.bring_retopo_path
)):
1113 bpy
.ops
.import_scene
.fbx(filepath
=coat3D
.bring_retopo_path
, global_scale
=1, axis_forward
='X', use_custom_normals
=False)
1114 os
.remove(coat3D
.bring_retopo_path
)
1116 kokeilu
= coat3D
.exchangeFolder
[:-9]
1117 Blender_folder2
= ("%s%sExchange" % (kokeilu
, os
.sep
))
1118 Blender_folder2
+= ('%sexport.txt' % (os
.sep
))
1119 if (os
.path
.isfile(Blender_folder2
)):
1120 os
.remove(Blender_folder2
)
1122 def blender_3DC(texturelist
, new_applink_address
):
1124 bpy
.ops
.object.select_all(action
='DESELECT')
1125 for old_obj
in bpy
.context
.collection
.objects
:
1126 old_obj
.coat3D
.applink_old
= True
1128 coat3D
= bpy
.context
.scene
.coat3D
1129 Blender_folder
= ("%s%sBlender"%(coat3D
.exchangeFolder
,os
.sep
))
1130 Blender_export
= Blender_folder
1131 path3b_now
= coat3D
.exchangeFolder
+ os
.sep
1132 path3b_now
+= ('last_saved_3b_file.txt')
1133 Blender_export
+= ('%sexport.txt'%(os
.sep
))
1136 if (os
.path
.isfile(path3b_now
)):
1137 path3b_fil
= open(path3b_now
)
1138 for lin
in path3b_fil
:
1141 head
, tail
= os
.path
.split(osoite_3b
)
1143 os
.remove(path3b_now
)
1145 create_collection
= True
1146 for collection
in bpy
.data
.collections
:
1147 if collection
.name
== 'Applink_Objects':
1148 create_collection
= False
1150 if create_collection
:
1151 bpy
.data
.collections
.new('Applink_Objects')
1153 coll_items
= bpy
.context
.scene
.collection
.children
.items()
1155 add_applink_collection
= True
1156 for coll
in coll_items
:
1157 if coll
[0] == 'Applink_Objects':
1158 add_applink_collection
= False
1160 if add_applink_collection
:
1161 bpy
.context
.scene
.collection
.children
.link(bpy
.data
.collections
['Applink_Objects'])
1163 bpy
.context
.view_layer
.active_layer_collection
= bpy
.context
.view_layer
.layer_collection
.children
['Applink_Objects']
1165 old_materials
= bpy
.data
.materials
.keys()
1166 old_objects
= bpy
.data
.objects
.keys()
1168 bpy
.ops
.import_scene
.fbx(filepath
=new_applink_address
, global_scale
= 1, axis_forward
='-Z', axis_up
='Y')
1170 new_materials
= bpy
.data
.materials
.keys()
1171 new_objects
= bpy
.data
.objects
.keys()
1173 diff_mat
= [i
for i
in new_materials
if i
not in old_materials
]
1174 diff_objects
= [i
for i
in new_objects
if i
not in old_objects
]
1177 for mark_mesh
in diff_mat
:
1178 bpy
.data
.materials
[mark_mesh
].coat3D
.name
= '3DC'
1179 bpy
.data
.materials
[mark_mesh
].use_fake_user
= True
1183 facture_object
= False
1185 for c_index
in diff_objects
:
1186 bpy
.data
.objects
[c_index
].data
.coat3D
.name
= '3DC'
1188 if(laskuri
== 2 and c_index
== ('vt_' + diff_objects
[0])):
1189 facture_object
= True
1190 print('Facture object founded!!')
1192 #bpy.ops.object.transforms_to_deltas(mode='SCALE')
1193 bpy
.ops
.object.select_all(action
='DESELECT')
1194 for new_obj
in bpy
.context
.collection
.objects
:
1196 if(new_obj
.coat3D
.applink_old
== False):
1197 new_obj
.select_set(True)
1198 new_obj
.coat3D
.applink_firsttime
= False
1199 new_obj
.select_set(False)
1200 new_obj
.coat3D
.type = 'ppp'
1201 new_obj
.coat3D
.applink_address
= new_applink_address
1202 new_obj
.coat3D
.applink_mesh
= True
1203 new_obj
.coat3D
.objecttime
= str(os
.path
.getmtime(new_obj
.coat3D
.applink_address
))
1205 new_obj
.coat3D
.applink_name
= new_obj
.name
1208 bpy
.context
.view_layer
.objects
.active
= new_obj
1210 new_obj
.coat3D
.applink_export
= True
1212 if (os
.path
.isfile(osoite_3b
)):
1213 mesh_time
= os
.path
.getmtime(new_obj
.coat3D
.applink_address
)
1214 b_time
= os
.path
.getmtime(osoite_3b
)
1215 if (abs(mesh_time
-b_time
) < 240):
1216 new_obj
.coat3D
.applink_3b_path
= osoite_3b
1217 new_obj
.coat3D
.applink_3b_just_name
= just_3b_name
1219 mat_list
.append(new_obj
.material_slots
[0].material
)
1223 texVR
.matlab(new_obj
, mat_list
, texturelist
, is_new
)
1224 new_obj
.scale
= (0.01, 0.01, 0.01)
1226 tex
.matlab(new_obj
, mat_list
, texturelist
, is_new
)
1230 for new_obj
in bpy
.context
.collection
.objects
:
1231 if(new_obj
.coat3D
.applink_old
== False):
1232 new_obj
.coat3D
.applink_old
= True
1234 kokeilu
= coat3D
.exchangeFolder
[:-10]
1235 Blender_folder2
= ("%s%sExchange%sBlender" % (kokeilu
, os
.sep
, os
.sep
))
1236 Blender_folder2
+= ('%sexport.txt' % (os
.sep
))
1238 if (os
.path
.isfile(Blender_export
)):
1239 os
.remove(Blender_export
)
1240 if (os
.path
.isfile(Blender_folder2
)):
1241 os
.remove(Blender_folder2
)
1243 for material
in bpy
.data
.materials
:
1244 if material
.use_nodes
== True:
1245 for node
in material
.node_tree
.nodes
:
1246 if (node
.name
).startswith('3DC'):
1247 node
.location
= node
.location
1250 def workflow1(ExportFolder
):
1252 coat3D
= bpy
.context
.scene
.coat3D
1254 texturelist
= make_texture_list(ExportFolder
)
1256 for texturepath
in texturelist
:
1257 for image
in bpy
.data
.images
:
1258 if(image
.filepath
== texturepath
[3] and image
.users
== 0):
1259 bpy
.data
.images
.remove(image
)
1261 path3b_now
= coat3D
.exchangeFolder
1263 path3b_now
+= ('last_saved_3b_file.txt')
1264 new_applink_address
= 'False'
1266 new_ref_object
= False
1268 exportfile3
= coat3D
.exchangeFolder
1269 exportfile3
+= ('%sexport.txt' % (os
.sep
))
1271 if(os
.path
.isfile(exportfile3
)):
1273 obj_pathh
= open(exportfile3
)
1275 for line
in obj_pathh
:
1276 new_applink_address
= line
1279 for scene_objects
in bpy
.context
.collection
.all_objects
:
1280 if(scene_objects
.type == 'MESH'):
1281 if(scene_objects
.coat3D
.applink_address
== new_applink_address
and scene_objects
.coat3D
.type == 'ref'):
1282 scene_objects
.coat3D
.type == ''
1283 new_ref_object
= True
1284 nimi
= scene_objects
.name
1289 exportfile
= coat3D
.exchangeFolder
1290 exportfile
+= ('%sBlender' % (os
.sep
))
1291 exportfile
+= ('%sexport.txt' % (os
.sep
))
1292 if (os
.path
.isfile(exportfile
)):
1293 os
.remove(exportfile
)
1297 new_ref_function(new_applink_address
, nimi
)
1300 blender_3DC_blender(texturelist
, new_applink_address
)
1302 def workflow2(BlenderFolder
):
1304 coat3D
= bpy
.context
.scene
.coat3D
1306 texturelist
= make_texture_list(BlenderFolder
)
1308 for texturepath
in texturelist
:
1309 for image
in bpy
.data
.images
:
1310 if(image
.filepath
== texturepath
[3] and image
.users
== 0):
1311 bpy
.data
.images
.remove(image
)
1313 kokeilu
= coat3D
.exchangeFolder
1315 Blender_export
= os
.path
.join(kokeilu
, 'Blender')
1317 path3b_now
= coat3D
.exchangeFolder
1319 path3b_now
+= ('last_saved_3b_file.txt')
1320 Blender_export
+= ('%sexport.txt'%(os
.sep
))
1321 new_applink_address
= 'False'
1323 new_ref_object
= False
1325 if(os
.path
.isfile(Blender_export
)):
1326 obj_pathh
= open(Blender_export
)
1328 for line
in obj_pathh
:
1329 new_applink_address
= line
1333 for scene_objects
in bpy
.context
.collection
.all_objects
:
1334 if(scene_objects
.type == 'MESH'):
1335 if(scene_objects
.coat3D
.applink_address
== new_applink_address
):
1338 exportfile
= coat3D
.exchangeFolder
1339 exportfile
+= ('%sBlender' % (os
.sep
))
1340 exportfile
+= ('%sexport.txt' % (os
.sep
))
1341 if (os
.path
.isfile(exportfile
)):
1342 os
.remove(exportfile
)
1346 new_ref_function(new_applink_address
, nimi
)
1350 blender_3DC(texturelist
, new_applink_address
)
1353 from mathutils
import Vector
, Matrix
1355 class SCENE_PT_Main(bpy
.types
.Panel
):
1356 bl_label
= "3D-Coat Applink"
1357 bl_space_type
= "VIEW_3D"
1358 bl_region_type
= "UI"
1359 bl_category
= '3D-Coat'
1362 def poll(cls
, context
):
1363 if bpy
.context
.mode
== 'OBJECT':
1368 def draw(self
, context
):
1369 layout
= self
.layout
1370 coat3D
= bpy
.context
.scene
.coat3D
1371 global foundExchangeFolder
1373 if(foundExchangeFolder
== False):
1375 row
.label(text
="Applink didn't find your 3d-Coat/Exchange folder.")
1377 row
.label(text
="Please select it before using Applink.")
1379 row
.prop(coat3D
,"exchangeFolder",text
="")
1381 row
.operator("update_exchange_folder.pilgway_3d_coat", text
="Apply folder")
1384 #Here you add your GUI
1386 row
.prop(coat3D
,"type",text
= "")
1387 flow
= layout
.grid_flow(row_major
=True, columns
=0, even_columns
=False, even_rows
=False, align
=True)
1391 row
.operator("export_applink.pilgway_3d_coat", text
="Send")
1392 row
.operator("getback.pilgway_3d_coat", text
="GetBack")
1395 class ObjectButtonsPanel():
1396 bl_space_type
= 'PROPERTIES'
1397 bl_region_type
= 'WINDOW'
1398 bl_context
= "object"
1400 class SCENE_PT_Settings(ObjectButtonsPanel
,bpy
.types
.Panel
):
1401 bl_label
= "3D-Coat Applink Settings"
1402 bl_space_type
= "PROPERTIES"
1403 bl_region_type
= "WINDOW"
1404 bl_context
= "scene"
1406 def draw(self
, context
):
1409 class MaterialButtonsPanel():
1410 bl_space_type
= 'PROPERTIES'
1411 bl_region_type
= 'WINDOW'
1412 bl_context
= "material"
1414 class SCENE_PT_Material(MaterialButtonsPanel
,bpy
.types
.Panel
):
1415 bl_label
= "3D-Coat Applink"
1416 bl_space_type
= "PROPERTIES"
1417 bl_region_type
= "WINDOW"
1418 bl_context
= "material"
1420 def draw(self
, context
):
1423 class SCENE_PT_Material_Import(MaterialButtonsPanel
, bpy
.types
.Panel
):
1424 bl_label
= "Import Textures:"
1425 bl_parent_id
= "SCENE_PT_Material"
1426 COMPAT_ENGINES
= {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
1428 def draw(self
, context
):
1429 layout
= self
.layout
1430 layout
.use_property_split
= False
1431 coat3D
= bpy
.context
.active_object
.active_material
1433 layout
.active
= True
1435 flow
= layout
.grid_flow(row_major
=True, columns
=0, even_columns
=False, even_rows
=False, align
=True)
1438 col
.prop(coat3D
, "coat3D_diffuse", text
="Diffuse")
1439 col
.prop(coat3D
, "coat3D_metalness", text
="Metalness")
1440 col
.prop(coat3D
, "coat3D_roughness", text
="Roughness")
1441 col
.prop(coat3D
, "coat3D_ao", text
="AO")
1443 col
.prop(coat3D
, "coat3D_normal", text
="NormalMap")
1444 col
.prop(coat3D
, "coat3D_displacement", text
="Displacement")
1445 col
.prop(coat3D
, "coat3D_emissive", text
="Emissive")
1446 col
.prop(coat3D
, "coat3D_alpha", text
="Alpha")
1450 class SCENE_PT_Settings_Update(ObjectButtonsPanel
, bpy
.types
.Panel
):
1452 bl_parent_id
= "SCENE_PT_Settings"
1453 COMPAT_ENGINES
= {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
1455 def draw(self
, context
):
1456 layout
= self
.layout
1457 layout
.use_property_split
= False
1458 coat3D
= bpy
.context
.scene
.coat3D
1460 layout
.active
= True
1462 flow
= layout
.grid_flow(row_major
=True, columns
=0, even_columns
=False, even_rows
=False, align
=True)
1465 col
.prop(coat3D
, "importmesh", text
="Update Mesh/UV")
1467 col
.prop(coat3D
, "createnodes", text
="Create Extra Nodes")
1469 col
.prop(coat3D
, "importtextures", text
="Update Textures")
1471 col
.prop(coat3D
, "exportmod", text
="Export with modifiers")
1473 class SCENE_PT_Bake_Settings(ObjectButtonsPanel
, bpy
.types
.Panel
):
1475 bl_parent_id
= "SCENE_PT_Settings"
1476 COMPAT_ENGINES
= {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
1478 def draw(self
, context
):
1479 layout
= self
.layout
1480 layout
.use_property_split
= False
1481 coat3D
= bpy
.context
.scene
.coat3D
1483 layout
.active
= True
1485 flow
= layout
.grid_flow(row_major
=True, columns
=0, even_columns
=False, even_rows
=False, align
=True)
1488 col
.prop(coat3D
, "bake_resolution", text
="Resolution")
1490 col
.prop(coat3D
, "bake_diffuse", text
="Diffuse")
1492 col
.prop(coat3D
, "bake_ao", text
="AO")
1494 col
.prop(coat3D
, "bake_normal", text
="Normal")
1496 col
.prop(coat3D
, "bake_roughness", text
="Roughness")
1498 class SCENE_PT_Settings_Folders(ObjectButtonsPanel
, bpy
.types
.Panel
):
1499 bl_label
= "Folders"
1500 bl_parent_id
= "SCENE_PT_Settings"
1501 COMPAT_ENGINES
= {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
1503 def draw(self
, context
):
1504 layout
= self
.layout
1505 layout
.use_property_split
= False
1506 coat3D
= bpy
.context
.scene
.coat3D
1508 layout
.active
= True
1510 flow
= layout
.grid_flow(row_major
=True, columns
=0, even_columns
=False, even_rows
=False, align
=True)
1513 col
.prop(coat3D
, "exchangeFolder", text
="Exchange folder")
1514 col
.operator("save_new_export.pilgway_3d_coat", text
="Save new Exchange folder")
1517 col
.prop(coat3D
, "defaultfolder", text
="Object/Texture folder")
1520 col
.prop(coat3D
, "folder_size", text
="Max count in Applink folder")
1522 class SCENE_PT_Settings_DeleteNodes(ObjectButtonsPanel
, bpy
.types
.Panel
):
1523 bl_label
= "Delete 3DC nodes from selected..."
1524 bl_parent_id
= "SCENE_PT_Settings"
1525 COMPAT_ENGINES
= {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
1527 def draw(self
, context
):
1528 layout
= self
.layout
1529 layout
.use_property_split
= False
1530 coat3D
= bpy
.context
.scene
.coat3D
1532 layout
.active
= True
1534 flow
= layout
.grid_flow(row_major
=True, columns
=0, even_columns
=False, even_rows
=False, align
=True)
1537 col
.operator("delete_material_nodes.pilgway_3d_coat", text
="Material")
1539 col
.operator("delete_object_nodes.pilgway_3d_coat", text
="Object(s)")
1542 col
.operator("delete_collection_nodes.pilgway_3d_coat", text
="Collection")
1544 col
.operator("delete_scene_nodes.pilgway_3d_coat", text
="Scene")
1547 col
.prop(coat3D
, "delete_images", text
="Delete nodes images")
1552 # 3D-Coat Dynamic Menu
1553 class VIEW3D_MT_Coat_Dynamic_Menu(bpy
.types
.Menu
):
1554 bl_label
= "3D-Coat Applink Menu"
1556 def draw(self
, context
):
1557 layout
= self
.layout
1559 layout
.operator_context
= 'INVOKE_REGION_WIN'
1562 if ob
.mode
== 'OBJECT':
1563 if(len(context
.selected_objects
) > 0):
1564 layout
.operator("import_applink.pilgway_3d_coat",
1565 text
="Update Scene")
1568 layout
.operator("export_applink.pilgway_3d_coat",
1569 text
="Transfer to 3D-Coat")
1572 if(context
.selected_objects
[0].coat3D
.applink_3b_path
!= ''):
1573 layout
.operator("open_3dcoat.pilgway_3d_coat",
1574 text
="Open " +context
.selected_objects
[0].coat3D
.applink_3b_just_name
)
1578 layout
.operator("import_applink.pilgway_3d_coat",
1579 text
="Update Scene")
1582 if (len(context
.selected_objects
) > 0):
1583 layout
.operator("delete_material_nodes.pilgway_3d_coat",
1584 text
="Delete 3D-Coat nodes from active material")
1586 layout
.operator("delete_object_nodes.pilgway_3d_coat",
1587 text
="Delete 3D-Coat nodes from selected objects")
1589 layout
.operator("delete_collection_nodes.pilgway_3d_coat",
1590 text
="Delete 3D-Coat nodes from active collection")
1592 layout
.operator("delete_scene_nodes.pilgway_3d_coat",
1593 text
="Delete all 3D-Coat nodes")
1598 class ObjectCoat3D(PropertyGroup
):
1600 obj_mat
: StringProperty(
1604 applink_address
: StringProperty(
1605 name
="Object_Applink_address"
1607 applink_index
: StringProperty(
1608 name
="Object_Applink_address"
1610 applink_3b_path
: StringProperty(
1611 name
="Object_3B_Path"
1613 applink_name
: StringProperty(
1614 name
="Applink object name"
1616 applink_3b_just_name
: StringProperty(
1617 name
="Applink object name"
1619 applink_firsttime
: BoolProperty(
1621 description
="FirstTime",
1624 retopo
: BoolProperty(
1625 name
="Retopo object",
1626 description
="Retopo object",
1629 delete_proxy_mesh
: BoolProperty(
1631 description
="FirstTime",
1634 applink_onlyone
: BoolProperty(
1636 description
="FirstTime",
1639 type: StringProperty(
1641 description
="shows type",
1644 import_mesh
: BoolProperty(
1646 description
="ImportMesh",
1649 applink_mesh
: BoolProperty(
1651 description
="ImportMesh",
1654 applink_old
: BoolProperty(
1656 description
="Old Object",
1659 applink_export
: BoolProperty(
1661 description
="Object is from 3d-ocat",
1664 objecttime
: StringProperty(
1668 path3b
: StringProperty(
1672 dime
: FloatVectorProperty(
1674 description
="Dimension"
1676 applink_scale
: FloatVectorProperty(
1681 class SceneCoat3D(PropertyGroup
):
1682 defaultfolder
: StringProperty(
1686 deleteMode
: StringProperty(
1691 coat3D_exe
: StringProperty(
1693 subtype
="FILE_PATH",
1695 exchangeFolder
: StringProperty(
1699 bring_retopo
: BoolProperty(
1700 name
="Import window",
1701 description
="Allows to skip import dialog",
1704 foundExchangeFolder
: BoolProperty(
1705 name
="found Exchange Folder",
1706 description
="found Exchange folder",
1709 delete_images
: BoolProperty(
1710 name
="Import window",
1711 description
="Allows to skip import dialog",
1714 bring_retopo_path
: StringProperty(
1718 remove_path
: BoolProperty(
1719 name
="Import window",
1720 description
="Allows to skip import dialog",
1723 exchange_found
: BoolProperty(
1724 name
="Exchange Found",
1725 description
="Alert if Exchange folder is not found",
1728 exportfile
: BoolProperty(
1729 name
="No Import File",
1730 description
="Add Modifiers and export",
1733 importmod
: BoolProperty(
1734 name
="Remove Modifiers",
1735 description
="Import and add modifiers",
1738 exportmod
: BoolProperty(
1740 description
="Export modifiers",
1743 importtextures
: BoolProperty(
1744 name
="Bring Textures",
1745 description
="Import Textures",
1748 createnodes
: BoolProperty(
1749 name
="Bring Textures",
1750 description
="Import Textures",
1753 importlevel
: BoolProperty(
1754 name
="Multires. Level",
1755 description
="Bring Specific Multires Level",
1758 importmesh
: BoolProperty(
1760 description
="Import Mesh",
1766 loca
: FloatVectorProperty(
1768 description
="Location",
1770 default
=(0.0, 0.0, 0.0)
1772 rota
: FloatVectorProperty(
1774 description
="Location",
1776 default
=(0.0, 0.0, 0.0)
1778 scal
: FloatVectorProperty(
1780 description
="Location",
1782 default
=(0.0, 0.0, 0.0)
1784 dime
: FloatVectorProperty(
1786 description
="Dimension",
1788 default
=(0.0, 0.0, 0.0)
1792 description
="Different Export Types",
1793 items
=(("ppp", "Per-Pixel Painting", ""),
1794 ("mv", "Microvertex Painting", ""),
1795 ("ptex", "Ptex Painting", ""),
1796 ("uv", "UV-Mapping", ""),
1797 ("ref", "Reference Mesh", ""),
1798 ("retopo", "Retopo mesh as new layer", ""),
1799 ("vox", "Mesh As Voxel Object", ""),
1800 ("alpha", "Mesh As New Pen Alpha", ""),
1801 ("prim", "Mesh As Voxel Primitive", ""),
1802 ("curv", "Mesh As a Curve Profile", ""),
1803 ("autopo", "Mesh For Auto-retopology", ""),
1804 ("update", "Update mesh/uvs", ""),
1808 bake_resolution
: EnumProperty(
1809 name
="Bake Resolution",
1810 description
="Bake resolution",
1811 items
=(("res_64", "64 x 64", ""),
1812 ("res_128", "128 x 128", ""),
1813 ("res_256", "256 x 256", ""),
1814 ("res_512", "512 x 512", ""),
1815 ("res_1024", "1024 x 1024", ""),
1816 ("res_2048", "2048 x 2048", ""),
1817 ("res_4096", "4096 x 4096", ""),
1818 ("res_8192", "8192 x 8192", ""),
1822 folder_size
: EnumProperty(
1823 name
="Applink folder size",
1824 description
="Applink folder size",
1825 items
=(("10", "10", ""),
1828 ("1000", "1000", ""),
1829 ("5000", "5000", ""),
1830 ("10000", "10000", ""),
1834 bake_textures
: BoolProperty(
1835 name
="Bake all textures",
1836 description
="Add Modifiers and export",
1839 bake_diffuse
: BoolProperty(
1840 name
="Bake diffuse texture",
1841 description
="Add Modifiers and export",
1844 bake_ao
: BoolProperty(
1845 name
="Bake AO texture",
1846 description
="Add Modifiers and export",
1849 bake_roughness
: BoolProperty(
1850 name
="Bake roughness texture",
1851 description
="Add Modifiers and export",
1854 bake_metalness
: BoolProperty(
1855 name
="Bake metalness texture",
1856 description
="Add Modifiers and export",
1859 bake_emissive
: BoolProperty(
1860 name
="Bake emissive texture",
1861 description
="Add Modifiers and export",
1864 bake_normal
: BoolProperty(
1865 name
="Bake normal texture",
1866 description
="Add Modifiers and export",
1869 bake_displacement
: BoolProperty(
1870 name
="Bake displacement",
1871 description
="Add Modifiers and export",
1875 class MeshCoat3D(PropertyGroup
):
1876 applink_address
: StringProperty(
1877 name
="ApplinkAddress",
1878 # subtype="APPLINK_ADDRESS",
1881 class MaterialCoat3D(PropertyGroup
):
1882 name
: StringProperty(
1883 name
="ApplinkAddress",
1884 # subtype="APPLINK_ADDRESS",
1887 bring_diffuse
: BoolProperty(
1888 name
="Import diffuse texture",
1889 description
="Import diffuse texture",
1892 bring_metalness
: BoolProperty(
1893 name
="Import diffuse texture",
1894 description
="Import diffuse texture",
1897 bring_roughness
: BoolProperty(
1898 name
="Import diffuse texture",
1899 description
="Import diffuse texture",
1902 bring_normal
: BoolProperty(
1903 name
="Import diffuse texture",
1904 description
="Import diffuse texture",
1907 bring_displacement
: BoolProperty(
1908 name
="Import diffuse texture",
1909 description
="Import diffuse texture",
1912 bring_emissive
: BoolProperty(
1913 name
="Import diffuse texture",
1914 description
="Import diffuse texture",
1917 bring_gloss
: BoolProperty(
1918 name
="Import diffuse texture",
1919 description
="Import diffuse texture",
1927 SCENE_PT_Settings_Update
,
1928 SCENE_PT_Bake_Settings
,
1929 SCENE_PT_Settings_DeleteNodes
,
1930 SCENE_PT_Settings_Folders
,
1931 SCENE_PT_Material_Import
,
1937 SCENE_OT_delete_material_nodes
,
1938 SCENE_OT_delete_object_nodes
,
1939 SCENE_OT_delete_collection_nodes
,
1940 SCENE_OT_delete_scene_nodes
,
1941 VIEW3D_MT_Coat_Dynamic_Menu
,
1950 bpy
.types
.Material
.coat3D_diffuse
= BoolProperty(
1951 name
="Import diffuse texture",
1952 description
="Import diffuse texture",
1955 bpy
.types
.Material
.coat3D_roughness
= BoolProperty(
1956 name
="Import diffuse texture",
1957 description
="Import diffuse texture",
1960 bpy
.types
.Material
.coat3D_metalness
= BoolProperty(
1961 name
="Import diffuse texture",
1962 description
="Import diffuse texture",
1965 bpy
.types
.Material
.coat3D_normal
= BoolProperty(
1966 name
="Import diffuse texture",
1967 description
="Import diffuse texture",
1970 bpy
.types
.Material
.coat3D_displacement
= BoolProperty(
1971 name
="Import diffuse texture",
1972 description
="Import diffuse texture",
1975 bpy
.types
.Material
.coat3D_emissive
= BoolProperty(
1976 name
="Import diffuse texture",
1977 description
="Import diffuse texture",
1980 bpy
.types
.Material
.coat3D_ao
= BoolProperty(
1981 name
="Import diffuse texture",
1982 description
="Import diffuse texture",
1985 bpy
.types
.Material
.coat3D_alpha
= BoolProperty(
1986 name
="Import alpha texture",
1987 description
="Import alpha texture",
1990 bpy
.types
.Material
.coat3D_gloss
= BoolProperty(
1991 name
="Import alpha texture",
1992 description
="Import alpha texture",
1999 from bpy
.utils
import register_class
2003 bpy
.types
.Object
.coat3D
= PointerProperty(type=ObjectCoat3D
)
2004 bpy
.types
.Scene
.coat3D
= PointerProperty(type=SceneCoat3D
)
2005 bpy
.types
.Mesh
.coat3D
= PointerProperty(type=MeshCoat3D
)
2006 bpy
.types
.Material
.coat3D
= PointerProperty(type=MaterialCoat3D
)
2007 bpy
.app
.handlers
.load_post
.append(load_handler
)
2009 kc
= bpy
.context
.window_manager
.keyconfigs
.addon
2012 km
= kc
.keymaps
.new(name
="3D View", space_type
="VIEW_3D")
2013 kmi
= km
.keymap_items
.new('wm.call_menu', 'Q', 'PRESS', shift
=True)
2014 kmi
.properties
.name
= "VIEW3D_MT_Coat_Dynamic_Menu"
2019 from bpy
.utils
import unregister_class
2021 del bpy
.types
.Object
.coat3D
2022 del bpy
.types
.Scene
.coat3D
2023 del bpy
.types
.Material
.coat3D
2024 bpy
.types
.Material
.coat3D_diffuse
2025 bpy
.types
.Material
.coat3D_metalness
2026 bpy
.types
.Material
.coat3D_roughness
2027 bpy
.types
.Material
.coat3D_normal
2028 bpy
.types
.Material
.coat3D_displacement
2029 bpy
.types
.Material
.coat3D_emissive
2030 bpy
.types
.Material
.coat3D_alpha
2032 kc
= bpy
.context
.window_manager
.keyconfigs
.addon
2034 km
= kc
.keymaps
.get('3D View')
2035 for kmi
in km
.keymap_items
:
2036 if kmi
.idname
== 'wm.call_menu':
2037 if kmi
.properties
.name
== "VIEW3D_MT_Coat_Dynamic_Menu":
2038 km
.keymap_items
.remove(kmi
)
2040 for cls
in reversed(classes
):
2041 unregister_class(cls
)