From feda4f76721439414a85c7f8f96c05bbf99688d7 Mon Sep 17 00:00:00 2001 From: Kalle-Samuli Riihikoski Date: Sat, 13 Oct 2018 22:02:55 +0300 Subject: Add fbx support and extend node system. --- io_coat3D/__init__.py | 170 +++++++++++++++++++++++++++++++++------------- io_coat3D/tex.py | 182 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 274 insertions(+), 78 deletions(-) diff --git a/io_coat3D/__init__.py b/io_coat3D/__init__.py index f7d0bc88..647f7002 100644 --- a/io_coat3D/__init__.py +++ b/io_coat3D/__init__.py @@ -195,9 +195,6 @@ def updatemesh(objekti, proxy): bpy.ops.object.vertex_group_copy_to_selected() bpy.ops.object.select_all(action='DESELECT') - - - # UV Set Copy proxy.select_set('SELECT') @@ -238,12 +235,12 @@ class SCENE_PT_Main(bpy.types.Panel): def draw(self, context): layout = self.layout + coat = bpy.coat3D coat3D = bpy.context.scene.coat3D if(bpy.context.active_object): coa = bpy.context.active_object.coat3D - if(coat3D.exchange_found == False): - bpy.coat3D['active_coat'] = set_exchange_folder() + if(coat['status'] == 0): row = layout.row() row.label(text="Applink didn't find your 3d-Coat/Excahnge folder.") row = layout.row() @@ -322,6 +319,7 @@ class SCENE_OT_opencoat(bpy.types.Operator): print('haippaa',active_3dcoat) if running() == False: + os.popen('"' + active_3dcoat + os.sep + '3D-CoatDX64C.exe' '" ' + coat3D) print('C:\\Program Files\\3D-Coat-V4.8.21\\3D-CoatDX64C.exe ' + coat3D) else: @@ -387,6 +385,7 @@ class SCENE_OT_export(bpy.types.Operator): coat3D.exchange_found = False return {'FINISHED'} + folder_objects = set_working_folders() folder_size(folder_objects) @@ -400,7 +399,7 @@ class SCENE_OT_export(bpy.types.Operator): while(looking == True): checkname = folder_objects + os.sep + activeobj - checkname = ("%s%.2d.dae"%(checkname,object_index)) + checkname = ("%s%.2d.fbx"%(checkname,object_index)) if(os.path.isfile(checkname)): object_index += 1 else: @@ -421,9 +420,11 @@ class SCENE_OT_export(bpy.types.Operator): bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY') #bpy.ops.object.transforms_to_deltas(mode='SCALE') + if(coat3D.type == 'ppp' or coat3D.type == 'mv' or coat3D.type == 'ptex'): + bpy.ops.export_scene.fbx(filepath=coa.applink_address, use_selection=True, use_mesh_modifiers=False, axis_forward='Y', axis_up='Z') + else: + bpy.ops.export_scene.fbx(filepath=coa.applink_address, use_selection=True, use_mesh_modifiers=False, axis_up='Z', axis_forward='Y') - bpy.ops.wm.collada_export(filepath=coa.applink_address, selected=True, - apply_modifiers=False, sort_by_name=True, use_blender_profile=False, triangulate=False) file = open(importfile, "w") file.write("%s"%(checkname)) @@ -438,6 +439,7 @@ class SCENE_OT_export(bpy.types.Operator): nimi += koko.data.name + ':::' objekti.coat3D.applink_group = nimi objekti.coat3D.applink_address = coa.applink_address + objekti.coat3D.obj_mat = '' objekti.coat3D.applink_name = coa.applink_name objekti.coat3D.applink_firsttime = True objekti.coat3D.objecttime = str(os.path.getmtime(objekti.coat3D.applink_address)) @@ -540,7 +542,7 @@ class SCENE_OT_import(bpy.types.Operator): import_list.append(obj_coat.applink_address) if(import_list): for list in import_list: - bpy.ops.wm.collada_import(filepath=list) + bpy.ops.import_scene.fbx(filepath=list, global_scale = 1,axis_forward='X') bpy.ops.object.select_all(action='DESELECT') new_materials = bpy.data.materials.keys() @@ -562,42 +564,36 @@ class SCENE_OT_import(bpy.types.Operator): for oname in object_list: objekti = bpy.data.objects[oname] - if(objekti.coat3D.import_mesh): + if(objekti.coat3D.import_mesh and coat3D.importmesh == True): objekti.coat3D.import_mesh = False objekti.select_set('SELECT') - if (objekti.coat3D.applink_export == False): - find_name = objekti.data.name + '-mesh' - find_name = find_name.replace('.', '_') + new_name = objekti.data.name + name_boxs = new_name.split('.') + if len(name_boxs) > 1: + if len(name_boxs[-1]) == 3: + luku = int(name_boxs[-1]) + luku +=1 + uusi_nimi = ("%s.%.3d" % (new_name[:-4], luku)) + find_name = uusi_nimi else: - - - new_name = objekti.data.name - name_boxs = new_name.split('.') - if len(name_boxs) > 1: - if len(name_boxs[-1]) == 3: - luku = int(name_boxs[-1]) - luku +=1 - uusi_nimi = ("%s.%.3d" % (new_name[:-4], luku)) - find_name = uusi_nimi - else: - find_name = objekti.data.name - tosi = True - luku = 1 - find_name = ("%s.%.3d" % (objekti.data.name, luku)) - loyty = False - while tosi: - for obj in bpy.data.meshes: - if (obj.name == find_name): - loyty = True - break - if(loyty == True): - luku += 1 - find_name = ("%s.%.3d" % (objekti.data.name, luku)) - loyty = False - else: - find_name = ("%s.%.3d" % (objekti.data.name, luku-1)) - tosi = False + find_name = objekti.data.name + tosi = True + luku = 1 + find_name = ("%s.%.3d" % (objekti.data.name, luku)) + loyty = False + while tosi: + for obj in bpy.data.meshes: + if (obj.name == find_name): + loyty = True + break + if(loyty == True): + luku += 1 + find_name = ("%s.%.3d" % (objekti.data.name, luku)) + loyty = False + else: + find_name = ("%s.%.3d" % (objekti.data.name, luku-1)) + tosi = False for proxy_objects in diff_objects: if (bpy.data.objects[proxy_objects].data.name == find_name): @@ -639,7 +635,7 @@ class SCENE_OT_import(bpy.types.Operator): 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') objekti.rotation_euler = (0,0,0) - #objekti.scale = (1,1,1) + objekti.scale = (0.01,0.01,0.01) objekti.coat3D.applink_firsttime = False if(coat3D.importlevel): @@ -682,6 +678,8 @@ class SCENE_OT_import(bpy.types.Operator): objekti.select_set('SELECT') if(coat3D.importtextures): is_new = False + print('mitas nimee tassa:',objekti.coat3D.applink_name) + print('objekti nimi', objekti) tex.matlab(mat_list,objekti,bpy.context.scene,is_new) objekti.select_set('DESELECT') else: @@ -741,7 +739,7 @@ class SCENE_OT_import(bpy.types.Operator): old_materials = bpy.data.materials.keys() old_objects = bpy.data.objects.keys() - bpy.ops.wm.collada_import(filepath=new_applink_address) + bpy.ops.import_scene.fbx(filepath=new_applink_address) new_materials = bpy.data.materials.keys() new_objects = bpy.data.objects.keys() @@ -807,6 +805,67 @@ class SCENE_OT_import(bpy.types.Operator): from bpy import * from mathutils import Vector, Matrix +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 SCENE_PT_Settings_Update(ObjectButtonsPanel, bpy.types.Panel): + bl_label = "Update" + bl_parent_id = "SCENE_PT_Settings" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = False + coat3D = bpy.context.scene.coat3D + + rd = context.scene.render + + 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") + 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, "creategroup", text="Group Nodes") + +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_OPENGL'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + coat3D = bpy.context.scene.coat3D + + rd = context.scene.render + + 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, "exchangedir", text="Exchange folder") + + col = flow.column() + col.prop(coat3D, "coat3D_exe", text="3D-Coat.exe") + # 3D-Coat Dynamic Menu class VIEW3D_MT_Coat_Dynamic_Menu(bpy.types.Menu): bl_label = "3D-Coat Applink Menu" @@ -822,7 +881,7 @@ class VIEW3D_MT_Coat_Dynamic_Menu(bpy.types.Menu): layout.operator("import_applink.pilgway_3d_coat", text="Update Scene") layout.separator() - layout.operator("export_applink.pilgway_3d_coat", text="Transfer selected object(s) into 3D-Coat") + layout.operator("export_applink.pilgway_3d_coat", text="Copy selected object(s) into 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) @@ -876,6 +935,10 @@ class ObjectCoat3D(PropertyGroup): objpath: StringProperty( name="Object_Path" ) + obj_mat: StringProperty( + name="Object_Path", + default='' + ) applink_address: StringProperty( name="Object_Applink_address" ) @@ -933,6 +996,10 @@ class SceneCoat3D(PropertyGroup): name="FilePath", subtype="DIR_PATH", ) + coat3D_exe: StringProperty( + name="FilePath", + subtype="DIR_PATH", + ) cursor_loc: FloatVectorProperty( name="Cursor_loc", description="location" @@ -1023,6 +1090,16 @@ class SceneCoat3D(PropertyGroup): description="Import Textures", default=True ) + createnodes: BoolProperty( + name="Bring Textures", + description="Import Textures", + default=True + ) + creategroup: BoolProperty( + name="Bring Textures", + description="Import Textures", + default=True + ) importlevel: BoolProperty( name="Multires. Level", description="Bring Specific Multires Level", @@ -1096,6 +1173,9 @@ class MaterialCoat3D(PropertyGroup): classes = ( #ObjectButtonsPanel, SCENE_PT_Main, + SCENE_PT_Settings, + SCENE_PT_Settings_Update, + SCENE_PT_Settings_Folders, SCENE_OT_folder, SCENE_OT_opencoat, SCENE_OT_export, @@ -1113,7 +1193,7 @@ classes = ( def register(): bpy.coat3D = dict() bpy.coat3D['active_coat'] = '' - bpy.coat3D['status'] = 0 + bpy.coat3D['status'] = 1 bpy.coat3D['kuva'] = 1 from bpy.utils import register_class diff --git a/io_coat3D/tex.py b/io_coat3D/tex.py index 403b4b88..6026e493 100644 --- a/io_coat3D/tex.py +++ b/io_coat3D/tex.py @@ -29,9 +29,21 @@ def find_index(objekti): luku = luku +1 return luku +def RemoveFbxNodes(objekti): + Node_Tree = objekti.active_material.node_tree + for node in Node_Tree.nodes: + if node.type != 'OUTPUT_MATERIAL': + Node_Tree.nodes.remove(node) + else: + output = node + output.location = 340,400 + Prin_mat = Node_Tree.nodes.new(type="ShaderNodeBsdfPrincipled") + Prin_mat.location = 13, 375 + + Node_Tree.links.new(Prin_mat.outputs[0], output.inputs[0]) + def readtexturefolder(objekti,is_new): #read textures from texture file - coat3D = bpy.context.scene.coat3D obj_coat = objekti.coat3D texcoat = {} @@ -45,12 +57,13 @@ def readtexturefolder(objekti,is_new): #read textures from texture file files_dir = os.path.dirname(os.path.abspath(objekti.coat3D.applink_address)) files = os.listdir(files_dir) materiaali_muutos = objekti.active_material.name - uusin_mat = materiaali_muutos.replace('Material.','Material_') - new_name = (obj_coat.applink_name + '_' + uusin_mat) - name_boxs = new_name.split('.') - if len(name_boxs) > 1: - if len(name_boxs[-1]) == 3: - new_name = new_name[:-4] + uusin_mat = materiaali_muutos + if(is_new == True and objekti.coat3D.obj_mat == ''): + obj_coat.obj_mat = (objekti.coat3D.applink_name + '_' + objekti.data.uv_layers[0].name) + elif (objekti.coat3D.obj_mat == ''): + obj_coat.obj_mat = (objekti.coat3D.applink_name + '_' + uusin_mat) + + new_name = obj_coat.obj_mat + '_' for i in files: if(i.startswith(new_name)): koko_osoite = files_dir + os.sep + i @@ -74,15 +87,29 @@ def createnodes(objekti,texcoat): #luo nodes palikat ja linkittaa tekstuurit nii bring_normal = True bring_disp = True - act_material = objekti.active_material + coat3D = bpy.context.scene.coat3D + print('createnodes:', objekti) + if(objekti.active_material.use_nodes == False): objekti.active_material.use_nodes = True + act_material = objekti.active_material.node_tree + main_material = objekti.active_material.node_tree + applink_group_node = False #ensimmaiseksi kaydaan kaikki image nodet lapi ja tarkistetaan onko nimi 3DC alkunen jos on niin reload - for node in act_material.node_tree.nodes: + for node in act_material.nodes: + if(node.name == '3DC_Applink' and node.type == 'GROUP'): + applink_group_node = True + act_material = node.node_tree + break + + + for node in act_material.nodes: + print(node.name) if(node.type == 'TEX_IMAGE'): if(node.name == '3DC_color'): + print('halloo helsinki') bring_color = False node.image.reload() elif(node.name == '3DC_metalness'): @@ -96,63 +123,152 @@ def createnodes(objekti,texcoat): #luo nodes palikat ja linkittaa tekstuurit nii node.image.reload() #seuraavaksi lahdemme rakentamaan node tree. Lahdetaan Material Outputista rakentaa + if(applink_group_node == False and coat3D.creategroup): + group_tree = bpy.data.node_groups.new('3DC_Applink', 'ShaderNodeTree') + applink_tree = act_material.nodes.new('ShaderNodeGroup') + applink_tree.name = '3DC_Applink' + applink_tree.node_tree = group_tree + applink_tree.location = -400, 300 + act_material = group_tree + notegroup = act_material.nodes.new('NodeGroupOutput') - main_mat = act_material.node_tree.nodes['Material Output'] + + main_mat = main_material.nodes['Material Output'] if(main_mat.inputs['Surface'].is_linked == True): glue_mat = main_mat.inputs['Surface'].links[0].from_node + input_color = glue_mat.inputs.find('Base Color') + input_index = 0 #Color if(bring_color == True and glue_mat.inputs.find('Base Color') != -1 and texcoat['color'] != []): - node = act_material.node_tree.nodes.new('ShaderNodeTexImage') - node.location = -400,400 - node.name='3DC_color' - if(texcoat['color']): + node = act_material.nodes.new('ShaderNodeTexImage') + node.name = '3DC_color' + if (texcoat['color']): node.image = bpy.data.images.load(texcoat['color'][0]) - input_color = glue_mat.inputs.find('Base Color') - act_material.node_tree.links.new(node.outputs[0], glue_mat.inputs[input_color]) + if(coat3D.createnodes): + curvenode = act_material.nodes.new('ShaderNodeRGBCurve') + curvenode.name = '3DC_RGBCurve' + huenode = act_material.nodes.new('ShaderNodeHueSaturation') + huenode.name = '3DC_HueSaturation' + act_material.links.new(huenode.outputs[0], glue_mat.inputs[input_color]) + act_material.links.new(curvenode.outputs[0], huenode.inputs[4]) + act_material.links.new(node.outputs[0], curvenode.inputs[1]) + node.location = -990, 530 + curvenode.location = -660, 480 + huenode.location = -337, 335 + if(coat3D.creategroup): + act_material.links.new(huenode.outputs[0], notegroup.inputs[input_index]) + print('Group nimi', group_tree) + group_tree.outputs[input_index].name = 'Color' + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + else: + if (coat3D.creategroup): + node.location = -400, 400 + act_material.links.new(node.outputs[0], notegroup.inputs[input_index]) + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + + else: + node.location = -400,400 + act_material.links.new(node.outputs[0], glue_mat.inputs[input_color]) #Metalness if(bring_metalness == True and glue_mat.inputs.find('Metallic') != -1 and texcoat['metalness'] != []): - node = act_material.node_tree.nodes.new('ShaderNodeTexImage') - node.location = -830,160 + node = act_material.nodes.new('ShaderNodeTexImage') node.name='3DC_metalness' + input_color = glue_mat.inputs.find('Metallic') if(texcoat['metalness']): node.image = bpy.data.images.load(texcoat['metalness'][0]) node.color_space = 'NONE' - input_color = glue_mat.inputs.find('Metallic') - act_material.node_tree.links.new(node.outputs[0], glue_mat.inputs[input_color]) + if (coat3D.createnodes): + curvenode = act_material.nodes.new('ShaderNodeRGBCurve') + curvenode.name = '3DC_RGBCurve' + huenode = act_material.nodes.new('ShaderNodeHueSaturation') + huenode.name = '3DC_HueSaturation' + act_material.links.new(huenode.outputs[0], glue_mat.inputs[input_color]) + act_material.links.new(curvenode.outputs[0], huenode.inputs[4]) + act_material.links.new(node.outputs[0], curvenode.inputs[1]) + node.location = -994, 119 + curvenode.location = -668, 113 + huenode.location = -345, 118 + if (coat3D.creategroup): + act_material.links.new(huenode.outputs[0], notegroup.inputs[input_index]) + group_tree.outputs[input_index].name = 'Metalness' + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + else: + if (coat3D.creategroup): + node.location = -830, 160 + act_material.links.new(node.outputs[0], notegroup.inputs[input_index]) + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + else: + node.location = -830, 160 + act_material.links.new(node.outputs[0], glue_mat.inputs[input_color]) #Roughness if(bring_roughness == True and glue_mat.inputs.find('Roughness') != -1 and texcoat['rough'] != []): - node = act_material.node_tree.nodes.new('ShaderNodeTexImage') - node.location = -550,0 + node = act_material.nodes.new('ShaderNodeTexImage') node.name='3DC_roughness' + input_color = glue_mat.inputs.find('Roughness') if(texcoat['rough']): node.image = bpy.data.images.load(texcoat['rough'][0]) node.color_space = 'NONE' - input_color = glue_mat.inputs.find('Roughness') - act_material.node_tree.links.new(node.outputs[0], glue_mat.inputs[input_color]) + if (coat3D.createnodes): + curvenode = act_material.nodes.new('ShaderNodeRGBCurve') + curvenode.name = '3DC_RGBCurve' + huenode = act_material.nodes.new('ShaderNodeHueSaturation') + huenode.name = '3DC_HueSaturation' + act_material.links.new(huenode.outputs[0], glue_mat.inputs[input_color]) + act_material.links.new(curvenode.outputs[0], huenode.inputs[4]) + act_material.links.new(node.outputs[0], curvenode.inputs[1]) + node.location = -1000, -276 + curvenode.location = -670, -245 + huenode.location = -340, -100 + if (coat3D.creategroup): + act_material.links.new(huenode.outputs[0], notegroup.inputs[input_index]) + group_tree.outputs[input_index].name = 'Roughness' + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + else: + if (coat3D.creategroup): + node.location = -550, 0 + act_material.links.new(node.outputs[0], notegroup.inputs[input_index]) + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + else: + node.location = -550, 0 + act_material.links.new(node.outputs[0], glue_mat.inputs[input_color]) #Normal map if(bring_normal == True and glue_mat.inputs.find('Normal') != -1 and texcoat['nmap'] != []): - node = act_material.node_tree.nodes.new('ShaderNodeTexImage') - normal_node = act_material.node_tree.nodes.new('ShaderNodeNormalMap') - node.location = -600,-370 - normal_node.location = -300,-270 + node = act_material.nodes.new('ShaderNodeTexImage') + normal_node = act_material.nodes.new('ShaderNodeNormalMap') + node.location = -600,-670 + normal_node.location = -300,-300 node.name='3DC_normal' + normal_node.name='3DC_normalnode' if(texcoat['nmap']): node.image = bpy.data.images.load(texcoat['nmap'][0]) node.color_space = 'NONE' input_color = glue_mat.inputs.find('Normal') - act_material.node_tree.links.new(node.outputs[0], normal_node.inputs[1]) - act_material.node_tree.links.new(normal_node.outputs[0], glue_mat.inputs[input_color]) - - bpy.ops.object.editmode_toggle() #HACKKI joka saa tekstuurit nakymaan heti - bpy.ops.object.editmode_toggle() + act_material.links.new(node.outputs[0], normal_node.inputs[1]) + act_material.links.new(normal_node.outputs[0], glue_mat.inputs[input_color]) + if (coat3D.creategroup): + act_material.links.new(normal_node.outputs[0], notegroup.inputs[input_index]) + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 def matlab(mat_list, objekti, scene,is_new): + + ''' FBX Materials: remove all nodes and create princibles node''' + if(is_new): + RemoveFbxNodes(objekti) + + '''Main Loop for Texture Update''' #checkmaterial(mat_list, objekti) readtexturefolder(objekti,is_new) -- cgit v1.2.3