2023-03-21 20:39:30 +00:00
|
|
|
import bpy
|
2023-03-29 10:43:53 +00:00
|
|
|
import os
|
|
|
|
import re
|
2023-03-21 20:39:30 +00:00
|
|
|
|
2023-03-29 10:43:53 +00:00
|
|
|
from ..common import addon
|
|
|
|
from ..common import validate_name
|
|
|
|
|
2024-05-18 11:09:47 +00:00
|
|
|
class GB_OT_export2godot(bpy.types.Operator):
|
2023-03-29 10:43:53 +00:00
|
|
|
"""Export whole collections to Godot throught glTF format"""
|
2024-05-18 11:09:47 +00:00
|
|
|
bl_idname = "gb.export2godot"
|
2023-03-29 10:43:53 +00:00
|
|
|
bl_label = "Export to Godot project"
|
2023-03-21 20:39:30 +00:00
|
|
|
bl_options = {'REGISTER', 'UNDO'}
|
2023-03-29 10:43:53 +00:00
|
|
|
|
2023-03-21 20:39:30 +00:00
|
|
|
def invoke(self, context, event):
|
|
|
|
return self.execute(context)
|
2023-03-29 10:43:53 +00:00
|
|
|
|
2023-03-21 20:39:30 +00:00
|
|
|
def execute(self, context):
|
2024-05-18 11:09:47 +00:00
|
|
|
# prefs = addon.get_prefs()
|
|
|
|
# print("Root collection : {}".format(prefs.default_root_collection))
|
|
|
|
# print("Godot path : {}".format(prefs.default_godot_project_path))
|
|
|
|
# print("Blender repository path : {}".format(
|
|
|
|
# prefs.default_blender_repository_path))
|
|
|
|
|
|
|
|
print("Root collection : {}".format(context.scene.root_collection))
|
|
|
|
print("Godot path : {}".format(context.scene.godot_project_path))
|
2023-03-29 10:43:53 +00:00
|
|
|
print("Blender repository path : {}".format(
|
2024-05-18 11:09:47 +00:00
|
|
|
context.scene.blender_repository_path))
|
2023-03-29 10:43:53 +00:00
|
|
|
|
|
|
|
def save_file_beforehand():
|
|
|
|
self.report(
|
|
|
|
{"WARNING"}, "File must be saved first - skipping export")
|
|
|
|
bpy.ops.wm.save_mainfile('INVOKE_AREA')
|
|
|
|
return {"CANCELLED"}
|
|
|
|
|
|
|
|
def create_destination_folder():
|
|
|
|
"""
|
|
|
|
Define the destination folder and creates it if nonexistent.
|
|
|
|
Return the path name
|
|
|
|
"""
|
|
|
|
|
|
|
|
final_path = bpy.data.filepath.replace(
|
2024-05-18 11:09:47 +00:00
|
|
|
context.scene.blender_repository_path, context.scene.godot_project_path)
|
2023-03-29 10:43:53 +00:00
|
|
|
gltf_path = os.path.splitext(final_path)[0]
|
|
|
|
if not os.path.isdir(gltf_path):
|
|
|
|
os.makedirs(gltf_path)
|
|
|
|
return gltf_path
|
|
|
|
|
|
|
|
def recurLayerCollection(layerColl, collName):
|
|
|
|
""" Activate the selected collection for export"""
|
|
|
|
found = None
|
|
|
|
if (layerColl.name == collName):
|
|
|
|
return layerColl
|
|
|
|
for layer in layerColl.children:
|
|
|
|
found = recurLayerCollection(layer, collName)
|
|
|
|
if found:
|
|
|
|
return found
|
|
|
|
|
|
|
|
def export_content(scene_collection):
|
|
|
|
|
|
|
|
def check_name(collection):
|
|
|
|
is_valid = validate_name.validate_name(collection.name)
|
|
|
|
if not is_valid:
|
|
|
|
self.report({"WARNING"},
|
|
|
|
"Name {} is not valid - skipping export".format(collection.name))
|
|
|
|
return {"CANCELLED"}
|
|
|
|
|
|
|
|
def export_to_file(tscn_collection):
|
|
|
|
print("Exporting {}".format(tscn_collection.name))
|
|
|
|
|
|
|
|
filename = tscn_collection.name
|
|
|
|
# Export collection - parameters : https://docs.blender.org/api/current/bpy.ops.export_scene.html?highlight=export_scene#bpy.ops.export_scene.gltf
|
|
|
|
print("Exporting to : {}/{}".format(gltf_path, filename))
|
|
|
|
print("Exporting textures to : {}_{}_textures".format((os.path.splitext(os.path.basename(gltf_path)))[0], filename))
|
|
|
|
bpy.ops.export_scene.gltf(
|
|
|
|
filepath="{}/{}".format(gltf_path, filename),
|
|
|
|
export_format="GLTF_SEPARATE", # Export glTF Separate (.gltf + .bin + textures), Exports multiple files, with separate JSON, binary and texture data
|
|
|
|
export_texture_dir="{}_{}_textures".format((os.path.splitext(os.path.basename(gltf_path)))[0], filename), # Textures folder
|
2024-05-18 11:09:47 +00:00
|
|
|
export_copyright=context.scene.licence,
|
2023-03-29 10:43:53 +00:00
|
|
|
use_active_collection = True,
|
|
|
|
use_renderable = True,
|
|
|
|
export_cameras=False,
|
|
|
|
export_lights=False,
|
2024-05-18 11:09:47 +00:00
|
|
|
export_apply=True, # Apply modifiers
|
|
|
|
export_gn_mesh=True # Apply Geometry Nodes Instance
|
2023-03-29 10:43:53 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
tscn_collections = [ coll for coll in bpy.data.collections if scene_collection.user_of_id(coll)]
|
|
|
|
|
|
|
|
for tscn in tscn_collections:
|
|
|
|
print("--------------------")
|
|
|
|
check_name(tscn)
|
|
|
|
# Activate proper collection for export
|
|
|
|
layer_collection = bpy.context.view_layer.layer_collection
|
|
|
|
layerColl = recurLayerCollection(layer_collection, tscn.name)
|
|
|
|
if layerColl.exclude:
|
|
|
|
print("{} is not activated - not exported".format(tscn.name))
|
|
|
|
else:
|
|
|
|
print("Set active collection to {}".format(tscn.name))
|
|
|
|
bpy.context.view_layer.active_layer_collection = layerColl
|
|
|
|
export_to_file(tscn)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not bpy.data.is_saved:
|
|
|
|
save_file_beforehand()
|
|
|
|
else:
|
|
|
|
try:
|
2024-05-18 11:09:47 +00:00
|
|
|
scn_col = bpy.data.collections[context.scene.root_collection]
|
2023-03-29 10:43:53 +00:00
|
|
|
except KeyError:
|
|
|
|
self.report({"WARNING"},
|
2024-05-18 11:09:47 +00:00
|
|
|
"No \"{}\" root collection in the file - skipping export".format(context.scene.root_collection))
|
2023-03-29 10:43:53 +00:00
|
|
|
return {"CANCELLED"}
|
|
|
|
|
|
|
|
# Create the proper destination path
|
|
|
|
gltf_path = create_destination_folder()
|
|
|
|
|
|
|
|
export_content(scn_col)
|
|
|
|
return {"FINISHED"}
|