Files
blender-addons/io_coat3D/__init__.py
Jesse Yurkovich 4eec817823 Fix: Use correct displacement_method property
Update addons to account for changes from[1].

The `displacement_method` is now shared for EEVEE and Cycles.

[1] a001cf9f2b

Pull Request: https://projects.blender.org/blender/blender-addons/pulls/105044
2023-12-04 19:12:10 +01:00

2042 lines
71 KiB
Python

# SPDX-FileCopyrightText: 2010-2022 Blender Foundation
#
# SPDX-License-Identifier: GPL-2.0-or-later
bl_info = {
"name": "3D-Coat Applink",
"author": "Kalle-Samuli Riihikoski (haikalle)",
"version": (4, 9, 35),
"blender": (4, 1, 0),
"location": "Scene > 3D-Coat Applink",
"description": "Transfer data between 3D-Coat/Blender",
"warning": "",
"doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/coat3D.html",
"category": "Import-Export",
}
if "bpy" in locals():
import importlib
importlib.reload(tex)
else:
from . import tex
from bpy.app.handlers import persistent
from io_coat3D import tex
from io_coat3D import texVR
from io_coat3D import folders
import os
import platform
import ntpath
import re
import shutil
import pathlib
import stat
import time
import bpy
import subprocess
from bpy.types import PropertyGroup
from bpy.props import (
BoolProperty,
EnumProperty,
FloatVectorProperty,
StringProperty,
PointerProperty,
)
only_one_time = True
global_exchange_folder = ''
foundExchangeFolder = True
saved_exchange_folder = ''
liveUpdate = True
mTime = 0
@persistent
def every_3_seconds():
global global_exchange_folder
global liveUpdate
global mTime
global only_one_time
if(only_one_time):
only_one_time = False
folders.loadExchangeFolder()
try:
coat3D = bpy.context.scene.coat3D
Export_folder = coat3D.exchangeFolder
Export_folder += ('%sexport.txt' % (os.sep))
if (os.path.isfile(Export_folder) and mTime != os.path.getmtime(Export_folder)):
for objekti in bpy.data.objects:
if(objekti.coat3D.applink_mesh):
tex.updatetextures(objekti)
mTime = os.path.getmtime(Export_folder)
except:
pass
return 3.0
@persistent
def load_handler(dummy):
bpy.app.timers.register(every_3_seconds)
def removeFile(exportfile):
if (os.path.isfile(exportfile)):
os.remove(exportfile)
def folder_size(path):
folder_size_max = int(bpy.context.scene.coat3D.folder_size)
if(bpy.context.scene.coat3D.defaultfolder == ''):
tosi = True
while tosi:
list_of_files = []
for file in os.listdir(path):
list_of_files.append(path + os.sep + file)
if len(list_of_files) >= folder_size_max:
oldest_file = min(list_of_files, key=os.path.getctime)
os.remove(os.path.abspath(oldest_file))
else:
tosi = False
def make_texture_list(texturefolder):
texturefolder += ('%stextures.txt'%(os.sep))
texturelist = []
if (os.path.isfile(texturefolder)):
texturefile = open(texturefolder)
index = 0
for line in texturefile:
if line != '' and index == 0:
line = line.rstrip('\n')
objekti = line
index += 1
elif index == 1:
line = line.rstrip('\n')
material = line
index += 1
elif index == 2:
line = line.rstrip('\n')
type = line
index += 1
elif index == 3:
line = line.rstrip('\n')
address = line
texturelist.append([objekti,material,type,address])
index = 0
texturefile.close()
return texturelist
'''
#Updating objects MESH part ( Mesh, Vertex Groups, Vertex Colors )
'''
def updatemesh(objekti, proxy, texturelist):
# Vertex colors
if(len(proxy.data.vertex_colors) > 0):
bring_vertex_map = True
else:
bring_vertex_map = False
if(bring_vertex_map):
if(len(objekti.data.vertex_colors) > 0):
for vertex_map in objekti.data.vertex_colors:
if vertex_map.name == 'Col':
copy_data = True
vertex_map_copy = vertex_map
break
else:
copy_data = False
else:
copy_data = False
if(copy_data):
for poly in objekti.data.polygons:
for loop_index in poly.loop_indices:
vertex_map_copy.data[loop_index].color = proxy.data.vertex_colors[0].data[loop_index].color
else:
objekti.data.vertex_colors.new()
vertex_map_copy = objekti.data.vertex_colors[-1]
for poly in objekti.data.polygons:
for loop_index in poly.loop_indices:
vertex_map_copy.data[loop_index].color = proxy.data.vertex_colors[0].data[loop_index].color
# UV -Sets
udim_textures = False
if(texturelist != []):
if(texturelist[0][0].startswith('100')):
udim_textures =True
proxy.select_set(True)
objekti.select_set(True)
uv_count = len(proxy.data.uv_layers)
index = 0
while(index < uv_count and len(proxy.data.polygons) == len(objekti.data.polygons)):
for poly in proxy.data.polygons:
for indi in poly.loop_indices:
if(proxy.data.uv_layers[index].data[indi].uv[0] != 0 and proxy.data.uv_layers[index].data[indi].uv[1] != 0):
if(udim_textures):
udim = proxy.data.uv_layers[index].name
udim_index = int(udim[2:]) - 1
objekti.data.uv_layers[0].data[indi].uv[0] = proxy.data.uv_layers[index].data[indi].uv[0]
objekti.data.uv_layers[0].data[indi].uv[1] = proxy.data.uv_layers[index].data[indi].uv[1]
index = index + 1
# Mesh Copy
if(proxy.name.startswith('RetopoGroup')):
objekti.data = proxy.data
else:
for ind, v in enumerate(objekti.data.vertices):
v.co = proxy.data.vertices[ind].co
class SCENE_OT_getback(bpy.types.Operator):
bl_idname = "getback.pilgway_3d_coat"
bl_label = "Export your custom property"
bl_description = "Export your custom property"
bl_options = {'UNDO'}
def invoke(self, context, event):
global global_exchange_folder
path_ex = ''
Export_folder = global_exchange_folder
Blender_folder = os.path.join(Export_folder, 'Blender')
BlenderFolder = Blender_folder
ExportFolder = Export_folder
Blender_folder += ('%sexport.txt' % (os.sep))
Export_folder += ('%sexport.txt' % (os.sep))
if (bpy.app.background == False):
if os.path.isfile(Export_folder):
print('BLENDER -> 3DC -> BLENDER WORKFLLOW')
DeleteExtra3DC()
workflow1(ExportFolder)
removeFile(Export_folder)
removeFile(Blender_folder)
elif os.path.isfile(Blender_folder):
print('3DC -> BLENDER WORKFLLOW')
DeleteExtra3DC()
workflow2(BlenderFolder)
removeFile(Blender_folder)
return {'FINISHED'}
class SCENE_OT_savenew(bpy.types.Operator):
bl_idname = "save_new_export.pilgway_3d_coat"
bl_label = "Export your custom property"
bl_description = "Export your custom property"
bl_options = {'UNDO'}
def invoke(self, context, event):
coat3D = bpy.context.scene.coat3D
platform = os.sys.platform
if(platform == 'win32' or platform == 'darwin'):
exchangeFile = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt'
else:
exchangeFile = os.path.expanduser("~") + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt'
if(os.path.isfile(exchangeFile)):
folderPath = ''
if(os.path.isfile(exchangeFile)):
file = open(exchangeFile, "w")
file.write("%s"%(coat3D.exchangeFolder))
file.close()
return {'FINISHED'}
class SCENE_OT_folder(bpy.types.Operator):
bl_idname = "update_exchange_folder.pilgway_3d_coat"
bl_label = "Export your custom property"
bl_description = "Export your custom property"
bl_options = {'UNDO'}
def invoke(self, context, event):
global foundExchangeFolder
coat3D = bpy.context.scene.coat3D
if(os.path.isdir(coat3D.exchangeFolder)):
foundExchangeFolder= True
folders.updateExchangeFile(coat3D.exchangeFolder)
return {'FINISHED'}
class SCENE_OT_opencoat(bpy.types.Operator):
bl_idname = "open_3dcoat.pilgway_3d_coat"
bl_label = "Export your custom property"
bl_description = "Export your custom property"
bl_options = {'UNDO'}
def invoke(self, context, event):
coat3D = bpy.context.selected_objects[0].coat3D.applink_3b_path
platform = os.sys.platform
if (platform == 'win32' or platform == 'darwin'):
importfile = bpy.context.scene.coat3D.exchangeFolder
importfile += ('%simport.txt' % (os.sep))
file = open(importfile, "w")
file.write("%s" % (coat3D))
file.write("\n%s" % (coat3D))
file.write("\n[3B]")
file.close()
else:
importfile = bpy.context.scene.coat3D.exchangeFolder
importfile += ('%simport.txt' % (os.sep))
file = open(importfile, "w")
file.write("%s" % (coat3D))
file.write("\n%s" % (coat3D))
file.write("\n[3B]")
file.close()
return {'FINISHED'}
def scaleParents():
save = []
names =[]
for objekti in bpy.context.selected_objects:
temp = objekti
while (temp.parent is not None and temp.parent.name not in names):
save.append([temp.parent,(temp.parent.scale[0],temp.parent.scale[1],temp.parent.scale[2])])
names.append(temp.parent)
temp = temp.parent
for name in names:
name.scale = (1,1,1)
return save
def scaleBackParents(save):
for data in save:
data[0].scale = data[1]
def deleteNodes(type):
deletelist = []
deleteimages = []
deletegroup =[]
delete_images = bpy.context.scene.coat3D.delete_images
if type == 'Material':
if(len(bpy.context.selected_objects) == 1):
material = bpy.context.selected_objects[0].active_material
if(material.use_nodes):
for node in material.node_tree.nodes:
if(node.name.startswith('3DC')):
if (node.type == 'GROUP'):
deletegroup.append(node.node_tree.name)
deletelist.append(node.name)
if node.type == 'TEX_IMAGE' and delete_images == True:
deleteimages.append(node.image.name)
if deletelist:
for node in deletelist:
material.node_tree.nodes.remove(material.node_tree.nodes[node])
if deleteimages:
for image in deleteimages:
bpy.data.images.remove(bpy.data.images[image])
elif type == 'Object':
if (len(bpy.context.selected_objects) > 0):
for objekti in bpy.context.selected_objects:
for material in objekti.material_slots:
if (material.material.use_nodes):
for node in material.material.node_tree.nodes:
if (node.name.startswith('3DC')):
if(node.type == 'GROUP'):
deletegroup.append(node.node_tree.name)
deletelist.append(node.name)
if node.type == 'TEX_IMAGE' and delete_images == True:
deleteimages.append(node.image.name)
if deletelist:
for node in deletelist:
material.material.node_tree.nodes.remove(material.material.node_tree.nodes[node])
deletelist = []
if deleteimages:
for image in deleteimages:
bpy.data.images.remove(bpy.data.images[image])
deleteimages = []
elif type == 'Collection':
for collection_object in bpy.context.view_layer.active_layer_collection.collection.all_objects:
if(collection_object.type == 'MESH'):
for material in collection_object.material_slots:
if (material.material.use_nodes):
for node in material.material.node_tree.nodes:
if (node.name.startswith('3DC')):
if (node.type == 'GROUP'):
deletegroup.append(node.node_tree.name)
deletelist.append(node.name)
if node.type == 'TEX_IMAGE' and delete_images == True:
deleteimages.append(node.image.name)
if deletelist:
for node in deletelist:
material.material.node_tree.nodes.remove(material.material.node_tree.nodes[node])
deletelist = []
if deleteimages:
for image in deleteimages:
bpy.data.images.remove(bpy.data.images[image])
deleteimages = []
elif type == 'Scene':
for collection in bpy.data.collections:
for collection_object in collection.all_objects:
if (collection_object.type == 'MESH'):
for material in collection_object.material_slots:
if (material.material.use_nodes):
for node in material.material.node_tree.nodes:
if (node.name.startswith('3DC')):
if (node.type == 'GROUP'):
deletegroup.append(node.node_tree.name)
deletelist.append(node.name)
if node.type == 'TEX_IMAGE' and delete_images == True:
deleteimages.append(node.image.name)
if deletelist:
for node in deletelist:
material.material.node_tree.nodes.remove(material.material.node_tree.nodes[node])
deletelist = []
if deleteimages:
for image in deleteimages:
bpy.data.images.remove(bpy.data.images[image])
deleteimages = []
if(deletelist):
for node in deletelist:
bpy.data.node_groups.remove(bpy.data.node_groups[node])
for image in bpy.data.images:
if (image.name.startswith('3DC') and image.name[6] == '_'):
deleteimages.append(image.name)
if(deletegroup):
for node in deletegroup:
bpy.data.node_groups.remove(bpy.data.node_groups[node])
if deleteimages:
for image in deleteimages:
bpy.data.images.remove(bpy.data.images[image])
def delete_materials_from_end(keep_materials_count, objekti):
#bpy.context.object.active_material_index = 0
index_t = 0
while (index_t < keep_materials_count):
temp_len = len(objekti.material_slots)-1
bpy.context.object.active_material_index = temp_len
bpy.ops.object.material_slot_remove()
index_t +=1
''' DELETE NODES BUTTONS'''
class SCENE_OT_delete_material_nodes(bpy.types.Operator):
bl_idname = "delete_material_nodes.pilgway_3d_coat"
bl_label = "Delete material nodes"
bl_description = "Delete material nodes"
bl_options = {'UNDO'}
def invoke(self, context, event):
type = bpy.context.scene.coat3D.deleteMode = 'Material'
deleteNodes(type)
return {'FINISHED'}
class SCENE_OT_delete_object_nodes(bpy.types.Operator):
bl_idname = "delete_object_nodes.pilgway_3d_coat"
bl_label = "Delete material nodes"
bl_description = "Delete material nodes"
bl_options = {'UNDO'}
def invoke(self, context, event):
type = bpy.context.scene.coat3D.deleteMode = 'Object'
deleteNodes(type)
return {'FINISHED'}
class SCENE_OT_delete_collection_nodes(bpy.types.Operator):
bl_idname = "delete_collection_nodes.pilgway_3d_coat"
bl_label = "Delete material nodes"
bl_description = "Delete material nodes"
bl_options = {'UNDO'}
def invoke(self, context, event):
type = bpy.context.scene.coat3D.deleteMode = 'Collection'
deleteNodes(type)
return {'FINISHED'}
class SCENE_OT_delete_scene_nodes(bpy.types.Operator):
bl_idname = "delete_scene_nodes.pilgway_3d_coat"
bl_label = "Delete material nodes"
bl_description = "Delete material nodes"
bl_options = {'UNDO'}
def invoke(self, context, event):
type = bpy.context.scene.coat3D.deleteMode = 'Scene'
deleteNodes(type)
return {'FINISHED'}
''' TRANSFER AND UPDATE BUTTONS'''
class SCENE_OT_export(bpy.types.Operator):
bl_idname = "export_applink.pilgway_3d_coat"
bl_label = "Export your custom property"
bl_description = "Export your custom property"
bl_options = {'UNDO'}
def invoke(self, context, event):
bpy.ops.export_applink.pilgway_3d_coat()
return {'FINISHED'}
def execute(self, context):
global foundExchangeFolder
global global_exchange_folder
global run_background_update
run_background_update = False
foundExchangeFolder, global_exchange_folder = folders.InitFolders()
for mesh in bpy.data.meshes:
if (mesh.users == 0 and mesh.coat3D.name == '3DC'):
bpy.data.meshes.remove(mesh)
for material in bpy.data.materials:
if (material.users == 1 and material.coat3D.name == '3DC'):
bpy.data.materials.remove(material)
export_ok = False
coat3D = bpy.context.scene.coat3D
if (bpy.context.selected_objects == []):
return {'FINISHED'}
else:
for objec in bpy.context.selected_objects:
if objec.type == 'MESH':
if(len(objec.data.uv_layers) == 0):
objec.data.uv_layers.new(name='UVMap', do_init = False)
export_ok = True
if (export_ok == False):
return {'FINISHED'}
scaled_objects = scaleParents()
activeobj = bpy.context.active_object.name
checkname = ''
coa = bpy.context.active_object.coat3D
p = pathlib.Path(coat3D.exchangeFolder)
kokeilu = coat3D.exchangeFolder[:-9]
Blender_folder2 = ("%s%sExchange" % (kokeilu, os.sep))
Blender_folder2 += ('%sexport.txt' % (os.sep))
if (os.path.isfile(Blender_folder2)):
os.remove(Blender_folder2)
if (not os.path.isdir(coat3D.exchangeFolder)):
coat3D.exchange_found = False
return {'FINISHED'}
folder_objects = folders.set_working_folders()
folder_size(folder_objects)
importfile = coat3D.exchangeFolder
texturefile = coat3D.exchangeFolder
importfile += ('%simport.txt'%(os.sep))
texturefile += ('%stextures.txt'%(os.sep))
looking = True
object_index = 0
active_render = bpy.context.scene.render.engine
if(coat3D.type == 'autopo'):
checkname = folder_objects + os.sep
checkname = ("%sretopo.fbx" % (checkname))
elif(coat3D.type == 'update'):
checkname = bpy.context.selected_objects[0].coat3D.applink_address
else:
while(looking == True):
checkname = folder_objects + os.sep + "3DC"
checkname = ("%s%.3d.fbx"%(checkname,object_index))
if(os.path.isfile(checkname)):
object_index += 1
else:
looking = False
coa.applink_name = ("%s%.2d"%(activeobj,object_index))
coa.applink_address = checkname
matindex = 0
for objekti in bpy.context.selected_objects:
if objekti.type == 'MESH':
objekti.name = '__' + objekti.name
if(objekti.material_slots.keys() == []):
newmat = bpy.data.materials.new('Material')
newmat.use_nodes = True
objekti.data.materials.append(newmat)
matindex += 1
objekti.coat3D.applink_name = objekti.name
mod_mat_list = {}
bake_location = folder_objects + os.sep + 'Bake'
if (os.path.isdir(bake_location)):
shutil.rmtree(bake_location)
os.makedirs(bake_location)
else:
os.makedirs(bake_location)
# BAKING #
temp_string = ''
for objekti in bpy.context.selected_objects:
if objekti.type == 'MESH':
mod_mat_list[objekti.name] = []
objekti.coat3D.applink_scale = objekti.scale
objekti.coat3D.retopo = False
''' Checks what materials are linked into UV '''
if(coat3D.type == 'ppp'):
final_material_indexs = []
uvtiles_index = []
for poly in objekti.data.polygons:
if(poly.material_index not in final_material_indexs):
final_material_indexs.append(poly.material_index)
loop_index = poly.loop_indices[0]
uvtiles_index.append([poly.material_index,objekti.data.uv_layers.active.data[loop_index].uv[0]])
if(len(final_material_indexs) == len(objekti.material_slots)):
break
material_index = 0
if (len(final_material_indexs) != len(objekti.material_slots)):
for material in objekti.material_slots:
if material_index not in final_material_indexs:
temp_mat = material.material
material.material = objekti.material_slots[0].material
mod_mat_list[objekti.name].append([material_index, temp_mat])
material_index = material_index + 1
bake_list = []
if(coat3D.bake_diffuse):
bake_list.append(['DIFFUSE', '$LOADTEX'])
if (coat3D.bake_ao):
bake_list.append(['AO', '$ExternalAO'])
if (coat3D.bake_normal):
bake_list.append(['NORMAL', '$LOADLOPOLYTANG'])
if (coat3D.bake_roughness):
bake_list.append(['ROUGHNESS', '$LOADROUGHNESS'])
if(coat3D.bake_resolution == 'res_64'):
res_size = 64
elif (coat3D.bake_resolution == 'res_128'):
res_size = 128
elif (coat3D.bake_resolution == 'res_256'):
res_size = 256
elif (coat3D.bake_resolution == 'res_512'):
res_size = 512
elif (coat3D.bake_resolution == 'res_1024'):
res_size = 1024
elif (coat3D.bake_resolution == 'res_2048'):
res_size = 2048
elif (coat3D.bake_resolution == 'res_4096'):
res_size = 4096
elif (coat3D.bake_resolution == 'res_8192'):
res_size = 8192
if(len(bake_list) > 0):
index_bake_tex = 0
while(index_bake_tex < len(bake_list)):
bake_index = 0
for bake_mat_index in final_material_indexs:
bake_node = objekti.material_slots[bake_mat_index].material.node_tree.nodes.new('ShaderNodeTexImage')
bake_node.name = 'ApplinkBake' + str(bake_index)
bpy.ops.image.new(name=bake_node.name, width=res_size, height=res_size)
bake_node.image = bpy.data.images[bake_node.name]
objekti.material_slots[bake_mat_index].material.node_tree.nodes.active = bake_node
bake_index += 1
if(bpy.context.scene.render.engine != 'CYCLES'):
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.render.bake.use_pass_direct = False
bpy.context.scene.render.bake.use_pass_indirect = False
bpy.context.scene.render.bake.use_pass_color = True
bpy.ops.object.bake(type=bake_list[index_bake_tex][0], margin=1, width=res_size, height=res_size)
bake_index = 0
for bake_mat_index in final_material_indexs:
bake_image = 'ApplinkBake' + str(bake_index)
bpy.data.images[bake_image].filepath_raw = bake_location + os.sep + objekti.name + '_' + bake_image + '_' + bake_list[index_bake_tex][0] + ".png"
image_bake_name = bpy.data.images[bake_image].filepath_raw
tie = image_bake_name.split(os.sep)
toi = ''
for sana in tie:
toi += sana
toi += "/"
final_bake_name = toi[:-1]
bpy.data.images[bake_image].save()
temp_string += '''\n[script ImportTexture("''' + bake_list[index_bake_tex][1] + '''","''' + objekti.material_slots[bake_mat_index].material.name + '''","''' + final_bake_name + '''");]'''
bake_index += 1
for material in objekti.material_slots:
if material.material.use_nodes == True:
for node in material.material.node_tree.nodes:
if (node.name.startswith('ApplinkBake') == True):
material.material.node_tree.nodes.remove(node)
for image in bpy.data.images:
if (image.name.startswith('ApplinkBake') == True):
bpy.data.images.remove(image)
index_bake_tex += 1
#BAKING ENDS
#bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
if(len(bpy.context.selected_objects) > 1 and coat3D.type != 'vox'):
bpy.ops.object.transforms_to_deltas(mode='ROT')
if(coat3D.type == 'autopo'):
coat3D.bring_retopo = True
coat3D.bring_retopo_path = checkname
bpy.ops.export_scene.fbx(filepath=checkname, global_scale = 1, use_selection=True, use_mesh_modifiers=coat3D.exportmod, axis_forward='-Z', axis_up='Y')
elif (coat3D.type == 'vox'):
coat3D.bring_retopo = False
bpy.ops.export_scene.fbx(filepath=coa.applink_address, global_scale = 0.01, use_selection=True,
use_mesh_modifiers=coat3D.exportmod, axis_forward='-Z', axis_up='Y')
else:
coat3D.bring_retopo = False
bpy.ops.export_scene.fbx(filepath=coa.applink_address,global_scale = 0.01, use_selection=True, use_mesh_modifiers=coat3D.exportmod, axis_forward='-Z', axis_up='Y')
file = open(importfile, "w")
file.write("%s"%(checkname))
file.write("\n%s"%(checkname))
file.write("\n[%s]"%(coat3D.type))
if(coat3D.type == 'ppp' or coat3D.type == 'mv' or coat3D.type == 'ptex'):
file.write("\n[export_preset Blender Cycles]")
file.write(temp_string)
file.close()
for idx, objekti in enumerate(bpy.context.selected_objects):
if objekti.type == 'MESH':
objekti.name = objekti.name[2:]
if(len(bpy.context.selected_objects) == 1):
objekti.coat3D.applink_onlyone = True
objekti.coat3D.type = coat3D.type
objekti.coat3D.applink_mesh = True
objekti.coat3D.obj_mat = ''
objekti.coat3D.applink_index = ("3DC%.3d" % (object_index))
objekti.coat3D.applink_firsttime = True
if(coat3D.type != 'autopo'):
objekti.coat3D.applink_address = coa.applink_address
objekti.coat3D.objecttime = str(os.path.getmtime(objekti.coat3D.applink_address))
objekti.data.coat3D.name = '3DC'
if(coat3D.type != 'vox'):
if(objekti.material_slots.keys() != []):
for material in objekti.material_slots:
if material.material.use_nodes == True:
for node in material.material.node_tree.nodes:
if(node.name.startswith('3DC_') == True):
material.material.node_tree.nodes.remove(node)
for ind, mat_list in enumerate(mod_mat_list):
if(mat_list == '__' + objekti.name):
for ind, mat in enumerate(mod_mat_list[mat_list]):
objekti.material_slots[mod_mat_list[mat_list][ind][0]].material = mod_mat_list[mat_list][ind][1]
scaleBackParents(scaled_objects)
bpy.context.scene.render.engine = active_render
return {'FINISHED'}
def DeleteExtra3DC():
for node_group in bpy.data.node_groups:
if(node_group.users == 0):
bpy.data.node_groups.remove(node_group)
for mesh in bpy.data.meshes:
if(mesh.users == 0 and mesh.coat3D.name == '3DC'):
bpy.data.meshes.remove(mesh)
for material in bpy.data.materials:
img_list = []
if (material.users == 1 and material.coat3D.name == '3DC'):
if material.use_nodes == True:
for node in material.node_tree.nodes:
if node.type == 'TEX_IMAGE' and node.name.startswith('3DC'):
img_list.append(node.image)
if img_list != []:
for del_img in img_list:
bpy.data.images.remove(del_img)
bpy.data.materials.remove(material)
image_del_list = []
for image in bpy.data.images:
if (image.name.startswith('3DC')):
if image.users == 0:
image_del_list.append(image.name)
if (image_del_list != []):
for image in image_del_list:
bpy.data.images.remove(bpy.data.images[image])
def new_ref_function(new_applink_address, nimi):
create_collection = True
for collection in bpy.data.collections:
if collection.name == 'Applink_Objects':
create_collection = False
if create_collection:
bpy.data.collections.new('Applink_Objects')
coll_items = bpy.context.scene.collection.children.items()
add_applink_collection = True
for coll in coll_items:
if coll[0] == 'Applink_Objects':
add_applink_collection = False
if add_applink_collection:
bpy.context.scene.collection.children.link(bpy.data.collections['Applink_Objects'])
bpy.context.view_layer.active_layer_collection = bpy.context.view_layer.layer_collection.children['Applink_Objects']
old_objects = bpy.data.objects.keys()
object_list = []
bpy.ops.import_scene.fbx(filepath=new_applink_address, global_scale = 0.01,axis_forward='X', axis_up='Y',use_custom_normals=False)
new_objects = bpy.data.objects.keys()
diff_objects = [i for i in new_objects if i not in old_objects]
texturelist = []
for diff_object in diff_objects:
refmesh = bpy.data.objects[nimi]
copymesh = bpy.data.objects[nimi].copy()
copymesh.data = bpy.data.objects[diff_object].data
copymesh.coat3D.applink_name = bpy.data.objects[diff_object].data.name
copymesh.coat3D.applink_address = refmesh.coat3D.applink_address
ne_name = bpy.data.objects[diff_object].data.name
copymesh.coat3D.type = 'ppp'
copymesh.coat3D.retopo = True
bpy.data.collections['Applink_Objects'].objects.link(copymesh)
bpy.data.objects.remove(bpy.data.objects[diff_object])
bpy.ops.object.select_all(action='DESELECT')
copymesh.select_set(True)
copymesh.delta_rotation_euler[0] = 1.5708
copymesh.name = ne_name
normal_node = copymesh.material_slots[0].material.node_tree.nodes['Normal Map']
copymesh.material_slots[0].material.node_tree.nodes.remove(normal_node)
copymesh.material_slots[0].material.node_tree.nodes['Principled BSDF'].inputs['Metallic'].default_value = 0
copymesh.material_slots[0].material.node_tree.nodes['Principled BSDF'].inputs['Specular'].default_value = 0.5
refmesh.coat3D.applink_name = ''
refmesh.coat3D.applink_address = ''
refmesh.coat3D.type = ''
copymesh.scale = (1,1,1)
copymesh.coat3D.applink_scale = (1,1,1)
copymesh.location = (0,0,0)
copymesh.rotation_euler = (0,0,0)
def blender_3DC_blender(texturelist, file_applink_address):
coat3D = bpy.context.scene.coat3D
old_materials = bpy.data.materials.keys()
old_objects = bpy.data.objects.keys()
cache_base = bpy.data.objects.keys()
object_list = []
import_list = []
import_type = []
for objekti in bpy.data.objects:
if objekti.type == 'MESH' and objekti.coat3D.applink_address == file_applink_address:
obj_coat = objekti.coat3D
object_list.append(objekti.name)
if(os.path.isfile(obj_coat.applink_address)):
if (obj_coat.objecttime != str(os.path.getmtime(obj_coat.applink_address))):
obj_coat.dime = objekti.dimensions
obj_coat.import_mesh = True
obj_coat.objecttime = str(os.path.getmtime(obj_coat.applink_address))
if(obj_coat.applink_address not in import_list):
import_list.append(obj_coat.applink_address)
import_type.append(coat3D.type)
if(import_list or coat3D.importmesh):
for idx, list in enumerate(import_list):
bpy.ops.import_scene.fbx(filepath=list, global_scale = 0.01,axis_forward='X',use_custom_normals=False)
cache_objects = bpy.data.objects.keys()
cache_objects = [i for i in cache_objects if i not in cache_base]
for cache_object in cache_objects:
bpy.data.objects[cache_object].coat3D.type = import_type[idx]
bpy.data.objects[cache_object].coat3D.applink_address = list
cache_base.append(cache_object)
bpy.ops.object.select_all(action='DESELECT')
new_materials = bpy.data.materials.keys()
new_objects = bpy.data.objects.keys()
diff_mat = [i for i in new_materials if i not in old_materials]
diff_objects = [i for i in new_objects if i not in old_objects]
for mark_mesh in diff_objects:
bpy.data.objects[mark_mesh].data.coat3D.name = '3DC'
for c_index in diff_mat:
bpy.data.materials.remove(bpy.data.materials[c_index])
'''The main Applink Object Loop'''
for oname in object_list:
objekti = bpy.data.objects[oname]
if(objekti.coat3D.applink_mesh == True):
path3b_n = coat3D.exchangeFolder
path3b_n += ('%slast_saved_3b_file.txt' % (os.sep))
if(objekti.coat3D.import_mesh and coat3D.importmesh == True):
objekti.coat3D.import_mesh = False
objekti.select_set(True)
use_smooth = objekti.data.polygons[0].use_smooth
found_obj = False
'''Changes objects mesh into proxy mesh'''
if(objekti.coat3D.type != 'ref'):
for proxy_objects in diff_objects:
if(objekti.coat3D.retopo == False):
if (proxy_objects == objekti.coat3D.applink_name):
obj_proxy = bpy.data.objects[proxy_objects]
obj_proxy.coat3D.delete_proxy_mesh = True
found_obj = True
else:
if (proxy_objects == objekti.coat3D.applink_name + '.001'):
obj_proxy = bpy.data.objects[proxy_objects]
obj_proxy.coat3D.delete_proxy_mesh = True
found_obj = True
mat_list = []
if (objekti.material_slots):
for obj_mat in objekti.material_slots:
mat_list.append(obj_mat.material)
if(found_obj == True):
exportfile = coat3D.exchangeFolder
path3b_n = coat3D.exchangeFolder
path3b_n += ('%slast_saved_3b_file.txt' % (os.sep))
exportfile += ('%sBlender' % (os.sep))
exportfile += ('%sexport.txt'%(os.sep))
if(os.path.isfile(exportfile)):
export_file = open(exportfile)
export_file.close()
os.remove(exportfile)
if(os.path.isfile(path3b_n)):
mesh_time = os.path.getmtime(objekti.coat3D.applink_address)
b_time = os.path.getmtime(path3b_n)
if (abs(mesh_time - b_time) < 240):
export_file = open(path3b_n)
for line in export_file:
objekti.coat3D.applink_3b_path = line
head, tail = os.path.split(line)
just_3b_name = tail
objekti.coat3D.applink_3b_just_name = just_3b_name
export_file.close()
coat3D.remove_path = True
bpy.ops.object.select_all(action='DESELECT')
obj_proxy.select_set(True)
bpy.ops.object.select_all(action='TOGGLE')
if objekti.coat3D.applink_firsttime == True and objekti.coat3D.type == 'vox':
objekti.select_set(True)
objekti.scale = (0.01, 0.01, 0.01)
objekti.rotation_euler[0] = 1.5708
objekti.rotation_euler[2] = 1.5708
bpy.ops.object.transforms_to_deltas(mode='ROT')
bpy.ops.object.transforms_to_deltas(mode='SCALE')
objekti.coat3D.applink_firsttime = False
objekti.select_set(False)
elif objekti.coat3D.applink_firsttime == True:
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])
#bpy.ops.object.transforms_to_deltas(mode='SCALE')
if(objekti.coat3D.applink_onlyone == False):
objekti.rotation_euler = (0,0,0)
objekti.coat3D.applink_firsttime = False
if(coat3D.importlevel):
obj_proxy.select = True
obj_proxy.modifiers.new(name='temp',type='MULTIRES')
objekti.select = True
bpy.ops.object.multires_reshape(modifier=multires_name)
bpy.ops.object.select_all(action='TOGGLE')
else:
bpy.context.view_layer.objects.active = obj_proxy
keep_materials_count = len(obj_proxy.material_slots) - len(objekti.material_slots)
#delete_materials_from_end(keep_materials_count, obj_proxy)
updatemesh(objekti,obj_proxy, texturelist)
bpy.context.view_layer.objects.active = objekti
#it is important to get the object translated correctly
objekti.select_set(True)
if (use_smooth):
for data_mesh in objekti.data.polygons:
data_mesh.use_smooth = True
else:
for data_mesh in objekti.data.polygons:
data_mesh.use_smooth = False
bpy.ops.object.select_all(action='DESELECT')
if(coat3D.importmesh and not(os.path.isfile(objekti.coat3D.applink_address))):
coat3D.importmesh = False
objekti.select_set(True)
if(coat3D.importtextures):
is_new = False
if(objekti.coat3D.retopo == False):
tex.matlab(objekti,mat_list,texturelist,is_new)
objekti.select_set(False)
else:
mat_list = []
if (objekti.material_slots):
for obj_mat in objekti.material_slots:
mat_list.append(obj_mat.material)
if (coat3D.importtextures):
is_new = False
if(objekti.coat3D.retopo == False):
tex.matlab(objekti,mat_list,texturelist, is_new)
objekti.select_set(False)
if(coat3D.remove_path == True):
if(os.path.isfile(path3b_n)):
os.remove(path3b_n)
coat3D.remove_path = False
bpy.ops.object.select_all(action='DESELECT')
if(import_list):
for del_obj in diff_objects:
if(bpy.context.collection.all_objects[del_obj].coat3D.type == 'vox' and bpy.context.collection.all_objects[del_obj].coat3D.delete_proxy_mesh == False):
bpy.context.collection.all_objects[del_obj].select_set(True)
objekti = bpy.context.collection.all_objects[del_obj]
#bpy.ops.object.transforms_to_deltas(mode='ROT')
objekti.scale = (1, 1, 1)
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
objekti.data.coat3D.name = '3DC'
objekti.coat3D.objecttime = str(os.path.getmtime(objekti.coat3D.applink_address))
objekti.coat3D.applink_name = objekti.name
objekti.coat3D.applink_mesh = True
objekti.coat3D.import_mesh = False
#bpy.ops.object.transforms_to_deltas(mode='SCALE')
objekti.coat3D.applink_firsttime = False
bpy.context.collection.all_objects[del_obj].select_set(False)
else:
bpy.context.collection.all_objects[del_obj].select_set(True)
bpy.data.objects.remove(bpy.data.objects[del_obj])
if (coat3D.bring_retopo or coat3D.bring_retopo_path):
if(os.path.isfile(coat3D.bring_retopo_path)):
bpy.ops.import_scene.fbx(filepath=coat3D.bring_retopo_path, global_scale=1, axis_forward='X', use_custom_normals=False)
os.remove(coat3D.bring_retopo_path)
kokeilu = coat3D.exchangeFolder[:-9]
Blender_folder2 = ("%s%sExchange" % (kokeilu, os.sep))
Blender_folder2 += ('%sexport.txt' % (os.sep))
if (os.path.isfile(Blender_folder2)):
os.remove(Blender_folder2)
def blender_3DC(texturelist, new_applink_address):
bpy.ops.object.select_all(action='DESELECT')
for old_obj in bpy.context.collection.objects:
old_obj.coat3D.applink_old = True
coat3D = bpy.context.scene.coat3D
Blender_folder = ("%s%sBlender"%(coat3D.exchangeFolder,os.sep))
Blender_export = Blender_folder
path3b_now = coat3D.exchangeFolder + os.sep
path3b_now += ('last_saved_3b_file.txt')
Blender_export += ('%sexport.txt'%(os.sep))
mat_list = []
osoite_3b = ''
if (os.path.isfile(path3b_now)):
path3b_fil = open(path3b_now)
for lin in path3b_fil:
osoite_3b = lin
path3b_fil.close()
head, tail = os.path.split(osoite_3b)
just_3b_name = tail
os.remove(path3b_now)
create_collection = True
for collection in bpy.data.collections:
if collection.name == 'Applink_Objects':
create_collection = False
if create_collection:
bpy.data.collections.new('Applink_Objects')
coll_items = bpy.context.scene.collection.children.items()
add_applink_collection = True
for coll in coll_items:
if coll[0] == 'Applink_Objects':
add_applink_collection = False
if add_applink_collection:
bpy.context.scene.collection.children.link(bpy.data.collections['Applink_Objects'])
bpy.context.view_layer.active_layer_collection = bpy.context.view_layer.layer_collection.children['Applink_Objects']
old_materials = bpy.data.materials.keys()
old_objects = bpy.data.objects.keys()
bpy.ops.import_scene.fbx(filepath=new_applink_address, global_scale = 1, axis_forward='-Z', axis_up='Y')
new_materials = bpy.data.materials.keys()
new_objects = bpy.data.objects.keys()
diff_mat = [i for i in new_materials if i not in old_materials]
diff_objects = [i for i in new_objects if i not in old_objects]
for mark_mesh in diff_mat:
bpy.data.materials[mark_mesh].coat3D.name = '3DC'
bpy.data.materials[mark_mesh].use_fake_user = True
laskuri = 0
index = 0
facture_object = False
for c_index in diff_objects:
bpy.data.objects[c_index].data.coat3D.name = '3DC'
laskuri += 1
if(laskuri == 2 and c_index == ('vt_' + diff_objects[0])):
facture_object = True
print('Facture object founded!!')
#bpy.ops.object.transforms_to_deltas(mode='SCALE')
bpy.ops.object.select_all(action='DESELECT')
for new_obj in bpy.context.collection.objects:
if(new_obj.coat3D.applink_old == False):
new_obj.select_set(True)
new_obj.coat3D.applink_firsttime = False
new_obj.select_set(False)
new_obj.coat3D.type = 'ppp'
new_obj.coat3D.applink_address = new_applink_address
new_obj.coat3D.applink_mesh = True
new_obj.coat3D.objecttime = str(os.path.getmtime(new_obj.coat3D.applink_address))
new_obj.coat3D.applink_name = new_obj.name
index = index + 1
bpy.context.view_layer.objects.active = new_obj
new_obj.coat3D.applink_export = True
if (os.path.isfile(osoite_3b)):
mesh_time = os.path.getmtime(new_obj.coat3D.applink_address)
b_time = os.path.getmtime(osoite_3b)
if (abs(mesh_time-b_time) < 240):
new_obj.coat3D.applink_3b_path = osoite_3b
new_obj.coat3D.applink_3b_just_name = just_3b_name
mat_list.append(new_obj.material_slots[0].material)
is_new = True
if(facture_object):
texVR.matlab(new_obj, mat_list, texturelist, is_new)
new_obj.scale = (0.01, 0.01, 0.01)
else:
tex.matlab(new_obj, mat_list, texturelist, is_new)
mat_list.pop()
for new_obj in bpy.context.collection.objects:
if(new_obj.coat3D.applink_old == False):
new_obj.coat3D.applink_old = True
kokeilu = coat3D.exchangeFolder[:-10]
Blender_folder2 = ("%s%sExchange%sBlender" % (kokeilu, os.sep, os.sep))
Blender_folder2 += ('%sexport.txt' % (os.sep))
if (os.path.isfile(Blender_export)):
os.remove(Blender_export)
if (os.path.isfile(Blender_folder2)):
os.remove(Blender_folder2)
for material in bpy.data.materials:
if material.use_nodes == True:
for node in material.node_tree.nodes:
if (node.name).startswith('3DC'):
node.location = node.location
def workflow1(ExportFolder):
coat3D = bpy.context.scene.coat3D
texturelist = make_texture_list(ExportFolder)
for texturepath in texturelist:
for image in bpy.data.images:
if(image.filepath == texturepath[3] and image.users == 0):
bpy.data.images.remove(image)
path3b_now = coat3D.exchangeFolder
path3b_now += ('last_saved_3b_file.txt')
new_applink_address = 'False'
new_object = False
new_ref_object = False
exportfile3 = coat3D.exchangeFolder
exportfile3 += ('%sexport.txt' % (os.sep))
if(os.path.isfile(exportfile3)):
obj_pathh = open(exportfile3)
for line in obj_pathh:
new_applink_address = line
break
obj_pathh.close()
for scene_objects in bpy.context.collection.all_objects:
if(scene_objects.type == 'MESH'):
if(scene_objects.coat3D.applink_address == new_applink_address and scene_objects.coat3D.type == 'ref'):
scene_objects.coat3D.type == ''
new_ref_object = True
nimi = scene_objects.name
exportfile = coat3D.exchangeFolder
exportfile += ('%sBlender' % (os.sep))
exportfile += ('%sexport.txt' % (os.sep))
if (os.path.isfile(exportfile)):
os.remove(exportfile)
if(new_ref_object):
new_ref_function(new_applink_address, nimi)
else:
blender_3DC_blender(texturelist, new_applink_address)
def workflow2(BlenderFolder):
coat3D = bpy.context.scene.coat3D
texturelist = make_texture_list(BlenderFolder)
for texturepath in texturelist:
for image in bpy.data.images:
if(image.filepath == texturepath[3] and image.users == 0):
bpy.data.images.remove(image)
kokeilu = coat3D.exchangeFolder
Blender_export = os.path.join(kokeilu, 'Blender')
path3b_now = coat3D.exchangeFolder
path3b_now += ('last_saved_3b_file.txt')
Blender_export += ('%sexport.txt'%(os.sep))
new_applink_address = 'False'
new_object = False
new_ref_object = False
if(os.path.isfile(Blender_export)):
obj_pathh = open(Blender_export)
new_object = True
for line in obj_pathh:
new_applink_address = line
break
obj_pathh.close()
for scene_objects in bpy.context.collection.all_objects:
if(scene_objects.type == 'MESH'):
if(scene_objects.coat3D.applink_address == new_applink_address):
new_object = False
exportfile = coat3D.exchangeFolder
exportfile += ('%sBlender' % (os.sep))
exportfile += ('%sexport.txt' % (os.sep))
if (os.path.isfile(exportfile)):
os.remove(exportfile)
if(new_ref_object):
new_ref_function(new_applink_address, nimi)
else:
blender_3DC(texturelist, new_applink_address)
from bpy import *
from mathutils import Vector, Matrix
class SCENE_PT_Main(bpy.types.Panel):
bl_label = "3D-Coat Applink"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = '3D-Coat'
@classmethod
def poll(cls, context):
if bpy.context.mode == 'OBJECT':
return True
else:
return False
def draw(self, context):
layout = self.layout
coat3D = bpy.context.scene.coat3D
global foundExchangeFolder
if(foundExchangeFolder == False):
row = layout.row()
row.label(text="Applink didn't find your 3d-Coat/Exchange folder.")
row = layout.row()
row.label(text="Please select it before using Applink.")
row = layout.row()
row.prop(coat3D,"exchangeFolder",text="")
row = layout.row()
row.operator("update_exchange_folder.pilgway_3d_coat", text="Apply folder")
else:
#Here you add your GUI
row = layout.row()
row.prop(coat3D,"type",text = "")
flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
row = layout.row()
row.operator("export_applink.pilgway_3d_coat", text="Send")
row.operator("getback.pilgway_3d_coat", text="GetBack")
class ObjectButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
class SCENE_PT_Settings(ObjectButtonsPanel,bpy.types.Panel):
bl_label = "3D-Coat Applink Settings"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
def draw(self, context):
pass
class MaterialButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "material"
class SCENE_PT_Material(MaterialButtonsPanel,bpy.types.Panel):
bl_label = "3D-Coat Applink"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "material"
def draw(self, context):
pass
class SCENE_PT_Material_Import(MaterialButtonsPanel, bpy.types.Panel):
bl_label = "Import Textures:"
bl_parent_id = "SCENE_PT_Material"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
layout.use_property_split = False
coat3D = bpy.context.active_object.active_material
layout.active = True
flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
col = flow.column()
col.prop(coat3D, "coat3D_diffuse", text="Diffuse")
col.prop(coat3D, "coat3D_metalness", text="Metalness")
col.prop(coat3D, "coat3D_roughness", text="Roughness")
col.prop(coat3D, "coat3D_ao", text="AO")
col = flow.column()
col.prop(coat3D, "coat3D_normal", text="NormalMap")
col.prop(coat3D, "coat3D_displacement", text="Displacement")
col.prop(coat3D, "coat3D_emissive", text="Emissive")
col.prop(coat3D, "coat3D_alpha", text="Alpha")
class SCENE_PT_Settings_Update(ObjectButtonsPanel, bpy.types.Panel):
bl_label = "Update"
bl_parent_id = "SCENE_PT_Settings"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
layout.use_property_split = False
coat3D = bpy.context.scene.coat3D
layout.active = True
flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
col = flow.column()
col.prop(coat3D, "importmesh", text="Update Mesh/UV")
col = flow.column()
col.prop(coat3D, "createnodes", text="Create Extra Nodes")
col = flow.column()
col.prop(coat3D, "importtextures", text="Update Textures")
col = flow.column()
col.prop(coat3D, "exportmod", text="Export with modifiers")
class SCENE_PT_Bake_Settings(ObjectButtonsPanel, bpy.types.Panel):
bl_label = "Bake"
bl_parent_id = "SCENE_PT_Settings"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
layout.use_property_split = False
coat3D = bpy.context.scene.coat3D
layout.active = True
flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
col = flow.column()
col.prop(coat3D, "bake_resolution", text="Resolution")
col = flow.column()
col.prop(coat3D, "bake_diffuse", text="Diffuse")
col = flow.column()
col.prop(coat3D, "bake_ao", text="AO")
col = flow.column()
col.prop(coat3D, "bake_normal", text="Normal")
col = flow.column()
col.prop(coat3D, "bake_roughness", text="Roughness")
class SCENE_PT_Settings_Folders(ObjectButtonsPanel, bpy.types.Panel):
bl_label = "Folders"
bl_parent_id = "SCENE_PT_Settings"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
layout.use_property_split = False
coat3D = bpy.context.scene.coat3D
layout.active = True
flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
col = flow.column()
col.prop(coat3D, "exchangeFolder", text="Exchange folder")
col.operator("save_new_export.pilgway_3d_coat", text="Save new Exchange folder")
col = flow.column()
col.prop(coat3D, "defaultfolder", text="Object/Texture folder")
col = flow.column()
col.prop(coat3D, "folder_size", text="Max count in Applink folder")
class SCENE_PT_Settings_DeleteNodes(ObjectButtonsPanel, bpy.types.Panel):
bl_label = "Delete 3DC nodes from selected..."
bl_parent_id = "SCENE_PT_Settings"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
layout.use_property_split = False
coat3D = bpy.context.scene.coat3D
layout.active = True
flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
col = flow.column()
col.operator("delete_material_nodes.pilgway_3d_coat", text="Material")
col.operator("delete_object_nodes.pilgway_3d_coat", text="Object(s)")
col = flow.column()
col.operator("delete_collection_nodes.pilgway_3d_coat", text="Collection")
col.operator("delete_scene_nodes.pilgway_3d_coat", text="Scene")
col = flow.column()
col.prop(coat3D, "delete_images", text="Delete nodes images")
# 3D-Coat Dynamic Menu
class VIEW3D_MT_Coat_Dynamic_Menu(bpy.types.Menu):
bl_label = "3D-Coat Applink Menu"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
ob = context
if ob.mode == 'OBJECT':
if(len(context.selected_objects) > 0):
layout.operator("import_applink.pilgway_3d_coat",
text="Update Scene")
layout.separator()
layout.operator("export_applink.pilgway_3d_coat",
text="Transfer to 3D-Coat")
layout.separator()
if(context.selected_objects[0].coat3D.applink_3b_path != ''):
layout.operator("open_3dcoat.pilgway_3d_coat",
text="Open " +context.selected_objects[0].coat3D.applink_3b_just_name)
layout.separator()
else:
layout.operator("import_applink.pilgway_3d_coat",
text="Update Scene")
layout.separator()
if (len(context.selected_objects) > 0):
layout.operator("delete_material_nodes.pilgway_3d_coat",
text="Delete 3D-Coat nodes from active material")
layout.operator("delete_object_nodes.pilgway_3d_coat",
text="Delete 3D-Coat nodes from selected objects")
layout.operator("delete_collection_nodes.pilgway_3d_coat",
text="Delete 3D-Coat nodes from active collection")
layout.operator("delete_scene_nodes.pilgway_3d_coat",
text="Delete all 3D-Coat nodes")
layout.separator()
class ObjectCoat3D(PropertyGroup):
obj_mat: StringProperty(
name="Object_Path",
default=''
)
applink_address: StringProperty(
name="Object_Applink_address"
)
applink_index: StringProperty(
name="Object_Applink_address"
)
applink_3b_path: StringProperty(
name="Object_3B_Path"
)
applink_name: StringProperty(
name="Applink object name"
)
applink_3b_just_name: StringProperty(
name="Applink object name"
)
applink_firsttime: BoolProperty(
name="FirstTime",
description="FirstTime",
default=True
)
retopo: BoolProperty(
name="Retopo object",
description="Retopo object",
default=False
)
delete_proxy_mesh: BoolProperty(
name="FirstTime",
description="FirstTime",
default=False
)
applink_onlyone: BoolProperty(
name="FirstTime",
description="FirstTime",
default=False
)
type: StringProperty(
name="type",
description="shows type",
default=''
)
import_mesh: BoolProperty(
name="ImportMesh",
description="ImportMesh",
default=False
)
applink_mesh: BoolProperty(
name="ImportMesh",
description="ImportMesh",
default=False
)
applink_old: BoolProperty(
name="OldObject",
description="Old Object",
default=False
)
applink_export: BoolProperty(
name="FirstTime",
description="Object is from 3d-ocat",
default=False
)
objecttime: StringProperty(
name="ObjectTime",
subtype="FILE_PATH"
)
path3b: StringProperty(
name="3B Path",
subtype="FILE_PATH"
)
dime: FloatVectorProperty(
name="dime",
description="Dimension"
)
applink_scale: FloatVectorProperty(
name="Scale",
description="Scale"
)
class SceneCoat3D(PropertyGroup):
defaultfolder: StringProperty(
name="FilePath",
subtype="DIR_PATH",
)
deleteMode: StringProperty(
name="FilePath",
subtype="DIR_PATH",
default=''
)
coat3D_exe: StringProperty(
name="FilePath",
subtype="FILE_PATH",
)
exchangeFolder: StringProperty(
name="FilePath",
subtype="DIR_PATH"
)
bring_retopo: BoolProperty(
name="Import window",
description="Allows to skip import dialog",
default=False
)
foundExchangeFolder: BoolProperty(
name="found Exchange Folder",
description="found Exchange folder",
default=False
)
delete_images: BoolProperty(
name="Import window",
description="Allows to skip import dialog",
default=True
)
bring_retopo_path: StringProperty(
name="FilePath",
subtype="DIR_PATH",
)
remove_path: BoolProperty(
name="Import window",
description="Allows to skip import dialog",
default=False
)
exchange_found: BoolProperty(
name="Exchange Found",
description="Alert if Exchange folder is not found",
default=True
)
exportfile: BoolProperty(
name="No Import File",
description="Add Modifiers and export",
default=False
)
importmod: BoolProperty(
name="Remove Modifiers",
description="Import and add modifiers",
default=False
)
exportmod: BoolProperty(
name="Modifiers",
description="Export modifiers",
default=False
)
importtextures: BoolProperty(
name="Bring Textures",
description="Import Textures",
default=True
)
createnodes: BoolProperty(
name="Bring Textures",
description="Import Textures",
default=True
)
importlevel: BoolProperty(
name="Multires. Level",
description="Bring Specific Multires Level",
default=False
)
importmesh: BoolProperty(
name="Mesh",
description="Import Mesh",
default=True
)
# copy location
loca: FloatVectorProperty(
name="location",
description="Location",
subtype="XYZ",
default=(0.0, 0.0, 0.0)
)
rota: FloatVectorProperty(
name="location",
description="Location",
subtype="EULER",
default=(0.0, 0.0, 0.0)
)
scal: FloatVectorProperty(
name="location",
description="Location",
subtype="XYZ",
default=(0.0, 0.0, 0.0)
)
dime: FloatVectorProperty(
name="dimension",
description="Dimension",
subtype="XYZ",
default=(0.0, 0.0, 0.0)
)
type: EnumProperty(
name="Export Type",
description="Different Export Types",
items=(("ppp", "Per-Pixel Painting", ""),
("mv", "Microvertex Painting", ""),
("ptex", "Ptex Painting", ""),
("uv", "UV-Mapping", ""),
("ref", "Reference Mesh", ""),
("retopo", "Retopo mesh as new layer", ""),
("vox", "Mesh As Voxel Object", ""),
("alpha", "Mesh As New Pen Alpha", ""),
("prim", "Mesh As Voxel Primitive", ""),
("curv", "Mesh As a Curve Profile", ""),
("autopo", "Mesh For Auto-retopology", ""),
("update", "Update mesh/uvs", ""),
),
default="ppp"
)
bake_resolution: EnumProperty(
name="Bake Resolution",
description="Bake resolution",
items=(("res_64", "64 x 64", ""),
("res_128", "128 x 128", ""),
("res_256", "256 x 256", ""),
("res_512", "512 x 512", ""),
("res_1024", "1024 x 1024", ""),
("res_2048", "2048 x 2048", ""),
("res_4096", "4096 x 4096", ""),
("res_8192", "8192 x 8192", ""),
),
default="res_1024"
)
folder_size: EnumProperty(
name="Applink folder size",
description="Applink folder size",
items=(("10", "10", ""),
("100", "100", ""),
("500", "500", ""),
("1000", "1000", ""),
("5000", "5000", ""),
("10000", "10000", ""),
),
default="500"
)
bake_textures: BoolProperty(
name="Bake all textures",
description="Add Modifiers and export",
default=False
)
bake_diffuse: BoolProperty(
name="Bake diffuse texture",
description="Add Modifiers and export",
default=False
)
bake_ao: BoolProperty(
name="Bake AO texture",
description="Add Modifiers and export",
default=False
)
bake_roughness: BoolProperty(
name="Bake roughness texture",
description="Add Modifiers and export",
default=False
)
bake_metalness: BoolProperty(
name="Bake metalness texture",
description="Add Modifiers and export",
default=False
)
bake_emissive: BoolProperty(
name="Bake emissive texture",
description="Add Modifiers and export",
default=False
)
bake_normal: BoolProperty(
name="Bake normal texture",
description="Add Modifiers and export",
default=False
)
bake_displacement: BoolProperty(
name="Bake displacement",
description="Add Modifiers and export",
default=False
)
class MeshCoat3D(PropertyGroup):
applink_address: StringProperty(
name="ApplinkAddress",
# subtype="APPLINK_ADDRESS",
)
class MaterialCoat3D(PropertyGroup):
name: StringProperty(
name="ApplinkAddress",
# subtype="APPLINK_ADDRESS",
default=''
)
bring_diffuse: BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bring_metalness: BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bring_roughness: BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bring_normal: BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bring_displacement: BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bring_emissive: BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bring_gloss: BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
classes = (
SCENE_PT_Main,
SCENE_PT_Settings,
SCENE_PT_Material,
SCENE_PT_Settings_Update,
SCENE_PT_Bake_Settings,
SCENE_PT_Settings_DeleteNodes,
SCENE_PT_Settings_Folders,
SCENE_PT_Material_Import,
SCENE_OT_folder,
SCENE_OT_opencoat,
SCENE_OT_export,
SCENE_OT_getback,
SCENE_OT_savenew,
SCENE_OT_delete_material_nodes,
SCENE_OT_delete_object_nodes,
SCENE_OT_delete_collection_nodes,
SCENE_OT_delete_scene_nodes,
VIEW3D_MT_Coat_Dynamic_Menu,
ObjectCoat3D,
SceneCoat3D,
MeshCoat3D,
MaterialCoat3D,
)
def register():
bpy.types.Material.coat3D_diffuse = BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bpy.types.Material.coat3D_roughness = BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bpy.types.Material.coat3D_metalness = BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bpy.types.Material.coat3D_normal = BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bpy.types.Material.coat3D_displacement = BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bpy.types.Material.coat3D_emissive = BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bpy.types.Material.coat3D_ao = BoolProperty(
name="Import diffuse texture",
description="Import diffuse texture",
default=True
)
bpy.types.Material.coat3D_alpha = BoolProperty(
name="Import alpha texture",
description="Import alpha texture",
default=True
)
bpy.types.Material.coat3D_gloss = BoolProperty(
name="Import alpha texture",
description="Import alpha texture",
default=True
)
from bpy.utils import register_class
for cls in classes:
register_class(cls)
bpy.types.Object.coat3D = PointerProperty(type=ObjectCoat3D)
bpy.types.Scene.coat3D = PointerProperty(type=SceneCoat3D)
bpy.types.Mesh.coat3D = PointerProperty(type=MeshCoat3D)
bpy.types.Material.coat3D = PointerProperty(type=MaterialCoat3D)
bpy.app.handlers.load_post.append(load_handler)
kc = bpy.context.window_manager.keyconfigs.addon
if kc:
km = kc.keymaps.new(name="3D View", space_type="VIEW_3D")
kmi = km.keymap_items.new('wm.call_menu', 'Q', 'PRESS', shift=True)
kmi.properties.name = "VIEW3D_MT_Coat_Dynamic_Menu"
def unregister():
import bpy
from bpy.utils import unregister_class
del bpy.types.Object.coat3D
del bpy.types.Scene.coat3D
del bpy.types.Material.coat3D
bpy.types.Material.coat3D_diffuse
bpy.types.Material.coat3D_metalness
bpy.types.Material.coat3D_roughness
bpy.types.Material.coat3D_normal
bpy.types.Material.coat3D_displacement
bpy.types.Material.coat3D_emissive
bpy.types.Material.coat3D_alpha
kc = bpy.context.window_manager.keyconfigs.addon
if kc:
km = kc.keymaps.get('3D View')
for kmi in km.keymap_items:
if kmi.idname == 'wm.call_menu':
if kmi.properties.name == "VIEW3D_MT_Coat_Dynamic_Menu":
km.keymap_items.remove(kmi)
for cls in reversed(classes):
unregister_class(cls)